Update CSS, add relationship between sensorModel and locationModel, and remove console.log statements
This commit is contained in:
parent
ba498a4d4b
commit
d38423fa6d
@ -9,13 +9,13 @@ const sequelize = new Sequelize(
|
||||
process.env.DB_USER,
|
||||
process.env.DB_PASS,
|
||||
{
|
||||
host: "mpsqldatabase.mysql.database.azure.com",
|
||||
host: "mpsqldatabasean.mysql.database.azure.com",
|
||||
dialect: 'mysql',
|
||||
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
||||
attributeBehavior: 'escape',
|
||||
dialectOptions: {
|
||||
ssl: {
|
||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')),
|
||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')),
|
||||
},
|
||||
|
||||
},
|
||||
|
2
api.MD
2
api.MD
@ -172,4 +172,4 @@ http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&p
|
||||
curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
|
||||
|
||||
|
||||
curl localhost:3000/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}'
|
||||
curl localhost/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}'
|
||||
|
@ -51,26 +51,16 @@ app.use("/", require("./routes/render"));
|
||||
// used, this is what will be called.
|
||||
app.use(function (req, res, next) {
|
||||
//application/json; charset=utf-8
|
||||
if (req.is("application/json" || "application/json; charset=utf-8")) {
|
||||
var err = new Error("Not Found");
|
||||
err.message = "Page not found";
|
||||
err.status = 404;
|
||||
next(err);
|
||||
} else {
|
||||
res.status(404).render("404");
|
||||
}
|
||||
});
|
||||
|
||||
// Error handler. This is where `next()` will go on error
|
||||
app.use(function (err, req, res, next) {
|
||||
console.error(err.status || res.status, err.name, req.method, req.url);
|
||||
if (![404].includes(err.status || res.status)) {
|
||||
console.error(err.message);
|
||||
console.error(err.stack);
|
||||
console.error("=========================================");
|
||||
}
|
||||
|
||||
console.log(err.name + " validation error");
|
||||
// Parse key error for Sequilzw
|
||||
let keyErrors = {};
|
||||
if (["SequelizeValidationError"].includes(err.name) && err.errors) {
|
||||
@ -82,17 +72,26 @@ app.use(function (err, req, res, next) {
|
||||
res.status = 422;
|
||||
}
|
||||
|
||||
if (![404, 422].includes(err.status || res.status)) {
|
||||
if (![404, 401, 422].includes(err.status || res.status)) {
|
||||
console.error(err.message);
|
||||
console.error(err.stack);
|
||||
console.error("=========================================");
|
||||
}
|
||||
|
||||
|
||||
res.status(err.status || 500);
|
||||
// res.status(err.status || 500);
|
||||
|
||||
if (req.get('Content-Type') && req.get('Content-Type').includes("json")) {
|
||||
res.json({
|
||||
name: err.name || "Unknown error",
|
||||
message: err.message,
|
||||
keyErrors,
|
||||
});
|
||||
}
|
||||
else {
|
||||
res.json({
|
||||
name: err.name || "Unknown error",
|
||||
message: err.message,
|
||||
keyErrors,
|
||||
});
|
||||
}
|
||||
});
|
@ -107,4 +107,6 @@ const sensorModel = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
sensorModel.belongsTo(locationModel);
|
||||
|
||||
module.exports = { sensorModel };
|
||||
|
@ -3,7 +3,7 @@ const { Sequelize, DataTypes } = require("sequelize");
|
||||
const { sequelize } = require("../mySQL");
|
||||
const { userModel } = require("./userModel");
|
||||
|
||||
//sequelize.sync();
|
||||
sequelize.sync();
|
||||
const tokenModel = sequelize.define(
|
||||
"token",
|
||||
{
|
||||
|
@ -9,13 +9,13 @@ const sequelize = new Sequelize(
|
||||
process.env.DB_USER,
|
||||
process.env.DB_PASS,
|
||||
{
|
||||
host: "mpsqldatabase.mysql.database.azure.com",
|
||||
host: "mpsqldatabasean.mysql.database.azure.com",
|
||||
dialect: 'mysql',
|
||||
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
||||
attributeBehavior: 'escape',
|
||||
dialectOptions: {
|
||||
ssl: {
|
||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')),
|
||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')),
|
||||
},
|
||||
|
||||
},
|
||||
|
@ -1,19 +1,41 @@
|
||||
const { hash, compareHash } = require("./bcrypt.js");
|
||||
const { tokenModel } = require("../database/model/tokenModel.js");
|
||||
const { userModel } = require("../database/model/userModel");
|
||||
const { hash, compareHash } = require("./bcrypt.js");
|
||||
const { generateUUID } = require("./generateUUID.js");
|
||||
const { isValid } = require("./isValid");
|
||||
|
||||
async function getTokenByToken(token) {
|
||||
const splitAuthToken = token.split("-");
|
||||
const rowid = splitAuthToken[0];
|
||||
const suppliedToken = splitAuthToken.slice(1).join("-");
|
||||
|
||||
token = await tokenModel.findByPk(rowid, { include: userModel });
|
||||
|
||||
token.isValid = await compareHash(suppliedToken, token.token); //true
|
||||
console.log("function api getTokenByToken token", token.isValid);
|
||||
token.isValid = token.isValid && isValid(token.expiration);
|
||||
console.log("function api getTokenByToken token", token.isValid);
|
||||
if (!token.isValid) {
|
||||
//add boolean to token table
|
||||
token.destroy();
|
||||
}
|
||||
/*
|
||||
1) take userid
|
||||
2) generate random api key
|
||||
3) hash the api key
|
||||
4) append userid with - and api key
|
||||
5) you give the user rowid-uuidv4
|
||||
6) store in database
|
||||
console.log(
|
||||
"function api getTokenByToken token",
|
||||
await compareHash(suppliedToken, token.token),
|
||||
isValid("token" , token.expiration)
|
||||
);
|
||||
*/
|
||||
//can be used for api key or token. Both are the same logic
|
||||
console.log(token.isValid);
|
||||
return token;
|
||||
}
|
||||
|
||||
async function addToken(userId, permission, expiry) {
|
||||
let uuid = await generateUUID();
|
||||
let hashtoken = await hash(uuid);
|
||||
//console.log("user id", userId);
|
||||
// return { token: token, userid: userRes.id, username: userRes.username };
|
||||
// let token = await addToken(userRes.id , "canRead" , tokenToLive);
|
||||
|
||||
let token = await tokenModel.create({
|
||||
userid: userId,
|
||||
@ -26,23 +48,4 @@ async function addToken(userId, permission , expiry) {
|
||||
return token.id + "-" + uuid;
|
||||
}
|
||||
|
||||
async function checkToken(Supplied, rowid) {
|
||||
try {
|
||||
const retrivedToken = await tokenModel.findOne({
|
||||
raw: true,
|
||||
attributes: ["token", "permission"],
|
||||
where: {
|
||||
id: rowid,
|
||||
},
|
||||
});
|
||||
//console.log(retrivedKey.apikey);
|
||||
if (compareHash(Supplied, retrivedToken.token)) {
|
||||
//return true;
|
||||
return retrivedToken.permission;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { addToken , checkToken };
|
||||
module.exports = { addToken, getTokenByToken };
|
||||
|
@ -1,20 +1,14 @@
|
||||
const moment = require("moment");
|
||||
const currentTime = moment().format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
//time is taken from the token
|
||||
function isValid(time) {
|
||||
const timeDiff = moment(currentTime).diff(time, "minutes");
|
||||
|
||||
if (timeDiff > 1) {
|
||||
console.log(timeDiff);
|
||||
if (
|
||||
Math.floor(new Date(time).getTime() / 1000) <
|
||||
Math.floor(new Date().getTime() / 1000)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = { isValid };
|
@ -18,15 +18,19 @@ async function getSensorData() {
|
||||
const sensorData = await sensorDataModel.findAll();
|
||||
return sensorData;
|
||||
}
|
||||
|
||||
let dataArray = [];
|
||||
async function addSensorData(id_sensor, id_location, sensordata) {
|
||||
const sensorData = await sensorDataModel.create({
|
||||
sensorid: id_sensor,
|
||||
locationid: id_location ,
|
||||
measurement: sensordata,
|
||||
measurement: sensordata.measurement,
|
||||
});
|
||||
io().emit('sensorData:new', sensorData)
|
||||
//console.log("sensorData", sensorData);
|
||||
//console.log("sensorData", sensordata);
|
||||
dataArray.push(sensordata);
|
||||
console.log("dataArray", dataArray);
|
||||
|
||||
io().emit('sensorData:new', dataArray)
|
||||
return sensorData;
|
||||
}
|
||||
|
||||
@ -61,6 +65,14 @@ async function getSensorDataById(id) {
|
||||
});
|
||||
return sensorData;
|
||||
}
|
||||
|
||||
async function getLatestData() {
|
||||
const sensorData = await sensorDataModel.findAll({
|
||||
limit: 1,
|
||||
order: [["createdAt", "DESC"]],
|
||||
});
|
||||
return sensorData;
|
||||
}
|
||||
var ormQuery = {};
|
||||
var whereClause = {};
|
||||
var whereDate = {};
|
||||
@ -724,5 +736,6 @@ module.exports = {
|
||||
getSensorDataById,
|
||||
getData,
|
||||
getDatabyRange,
|
||||
getLatestData,
|
||||
|
||||
};
|
@ -2,7 +2,6 @@ const { Op } = require('sequelize')
|
||||
const { hash, compareHash } = require("./bcrypt.js");
|
||||
const { addToken } = require("./api");
|
||||
const { userModel } = require("../database/model/userModel");
|
||||
moment = require('moment')
|
||||
|
||||
|
||||
|
||||
@ -71,9 +70,11 @@ async function loginUser(user) {
|
||||
if (!match) return false;
|
||||
//console.log('loginUser', userRes.id, userRes.username);
|
||||
|
||||
//generate token and permission and experiation time
|
||||
const currentTime = moment().format('YYYY-MM-DD HH:mm:ss');
|
||||
let token = await addToken(userRes.id , "canRead" , currentTime);
|
||||
//generate token and permission and experiation time + 30 mins
|
||||
//let tokenToLive = moment().add(30, 'minutes').format();
|
||||
let currentDate = new Date();
|
||||
let tokenToLive = new Date(currentDate.getTime() + 30 * 60000);
|
||||
let token = await addToken(userRes.id , "canRead" , tokenToLive);
|
||||
return { token: token, userid: userRes.id, username: userRes.username };
|
||||
}
|
||||
|
||||
|
@ -1,68 +1,36 @@
|
||||
const { tokenModel } = require("../database/model/tokenModel");
|
||||
const { userModel } = require("../database/model/userModel");
|
||||
const { compareHash } = require("../functions/bcrypt");
|
||||
const { checkToken } = require("../functions/api");
|
||||
const { isValid } = require("../functions/isValid");
|
||||
const { getTokenByToken } = require("../functions/api");
|
||||
|
||||
const permissionError = new Error('PermissionError')
|
||||
permissionError.name = "Inadequate Permission Error"
|
||||
permissionError.status = 401
|
||||
permissionError.message = "Inadequate permission to complete this response"
|
||||
|
||||
async function auth(req, res, next) {
|
||||
try {
|
||||
const authToken = req.header("auth-token");
|
||||
if (!authToken) {
|
||||
const error = new Error("No Token key was supplied. Invalid request");
|
||||
throw error;
|
||||
const token = await getTokenByToken(req.header("auth-token"));
|
||||
|
||||
if (!token || !token.isValid){
|
||||
throw permissionError;
|
||||
}
|
||||
|
||||
const splitAuthToken = authToken.split("-");
|
||||
const rowid = splitAuthToken[0];
|
||||
const suppliedToken = splitAuthToken.slice(1).join("-");
|
||||
|
||||
const token = await tokenModel.findByPk(rowid, { include: userModel });
|
||||
|
||||
if (!token) {
|
||||
const error = new Error("Token key not found. Invalid request");
|
||||
throw error;
|
||||
}
|
||||
|
||||
const isMatch = await compareHash(suppliedToken, token.token);
|
||||
|
||||
console.log(isMatch);
|
||||
if (!isMatch) {
|
||||
const error = new Error("Token key not found. Invalid request");
|
||||
throw error;
|
||||
}
|
||||
//if token is a match
|
||||
req.token = token;
|
||||
req.user = await token.getUser();
|
||||
const permission = await checkToken(suppliedToken, rowid);
|
||||
|
||||
const route = req.originalUrl.split("?")[0]; // Removing query parameters
|
||||
//if route is from user/ and permission is canRead allow it to do CRUD
|
||||
if (route.includes("/user/") && permission === "canRead") {
|
||||
next();
|
||||
if (route.includes("/user/") && token.permission === "canRead") {
|
||||
return next();
|
||||
}
|
||||
if ((req.method === "GET" && permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && permission === "canWrite")) {
|
||||
next();
|
||||
}
|
||||
|
||||
if (!isValid(token.expiration)){
|
||||
req.token.destroy();
|
||||
throw new Error("Token expired");
|
||||
if ((req.method === "GET" && token.permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite")) {
|
||||
return next();
|
||||
}
|
||||
|
||||
throw permissionError
|
||||
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { auth };
|
||||
|
||||
/*
|
||||
else {
|
||||
const error = new Error("Insufficient permission");
|
||||
error.status = 401;
|
||||
throw error;
|
||||
}
|
||||
|
||||
*/
|
@ -3812,6 +3812,7 @@
|
||||
|
||||
.card-text {
|
||||
color: #000000;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* edit profile */
|
||||
|
@ -186,9 +186,7 @@ app.auth = (function (app) {
|
||||
function isLoggedIn(callback) {
|
||||
|
||||
if (getToken()) {
|
||||
console.log("you shldnt appear at all");
|
||||
return app.api.get("user/me", function (error, data) {
|
||||
console.log(error, data);
|
||||
if (!error) app.auth.user = data;
|
||||
return callback(error, data);
|
||||
});
|
||||
|
@ -18,5 +18,8 @@ router.use('/sensor', [auth, APIlogger], require('./sensor.js'));
|
||||
//sensor data route
|
||||
router.use('/sensor-data', [auth, APIlogger], require('./sensorData.js'));
|
||||
|
||||
//latest sensor data to display on dashboard
|
||||
router.use('/latest-sensor-data', [APIlogger], require('./latestsensorData.js'));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
21
consumerWebsite/routes/latestsensorData.js
Normal file
21
consumerWebsite/routes/latestsensorData.js
Normal file
@ -0,0 +1,21 @@
|
||||
const {
|
||||
getLatestData,
|
||||
|
||||
} = require("../functions/sensorData");
|
||||
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/data", async (req, res, next) => {
|
||||
try {
|
||||
console.log(req.query);
|
||||
const data = await getLatestData();
|
||||
res.status(200).json(data);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -8,7 +8,7 @@ const router = express.Router();
|
||||
router.get("/me", async function (req, res, next) {
|
||||
try {
|
||||
let user = await getUserByID(req.user);
|
||||
console.log(user);
|
||||
//console.log(user);
|
||||
res.json({
|
||||
user: user,
|
||||
});
|
||||
|
@ -1,9 +1,17 @@
|
||||
<%- include('top') %>
|
||||
<script>
|
||||
//call socket.io
|
||||
$(document).ready(async function () {
|
||||
|
||||
app.api.get('latest-sensor-data/data', function (error, data) {
|
||||
//console.log(data[0]);
|
||||
$.scope.LatestSensorData.push(data[0]);
|
||||
});
|
||||
});
|
||||
//call socket.io to get live data
|
||||
app.socket.on("sensorData:new", function (data) {
|
||||
console.log("new data!!")
|
||||
console.log(data);
|
||||
|
||||
console.log(data[0]);
|
||||
$.scope.LatestSensorData.update(data[0]);
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -53,7 +61,7 @@
|
||||
</header>
|
||||
<!-- Page Content -->
|
||||
<div class="container">
|
||||
<div class="services-bar">
|
||||
<div class="services-bar" jq-repeat="LatestSensorData">
|
||||
<h1 class="my-4">Services</h1>
|
||||
<!-- Services Section -->
|
||||
<div class="row">
|
||||
@ -61,7 +69,7 @@
|
||||
<div class="card">
|
||||
<h4 class="card-header">Air Quality Index</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">15 - 18 PSI</p>
|
||||
<p class="card-text display-4">{{ measurement.psi }} PSI</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
@ -72,7 +80,7 @@
|
||||
<div class="card">
|
||||
<h4 class="card-header">Humidity</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">70% - 75%</p>
|
||||
<p class="card-text display-4">{{ measurement.humidity }} %</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
@ -83,7 +91,7 @@
|
||||
<div class="card">
|
||||
<h4 class="card-header">Temperature</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">30° - 37°</p>
|
||||
<p class="card-text display-4">{{ measurement.temperature }}°</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
@ -92,9 +100,9 @@
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Another Category</h4>
|
||||
<h4 class="card-header">Wind Speed</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">values</p>
|
||||
<p class="card-text display-4">{{ measurement.windspeed }} Km/h </p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
|
@ -8,10 +8,9 @@
|
||||
|
||||
<ul id="sensorDataList">
|
||||
<li jq-repeat='sensorData'>
|
||||
rowid: {{ id }}
|
||||
sensorId: {{ sensorid }}
|
||||
created: {{ createdAt }}
|
||||
location: {{ locationid }}
|
||||
created: {{ createdAt }}
|
||||
<br />
|
||||
co: {{ measurement.co }}
|
||||
humidity: {{ measurement.humidity }}
|
||||
@ -30,7 +29,7 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(async function () {
|
||||
app.api.get('sensor-data/data?order=DESC&limit=40', function(error, data){
|
||||
app.api.get('sensor-data/data?order=DESC&limit=6', function(error, data){
|
||||
$.scope.sensorData.push(...data);
|
||||
})
|
||||
})
|
||||
|
@ -57,9 +57,7 @@
|
||||
//check if user is logged in
|
||||
app.auth.isLoggedIn(function (error, data) {
|
||||
if (!error) {
|
||||
console.log(error);
|
||||
$.scope.getUsername.update(data);
|
||||
|
||||
if (location.pathname == "/profile") {
|
||||
$.scope.getUserDetails.update(data);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user