diff --git a/IoT-sensor/index.js b/IoT-sensor/index.js
index a5cfb75..0d2dd8b 100644
--- a/IoT-sensor/index.js
+++ b/IoT-sensor/index.js
@@ -1,9 +1,10 @@
-const { run } = require("./modules/IoT-sensor");
+const { IoTdataGenerator } = require("./modules/IoT-sensor");
const client = require("./modules/mqtt");
async function publishData() {
try {
- const data = await run();
+ let iothub = new IoTdataGenerator();
+ let data = await iothub.generateData();
console.log(data);
client.publish("iot-data", JSON.stringify(data));
} catch (err) {
diff --git a/IoT-sensor/modules/IoT-sensor.js b/IoT-sensor/modules/IoT-sensor.js
index 2c6916e..cdaaa35 100644
--- a/IoT-sensor/modules/IoT-sensor.js
+++ b/IoT-sensor/modules/IoT-sensor.js
@@ -18,19 +18,19 @@ class IoTdataGenerator {
async generateData() {
try {
const { loc, sen } = await this.getLocationAndSensorId();
+ const dataAray = []; // create a new array for each call
+
for (let i = 0; i < sen.length; i++) {
- //console.log(sen[i].id);
- //console.log(loc[i].id);
- //console.log("you should appear 6 times only")
dataAray.push(firstDataRow(sen[i].id, loc[i].id));
- }
+ }
+
+ return dataAray;
} catch (err) {
console.error(err);
}
- return dataAray;
-
}
}
+
//helper function to generate random data
function firstDataRow(sensorId, locationId) {
@@ -57,15 +57,7 @@ function firstDataRow(sensorId, locationId) {
2) loop through each sensor id and location id and generate random data and pass to mqtt
*/
-async function run() {
- let iotData = new IoTdataGenerator();
- const result = await iotData.generateData();
- console.log(result);
- return result;
-}
-
-
-module.exports = { run };
+module.exports = { IoTdataGenerator };
diff --git a/api.MD b/api.MD
index 2f590e4..c435b69 100644
--- a/api.MD
+++ b/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/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}'
+curl localhost:3000/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}'
diff --git a/consumerWebsite/app.js b/consumerWebsite/app.js
index ce7fee1..f8dc2a8 100644
--- a/consumerWebsite/app.js
+++ b/consumerWebsite/app.js
@@ -7,7 +7,7 @@ const ejs = require("ejs");
module.exports = app;
-process.nextTick(() => require('./mqttApp'));
+process.nextTick(() => require("./mqttApp"));
app.use(express.json());
app.set("json spaces", 2);
@@ -16,12 +16,16 @@ app.set("json spaces", 2);
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
limit: 600, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
- standardHeaders: 'draft-7', // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
+ standardHeaders: "draft-7", // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
legacyHeaders: false, // Disable the `X-RateLimit-*` headers.
});
// Hold list of functions to run when the server is ready
-app.onListen = [function(){console.log('Express is ready')}];
+app.onListen = [
+ function () {
+ console.log("Express is ready");
+ },
+];
// Apply the rate limiting middleware to all requests.
app.use(limiter);
@@ -36,10 +40,9 @@ app.set("view engine", "ejs");
// Have express server static content( images, CSS, browser JS) from the public
app.use(express.static(path.join(__dirname, "./public")));
-
//route logic
-app.use("/api/seed/v0" ,require("./routes/seed_route.js"));
-app.use("/api/v0", require("./routes/api_routes"));
+app.use("/api/seed/v0", require("./routes/seed_route.js"));
+app.use("/api/v0", require("./routes/api_routes"));
//render logic
app.use("/", require("./routes/render"));
@@ -47,19 +50,17 @@ app.use("/", require("./routes/render"));
// Catch 404 and forward to error handler. If none of the above routes are
// used, this is what will be called.
app.use(function (req, res, next) {
- if (req.is("application/json")) {
- var err = new Error("Not Found");
- err.message = "Page not found";
- err.status = 404;
- next(err);
- }
- else{
+ //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);
@@ -78,14 +79,20 @@ app.use(function (err, req, res, next) {
keyErrors[item.path] = item.message;
}
}
+ res.status = 422;
}
+ if (![404, 422].includes(err.status || res.status)) {
+ console.error(err.message);
+ console.error(err.stack);
+ console.error("=========================================");
+ }
+
+
res.status(err.status || 500);
- console.log(keyErrors);
res.json({
- name: err.name,
+ name: err.name || "Unknown error",
message: err.message,
keyErrors,
});
});
-
diff --git a/consumerWebsite/database/model/apiKeyModel.js b/consumerWebsite/database/model/tokenModel.js
similarity index 85%
rename from consumerWebsite/database/model/apiKeyModel.js
rename to consumerWebsite/database/model/tokenModel.js
index 2604d2f..26ec8af 100644
--- a/consumerWebsite/database/model/apiKeyModel.js
+++ b/consumerWebsite/database/model/tokenModel.js
@@ -4,8 +4,8 @@ const { sequelize } = require("../mySQL");
const { userModel } = require("./userModel");
//sequelize.sync();
-const apikeyModel = sequelize.define(
- "apikey",
+const tokenModel = sequelize.define(
+ "token",
{
id: {
type: DataTypes.INTEGER,
@@ -28,7 +28,7 @@ const apikeyModel = sequelize.define(
key: "id",
},
},
- apikey: {
+ token: {
type: DataTypes.STRING,
allowNull: false,
length: 255,
@@ -45,7 +45,14 @@ const apikeyModel = sequelize.define(
validate: {
notEmpty: true,
len: [1, 255],
- isIn: [["canRead", "canWrite" , "auto-generated"]],
+ isIn: [["canRead", "canWrite",]],
+ },
+ },
+ expiration: {
+ type: DataTypes.DATE,
+ allowNull: false,
+ validate: {
+ isDate: true,
},
},
createdAt: {
@@ -61,9 +68,9 @@ const apikeyModel = sequelize.define(
timestamps: true,
}
);
-apikeyModel.belongsTo(userModel);
+tokenModel.belongsTo(userModel);
-module.exports = { apikeyModel };
+module.exports = { tokenModel };
/*
class AuthToken extends Model {
diff --git a/consumerWebsite/functions/api.js b/consumerWebsite/functions/api.js
index bbdbbe0..fcba1f3 100644
--- a/consumerWebsite/functions/api.js
+++ b/consumerWebsite/functions/api.js
@@ -1,5 +1,5 @@
const { hash, compareHash } = require("./bcrypt.js");
-const { apikeyModel } = require("../database/model/apiKeyModel");
+const { tokenModel } = require("../database/model/tokenModel.js");
const { generateUUID } = require("./generateUUID.js");
/*
@@ -11,37 +11,38 @@ const { generateUUID } = require("./generateUUID.js");
6) store in database
*/
//can be used for api key or token. Both are the same logic
-async function addAPIKey(userId, permission) {
- let hashtoken = await generateUUID();
- let apikey = await hash(hashtoken);
+async function addToken(userId, permission , expiry) {
+ let uuid = await generateUUID();
+ let hashtoken = await hash(uuid);
- let token = await apikeyModel.create({
+ let token = await tokenModel.create({
userid: userId,
- apikey: apikey,
+ token: hashtoken,
permission: permission,
+ expiration: expiry,
});
//user token with - tokenid is table id
- return token.id + "-" + hashtoken;
+ return token.id + "-" + uuid;
}
-async function checkAPikey(SuppliedKey, rowid) {
+async function checkToken(Supplied, rowid) {
try {
- const retrivedKey = await apikeyModel.findOne({
+ const retrivedToken = await tokenModel.findOne({
raw: true,
- attributes: ["apikey", "permission"],
+ attributes: ["token", "permission"],
where: {
id: rowid,
},
});
//console.log(retrivedKey.apikey);
- if (compareHash(SuppliedKey, retrivedKey.apikey)) {
+ if (compareHash(Supplied, retrivedToken.token)) {
//return true;
- return retrivedKey.permission;
+ return retrivedToken.permission;
}
} catch (error) {
console.error(error);
}
}
-module.exports = { addAPIKey , checkAPikey };
\ No newline at end of file
+module.exports = { addToken , checkToken };
\ No newline at end of file
diff --git a/consumerWebsite/functions/isValid.js b/consumerWebsite/functions/isValid.js
new file mode 100644
index 0000000..2d79e13
--- /dev/null
+++ b/consumerWebsite/functions/isValid.js
@@ -0,0 +1,20 @@
+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);
+ return false;
+ }
+
+ return true;
+
+}
+
+
+
+
+module.exports = { isValid };
\ No newline at end of file
diff --git a/consumerWebsite/functions/user.js b/consumerWebsite/functions/user.js
index ee5cdb0..75bc428 100644
--- a/consumerWebsite/functions/user.js
+++ b/consumerWebsite/functions/user.js
@@ -1,7 +1,8 @@
const { Op } = require('sequelize')
const { hash, compareHash } = require("./bcrypt.js");
-const { addAPIKey } = require("./api");
+const { addToken } = require("./api");
const { userModel } = require("../database/model/userModel");
+moment = require('moment')
@@ -70,9 +71,9 @@ async function loginUser(user) {
if (!match) return false;
//console.log('loginUser', userRes.id, userRes.username);
- //generate token
- let token = await addAPIKey(userRes.id, "auto-generated");
-
+ //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);
return { token: token, userid: userRes.id, username: userRes.username };
}
diff --git a/consumerWebsite/middleware/apiKey.js b/consumerWebsite/middleware/apiKey.js
deleted file mode 100644
index 4d91dcb..0000000
--- a/consumerWebsite/middleware/apiKey.js
+++ /dev/null
@@ -1,65 +0,0 @@
-const { checkAPikey } = require("../functions/api.js");
-async function apikeyCheck(req, res, next) {
- //const authHeader = req.headers.authorization
- try {
- let apikey = req.headers.authorization;
- if (!apikey) {
- res.status(401).json({
- message: "No API key was supplied. Invalid request",
- });
- //throw new Error("No API key was supplied. Invalid request");
- } else {
- //split the string by the -
- let splitAPIkey = apikey.split("-");
- let rowid = splitAPIkey[0];
-
- //rejoin withouth the rowid
- let SuppliedKey = splitAPIkey.slice(1).join("-");
- if (checkAPikey(SuppliedKey, rowid)) {
- //get permission
- let permission = await checkAPikey(SuppliedKey, rowid);
- console.log(permission);
- if (req.method === "GET" && permission === "canRead") {
- return next();
- }
- //['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)
- if (
- ["GET", "POST", "PUT", "DELETE"].includes(req.method) &&
- permission === "canWrite"
- ) {
- console.log("write");
- return next();
- }
- //throw status 403
- res.status(403).json({
- message:
- "Your API key does not have the correct permissions to access this resource",
- });
- }
- }
- } catch (error) {
- next(error);
- }
-}
-
-module.exports = { apikeyCheck };
-
-/*
-//web server microservice
-1) take user supplied rowid-apikey
-2) split the string by -
-3) get the rowid or table id
-4) get the apikey
-5) compare the apikey with the one in database
-6) if match, return true
-*/
-
-/*
-
-I plan to seed some data in user and api
-Than use the system info and my API middleware will somehow check the supplied API key and check
-If it's correct API key and has canWrite perms
-I allow it to access put and post
-
-
-*/
diff --git a/consumerWebsite/middleware/authChecker.js b/consumerWebsite/middleware/authChecker.js
index 7855998..1379aa5 100644
--- a/consumerWebsite/middleware/authChecker.js
+++ b/consumerWebsite/middleware/authChecker.js
@@ -1,31 +1,65 @@
-const { apikeyModel } = require("../database/model/apiKeyModel");
+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");
-async function auth(req, res, next){
- try{
- // let user = await Auth.checkToken({token: req.header('auth-token')});
- let authToken = req.header('auth-token');
- let splitAuthToken = authToken.split('-');
- let rowid = splitAuthToken[0];
- let suppliedToken = splitAuthToken.slice(1).join('-');
- //get from db
- let token = await apikeyModel.findByPk(rowid, {include: userModel});
- if (!token) return false;
+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");
+ error.status = 401;
+ throw error;
+ }
- //compare
- let isMatch = await compareHash(suppliedToken, token.apikey);
- if (!isMatch) return false;
+ const splitAuthToken = authToken.split("-");
+ const rowid = splitAuthToken[0];
+ const suppliedToken = splitAuthToken.slice(1).join("-");
- //else do logic
- //pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT)
- req.token = token
- req.user = await token.getUser(); //taking user seq obj from usermodel
- next();
- }catch(error){
+ const token = await tokenModel.findByPk(rowid, { include: userModel });
+
+ if (!token) {
+ const error = new Error("Token key not found. Invalid request");
+ error.status = 401;
+ throw error;
+ }
+
+ const isMatch = await compareHash(suppliedToken, token.token);
+
+ if (!isMatch) {
+ const error = new Error("Token key not found. Invalid request");
+ error.status = 401;
+ 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();
+ }
+ else if ((req.method === "GET" && permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && permission === "canWrite")) {
+ next();
+ }
+ else {
+ const error = new Error("Insufficient permission");
+ error.status = 401;
+ throw error;
+ }
+ if (!isValid(token.expiration)){
+ req.token.destroy();
+ throw new Error("Token expired");
+ }
+
+
+ } catch (error) {
next(error);
}
}
-module.exports = { auth };
\ No newline at end of file
+module.exports = { auth };
diff --git a/consumerWebsite/modules/nodemailer.js b/consumerWebsite/modules/nodemailer.js
index 78e3342..64e745f 100644
--- a/consumerWebsite/modules/nodemailer.js
+++ b/consumerWebsite/modules/nodemailer.js
@@ -9,8 +9,8 @@ let transporter = nodemailer.createTransport({
port: 587,
secure: false,
auth: {
- user:
- pass:
+ user: process.env.euser,
+ pass: process.env.epass
},
});
module.exports = { transporter };
\ No newline at end of file
diff --git a/consumerWebsite/public/js/app.js b/consumerWebsite/public/js/app.js
index 5aed168..b8cf311 100644
--- a/consumerWebsite/public/js/app.js
+++ b/consumerWebsite/public/js/app.js
@@ -165,6 +165,7 @@ app.socket = (function (app) {
});
return socket;
})(app);
+
//sensor data
app.sensordata = (function (app) {
@@ -183,21 +184,11 @@ app.auth = (function (app) {
}
function isLoggedIn(callback) {
+
if (getToken()) {
return app.api.get("user/me", function (error, data) {
+ console.log(error, data);
if (!error) app.auth.user = data;
- //for navbar to show username
- if (!location.pathname === "/login")
- {
- $.scope.getUsername.update(data);
-
- }
-
- //for edit profile to show user details
- //if not in edit profile page, it will not show
- if (location.pathname === "/profile") {
- $.scope.getUserDetails.update(data);
- }
return callback(error, data);
});
} else {
@@ -206,7 +197,7 @@ app.auth = (function (app) {
}
function logOut(callback) {
- //call logout route
+ console.log("Logging out");
$.ajax({
type: "DELETE",
url: "/api/v0/user/logout",
diff --git a/consumerWebsite/routes/api_routes.js b/consumerWebsite/routes/api_routes.js
index ebd16ed..7715165 100644
--- a/consumerWebsite/routes/api_routes.js
+++ b/consumerWebsite/routes/api_routes.js
@@ -2,42 +2,21 @@
const router = require('express').Router();
const { auth } = require("../middleware/authChecker")
const { APIlogger } = require('../middleware/apiLogger.js');
-const { apikeyCheck } = require('../middleware/apiKey.js');
router.use('/auth', require('./auth'));
-router.use('/apikey', require('./apikey'));
+router.use('/token', [auth, APIlogger], require('./token.js'));
router.use('/user', [auth, APIlogger], require('./user'));
-//TO REFACTOR INTO ONE MIDDLWARE
+//location route
+router.use('/location', [auth, APIlogger], require('./location.js'));
//location route
-router.use('/location', [apikeyCheck , APIlogger], require('./location.js'));
-
-//location route
-router.use('/sensor', [apikeyCheck , APIlogger], require('./sensor.js'));
+router.use('/sensor', [auth, APIlogger], require('./sensor.js'));
//sensor data route
-router.use('/sensor-data', [ APIlogger], require('./sensorData.js'));
+router.use('/sensor-data', [auth, APIlogger], require('./sensorData.js'));
module.exports = router;
-
-/*
-
-'use strict';
-const router = require('express').Router();
-const { auth } = require("../middleware/authChecker")
-
-
-router.use('/auth', require('./auth'));
-
-router.use('/apikey', require('./apikey'));
-
-router.use('/user', auth ,require('./user'));
-
-module.exports = router;
-
-
-*/
\ No newline at end of file
diff --git a/consumerWebsite/routes/auth.js b/consumerWebsite/routes/auth.js
index 863d863..dd16dc1 100644
--- a/consumerWebsite/routes/auth.js
+++ b/consumerWebsite/routes/auth.js
@@ -51,7 +51,6 @@ router.post("/login", async (req, res, next) => {
//contact
//auth/contact
-
router.post("/contact", async (req, res, next) => {
});
diff --git a/consumerWebsite/routes/apikey.js b/consumerWebsite/routes/token.js
similarity index 54%
rename from consumerWebsite/routes/apikey.js
rename to consumerWebsite/routes/token.js
index 521cfdb..f6d4b46 100644
--- a/consumerWebsite/routes/apikey.js
+++ b/consumerWebsite/routes/token.js
@@ -1,4 +1,4 @@
-const { addAPIKey } = require("../functions/api");
+const { addToken } = require("../functions/api");
const express = require("express");
@@ -10,14 +10,13 @@ const router = express.Router();
3) hash the api key
4) store the api key in database
*/
+//token/new
+//curl localhost:3000/api/v0/token/new -H "Content-Type: application/json" -X POST -d
+//'{"userid": "5", "permission": "canRead" ,}'
router.post("/new", async (req, res, next) => {
try {
- //curl localhost/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d
- //'{"userid": 1, "permission": "canWrite"}'
- const apikey = await addAPIKey(req.body.userid, req.body.permission);
- //console.log(typeof req.body.userid);
- //console.log(typeof req.body.permission);
- res.json({apikey: apikey});
+ const token = await addToken(req.body.userid, req.body.permission , "2204-01-24 07:34:36" );
+ res.json({token: token});
} catch (error) {
console.error(error);
next(error);
diff --git a/consumerWebsite/routes/user.js b/consumerWebsite/routes/user.js
index 474b905..5c9a3a1 100644
--- a/consumerWebsite/routes/user.js
+++ b/consumerWebsite/routes/user.js
@@ -11,11 +11,14 @@ router.get("/me", async function (req, res, next) {
if (!user) {
let error = new Error("User not found");
error.status = 400;
+ console.log(error);
return next(error);
}
+ if (user){
res.json({
user: user,
});
+ }
} catch (error) {
next(error);
}
diff --git a/consumerWebsite/views/profile.ejs b/consumerWebsite/views/profile.ejs
index 0670852..01ee0cb 100644
--- a/consumerWebsite/views/profile.ejs
+++ b/consumerWebsite/views/profile.ejs
@@ -1,4 +1,5 @@
<%- include('top') %>
+
diff --git a/consumerWebsite/views/top.ejs b/consumerWebsite/views/top.ejs
index df0b5a5..6f06d53 100644
--- a/consumerWebsite/views/top.ejs
+++ b/consumerWebsite/views/top.ejs
@@ -57,6 +57,11 @@
//check if user is logged in
app.auth.isLoggedIn(function (error, data) {
if (data) {
+ $.scope.getUsername.update(data);
+
+ if (location.pathname == "/profile") {
+ $.scope.getUserDetails.update(data);
+ }
$("#cl-logout-button").show("fast");
$("#cl-api-button").show("fast");
$("#cl-profile-button").show("fast");
@@ -127,4 +132,4 @@
-
+
\ No newline at end of file
diff --git a/contact.js b/contact.js
index 5fb66c9..5ef41df 100644
--- a/contact.js
+++ b/contact.js
@@ -1,43 +1,4 @@
-//import('dotenv').config({ path: path.resolve(__dirname, '../../../.env') })
-
-
-
-document.addEventListener('DOMContentLoaded', () => {
- const form = document.getElementById('form');
-
- // Set the new value for the access_key input field
- form.querySelector('input[name="access_key"]').value = process.env.emailKey;
-
- form.addEventListener('submit', async (event) => {
- event.preventDefault(); // Prevent default form submission
-
- // Create a FormData object to include the key
- const formData = new FormData(form);
-
- // Submit the form using fetch API
- try {
- const response = await fetch('https://api.web3forms.com/submit', {
- method: 'POST',
- body: formData
- });
-
- const result = await response.json();
-
- // Handle the API response
- console.log(result);
-
- if (result.success) {
- // Form submitted successfully, display notification
- alert('Form submitted successfully!');
- location.reload()
- } else {
- // Form submission failed, display error notification
- alert('Form submission failed. Please try again.');
- }
-
- } catch (error) {
- //console.error('Error:', error);
- }
- });
-});
+moment = require('moment')
+//current time
+console.log(moment().format('hh:mm:ss a'))
\ No newline at end of file