Merge branch 'main' into sensor
This commit is contained in:
		| @ -1,7 +1,6 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| const { Sequelize, DataTypes } = require("sequelize"); | const { Sequelize, DataTypes } = require("sequelize"); | ||||||
| const { sequelize } = require("./mySQL"); | const { sequelize } = require("./mySQL"); | ||||||
| const { isAlphaNumericwithSpaces } = require('../../Web-Server/functions/validateData') |  | ||||||
|  |  | ||||||
| //sequelize.sync(); | //sequelize.sync(); | ||||||
| const locationModel = sequelize.define( | const locationModel = sequelize.define( | ||||||
|  | |||||||
| @ -2,11 +2,7 @@ | |||||||
| const { Sequelize, DataTypes } = require("sequelize"); | const { Sequelize, DataTypes } = require("sequelize"); | ||||||
| const { sequelize } = require("./mySQL"); | const { sequelize } = require("./mySQL"); | ||||||
| const { locationModel } = require("./locationModel"); | const { locationModel } = require("./locationModel"); | ||||||
| const { |  | ||||||
| 	isAlphaNumericwithSpaces, |  | ||||||
| 	isAlphaNumericWithSpacesAndDash, |  | ||||||
| 	isMacAddress, |  | ||||||
| } = require("../../Web-Server/functions/validateData"); |  | ||||||
|  |  | ||||||
| //sequelize.sync(); | //sequelize.sync(); | ||||||
| const sensorModel = sequelize.define( | const sensorModel = sequelize.define( | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| const { locationModel } = require("../Database/locationModel"); | const { locationModel } = require("../database/locationModel"); | ||||||
| const { sensorModel } = require("../Database/sensorModel"); | const { sensorModel } = require("../database/sensorModel"); | ||||||
|  |  | ||||||
| async function getLocation() { | async function getLocation() { | ||||||
| 	const location = locationModel.findAll({ | 	const location = locationModel.findAll({ | ||||||
|  | |||||||
| @ -27,9 +27,9 @@ client.on("error", (err) => { | |||||||
| }); | }); | ||||||
|  |  | ||||||
| //every 15 minutes | //every 15 minutes | ||||||
| setInterval(publishData, 900000); | //setInterval(publishData, 900000); | ||||||
| //every 1 minute | //every 1 minute | ||||||
| //setInterval(publishData, 60000); | setInterval(publishData, 60000); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -13,3 +13,10 @@ i repeat DO NOT USE CREDS IN CODE! Please use .env files (https://www.npmjs.com/ | |||||||
| * consumer website api and user function | * consumer website api and user function | ||||||
| 2) Sean | 2) Sean | ||||||
| * Admin Website Microservice | * Admin Website Microservice | ||||||
|  |  | ||||||
|  | Micro Service | ||||||
|  | 1) api.blah handle api | ||||||
|  | 2) admin.blah admin website | ||||||
|  | 3) consumer.blah comsumer | ||||||
|  | 4) proxy.blah reverproxy | ||||||
|  | 5) mqtt.blah mqtt service  | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								api.MD
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								api.MD
									
									
									
									
									
								
							| @ -169,9 +169,7 @@ http://localhost/api/v0/sensor-data/filter?windspeed=highest&limit=1 | |||||||
| http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&pagesize=10 | http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&pagesize=10 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 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/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/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}' | curl localhost:3000/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}' | ||||||
|  | |||||||
| @ -1,29 +1,48 @@ | |||||||
| const express = require("express"); | const express = require("express"); | ||||||
|  | const { rateLimit } = require("express-rate-limit"); | ||||||
| const path = require("path"); | const path = require("path"); | ||||||
| const app = express(); | const app = express(); | ||||||
| const port = 3000; | const port = 3000; | ||||||
| const ejs = require("ejs"); | const ejs = require("ejs"); | ||||||
| 
 | 
 | ||||||
|  | module.exports = app; | ||||||
|  | 
 | ||||||
|  | process.nextTick(() => require('./mqttApp')); | ||||||
| 
 | 
 | ||||||
| app.use(express.json()); | app.use(express.json()); | ||||||
| app.set("json spaces", 2); | app.set("json spaces", 2); | ||||||
| 
 | 
 | ||||||
|  | //express-rate-limit stolen from docs
 | ||||||
|  | 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
 | ||||||
|  | 	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')}]; | ||||||
|  | 
 | ||||||
|  | // Apply the rate limiting middleware to all requests.
 | ||||||
|  | app.use(limiter); | ||||||
|  | 
 | ||||||
|  | //disable x-powered-by header for security reasons
 | ||||||
|  | app.disable("x-powered-by"); | ||||||
|  | 
 | ||||||
| // Set up the templating engine to build HTML for the front end.
 | // Set up the templating engine to build HTML for the front end.
 | ||||||
| app.set("views", path.join(__dirname, "../views")); | app.set("views", path.join(__dirname, "./views")); | ||||||
| app.set("view engine", "ejs"); | app.set("view engine", "ejs"); | ||||||
| 
 | 
 | ||||||
| // Have express server static content( images, CSS, browser JS) from the public
 | // Have express server static content( images, CSS, browser JS) from the public
 | ||||||
| app.use(express.static(path.join(__dirname, "../public"))); | app.use(express.static(path.join(__dirname, "./public"))); | ||||||
| 
 |  | ||||||
| //middleware logic ( called by next() )
 |  | ||||||
| const auth = require("../middleware/authChecker");  |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| //route logic
 | //route logic
 | ||||||
| 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
 | //render logic
 | ||||||
| app.use("/", require("../routes/render")); | app.use("/", require("./routes/render")); | ||||||
| 
 | 
 | ||||||
| // Catch 404 and forward to error handler. If none of the above routes are
 | // Catch 404 and forward to error handler. If none of the above routes are
 | ||||||
| // used, this is what will be called.
 | // used, this is what will be called.
 | ||||||
| @ -69,8 +88,4 @@ app.use(function (err, req, res, next) { | |||||||
| 		keyErrors, | 		keyErrors, | ||||||
| 	}); | 	}); | ||||||
| }); | }); | ||||||
| app.listen(port, () => { |  | ||||||
| 	console.log(`app listening on port ${port}`); |  | ||||||
| }); |  | ||||||
| 
 | 
 | ||||||
| module.exports = { app }; |  | ||||||
							
								
								
									
										101
									
								
								consumerWebsite/bin/www
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								consumerWebsite/bin/www
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | |||||||
|  | #!/usr/bin/env node | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Module dependencies. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | const app = require('../app'); | ||||||
|  | const debug = require('debug')('proxy-api:server'); | ||||||
|  | const http = require('http'); | ||||||
|  | const path = require('path'); | ||||||
|  | require('dotenv').config({ path: path.resolve(__dirname, '../../.env')}) | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get port from environment and store in Express. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | var port = normalizePort(process.env.NODE_PORT  || '3000'); | ||||||
|  | app.set('port', port); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Create HTTP server. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | //create server with app | ||||||
|  | var server = http.createServer(app); | ||||||
|  |  | ||||||
|  | var io = require('socket.io')(server); | ||||||
|  | app.io = io; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Listen on provided port, on all network interfaces. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | server.listen(port); | ||||||
|  | server.on('error', onError); | ||||||
|  | server.on('listening', onListening); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Normalize a port into a number, string, or false. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | function normalizePort(val) { | ||||||
|  |   var port = parseInt(val, 10); | ||||||
|  |  | ||||||
|  |   if (isNaN(port)) { | ||||||
|  |     // named pipe | ||||||
|  |     return val; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (port >= 0) { | ||||||
|  |     // port number | ||||||
|  |     return port; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Event listener for HTTP server "error" event. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | function onError(error) { | ||||||
|  |   if (error.syscall !== 'listen') { | ||||||
|  |     throw error; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   var bind = typeof port === 'string' | ||||||
|  |     ? 'Pipe ' + port | ||||||
|  |     : 'Port ' + port; | ||||||
|  |  | ||||||
|  |   // handle specific listen errors with friendly messages | ||||||
|  |   switch (error.code) { | ||||||
|  |     case 'EACCES': | ||||||
|  |       console.error(bind + ' requires elevated privileges'); | ||||||
|  |       process.exit(1); | ||||||
|  |       break; | ||||||
|  |     case 'EADDRINUSE': | ||||||
|  |       console.error(bind + ' is already in use'); | ||||||
|  |       process.exit(1); | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       throw error; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Event listener for HTTP server "listening" event. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | function onListening() { | ||||||
|  |   var addr = server.address(); | ||||||
|  |   var bind = typeof addr === 'string' | ||||||
|  |     ? 'pipe ' + addr | ||||||
|  |     : 'port ' + addr.port; | ||||||
|  |   console.log('Listening on ' + bind); | ||||||
|  |  | ||||||
|  |   // execute list of functions when app is ready | ||||||
|  |   for(let listener of app.onListen){ | ||||||
|  |     listener() | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								consumerWebsite/functions/api.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								consumerWebsite/functions/api.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | const { hash, compareHash } = require("./bcrypt.js"); | ||||||
|  | const { apikeyModel } = require("../database/model/apiKeyModel"); | ||||||
|  | const { generateUUID } = require("./generateUUID.js"); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | 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 | ||||||
|  | */ | ||||||
|  | //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); | ||||||
|  |  | ||||||
|  | 	let token = await apikeyModel.create({ | ||||||
|  | 		userid: userId, | ||||||
|  | 		apikey: apikey, | ||||||
|  | 		permission: permission, | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	//user token with - tokenid is table id | ||||||
|  | 	return token.id + "-" + hashtoken; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function checkAPikey(SuppliedKey, rowid) { | ||||||
|  | 	try { | ||||||
|  | 		const retrivedKey = await apikeyModel.findOne({ | ||||||
|  | 			raw: true, | ||||||
|  | 			attributes: ["apikey", "permission"], | ||||||
|  | 			where: { | ||||||
|  | 				id: rowid, | ||||||
|  | 			}, | ||||||
|  | 		}); | ||||||
|  | 		//console.log(retrivedKey.apikey); | ||||||
|  | 		if (compareHash(SuppliedKey, retrivedKey.apikey)) { | ||||||
|  | 			//return true; | ||||||
|  | 			return retrivedKey.permission; | ||||||
|  | 		} | ||||||
|  | 	} catch (error) { | ||||||
|  | 		console.error(error); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { addAPIKey  , checkAPikey }; | ||||||
| @ -1,138 +0,0 @@ | |||||||
| const { sequelize } = require("../database/mySql.js"); |  | ||||||
| const { apikeyModel } = require("../database/model/apikeyModel.js"); |  | ||||||
| const { userModel } = require("../database/model/userModel.js"); |  | ||||||
| const { Op, Sequelize } = require("sequelize"); |  | ||||||
| const { generateUUID } = require("../functions/generateUUID.js"); |  | ||||||
| const { |  | ||||||
| 	hashPassword, |  | ||||||
| 	comparePassword, |  | ||||||
| 	hashAPIKey, |  | ||||||
| } = require("../functions/bcrypt.js"); |  | ||||||
|  |  | ||||||
| //getuser |  | ||||||
| //api/v0/user/me |  | ||||||
| async function getUserID(userid) { |  | ||||||
|     //console.log(userid); |  | ||||||
|     //console.log(userid.id); |  | ||||||
|     let userRes = await userModel.findByPk(userid.id, { |  | ||||||
|         attributes: { |  | ||||||
|             exclude: ["password"], |  | ||||||
|         }, |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     if (!userRes) return false; |  | ||||||
|     return userRes; |  | ||||||
|      |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //api/v0/auth/register |  | ||||||
| /* Registering new user  |  | ||||||
| 1) req.body is taken from html form or wtv  |  | ||||||
| 2) bcrpyt and hash the password on the server side |  | ||||||
| 3) pass to db  |  | ||||||
| */ |  | ||||||
| async function addUser(user) { |  | ||||||
| 	//hash password |  | ||||||
| 	let hash = await hashPassword(user.password); |  | ||||||
|  |  | ||||||
| 	const addRes = await userModel.create({ |  | ||||||
|         firstname: user.firstname, |  | ||||||
|         lastname: user.lastname, |  | ||||||
| 		username: user.username, |  | ||||||
| 		password: hash, |  | ||||||
| 		email: user.email, |  | ||||||
| 		address: user.address, |  | ||||||
| 		phone: user.phone, |  | ||||||
| 	}); |  | ||||||
| 	if (addRes) { |  | ||||||
| 		return true; |  | ||||||
| 	} else { |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //api/v0/auth/login |  | ||||||
| async function loginUser(user) { |  | ||||||
|     //console.log(user); |  | ||||||
|     //look up username or email in db |  | ||||||
|     const userRes = await userModel.findOne({ |  | ||||||
|         where: { |  | ||||||
|             [Op.or]: [ |  | ||||||
|                 { |  | ||||||
|                     username: user.username, |  | ||||||
|                 }, |  | ||||||
|                 { |  | ||||||
|                     email: user.username, |  | ||||||
|                 }, |  | ||||||
|             ], |  | ||||||
|         }, |  | ||||||
|     }); |  | ||||||
|     // Make sure user exists |  | ||||||
|     if (!userRes) return false;  |  | ||||||
|      |  | ||||||
|     // Compare passwords |  | ||||||
|     let match = await comparePassword(user.password, userRes.password); |  | ||||||
|     if (!match) return false; |  | ||||||
|     //console.log('loginUser', userRes.id, userRes.username); |  | ||||||
|  |  | ||||||
|     //generate token |  | ||||||
|     let token = await addAPIKey(userRes.id, "auto-generated");  |  | ||||||
|  |  | ||||||
|     return { token: token, userid: userRes.id, username: userRes.username }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| 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 |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| //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 hashAPIKey(hashtoken); |  | ||||||
|  |  | ||||||
| 	let token = await apikeyModel.create({ |  | ||||||
| 		userid: userId, |  | ||||||
| 		apikey: apikey, |  | ||||||
| 		permission: permission, |  | ||||||
| 	}); |  | ||||||
|  |  | ||||||
| 	//user token with - tokenid is table id |  | ||||||
| 	return token.id + "-" + hashtoken; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //api/v0/user/logout |  | ||||||
| async function deleteUserToken(token) { |  | ||||||
|     //get row id |  | ||||||
|     let splitAuthToken = token.split("-"); |  | ||||||
|     let rowid = splitAuthToken[0]; |  | ||||||
|  |  | ||||||
|     //console.log(rowid); |  | ||||||
|  |  | ||||||
|     //delete from db |  | ||||||
|     let delRes = await apikeyModel.destroy({ |  | ||||||
|         where: { |  | ||||||
|             id: rowid, |  | ||||||
|         }, |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     if (!delRes) return false;  |  | ||||||
|     return true; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
| module.exports = { |  | ||||||
|     getUserID, |  | ||||||
| 	addUser, |  | ||||||
| 	loginUser, |  | ||||||
| 	addAPIKey, |  | ||||||
|     deleteUserToken, |  | ||||||
| }; |  | ||||||
| @ -2,44 +2,19 @@ const bcrypt = require('bcrypt'); | |||||||
| const saltRounds = 10; | const saltRounds = 10; | ||||||
| //https://github.com/kelektiv/node.bcrypt.js#readme | //https://github.com/kelektiv/node.bcrypt.js#readme | ||||||
|  |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| // Load hash from your password DB. |  | ||||||
| bcrypt.compare(myPlaintextPassword, hash, function(err, result) { |  | ||||||
|     // result == true |  | ||||||
| }); |  | ||||||
| bcrypt.compare(someOtherPlaintextPassword, hash, function(err, result) { |  | ||||||
|     // result == false |  | ||||||
| }); |  | ||||||
| */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| //hash with salt |  | ||||||
| bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) { |  | ||||||
|     // Store hash in your password DB. |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| //hash for pass or token lol doesnt matter | //hash for pass or token lol doesnt matter | ||||||
| async function hashPassword(password) { | async function hash(password) { | ||||||
|     return await bcrypt.hash(password, saltRounds); |     return await bcrypt.hash(password, saltRounds); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function hashAPIKey(apikey) { |  | ||||||
|     return await bcrypt.hash(apikey, saltRounds); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //can be used to compare password or token | //can be used to compare password or token | ||||||
| async function comparePassword(password, hash) { | async function compareHash(password, hash) { | ||||||
|     return await bcrypt.compare(password, hash); |     return await bcrypt.compare(password, hash); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = {  | module.exports = {  | ||||||
|     hashPassword, |     hash, | ||||||
|     hashAPIKey, |     compareHash | ||||||
|     comparePassword |  | ||||||
| }; | }; | ||||||
							
								
								
									
										55
									
								
								consumerWebsite/functions/location.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								consumerWebsite/functions/location.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | const {locationModel} = require("../database/model/locationModel"); | ||||||
|  |  | ||||||
|  | async function getLocation() { | ||||||
|  | 	const location = await locationModel.findAll(); | ||||||
|  | 	return location; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function addLocation(name, added_by, description) { | ||||||
|  | 	const location = await locationModel.create({ | ||||||
|  | 		name: name, | ||||||
|  | 		added_by: added_by, | ||||||
|  | 		description: description, | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function updateLocation(id, name, added_by, description) { | ||||||
|  | 	const location = await locationModel.update( | ||||||
|  | 		{ | ||||||
|  | 			name: name, | ||||||
|  | 			added_by: added_by, | ||||||
|  | 			description: description, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			where: { | ||||||
|  | 				id: id, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function deleteLocation(id) { | ||||||
|  | 	const location = await locationModel.destroy({ | ||||||
|  | 		where: { | ||||||
|  | 			id: id, | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async function getLocationById(id) { | ||||||
|  | 	const location = await locationModel.findAll({ | ||||||
|  | 		where: { | ||||||
|  | 			id: id, | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  | 	return location; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  | 	getLocation, | ||||||
|  | 	addLocation, | ||||||
|  | 	updateLocation, | ||||||
|  | 	deleteLocation, | ||||||
|  | 	getLocationById, | ||||||
|  | }; | ||||||
							
								
								
									
										23
									
								
								consumerWebsite/functions/logger.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								consumerWebsite/functions/logger.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | const { api_log_Model } = require("../database/model/apiLogModel.js"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async function insertLogData(log) { | ||||||
|  | 	try { | ||||||
|  | 		api_log_Model.create({ | ||||||
|  | 			ip: log.ip, | ||||||
|  | 			time: log.time, | ||||||
|  | 			method: log.method, | ||||||
|  | 			host: log.host, | ||||||
|  | 			statusCode: log.statusCode, | ||||||
|  | 			Responsesize: log.Responsesize, | ||||||
|  | 			referrer: log.referrer, | ||||||
|  | 			userAgent: log.userAgent, | ||||||
|  | 		}); | ||||||
|  | 	} catch (error) { | ||||||
|  | 		console.error(error); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  | 	insertLogData, | ||||||
|  | }; | ||||||
							
								
								
									
										74
									
								
								consumerWebsite/functions/sensor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								consumerWebsite/functions/sensor.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | const { sensorModel } = require("../database/model/sensorModel"); | ||||||
|  |  | ||||||
|  | async function getSensor() { | ||||||
|  | 	const sensor = await sensorModel.findAll(); | ||||||
|  | 	return sensor; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function addSensor( | ||||||
|  | 	sensorname, | ||||||
|  | 	added_by, | ||||||
|  | 	mac_address, | ||||||
|  | 	description, | ||||||
|  | 	location | ||||||
|  | ) { | ||||||
|  | 	const sensor = await sensorModel.create({ | ||||||
|  | 		name: sensorname, | ||||||
|  | 		added_by: added_by, | ||||||
|  | 		mac_address: mac_address, | ||||||
|  | 		description: description, | ||||||
|  | 		location: location, | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function updateSensor( | ||||||
|  | 	id, | ||||||
|  | 	sensorname, | ||||||
|  | 	added_by, | ||||||
|  | 	mac_address, | ||||||
|  | 	description, | ||||||
|  | 	location | ||||||
|  | ) { | ||||||
|  | 	const sensor = await sensorModel.update( | ||||||
|  | 		{ | ||||||
|  | 			name: sensorname, | ||||||
|  | 			added_by: added_by, | ||||||
|  | 			mac_address: mac_address, | ||||||
|  | 			description: description, | ||||||
|  | 			location: location, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			where: { | ||||||
|  | 				id: id, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function deleteSensor(id) { | ||||||
|  | 	//delete by id | ||||||
|  | 	const sensor = await sensorModel.destroy({ | ||||||
|  | 		//cascade delete | ||||||
|  | 		onDelete: "cascade", | ||||||
|  | 		where: { | ||||||
|  | 			id: id, | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function getSensorById(id) { | ||||||
|  | 	const sensor = await sensorModel.findAll({ | ||||||
|  | 		where: { | ||||||
|  | 			id: id, | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  | 	return sensor; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  | 	getSensor, | ||||||
|  | 	addSensor, | ||||||
|  | 	updateSensor, | ||||||
|  | 	deleteSensor, | ||||||
|  | 	getSensorById, | ||||||
|  | }; | ||||||
| @ -1,8 +1,7 @@ | |||||||
| const { sequelize }  = require("../Database/mySql.js"); |  | ||||||
| const { locationModel } = require("../Database/model/locationModel.js"); |  | ||||||
| const { sensorModel } = require("../Database/model/sensorModel.js"); |  | ||||||
| const { sensorDataModel } = require("../Database/model/sensorDataModel.js"); |  | ||||||
| const { Op, Sequelize } = require("sequelize"); | const { Op, Sequelize } = require("sequelize"); | ||||||
|  | const { sequelize }  = require("../database/mySQL.js"); | ||||||
|  | const { sensorDataModel } = require("../database/model/sensorDataModel.js"); | ||||||
|  | const io = require('../functions/socket'); | ||||||
| 
 | 
 | ||||||
| //helper function to convert month name to month number
 | //helper function to convert month name to month number
 | ||||||
| //https://stackoverflow.com/questions/13566552/easiest-way-to-convert-month-name-to-month-number-in-js-jan-01
 | //https://stackoverflow.com/questions/13566552/easiest-way-to-convert-month-name-to-month-number-in-js-jan-01
 | ||||||
| @ -13,130 +12,22 @@ function getMonthFromString(mon) { | |||||||
| 	} | 	} | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
| async function getLocation() { |  | ||||||
| 	const location = await locationModel.findAll(); |  | ||||||
| 	return location; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| async function addLocation(name, added_by, description) { |  | ||||||
| 	const location = await locationModel.create({ |  | ||||||
| 		name: name, |  | ||||||
| 		added_by: added_by, |  | ||||||
| 		description: description, |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function updateLocation(id, name, added_by, description) { |  | ||||||
| 	const location = await locationModel.update( |  | ||||||
| 		{ |  | ||||||
| 			name: name, |  | ||||||
| 			added_by: added_by, |  | ||||||
| 			description: description, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			where: { |  | ||||||
| 				id: id, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function deleteLocation(id) { |  | ||||||
| 	//delete by id
 |  | ||||||
| 	const location = await locationModel.destroy({ |  | ||||||
| 		where: { |  | ||||||
| 			id: id, |  | ||||||
| 		}, |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function getLocationById(id) { |  | ||||||
| 	const location = await locationModel.findAll({ |  | ||||||
| 		where: { |  | ||||||
| 			id: id, |  | ||||||
| 		}, |  | ||||||
| 	}); |  | ||||||
| 	return location; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function getSensor() { |  | ||||||
| 	const sensor = await sensorModel.findAll(); |  | ||||||
| 	return sensor; |  | ||||||
| 	console.error(error); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function addSensor( |  | ||||||
| 	sensorname, |  | ||||||
| 	added_by, |  | ||||||
| 	mac_address, |  | ||||||
| 	description, |  | ||||||
| 	location |  | ||||||
| ) { |  | ||||||
| 	const sensor = await sensorModel.create({ |  | ||||||
| 		name: sensorname, |  | ||||||
| 		added_by: added_by, |  | ||||||
| 		mac_address: mac_address, |  | ||||||
| 		description: description, |  | ||||||
| 		location: location, |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function updateSensor( |  | ||||||
| 	id, |  | ||||||
| 	sensorname, |  | ||||||
| 	added_by, |  | ||||||
| 	mac_address, |  | ||||||
| 	description, |  | ||||||
| 	location |  | ||||||
| ) { |  | ||||||
| 	const sensor = await sensorModel.update( |  | ||||||
| 		{ |  | ||||||
| 			name: sensorname, |  | ||||||
| 			added_by: added_by, |  | ||||||
| 			mac_address: mac_address, |  | ||||||
| 			description: description, |  | ||||||
| 			location: location, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			where: { |  | ||||||
| 				id: id, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function deleteSensor(id) { |  | ||||||
| 	//delete by id
 |  | ||||||
| 	const sensor = await sensorModel.destroy({ |  | ||||||
| 		where: { |  | ||||||
| 			id: id, |  | ||||||
| 		}, |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	console.error(error); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function getSensorById(id) { |  | ||||||
| 	const sensor = await sensorModel.findAll({ |  | ||||||
| 		where: { |  | ||||||
| 			id: id, |  | ||||||
| 		}, |  | ||||||
| 	}); |  | ||||||
| 	return sensor; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| async function getSensorData() { | async function getSensorData() { | ||||||
| 	const sensorData = await sensorDataModel.findAll(); | 	const sensorData = await sensorDataModel.findAll(); | ||||||
| 	return sensorData; | 	return sensorData; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function addSensorData(id, id_sensor, id_location, sensordata) { | async function addSensorData(id_sensor, id_location, sensordata) { | ||||||
| 	const sensorData = await sensorDataModel.create({ | 	const sensorData = await sensorDataModel.create({ | ||||||
| 		id: id, |  | ||||||
| 		sensorid: id_sensor, | 		sensorid: id_sensor, | ||||||
| 		locationid: id_location, | 		locationid: id_location, | ||||||
| 		measurement: sensordata, | 		measurement: sensordata, | ||||||
| 	}); | 	}); | ||||||
|  | 	io().emit('sensorData:new', sensorData) | ||||||
|  | 
 | ||||||
|  | 	return sensorData; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function updateSensorData(id, id_sensor, id_location, sensordata) { | async function updateSensorData(id, id_sensor, id_location, sensordata) { | ||||||
| @ -826,16 +717,6 @@ async function getDatabyRange(queryString) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | module.exports = { | ||||||
| 	getLocation, |  | ||||||
| 	addLocation, |  | ||||||
| 	updateLocation, |  | ||||||
| 	deleteLocation, |  | ||||||
| 	getLocationById, |  | ||||||
| 	getSensor, |  | ||||||
| 	addSensor, |  | ||||||
| 	updateSensor, |  | ||||||
| 	deleteSensor, |  | ||||||
| 	getSensorById, |  | ||||||
| 	getSensorData, | 	getSensorData, | ||||||
| 	addSensorData, | 	addSensorData, | ||||||
| 	updateSensorData, | 	updateSensorData, | ||||||
| @ -843,4 +724,5 @@ module.exports = { | |||||||
| 	getSensorDataById, | 	getSensorDataById, | ||||||
| 	getData, | 	getData, | ||||||
| 	getDatabyRange, | 	getDatabyRange, | ||||||
| }; | 
 | ||||||
|  | }; | ||||||
							
								
								
									
										17
									
								
								consumerWebsite/functions/socket.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								consumerWebsite/functions/socket.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | const app = require("../app"); | ||||||
|  | const io = ()=> app.io; | ||||||
|  |  | ||||||
|  | // We have to wait for the express HTTP server to be finished starting before we | ||||||
|  | // can use any of the socket.io stuff.  | ||||||
|  | app.onListen.push(function(){ | ||||||
|  | 	app.io.on('connection', (socket) => { | ||||||
|  | 		console.log('User connected via WebsSocket') | ||||||
|  |  | ||||||
|  | 		socket.on('disconnect', (socket) => { | ||||||
|  | 			console.log('User disconnect via WebsSocket') | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | module.exports = io; | ||||||
							
								
								
									
										137
									
								
								consumerWebsite/functions/user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								consumerWebsite/functions/user.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,137 @@ | |||||||
|  | const { Op } = require('sequelize') | ||||||
|  | const { hash, compareHash } = require("./bcrypt.js"); | ||||||
|  | const { addAPIKey } = require("./api"); | ||||||
|  | const { userModel } = require("../database/model/userModel"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //getuser | ||||||
|  | //api/v0/user/me | ||||||
|  | async function getUserID(userid) { | ||||||
|  | 	//console.log(userid); | ||||||
|  | 	//console.log(userid.id); | ||||||
|  | 	let userRes = await userModel.findByPk(userid.id, { | ||||||
|  | 		attributes: { | ||||||
|  | 			exclude: ["password"], | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	if (!userRes) return false; | ||||||
|  | 	return userRes; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //api/v0/auth/register | ||||||
|  | /* Registering new user  | ||||||
|  | 1) req.body is taken from html form or wtv  | ||||||
|  | 2) bcrpyt and hash the password on the server side | ||||||
|  | 3) pass to db  | ||||||
|  | */ | ||||||
|  | async function addUser(user) { | ||||||
|  | 	//hash password | ||||||
|  | 	let hashed = await hash(user.password); | ||||||
|  |  | ||||||
|  | 	const addRes = await userModel.create({ | ||||||
|  | 		firstname: user.firstname, | ||||||
|  | 		lastname: user.lastname, | ||||||
|  | 		username: user.username, | ||||||
|  | 		password: hashed, | ||||||
|  | 		email: user.email, | ||||||
|  | 		address: user.address, | ||||||
|  | 		phone: user.phone, | ||||||
|  | 	}); | ||||||
|  | 	if (addRes) { | ||||||
|  | 		return true; | ||||||
|  | 	} else { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //api/v0/auth/login | ||||||
|  | async function loginUser(user) { | ||||||
|  | 	//console.log(user); | ||||||
|  | 	//look up username or email in db | ||||||
|  | 	const userRes = await userModel.findOne({ | ||||||
|  | 		where: { | ||||||
|  | 			[Op.or]: [ | ||||||
|  | 				{ | ||||||
|  | 					username: user.username, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					email: user.username, | ||||||
|  | 				}, | ||||||
|  | 			], | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  | 	// Make sure user exists | ||||||
|  | 	if (!userRes) return false; | ||||||
|  |  | ||||||
|  | 	// Compare passwords | ||||||
|  | 	let match = await compareHash(user.password, userRes.password); | ||||||
|  | 	if (!match) return false; | ||||||
|  | 	//console.log('loginUser', userRes.id, userRes.username); | ||||||
|  |  | ||||||
|  | 	//generate token | ||||||
|  | 	let token = await addAPIKey(userRes.id, "auto-generated"); | ||||||
|  |  | ||||||
|  | 	return { token: token, userid: userRes.id, username: userRes.username }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | 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 | ||||||
|  | */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //api/v0/user/update | ||||||
|  | async function updateProfile(user, body) { | ||||||
|  | 	if (!body.password) { | ||||||
|  | 		let updateUser = await userModel.update( | ||||||
|  | 			{ | ||||||
|  | 				firstname: body.first_name, | ||||||
|  | 				lastname: body.last_name, | ||||||
|  | 				username: body.username, | ||||||
|  | 				email: body.email, | ||||||
|  | 				address: body.address, | ||||||
|  | 				phone: body.phone, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				where: { | ||||||
|  | 					id: user.id, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 		); | ||||||
|  | 		if (!updateUser) return false; | ||||||
|  | 		return true; | ||||||
|  | 	} else { | ||||||
|  | 		let hashed = await hash(body.password); | ||||||
|  | 		let updateUser = await userModel.update( | ||||||
|  | 			{ | ||||||
|  | 				firstname: body.first_name, | ||||||
|  | 				lastname: body.last_name, | ||||||
|  | 				username: body.username, | ||||||
|  | 				email: body.email, | ||||||
|  | 				address: body.address, | ||||||
|  | 				phone: body.phone, | ||||||
|  | 				password: hashed, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				where: { | ||||||
|  | 					id: user.id, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 		); | ||||||
|  | 		if (!updateUser) return false; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  | 	getUserID, | ||||||
|  | 	addUser, | ||||||
|  | 	loginUser, | ||||||
|  | 	updateProfile, | ||||||
|  | }; | ||||||
| @ -1,5 +1,27 @@ | |||||||
| var validator = require("validator"); | var validator = require("validator"); | ||||||
|  |  | ||||||
|  | const dateRegex = /^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/; | ||||||
|  |  | ||||||
|  | function isValidDateString(value) { | ||||||
|  | 	return dateRegex.test(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function isMacAddress(value) { | ||||||
|  | 	//	Joi.string().regex(/^([0-9a-f]{2}-){5}([0-9a-f]{2})$/i).lowercase() | ||||||
|  | 	//return validator.isMACAddress(value, { no_separators: true, eui: 48 }); | ||||||
|  | 	const macAddress = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/; | ||||||
|  | 	const valid = macAddress.test(value); | ||||||
|  | 	return valid; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function isNumber(value) { | ||||||
|  | 	if (typeof value === "number") { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| function isAlphaNumericwithSpaces(value) { | function isAlphaNumericwithSpaces(value) { | ||||||
| 	return validator.isAlphanumeric(value, ["en-US"], { ignore: " " }); | 	return validator.isAlphanumeric(value, ["en-US"], { ignore: " " }); | ||||||
| } | } | ||||||
| @ -16,7 +38,6 @@ function isAlphaNumericWithSpacesAndDash(value) { | |||||||
| function isJson(value) { | function isJson(value) { | ||||||
|   //check if its object |   //check if its object | ||||||
|   if(typeof value === "object"){ |   if(typeof value === "object"){ | ||||||
|     console.log("its an object") |  | ||||||
|     return true  |     return true  | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @ -44,6 +65,8 @@ module.exports = { | |||||||
| 	isAlphaNumericwithSpaces, | 	isAlphaNumericwithSpaces, | ||||||
| 	isAlphaNumericWithSpacesAndDash, | 	isAlphaNumericWithSpacesAndDash, | ||||||
| 	isJson, | 	isJson, | ||||||
| 	isAddress | 	isAddress, | ||||||
| }; | 	isValidDateString, | ||||||
|  | 	isMacAddress, | ||||||
|  | 	isNumber, | ||||||
|  | }; | ||||||
| @ -1,4 +1,4 @@ | |||||||
| const { checkAPikey } = require("../functions/database.js"); | const { checkAPikey } = require("../functions/api.js"); | ||||||
| async function apikeyCheck(req, res, next) { | async function apikeyCheck(req, res, next) { | ||||||
| 	//const authHeader = req.headers.authorization
 | 	//const authHeader = req.headers.authorization
 | ||||||
| 	try { | 	try { | ||||||
| @ -1,4 +1,4 @@ | |||||||
| const { insertLogData } = require("../functions/database.js"); | const { insertLogData } = require("../functions/logger.js"); | ||||||
| const APIlogger = (req, res, next) => { | const APIlogger = (req, res, next) => { | ||||||
|   try { |   try { | ||||||
|     const log = { |     const log = { | ||||||
| @ -1,6 +1,6 @@ | |||||||
| const { apikeyModel } = require("../database/model/apiKeyModel"); | const { apikeyModel } = require("../database/model/apiKeyModel"); | ||||||
| const { userModel } = require("../database/model/userModel"); | const { userModel } = require("../database/model/userModel"); | ||||||
| const { comparePassword } = require("../functions/bcrypt"); | const { compareHash } = require("../functions/bcrypt"); | ||||||
|  |  | ||||||
| async function auth(req, res, next){ | async function auth(req, res, next){ | ||||||
|     try{  |     try{  | ||||||
| @ -12,19 +12,20 @@ async function auth(req, res, next){ | |||||||
|  |  | ||||||
|         //get from db |         //get from db | ||||||
|         let token = await apikeyModel.findByPk(rowid, {include: userModel}); |         let token = await apikeyModel.findByPk(rowid, {include: userModel}); | ||||||
|  |         if (!token) return false; | ||||||
|  |  | ||||||
|         //compare |         //compare | ||||||
|         let isMatch = await comparePassword(suppliedToken, token.apikey); |         let isMatch = await compareHash(suppliedToken, token.apikey); | ||||||
|         if (!isMatch) return false; |         if (!isMatch) return false; | ||||||
|  |  | ||||||
|         //else do logic |         //else do logic | ||||||
|         //pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT) |         //pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT) | ||||||
|         req.token = token |         req.token = token | ||||||
|         req.user = await token.getUser(); |         req.user = await token.getUser(); //taking user seq obj from usermodel | ||||||
|         next(); |         next(); | ||||||
|     }catch(error){ |     }catch(error){ | ||||||
|         next(error); |         next(error); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { auth }; | module.exports = { auth }; | ||||||
| @ -10,13 +10,11 @@ const options = { | |||||||
|   username: process.env.MQTT_USER,  |   username: process.env.MQTT_USER,  | ||||||
|   password: process.env.MQTT_PASS,  |   password: process.env.MQTT_PASS,  | ||||||
|   protocol: 'mqtts', // Use MQTT over TLS
 |   protocol: 'mqtts', // Use MQTT over TLS
 | ||||||
|   key: fs.readFileSync(path.resolve(__dirname, '../../cert/privkey.pem')),  |   key: fs.readFileSync(path.resolve(__dirname, '../cert/privkey.pem')),  | ||||||
|   cert: fs.readFileSync(path.resolve(__dirname, '../../cert/cert.pem')),  |   cert: fs.readFileSync(path.resolve(__dirname, '../cert/cert.pem')),  | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const client = mqtt.connect(brokerUrl, options); | const client = mqtt.connect(brokerUrl, options); | ||||||
| 
 | 
 | ||||||
| module.exports = client; | module.exports = client; | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @ -1,7 +1,6 @@ | |||||||
| const { app } = require("./modules/express.js"); | const client = require("./modules/mqtt.js"); | ||||||
| const client = require("./modules/mqtt"); |  | ||||||
| const { isJson, isNumber } = require("./functions/validateData.js"); | const { isJson, isNumber } = require("./functions/validateData.js"); | ||||||
| const { insertDatatoDB } = require("./functions/database.js"); | const { addSensorData } = require("./functions/sensorData"); | ||||||
| 
 | 
 | ||||||
| // Event handlers
 | // Event handlers
 | ||||||
| client.on("connect", () => { | client.on("connect", () => { | ||||||
| @ -38,7 +37,7 @@ client.on("message", (topic, message) => { | |||||||
| 				if (isNumber(data)) { | 				if (isNumber(data)) { | ||||||
| 					{ | 					{ | ||||||
| 						//pass datas to database
 | 						//pass datas to database
 | ||||||
| 						insertDatatoDB(datas[key]); | 						addSensorData(datas[key].sensorid, datas[key].locationid, datas[key]); | ||||||
| 
 | 
 | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| @ -64,3 +63,4 @@ client.on("end", () => { | |||||||
| 	console.log("Disconnected from MQTT broker"); | 	console.log("Disconnected from MQTT broker"); | ||||||
| 	client.reconnect(); | 	client.reconnect(); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
| @ -3813,3 +3813,12 @@ | |||||||
| .card-text { | .card-text { | ||||||
|     color: #000000; |     color: #000000; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* edit profile */ | ||||||
|  | .profile { | ||||||
|  |   margin: auto; | ||||||
|  |   width: 40%; | ||||||
|  |   border: 1px solid #000000; | ||||||
|  |   padding: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -523,4 +523,27 @@ body.one-content-column-version .content thead { | |||||||
|  |  | ||||||
| .cf:before, .cf:after { content: ""; display: block; } | .cf:before, .cf:after { content: ""; display: block; } | ||||||
| .cf:after { clear: both; } | .cf:after { clear: both; } | ||||||
| .ie6 .cf { zoom: 1 } | .ie6 .cf { zoom: 1 } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .generate-key-button { | ||||||
|  |     float: right; /* Align the button to the right */ | ||||||
|  |     margin-right: 85%; | ||||||
|  |     margin-top: -40px; /* Adjust the margin-top value based on your layout */ | ||||||
|  |     /* Add any additional styling you want for the button */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #content-get-api .generate-key-button { | ||||||
|  |     background-color: #4caf50; /* Green background color */ | ||||||
|  |     color: white; /* White text color */ | ||||||
|  |     padding: 5px 11px; /* Padding for the button */ | ||||||
|  |     border: none; /* Remove button border */ | ||||||
|  |     border-radius: 5px; /* Add border-radius for rounded corners */ | ||||||
|  |     cursor: pointer; /* Add pointer cursor on hover */ | ||||||
|  |     font-size: 14px; /* Font size */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #content-get-api .generate-key-button:hover { | ||||||
|  |     background-color: #45a049; /* Darker green on hover */ | ||||||
|  | } | ||||||
| @ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
|   form { |   form { | ||||||
|     background-color: #fff; |     background-color: #fff; | ||||||
|     padding: 20px; |     padding: 25px; | ||||||
|     border-radius: 8px; |     border-radius: 8px; | ||||||
|     box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |     box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | ||||||
|     width: 66%; |     width: 66%; | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 14 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								consumerWebsite/public/images/logo.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								consumerWebsite/public/images/logo.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 8.4 KiB | 
| @ -144,6 +144,34 @@ app.api = (function (app) { | |||||||
| 	return { post: post, get: get, put: put, delete: remove }; | 	return { post: post, get: get, put: put, delete: remove }; | ||||||
| })(app); | })(app); | ||||||
|  |  | ||||||
|  | //socket.io | ||||||
|  | //socket.io | ||||||
|  | app.socket = (function (app) { | ||||||
|  | 	//need to replace with domain name of server when published | ||||||
|  | 	var socket = io(); | ||||||
|  | 	socket.on("disconnect", () => { | ||||||
|  | 		console.log("disconnected"); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	socket.on('connect', ()=>{ | ||||||
|  | 		console.info('WS connected'); | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	socket.io.on("reconnect", () => { | ||||||
|  | 		console.log("reconnected"); | ||||||
|  | 	}); | ||||||
|  | 	socket.io.on("connect_error", (err) => { | ||||||
|  | 		console.log(err); | ||||||
|  | 	}); | ||||||
|  | 	return socket; | ||||||
|  | })(app); | ||||||
|  | //sensor data | ||||||
|  | app.sensordata = (function (app) { | ||||||
|  |  | ||||||
|  |  | ||||||
|  | })(app); | ||||||
|  |  | ||||||
|  |  | ||||||
| app.auth = (function (app) { | app.auth = (function (app) { | ||||||
| 	var user = {}; | 	var user = {}; | ||||||
| 	function setToken(token) { | 	function setToken(token) { | ||||||
| @ -154,12 +182,22 @@ app.auth = (function (app) { | |||||||
| 		return localStorage.getItem("APIToken"); | 		return localStorage.getItem("APIToken"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	function isLoggedIn(callback) { | 	function isLoggedIn(callback) { | ||||||
| 		if (getToken()) { | 		if (getToken()) { | ||||||
| 			return app.api.get("user/me", function (error, data) { | 			return app.api.get("user/me", function (error, data) { | ||||||
| 				if (!error) app.auth.user = data; | 				if (!error) app.auth.user = data; | ||||||
| 				//$.scope.getUsername.push(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); | 				return callback(error, data); | ||||||
| 			}); | 			}); | ||||||
| 		} else { | 		} else { | ||||||
| @ -167,16 +205,6 @@ app.auth = (function (app) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function showUser(){ |  | ||||||
| 		app.api.get("user/me", function (error, data) { |  | ||||||
| 			if (!error) app.auth.user = data; |  | ||||||
| 			$.scope.getUsername.push(data); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	 |  | ||||||
|  |  | ||||||
| 	function logOut(callback) { | 	function logOut(callback) { | ||||||
| 		//call logout route | 		//call logout route | ||||||
| 		$.ajax({ | 		$.ajax({ | ||||||
| @ -217,19 +245,13 @@ app.auth = (function (app) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function homeRedirect() { | 	function homeRedirect() { | ||||||
| 		window.location.href = location.href.replace(location.replace(`/`)) || "/"; | 		//window.location.href = location.href.replace(location.replace(`/`)) || "/"; | ||||||
|  | 		location.replace(`/`); | ||||||
| 	} | 	} | ||||||
| 	/* |  | ||||||
| 	function redirectIfLoggedIn() { |  | ||||||
| 		if (getToken()){ |  | ||||||
| 			homeRedirect(); |  | ||||||
| 		} |  | ||||||
| 		logInRedirect(); |  | ||||||
|  |  | ||||||
|  | 	function profileRedirect() { | ||||||
|  | 		location.replace(`/profile`); | ||||||
| 	} | 	} | ||||||
| 	*/ |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	return { | 	return { | ||||||
| 		getToken: getToken, | 		getToken: getToken, | ||||||
| @ -239,8 +261,25 @@ app.auth = (function (app) { | |||||||
| 		forceLogin, | 		forceLogin, | ||||||
| 		logInRedirect, | 		logInRedirect, | ||||||
| 		homeRedirect, | 		homeRedirect, | ||||||
| 		showUser, | 		profileRedirect, | ||||||
| 		//redirectIfLoggedIn, | 	}; | ||||||
|  | })(app); | ||||||
|  |  | ||||||
|  | app.user = (function (app) { | ||||||
|  | 	//delete profile | ||||||
|  | 	function deleteProfile() { | ||||||
|  | 		app.api.delete("user/delete", function (error, data) { | ||||||
|  | 			if (error) { | ||||||
|  | 				app.util.actionMessage(error.message, $("#deleteProfile"), "danger"); | ||||||
|  | 			} else { | ||||||
|  | 				app.auth.logOut(function () { | ||||||
|  | 					location.replace(`/login`); | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 	return { | ||||||
|  | 		deleteProfile, | ||||||
| 	}; | 	}; | ||||||
| })(app); | })(app); | ||||||
|  |  | ||||||
| @ -251,11 +290,6 @@ function formAJAX(btn, del) { | |||||||
| 	var formData = $form.find("[name]").serializeObject(); // builds query formDataing | 	var formData = $form.find("[name]").serializeObject(); // builds query formDataing | ||||||
| 	var method = $form.attr("method") || "post"; | 	var method = $form.attr("method") || "post"; | ||||||
|  |  | ||||||
| 	// if( !$form.validate()) { |  | ||||||
| 	//     app.util.actionMessage('Please fix the form errors.', $form, 'danger') |  | ||||||
| 	//     return false; |  | ||||||
| 	// } |  | ||||||
|  |  | ||||||
| 	app.util.actionMessage("Loading...", $form, "info"); | 	app.util.actionMessage("Loading...", $form, "info"); | ||||||
|  |  | ||||||
| 	//console.log('Data being sent to', $form.attr('action'), formData) | 	//console.log('Data being sent to', $form.attr('action'), formData) | ||||||
|  | |||||||
| @ -1,28 +1,60 @@ | |||||||
| document.addEventListener("DOMContentLoaded", function () { | document.addEventListener("DOMContentLoaded", function () { | ||||||
|     function updateAdditionalInfo(region) { |     function updateAdditionalInfo(region) { | ||||||
|         const infoContainer = document.getElementById("additional-info"); |         const infoContainer = document.getElementById("additional-info"); | ||||||
|         // Replace the following with actual data retrieval based on the region | // Replace the following with actual data retrieval based on the region | ||||||
|         const aqi = "15"; | const aqi = "15"; | ||||||
|         const temperature = "25°C"; | const temperature = "25°C"; | ||||||
|         const humidity = "60%"; | const humidity = "60%"; | ||||||
|  | const pm25 = "10"; | ||||||
|  | const pm10 = "20"; | ||||||
|  | const so2 = "5"; | ||||||
|  | const o3 = "35"; | ||||||
|  | const co = "0.5"; | ||||||
|  | const no2 = "15"; | ||||||
|  |  | ||||||
|  | infoContainer.innerHTML = ` | ||||||
|  |     <div class="additional-info-box"> | ||||||
|  |         <h3>Additional Information - ${region}</h3> | ||||||
|  |         <button id="downloadCsvButton">Download CSV</button> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">Air Quality Index:</span> | ||||||
|  |             <span class="info-value">${aqi}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">Temperature:</span> | ||||||
|  |             <span class="info-value">${temperature}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">Humidity:</span> | ||||||
|  |             <span class="info-value">${humidity}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">PM2.5:</span> | ||||||
|  |             <span class="info-value">${pm25}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">PM10:</span> | ||||||
|  |             <span class="info-value">${pm10}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">SO2:</span> | ||||||
|  |             <span class="info-value">${so2}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">O3:</span> | ||||||
|  |             <span class="info-value">${o3}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">CO:</span> | ||||||
|  |             <span class="info-value">${co}</span> | ||||||
|  |         </div> | ||||||
|  |         <div class="info-item"> | ||||||
|  |             <span class="info-label">NO2:</span> | ||||||
|  |             <span class="info-value">${no2}</span> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | `; | ||||||
|  |  | ||||||
|         infoContainer.innerHTML = ` |  | ||||||
|             <div class="additional-info-box"> |  | ||||||
|                 <h3>Additional Information - ${region}</h3> |  | ||||||
|                 <div class="info-item"> |  | ||||||
|                     <span class="info-label">Air Quality Index:</span> |  | ||||||
|                     <span class="info-value">${aqi}</span> |  | ||||||
|                 </div> |  | ||||||
|                 <div class="info-item"> |  | ||||||
|                     <span class="info-label">Temperature:</span> |  | ||||||
|                     <span class="info-value">${temperature}</span> |  | ||||||
|                 </div> |  | ||||||
|                 <div class="info-item"> |  | ||||||
|                     <span class="info-label">Humidity:</span> |  | ||||||
|                     <span class="info-value">${humidity}</span> |  | ||||||
|                 </div> |  | ||||||
|             </div> |  | ||||||
|         `; |  | ||||||
|  |  | ||||||
|         // Remove the 'active' class from all info-box elements |         // Remove the 'active' class from all info-box elements | ||||||
|         const infoBoxes = document.querySelectorAll('.info-box'); |         const infoBoxes = document.querySelectorAll('.info-box'); | ||||||
|  | |||||||
| @ -1,3 +1,31 @@ | |||||||
|  | 'use strict'; | ||||||
|  | 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('/user', [auth, APIlogger], require('./user')); | ||||||
|  |  | ||||||
|  | //TO REFACTOR INTO ONE MIDDLWARE | ||||||
|  |  | ||||||
|  | //location route | ||||||
|  | router.use('/location', [apikeyCheck , APIlogger], require('./location.js')); | ||||||
|  |  | ||||||
|  | //location route | ||||||
|  | router.use('/sensor', [apikeyCheck , APIlogger], require('./sensor.js')); | ||||||
|  |  | ||||||
|  | //sensor data route | ||||||
|  | router.use('/sensor-data', [ APIlogger], require('./sensorData.js')); | ||||||
|  |  | ||||||
|  | module.exports = router; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  | ||||||
| 'use strict'; | 'use strict'; | ||||||
| const router = require('express').Router(); | const router = require('express').Router(); | ||||||
| const { auth }   = require("../middleware/authChecker") | const { auth }   = require("../middleware/authChecker") | ||||||
| @ -12,3 +40,4 @@ router.use('/user', auth ,require('./user')); | |||||||
| module.exports = router; | module.exports = router; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | */ | ||||||
| @ -1,19 +1,9 @@ | |||||||
| const { getAPIKey , addAPIKey } = require("../functions/apiDatabase.js"); | const { addAPIKey } = require("../functions/api"); | ||||||
|  |  | ||||||
|  |  | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
|  |  | ||||||
| router.get("/", async (req, res, next) => { |  | ||||||
| 	try { |  | ||||||
| 		const location = await getAPIKey(); |  | ||||||
| 		res.status(200).json(location); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 		next(error); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
| 1) ensure user is logged in (frontend session validation blah or wtv) | 1) ensure user is logged in (frontend session validation blah or wtv) | ||||||
| 2) when user click on generate api key button, it will generate a random api key. how to get userid can be done by session or wtv | 2) when user click on generate api key button, it will generate a random api key. how to get userid can be done by session or wtv | ||||||
| @ -34,9 +24,6 @@ router.post("/new", async (req, res, next) => { | |||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
|  |  | ||||||
| //update |  | ||||||
| //delete |  | ||||||
| //getbyid |  | ||||||
|  |  | ||||||
| module.exports = router; | module.exports = router; | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| const { addUser, loginUser } = require("../functions/apiDatabase.js"); | const { addUser, loginUser } = require("../functions/user"); | ||||||
|  |  | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ const { | |||||||
| 	getLocationById, | 	getLocationById, | ||||||
| 	updateLocation, | 	updateLocation, | ||||||
| 	deleteLocation, | 	deleteLocation, | ||||||
| } = require("../functions/apiDatabase.js"); | } = require("../functions/location"); | ||||||
| 
 | 
 | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| @ -1,42 +1,3 @@ | |||||||
| /* |  | ||||||
| 'use strict'; |  | ||||||
|  |  | ||||||
| var router = require('express').Router(); |  | ||||||
| const conf = require('../conf') |  | ||||||
|  |  | ||||||
| const values ={ |  | ||||||
|   title: conf.environment !== 'production' ? `<i class="fa-brands fa-dev"></i>` : '' |  | ||||||
| } |  | ||||||
|  |  | ||||||
| router.get('/', async function(req, res, next) { |  | ||||||
|   res.render('runner', {...values}); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| router.get('/topics', function(req, res, next) { |  | ||||||
|   res.render('topics', {...values}); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| router.get('/chat', function(req, res, next) { |  | ||||||
|   res.render('chat', {...values}); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| router.get('/login*', function(req, res, next) { |  | ||||||
|   res.render('login', {redirect: req.query.redirect, ...values}); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| router.get('/runner', function(req, res, next) { |  | ||||||
|   res.render('runner', {...values}); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| router.get('/worker', function(req, res, next) { |  | ||||||
|   res.render('worker', {...values}); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| module.exports = router; |  | ||||||
|  |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| var router = require("express").Router(); | var router = require("express").Router(); | ||||||
| @ -66,11 +27,17 @@ router.get("/profile", function (req, res, next) { | |||||||
| 	res.render("profile"); | 	res.render("profile"); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  |  | ||||||
| //forgot password page | //forgot password page | ||||||
| router.get("/forgotpassword", function (req, res, next) { | router.get("/forgotpassword", function (req, res, next) { | ||||||
| 	res.render("forgotpassword"); | 	res.render("forgotpassword"); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | //resetted password page | ||||||
|  | router.get("/resetpassword", function (req, res, next) { | ||||||
|  | 	res.render("resetpassword"); | ||||||
|  | }); | ||||||
|  |  | ||||||
| //contact page | //contact page | ||||||
| router.get("/contact", function (req, res, next) { | router.get("/contact", function (req, res, next) { | ||||||
| 	res.render("contact"); | 	res.render("contact"); | ||||||
| @ -81,6 +48,9 @@ router.get("/api", function (req, res, next) { | |||||||
| 	res.render("api"); | 	res.render("api"); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | // sensor data | ||||||
|  | router.get("/sensor-data", function (req, res, next) { | ||||||
|  | 	res.render("sensor-data"); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | module.exports = router; | ||||||
| module.exports = router; |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
| const { sequelize } = require("../Database/mySql.js"); | const { sequelize } = require("../database/mySQL.js"); | ||||||
| const { locationModel } = require("../Database/model/locationModel.js"); | const { locationModel } = require("../database/model/locationModel.js"); | ||||||
| const { sensorModel } = require("../Database/model/sensorModel.js"); | const { sensorModel } = require("../database/model/sensorModel.js"); | ||||||
| 
 | 
 | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| @ -38,4 +38,4 @@ router.post("/new", async (req, res, next) => { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = router; | ||||||
							
								
								
									
										14
									
								
								consumerWebsite/routes/seed_route.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								consumerWebsite/routes/seed_route.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | 'use strict'; | ||||||
|  | const router = require('express').Router(); | ||||||
|  |  | ||||||
|  | //location route | ||||||
|  | router.use('/seedSensorData', require('./seedsensorData.js')); | ||||||
|  |  | ||||||
|  | router.use('/seed', require('./seedLocationAndSensor.js')); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | module.exports = router; | ||||||
| @ -1,7 +1,7 @@ | |||||||
| const { sequelize } = require("../Database/mySql.js"); | const { sequelize } = require("../database/mySQL.js"); | ||||||
| const { locationModel } = require("../Database/model/locationModel.js"); | const { locationModel } = require("../database/model/locationModel.js"); | ||||||
| const { sensorModel } = require("../Database/model/sensorModel.js"); | const { sensorModel } = require("../database/model/sensorModel.js"); | ||||||
| const { sensorDataModel } = require("../Database/model/sensorDataModel.js"); | const { sensorDataModel } = require("../database/model/sensorDataModel.js"); | ||||||
| 
 | 
 | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| @ -4,7 +4,7 @@ const { | |||||||
| 	updateSensor, | 	updateSensor, | ||||||
|     deleteSensor, |     deleteSensor, | ||||||
|     getSensorById |     getSensorById | ||||||
| } = require("../functions/apiDatabase.js"); | } = require("../functions/sensor.js"); | ||||||
| 
 | 
 | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| @ -63,4 +63,4 @@ router.get("/:id", async (req, res, next) => { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = router; | ||||||
| @ -6,10 +6,9 @@ const { | |||||||
| 	getSensorDataById, | 	getSensorDataById, | ||||||
| 	getData, | 	getData, | ||||||
| 	getDatabyRange, | 	getDatabyRange, | ||||||
| } = require("../functions/apiDatabase.js"); | } = require("../functions/sensorData"); | ||||||
| 
 | 
 | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const { json } = require("body-parser"); |  | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| 
 | 
 | ||||||
| router.get("/", async (req, res, next) => { | router.get("/", async (req, res, next) => { | ||||||
| @ -24,9 +23,9 @@ router.get("/", async (req, res, next) => { | |||||||
| 
 | 
 | ||||||
| router.post("/new", async (req, res, next) => { | router.post("/new", async (req, res, next) => { | ||||||
| 	try { | 	try { | ||||||
| 		const { id, id_sensor, id_location, sensordata } = req.body; | 		const { id_sensor, id_location, sensordata } = req.body; | ||||||
| 		await addSensorData(id, id_sensor, id_location, sensordata); | 		let data = await addSensorData(id_sensor, id_location, sensordata); | ||||||
| 		res.sendStatus(200).json({ message: "SensorData " + id + " added" }); | 		res.json({ message: "SensorData " + data.id + " added", ...data }); | ||||||
| 	} catch (error) { | 	} catch (error) { | ||||||
| 		console.error(error); | 		console.error(error); | ||||||
| 		next(error); | 		next(error); | ||||||
| @ -91,4 +90,3 @@ router.get("/:id", async (req, res, next) => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = router; | ||||||
| 
 |  | ||||||
| @ -1,4 +1,4 @@ | |||||||
| const { getUserID , deleteUserToken } = require("../functions/apiDatabase.js"); | const { getUserID, updateProfile } = require("../functions/user"); | ||||||
|  |  | ||||||
| const express = require("express"); | const express = require("express"); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| @ -6,27 +6,25 @@ const router = express.Router(); | |||||||
| //api/v0/user/me | //api/v0/user/me | ||||||
| //getbyid | //getbyid | ||||||
| router.get("/me", async function (req, res, next) { | router.get("/me", async function (req, res, next) { | ||||||
|     try { | 	try { | ||||||
|         let user = await getUserID(req.user); | 		let user = await getUserID(req.user); | ||||||
|         if (!user) { | 		if (!user) { | ||||||
|             let error = new Error("User not found"); | 			let error = new Error("User not found"); | ||||||
|             error.status = 400; | 			error.status = 400; | ||||||
|             return next(error); | 			return next(error); | ||||||
|         } | 		} | ||||||
|         res.json({ | 		res.json({ | ||||||
|             user: user, | 			user: user, | ||||||
|         }); | 		}); | ||||||
|  | 	} catch (error) { | ||||||
|     } catch (error) { | 		next(error); | ||||||
|         next(error); | 	} | ||||||
|     } |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | //logout | ||||||
| //logout  | router.delete("/logout", async function (req, res, next) { | ||||||
| router.delete('/logout', async function(req, res, next){ | 	try { | ||||||
|     try{ | 		/* | ||||||
|         /* |  | ||||||
|         let authToken = req.header('auth-token'); |         let authToken = req.header('auth-token'); | ||||||
|         let userDel = await deleteUserToken(authToken); |         let userDel = await deleteUserToken(authToken); | ||||||
|         if (!userDel) { |         if (!userDel) { | ||||||
| @ -35,23 +33,51 @@ router.delete('/logout', async function(req, res, next){ | |||||||
|             return next(error); |             return next(error); | ||||||
|         } |         } | ||||||
|         */ |         */ | ||||||
|        //destroy method call on seq object   | 		//destroy method call on seq object | ||||||
|         req.token.destroy(); | 		req.token.destroy(); | ||||||
|         // DO NOT CALL THIS!!! IT WILL DESTROY USERMODEL SEQ OBJ | 		// DO NOT CALL THIS!!! IT WILL DESTROY USERMODEL SEQ OBJ | ||||||
|         //req.user.destroy();  | 		//req.user.destroy(); | ||||||
|         res.json({ | 		res.json({ | ||||||
|             message: "User logged out successfully", | 			message: "User logged out successfully", | ||||||
|         }); | 		}); | ||||||
|  | 	} catch (error) { | ||||||
|     }catch(error){ | 		next(error); | ||||||
|         next(error); | 	} | ||||||
|     } | }); | ||||||
|   }); |  | ||||||
|  |  | ||||||
| //update | //update | ||||||
|  | router.put("/update", async function (req, res, next) { | ||||||
|  | 	try { | ||||||
|  | 		if (!req.body.password) { | ||||||
|  | 			let updateRes = await updateProfile(req.user, req.body); | ||||||
|  | 			if (!updateRes) return next(error); | ||||||
|  |             console.log(updateRes); | ||||||
|  | 			res.json({ | ||||||
|  | 				message: "User updated successfully", | ||||||
|  | 			}); | ||||||
|  | 		} else { | ||||||
|  | 			let updateRes = await updateProfile(req.user, req.body); | ||||||
|  | 			if (!updateRes) return next(error); | ||||||
|  | 			res.json({ | ||||||
|  | 				message: "User updated successfully", | ||||||
|  | 			});             | ||||||
|  | 		} | ||||||
|  | 	} catch (error) { | ||||||
|  | 		next(error); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  |  | ||||||
| //delete | //delete | ||||||
|  | router.delete("/delete", async function (req, res, next) { | ||||||
|  | 	//https://stackoverflow.com/questions/23128816/sequelize-js-ondelete-cascade-is-not-deleting-records-sequelize | ||||||
|  | 	//destroy method call on seq object | ||||||
|  | 	req.token.destroy({ | ||||||
|  | 		onDelete: "cascade", | ||||||
|  | 	}); | ||||||
|  | 	req.user.destroy(); | ||||||
|  | 	res.json({ | ||||||
|  | 		message: "User deleted successfully", | ||||||
|  | 	}); | ||||||
|  | }); | ||||||
|  |  | ||||||
| module.exports = router; | module.exports = router; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
|  !--> |  !--> | ||||||
|  |  | ||||||
| <%- include('top') %> | <%- include('top') %> | ||||||
|  |     <link rel="stylesheet" href="css/api.css" media="all"> | ||||||
|  |  | ||||||
|     <body class="one-content-column-version"> |     <body class="one-content-column-version"> | ||||||
|         <div class="left-menu"> |         <div class="left-menu"> | ||||||
| @ -38,8 +39,8 @@ | |||||||
|                     <li class="scroll-to-link active" data-target="content-get-started"> |                     <li class="scroll-to-link active" data-target="content-get-started"> | ||||||
|                         <a>GET STARTED</a> |                         <a>GET STARTED</a> | ||||||
|                     </li> |                     </li> | ||||||
|                     <li class="scroll-to-link" data-target="content-get-characters"> |                     <li class="scroll-to-link" data-target="content-get-api"> | ||||||
|                         <a>Get Data From API</a> |                         <a>Generate API</a> | ||||||
|                     </li> |                     </li> | ||||||
|                     <li class="scroll-to-link" data-target="content-errors"> |                     <li class="scroll-to-link" data-target="content-errors"> | ||||||
|                         <a>Errors</a> |                         <a>Errors</a> | ||||||
| @ -86,7 +87,8 @@ | |||||||
|                                 <td>Authorization</td> |                                 <td>Authorization</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Your API key.</td> |                                 <td>Your API key.</td> | ||||||
|                                 <td>(Required) Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide your |                                 <td>(Required) Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: | ||||||
|  |                                     {provide your | ||||||
|                                     API key here}"</td> |                                     API key here}"</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -118,7 +120,8 @@ | |||||||
|                                 <td>Authorization</td> |                                 <td>Authorization</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>(Required) Your API key.</td> |                                 <td>(Required) Your API key.</td> | ||||||
|                                 <td>Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide your |                                 <td>Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide | ||||||
|  |                                     your | ||||||
|                                     API key here}"</td> |                                     API key here}"</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -129,11 +132,12 @@ | |||||||
|                     <h2>Add Location (Only for system or admin API key)</h2> |                     <h2>Add Location (Only for system or admin API key)</h2> | ||||||
|                     <p> |                     <p> | ||||||
|                         To add an Location you need to make a POST call to the following url :<br> |                         To add an Location you need to make a POST call to the following url :<br> | ||||||
|                         <code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/new</code>  |                         <code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/new</code> | ||||||
|                         <br> |                         <br> | ||||||
|                         <br> |                         <br> | ||||||
|                         Example :<br> |                         Example :<br> | ||||||
|                         <code class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'</code> |                         <code | ||||||
|  |                             class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'</code> | ||||||
|                         <br> |                         <br> | ||||||
|                         <br> |                         <br> | ||||||
|                         Return Response :<br> |                         Return Response :<br> | ||||||
| @ -154,7 +158,8 @@ | |||||||
|                                 <td>Authorization</td> |                                 <td>Authorization</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Your API key.</td> |                                 <td>Your API key.</td> | ||||||
|                                 <td>(Required) Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: {provide your |                                 <td>(Required) Example: curl https://api.teeseng.uk/api/v0/location/new -H | ||||||
|  |                                     "Authorization: {provide your | ||||||
|                                     API key here}"</td> |                                     API key here}"</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -162,7 +167,8 @@ | |||||||
|                                 <td>Location name</td> |                                 <td>Location name</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Location name.</td> |                                 <td>Location name.</td> | ||||||
|                                 <td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: provide |                                 <td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"name":"Location name"}'</td> |                                     your API key here" -d '{"name":"Location name"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -170,7 +176,8 @@ | |||||||
|                                 <td>Added by </td> |                                 <td>Added by </td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>System or Admin</td> |                                 <td>System or Admin</td> | ||||||
|                                 <td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: provide |                                 <td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"added_by":"system"}'</td> |                                     your API key here" -d '{"added_by":"system"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -178,7 +185,8 @@ | |||||||
|                                 <td>Description</td> |                                 <td>Description</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Description of Location</td> |                                 <td>Description of Location</td> | ||||||
|                                 <td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: provide |                                 <td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"description":"test"}'</td> |                                     your API key here" -d '{"description":"test"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -190,13 +198,14 @@ | |||||||
|                     <h2>Update Location (Only for system or admin API key)</h2> |                     <h2>Update Location (Only for system or admin API key)</h2> | ||||||
|                     <p> |                     <p> | ||||||
|                         To update an Location you need to make a PUT call to the following url :<br> |                         To update an Location you need to make a PUT call to the following url :<br> | ||||||
|                         <code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/update</code>  |                         <code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/update</code> | ||||||
|                         <br> |                         <br> | ||||||
|                         <br> |                         <br> | ||||||
|                         Example :<br> |                         Example :<br> | ||||||
|                         <code class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/update -H "Content-Type: application/json" -X POST -d '{"id": "7" , "name": "SAMPLE", "added_by": "system" , "description": "test"}'</code> |                         <code | ||||||
|  |                             class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/update -H "Content-Type: application/json" -X POST -d '{"id": "7" , "name": "SAMPLE", "added_by": "system" , "description": "test"}'</code> | ||||||
|  |                         <br> | ||||||
|                         <br> |                         <br> | ||||||
|                         <br>                        |  | ||||||
|                         Return Response :<br> |                         Return Response :<br> | ||||||
|                         <code class="higlighted break-word">{"status":"200","message":"Location 7 updated"}</code> |                         <code class="higlighted break-word">{"status":"200","message":"Location 7 updated"}</code> | ||||||
|                     </p> |                     </p> | ||||||
| @ -215,7 +224,8 @@ | |||||||
|                                 <td>Authorization</td> |                                 <td>Authorization</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Your API key.</td> |                                 <td>Your API key.</td> | ||||||
|                                 <td>(Required) example: curl https://api.teeseng.uk/api/v0/location/update -H "Authorization: {provide your |                                 <td>(Required) example: curl https://api.teeseng.uk/api/v0/location/update -H | ||||||
|  |                                     "Authorization: {provide your | ||||||
|                                     API key here}"</td> |                                     API key here}"</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -223,7 +233,8 @@ | |||||||
|                                 <td>ID</td> |                                 <td>ID</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Location ID</td> |                                 <td>Location ID</td> | ||||||
|                                 <td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/update -H "Authorization: provide |                                 <td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/update | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"id": "7"}'</td> |                                     your API key here" -d '{"id": "7"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -231,7 +242,8 @@ | |||||||
|                                 <td>Location name</td> |                                 <td>Location name</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Location name.</td> |                                 <td>Location name.</td> | ||||||
|                                 <td>(Optional) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: provide |                                 <td>(Optional) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"name":"Location name"}'</td> |                                     your API key here" -d '{"name":"Location name"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -239,7 +251,8 @@ | |||||||
|                                 <td>Added by </td> |                                 <td>Added by </td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>System or Admin</td> |                                 <td>System or Admin</td> | ||||||
|                                 <td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: provide |                                 <td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"added_by":"system"}'</td> |                                     your API key here" -d '{"added_by":"system"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -247,7 +260,8 @@ | |||||||
|                                 <td>Description</td> |                                 <td>Description</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Description of Location</td> |                                 <td>Description of Location</td> | ||||||
|                                 <td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new -H "Authorization: provide |                                 <td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"description":"test"}'</td> |                                     your API key here" -d '{"description":"test"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -259,11 +273,12 @@ | |||||||
|                     <h2>Delete Location (Only for system or admin API key)</h2> |                     <h2>Delete Location (Only for system or admin API key)</h2> | ||||||
|                     <p> |                     <p> | ||||||
|                         To delete an Location you need to make a DELETE call to the following url :<br> |                         To delete an Location you need to make a DELETE call to the following url :<br> | ||||||
|                         <code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/delete</code>  |                         <code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/delete</code> | ||||||
|                         <br> |                         <br> | ||||||
|                         <br> |                         <br> | ||||||
|                         Example :<br> |                         Example :<br> | ||||||
|                         <code class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code> |                         <code | ||||||
|  |                             class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code> | ||||||
|                     </p> |                     </p> | ||||||
|                     <br> |                     <br> | ||||||
|                     <h4>QUERY PARAMETERS</h4> |                     <h4>QUERY PARAMETERS</h4> | ||||||
| @ -280,7 +295,8 @@ | |||||||
|                                 <td>Authorization</td> |                                 <td>Authorization</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Your API key.</td> |                                 <td>Your API key.</td> | ||||||
|                                 <td>(Required) example: curl https://api.teeseng.uk/api/v0/location/delete -H "Authorization: {provide your |                                 <td>(Required) example: curl https://api.teeseng.uk/api/v0/location/delete -H | ||||||
|  |                                     "Authorization: {provide your | ||||||
|                                     API key here}"</td> |                                     API key here}"</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -288,7 +304,8 @@ | |||||||
|                                 <td>ID</td> |                                 <td>ID</td> | ||||||
|                                 <td>JSON</td> |                                 <td>JSON</td> | ||||||
|                                 <td>Location ID</td> |                                 <td>Location ID</td> | ||||||
|                                 <td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/delete -H "Authorization: provide |                                 <td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/delete | ||||||
|  |                                     -H "Authorization: provide | ||||||
|                                     your API key here" -d '{"id": "7"}'</td> |                                     your API key here" -d '{"id": "7"}'</td> | ||||||
|                                 </td> |                                 </td> | ||||||
|                             </tr> |                             </tr> | ||||||
| @ -296,24 +313,6 @@ | |||||||
|                     </table> |                     </table> | ||||||
|                 </div> |                 </div> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|                 <div class="overflow-hidden content-section" id="content-errors"> |                 <div class="overflow-hidden content-section" id="content-errors"> | ||||||
|                     <h2>Errors</h2> |                     <h2>Errors</h2> | ||||||
|                     <p> |                     <p> | ||||||
| @ -359,9 +358,41 @@ | |||||||
|                         </tbody> |                         </tbody> | ||||||
|                     </table> |                     </table> | ||||||
|                 </div> |                 </div> | ||||||
|  |                 <div class="overflow-hidden content-section" id="content-get-api"> | ||||||
|  |                     <div class="api-keys-header"> | ||||||
|  |                         <h2>API Keys</h2> | ||||||
|  |                         <button class="generate-key-button">Generate Key</button> | ||||||
|  |                         <p> | ||||||
|  |                             You can generate API Keys here: | ||||||
|  |                         </p> | ||||||
|  |                         <table> | ||||||
|  |                             <thead> | ||||||
|  |                                 <tr> | ||||||
|  |                                   <th>Name</th> | ||||||
|  |                                   <th>Public Key</th> | ||||||
|  |                                   <th>Private Key</th> | ||||||
|  |                                   <th>Key Type</th> | ||||||
|  |                                   <th>Created</th> | ||||||
|  |                                 </tr> | ||||||
|  |                               </thead> | ||||||
|  |                               <tbody> | ||||||
|  |                                 <tr> | ||||||
|  |                                   <td>API Key</td> | ||||||
|  |                                   <td>GR234-We34</td> | ||||||
|  |                                   <td>greR-234-fEG</td> | ||||||
|  |                                   <td>Type</td> | ||||||
|  |                                   <td>2024-01-22</td> | ||||||
|  |                                 </tr> | ||||||
|  |                               </tbody> | ||||||
|  |                           </table>    | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                  | ||||||
|  |                  | ||||||
|  |  | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|     </body> |     </body> | ||||||
|  |     <script src="js/api.js"></script> | ||||||
|     </html> |     </html> | ||||||
|  | |||||||
| @ -81,12 +81,7 @@ | |||||||
|       </p> |       </p> | ||||||
|    </div> |    </div> | ||||||
| </footer> | </footer> | ||||||
|  |  | ||||||
| <script src="js/learnmore.js"></script> |  | ||||||
| <script src="js/search.js"></script> | <script src="js/search.js"></script> | ||||||
| <script src="js/api.js"></script> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
| </html> | </html> | ||||||
| @ -1,4 +1,5 @@ | |||||||
| <%- include('top') %> | <%- include('top') %> | ||||||
|  | <link href="css/contact.css" rel="stylesheet" /> | ||||||
|  |  | ||||||
|   <!-- full Title --> |   <!-- full Title --> | ||||||
|   <div class="full-title"> |   <div class="full-title"> | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
|     <section class="wrapper"> |     <section class="wrapper"> | ||||||
|         <div class="form"> |         <div class="form"> | ||||||
|             <header>Reset Password</header> |             <header>Reset Password</header> | ||||||
|             <form action="resetpassword.html"> |             <form action="/resetpassword"> | ||||||
|                 <input type="text" id="email" placeholder="Email" required /> |                 <input type="text" id="email" placeholder="Email" required /> | ||||||
|                 <input type="password" id="password" placeholder="Password" required /> |                 <input type="password" id="password" placeholder="Password" required /> | ||||||
|                 <input type="password" id="confirmPassword" placeholder="Confirm Password" required /> |                 <input type="password" id="confirmPassword" placeholder="Confirm Password" required /> | ||||||
|  | |||||||
| @ -1,5 +1,12 @@ | |||||||
| <%- include('top') %> | <%- include('top') %> | ||||||
|  |    <script> | ||||||
|  |       //call socket.io | ||||||
|  |       app.socket.on("sensorData:new", function (data) { | ||||||
|  |          console.log("new data!!") | ||||||
|  |          console.log(data); | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |    </script> | ||||||
|  |  | ||||||
|  |  | ||||||
|    <header class="slider-main"> |    <header class="slider-main"> | ||||||
| @ -47,43 +54,55 @@ | |||||||
|    <!-- Page Content --> |    <!-- Page Content --> | ||||||
|    <div class="container"> |    <div class="container"> | ||||||
|       <div class="services-bar"> |       <div class="services-bar"> | ||||||
|          <h1 class="my-4">Services </h1> |           <h1 class="my-4">Services</h1> | ||||||
|          <!-- Services Section --> |           <!-- Services Section --> | ||||||
|          <div class="row"> |           <div class="row"> | ||||||
|             <div class="col-lg-4 mb-4"> |               <div class="col-lg-3 mb-4"> | ||||||
|                <div class="card"> |                   <div class="card"> | ||||||
|                   <h4 class="card-header">Humidity</h4> |                       <h4 class="card-header">Air Quality Index</h4> | ||||||
|                   <div class="card-body text-center"> |                       <div class="card-body text-center"> | ||||||
|                      <p class="card-text display-4"> 70% - 75% </p> |                           <p class="card-text display-4">15 - 18 PSI</p> | ||||||
|  |                       </div> | ||||||
|  |                       <div class="card-footer"> | ||||||
|  |                           <a href="/learnmore" class="btn btn-primary">Learn More</a> | ||||||
|  |                       </div> | ||||||
|                   </div> |                   </div> | ||||||
|                   <div class="card-footer"> |               </div> | ||||||
|                      <a href="/learnmore" class="btn btn-primary">Learn More</a> |               <div class="col-lg-3 mb-4"> | ||||||
|  |                   <div class="card"> | ||||||
|  |                       <h4 class="card-header">Humidity</h4> | ||||||
|  |                       <div class="card-body text-center"> | ||||||
|  |                           <p class="card-text display-4">70% - 75%</p> | ||||||
|  |                       </div> | ||||||
|  |                       <div class="card-footer"> | ||||||
|  |                           <a href="/learnmore" class="btn btn-primary">Learn More</a> | ||||||
|  |                       </div> | ||||||
|                   </div> |                   </div> | ||||||
|                </div> |               </div> | ||||||
|             </div> |               <div class="col-lg-3 mb-4"> | ||||||
|             <div class="col-lg-4 mb-4"> |                   <div class="card"> | ||||||
|                <div class="card"> |                       <h4 class="card-header">Temperature</h4> | ||||||
|                   <h4 class="card-header">Air Quality Index</h4> |                       <div class="card-body text-center"> | ||||||
|                   <div class="card-body text-center"> |                           <p class="card-text display-4">30° - 37°</p> | ||||||
|                      <p class="card-text display-4"> 15 - 18 PSI </p> |                       </div> | ||||||
|  |                       <div class="card-footer"> | ||||||
|  |                           <a href="/learnmore" class="btn btn-primary">Learn More</a> | ||||||
|  |                       </div> | ||||||
|                   </div> |                   </div> | ||||||
|                   <div class="card-footer"> |               </div> | ||||||
|                      <a href="/learnmore" class="btn btn-primary">Learn More</a> |               <div class="col-lg-3 mb-4"> | ||||||
|  |                   <div class="card"> | ||||||
|  |                       <h4 class="card-header">Another Category</h4> | ||||||
|  |                       <div class="card-body text-center"> | ||||||
|  |                           <p class="card-text display-4">values</p> | ||||||
|  |                       </div> | ||||||
|  |                       <div class="card-footer"> | ||||||
|  |                           <a href="/learnmore" class="btn btn-primary">Learn More</a> | ||||||
|  |                       </div> | ||||||
|                   </div> |                   </div> | ||||||
|                </div> |               </div> | ||||||
|             </div> |           </div> | ||||||
|             <div class="col-lg-4 mb-4"> |    | ||||||
|                <div class="card"> |  | ||||||
|                   <h4 class="card-header">Temperature</h4> |  | ||||||
|                   <div class="card-body text-center"> |  | ||||||
|                      <p class="card-text display-4"> 30° - 37° </p> |  | ||||||
|                   </div> |  | ||||||
|                   <div class="card-footer"> |  | ||||||
|                      <a href="/learnmore" class="btn btn-primary">Learn More</a> |  | ||||||
|                   </div> |  | ||||||
|                </div> |  | ||||||
|             </div> |  | ||||||
|          </div> |  | ||||||
|          <!-- /.row --> |          <!-- /.row --> | ||||||
|       </div> |       </div> | ||||||
|       <!-- About Section --> |       <!-- About Section --> | ||||||
| @ -121,4 +140,4 @@ | |||||||
|    </div> |    </div> | ||||||
|    <hr> |    <hr> | ||||||
|    </div> |    </div> | ||||||
| <%- include('bot') %> |    <%- include('bot') %> | ||||||
| @ -1,4 +1,5 @@ | |||||||
| <%- include('top') %> | <%- include('top') %> | ||||||
|  | <link href="css/learnmore.css" rel="stylesheet" /> | ||||||
|  |  | ||||||
| <br> | <br> | ||||||
| <br> | <br> | ||||||
| @ -37,5 +38,7 @@ | |||||||
|  |  | ||||||
| <br> | <br> | ||||||
| <br> | <br> | ||||||
|  | <script src="js/learnmore.js"></script> | ||||||
|  |  | ||||||
| <%- include('bot') %> |  | ||||||
|  | <%- include('bot') %> | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||||||
|     <meta name="description" content=""> |     <meta name="description" content=""> | ||||||
|     <meta name="author" content=""> |     <meta name="author" content=""> | ||||||
|  |     <link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" /> | ||||||
|     <!-- Bootstrap core CSS --> |     <!-- Bootstrap core CSS --> | ||||||
|     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" |     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" | ||||||
|         integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> |         integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> | ||||||
| @ -26,6 +26,8 @@ | |||||||
|     <!-- Mustache JS --> |     <!-- Mustache JS --> | ||||||
|     <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.min.js"></script> |     <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.min.js"></script> | ||||||
|     <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.js"></script> |     <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.js"></script> | ||||||
|  |     <!-- socket.io scriot --> | ||||||
|  | 	<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script> | ||||||
|  |  | ||||||
|     <!-- jquery app.js --> |     <!-- jquery app.js --> | ||||||
|     <script src="js/app.js"></script> |     <script src="js/app.js"></script> | ||||||
|  | |||||||
| @ -1,64 +1,111 @@ | |||||||
| <%- include('top') %> | <%- include('top') %> | ||||||
| <script type="text/javascript"> |     <br> | ||||||
| 	// Require login to see this page. |     <br> | ||||||
| 	app.auth.forceLogin() |     <br> | ||||||
| </script> |     <div class="profile"> | ||||||
|  |         <!-- <li jq-repeat="getUsername" class="nav-item"> --> | ||||||
|  |         <div class="edit_information" jq-repeat="getUserDetails"> | ||||||
|  |             <div class="card-header shadow actionMessage" style="display:none"></div> | ||||||
|  |             <form id="profileForm" action="user/update" method="put" onsubmit="formAJAX(this)" | ||||||
|  |                 evalAJAX="app.auth.profileRedirect();"> | ||||||
|  |                 <h3 class="text-center">Edit Personal Information</h3> | ||||||
|  |                 <br> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">First Name:</label> | ||||||
|  |                             <input type="text" name="first_name" value="{{ user.firstname }}" class="form-control" | ||||||
|  |                                 pattern="^[a-zA-Z\s]+$"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">Last Name: </label> | ||||||
|  |                             <input type="text" name="last_name" value="{{ user.lastname }}" class="form-control" | ||||||
|  |                                 pattern="^[a-zA-Z\s]+$"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">Username:</label> | ||||||
|  |                             <input type="text" name="username" value="{{ user.username }}" class="form-control" | ||||||
|  |                                 pattern="^\w+$"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">Password:</label> | ||||||
|  |                             <input type="password" name="password" placeholder="Password" class="form-control" value="" | ||||||
|  |                                 pattern="^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">Email Address:</label> | ||||||
|  |                             <input type="email" name="email" value="{{user.email}}" class="form-control" | ||||||
|  |                                 pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">Address:</label> | ||||||
|  |                             <input type="text" name="address" value="{{ user.address }}" class="form-control" | ||||||
|  |                                 pattern="^(\d{1,3}.)?.+\s(\d{6})$"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label class="profile_details_text">Phone Number:</label> | ||||||
|  |                             <input type="tel" name="phone" value="{{ user.phone }}" class="form-control" value="" | ||||||
|  |                                 pattern="^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,8}$"> | ||||||
|  |  | ||||||
| 	<div class="full-title"> |                         </div> | ||||||
| 		<div class="container"> |                     </div> | ||||||
| 			<h1 class="mt-4 mb-3">Profile |                 </div> | ||||||
| 			</h1> |                 <br> | ||||||
| 		</div> |                 <div class="row justify-content-center mt-3"> | ||||||
| 	</div> |                     <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 submit"> | ||||||
|  |                         <div class="form-group text-center"> | ||||||
|  |                             <input type="submit" class="btn btn-success updateButton" value="Update Profile"> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 text-center"> | ||||||
|  |                         <button type="button" class="btn btn-danger deleteButton" onclick="return myConfirm();">Delete | ||||||
|  |                             Profile</button> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </form> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |     <br> | ||||||
|  |     <br> | ||||||
|  |     <br> | ||||||
|  |     <br> | ||||||
|  |     <br> | ||||||
|  |     <br> | ||||||
|  |     <script> | ||||||
|  |         function myConfirm() { | ||||||
|  |             var result = confirm("Do you wish to Delete your Profile"); | ||||||
|  |             if (result == true) { | ||||||
|  |                 app.user.deleteProfile(); | ||||||
|  |             } else { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
| 	<br> |  | ||||||
| 	<br> |  | ||||||
|  |  | ||||||
| 	<div class="centered-content"> |     </script> | ||||||
| 		<div class="container"> |  | ||||||
| 			<div class="row"> |  | ||||||
| 				<div class="col-md-3 border-right"> |  | ||||||
| 					<div class="d-flex flex-column align-items-center text-center p-3 py-5"><img |  | ||||||
| 							class="rounded-circle mt-5" width="150px" |  | ||||||
| 							src="https://st3.depositphotos.com/15648834/17930/v/600/depositphotos_179308454-stock-illustration-unknown-person-silhouette-glasses-profile.jpg"> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="col-md-5 border-right"> |  | ||||||
| 					<div class="p-3 py-5"> |  | ||||||
| 						<div class="d-flex justify-content-between align-items-center mb-3"> |  | ||||||
| 							<h4 class="text-right">Profile Settings</h4> |  | ||||||
| 						</div> |  | ||||||
| 						<div class="row mt-2"> |  | ||||||
| 							<div class="col-md-6"><label class="labels">Name</label><input type="text" |  | ||||||
| 									class="form-control" placeholder="first name" value=""></div> |  | ||||||
| 							<div class="col-md-6"><label class="labels">Surname</label><input type="text" |  | ||||||
| 									class="form-control" value="" placeholder="surname"></div> |  | ||||||
| 						</div> |  | ||||||
| 						<div class="row mt-3"> |  | ||||||
| 							<div class="col-md-12"><label class="labels">Mobile Number</label><input type="text" |  | ||||||
| 									class="form-control" placeholder="enter phone number" value=""></div> |  | ||||||
| 							<div class="col-md-12"><label class="labels">Address</label><input type="text" |  | ||||||
| 									class="form-control" placeholder="enter address" value=""></div> |  | ||||||
| 							<div class="col-md-12"><label class="labels">Email</label><input type="text" |  | ||||||
| 									class="form-control" placeholder="enter email" value=""></div> |  | ||||||
| 							<div class="col-md-12"><label class="labels">Password</label><input type="text" |  | ||||||
| 									class="form-control" placeholder="enter password" value=""></div> |  | ||||||
| 							<div class="col-md-12"><label class="labels">Password</label><input type="text" |  | ||||||
| 									class="form-control" placeholder="re enter password" value=""></div> |  | ||||||
| 						</div> |  | ||||||
| 						<div class="mt-2 text-center"> |  | ||||||
| 							<button class="btn btn-sm btn-secondary change-password-button" type="button">Change |  | ||||||
| 								Password</button> |  | ||||||
| 						</div> |  | ||||||
| 						<div class="mt-5 text-center"><button class="btn btn-primary profile-button" type="button">Save |  | ||||||
| 								Profile</button></div> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
|  |  | ||||||
| 	<br> |     <%- include('bot') %> | ||||||
| <%- include('bot') %> |  | ||||||
|  |  | ||||||
| 	 |  | ||||||
							
								
								
									
										39
									
								
								consumerWebsite/views/sensor-data.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								consumerWebsite/views/sensor-data.ejs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | <%- include('top') %> | ||||||
|  |  | ||||||
|  | 	<style> | ||||||
|  | 		#sensorDataList { | ||||||
|  | 			padding-top: 2.5em; | ||||||
|  | 		} | ||||||
|  | 	</style> | ||||||
|  |  | ||||||
|  | 	<ul id="sensorDataList"> | ||||||
|  | 		<li jq-repeat='sensorData'> | ||||||
|  | 			rowid: {{ id }} | ||||||
|  | 			sensorId: {{ sensorid }} | ||||||
|  | 			created: {{ createdAt }} | ||||||
|  | 			location: {{ locationid }} | ||||||
|  | 			<br /> | ||||||
|  | 			co: {{ measurement.co }} | ||||||
|  | 			humidity: {{ measurement.humidity }} | ||||||
|  | 			no2: {{ measurement.no2 }} | ||||||
|  | 			o3: {{ measurement.o3 }} | ||||||
|  | 			psi: {{ measurement.psi }} | ||||||
|  | 			so2: {{ measurement.so2 }} | ||||||
|  | 			temperature: {{ measurement.temperature }} | ||||||
|  | 			windspeed: {{ measurement.windspeed }} | ||||||
|  | 			<hr /> | ||||||
|  | 		</li> | ||||||
|  | 		<li jq-repeat-defualt='sensorData'> | ||||||
|  | 			Loading... | ||||||
|  | 		</li> | ||||||
|  | 	</ul> | ||||||
|  |  | ||||||
|  | 	<script type="text/javascript"> | ||||||
|  | 		$(document).ready(async function () { | ||||||
|  | 			app.api.get('sensor-data/data?order=DESC&limit=40', function(error, data){ | ||||||
|  |             $.scope.sensorData.push(...data); | ||||||
|  |         }) | ||||||
|  | 		}) | ||||||
|  |  | ||||||
|  | 	</script> | ||||||
|  | 	<%- include('bot') %> | ||||||
| @ -9,6 +9,7 @@ | |||||||
|             <div class="form signup iot-card"> |             <div class="form signup iot-card"> | ||||||
|                 <!--<div class="form signup card" --> |                 <!--<div class="form signup card" --> | ||||||
|                 <header>Signup</header> |                 <header>Signup</header> | ||||||
|  |                 <div class="card-header shadow actionMessage" style="display:none"></div> | ||||||
|                 <!-- localhost/api/v0/user/register --> |                 <!-- localhost/api/v0/user/register --> | ||||||
|                 <!-- evalAjax Fires when status 200 is returned  --> |                 <!-- evalAjax Fires when status 200 is returned  --> | ||||||
|                 <form action="auth/register" onsubmit="formAJAX(this)" evalAJAX="app.auth.logInRedirect();"> |                 <form action="auth/register" onsubmit="formAJAX(this)" evalAJAX="app.auth.logInRedirect();"> | ||||||
| @ -35,7 +36,7 @@ | |||||||
|                 <form action="auth/login" onsubmit="formAJAX(this)" evalAJAX="app.auth.homeRedirect(); |                 <form action="auth/login" onsubmit="formAJAX(this)" evalAJAX="app.auth.homeRedirect(); | ||||||
|                 app.auth.setToken(data.token);"> |                 app.auth.setToken(data.token);"> | ||||||
|                     <input type="text" name="username" placeholder="Email address | Username" required |                     <input type="text" name="username" placeholder="Email address | Username" required | ||||||
|                         pattern="^\w+$" /> |                         pattern="^(\w+@\w+\.\w+)$|^\w+$"/> | ||||||
|                     <input type="password" name="password" placeholder="Password" required /> |                     <input type="password" name="password" placeholder="Password" required /> | ||||||
|                     <a href="/forgotpassword">Forgot password?</a> |                     <a href="/forgotpassword">Forgot password?</a> | ||||||
|                     <input type="submit" value="Login" /> |                     <input type="submit" value="Login" /> | ||||||
|  | |||||||
| @ -1,146 +1,130 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
| 	<head> |  | ||||||
| 		<meta charset="utf-8" /> |  | ||||||
| 		<meta |  | ||||||
| 			name="viewport" |  | ||||||
| 			content="width=device-width, initial-scale=1, shrink-to-fit=no" /> |  | ||||||
| 		<meta name="description" content="" /> |  | ||||||
| 		<meta name="author" content="" /> |  | ||||||
| 		<meta http-equiv="cleartype" content="on" /> |  | ||||||
| 		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> |  | ||||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |  | ||||||
|  |  | ||||||
| 		<!-- Bootstrap core CSS --> | <head> | ||||||
| 		<link | 	<meta charset="utf-8" /> | ||||||
| 			href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" | 	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> | ||||||
| 			rel="stylesheet" | 	<meta name="description" content="" /> | ||||||
| 			integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" | 	<meta name="author" content="" /> | ||||||
| 			crossorigin="anonymous" /> | 	<meta http-equiv="cleartype" content="on" /> | ||||||
|  | 	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> | ||||||
|  | 	<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||||
|  | 	<link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" /> | ||||||
|  |  | ||||||
| 		<!-- Custom styles for this template --> |  | ||||||
| 		<link href="css/all.css" rel="stylesheet" /> |  | ||||||
| 		<link href="css/style.css" rel="stylesheet" /> |  | ||||||
| 		<link href="css/learnmore.css" rel="stylesheet" /> |  | ||||||
| 		<link href="css/contact.css" rel="stylesheet" /> |  | ||||||
| 		<link rel="stylesheet" href="css/api.css" media="all" /> |  | ||||||
| 		<!-- weird api page cdn --> |  | ||||||
| 		<link rel="preconnect" href="https://fonts.googleapis.com" /> |  | ||||||
| 		<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> |  | ||||||
| 		<link |  | ||||||
| 			href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;1,300&family=Source+Code+Pro:wght@300&display=swap" |  | ||||||
| 			rel="stylesheet" /> |  | ||||||
|         <!-- Mustache JS --> |  | ||||||
| 		<script src="https://sso.theta42.com/static/js/mustache.min.js"></script> |  | ||||||
| 		<!-- jQuery library --> |  | ||||||
|         <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> |  | ||||||
|  |  | ||||||
| 		<!-- Bootstrap 5 JavaScript --> | 	<!-- Bootstrap core CSS --> | ||||||
| 		<script | 	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" | ||||||
| 			src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" | 		integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" /> | ||||||
| 			integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" |  | ||||||
| 			crossorigin="anonymous"></script> |  | ||||||
|  |  | ||||||
| 		<!-- weird api page cdn --> | 	<!-- Custom styles for this template --> | ||||||
| 		<!-- https://github.com/floriannicolas/API-Documentation-HTML-Template/tree/master --> | 	<link href="css/all.css" rel="stylesheet" /> | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/highlight.min.js"></script> | 	<link href="css/style.css" rel="stylesheet" /> | ||||||
| 		<script> | 	<!-- weird api page cdn --> | ||||||
| 			hljs.initHighlightingOnLoad(); | 	<link rel="preconnect" href="https://fonts.googleapis.com" /> | ||||||
| 		</script> | 	<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | ||||||
|  | 	<link | ||||||
|  | 		href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;1,300&family=Source+Code+Pro:wght@300&display=swap" | ||||||
|  | 		rel="stylesheet" /> | ||||||
|  | 	<!-- Mustache JS --> | ||||||
|  | 	<script src="https://sso.theta42.com/static/js/mustache.min.js"></script> | ||||||
|  | 	<!-- jQuery library --> | ||||||
|  | 	<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> | ||||||
|  | 	<!-- Bootstrap 5 JavaScript --> | ||||||
|  | 	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" | ||||||
|  | 		integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" | ||||||
|  | 		crossorigin="anonymous"></script> | ||||||
|  |  | ||||||
| 		<!-- jq-repeat --> | 	<!-- weird api page cdn --> | ||||||
| 		<script src="js/jq-repeat.js"></script> | 	<!-- https://github.com/floriannicolas/API-Documentation-HTML-Template/tree/master --> | ||||||
|  | 	<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/highlight.min.js"></script> | ||||||
| 		<!-- jquery app.js --> |  | ||||||
| 		<script src="js/app.js"></script> |  | ||||||
| 	</head> |  | ||||||
| 	<!-- javascript function to check if user is auth --> |  | ||||||
| 	<script> | 	<script> | ||||||
| 		//make document ready | 		hljs.initHighlightingOnLoad(); | ||||||
| 		$(document).ready(function () { |  | ||||||
| 			//check if user is logged in |  | ||||||
| 			app.auth.isLoggedIn(function (error, data) { |  | ||||||
| 				if (data) { |  | ||||||
|                     app.auth.showUser(); |  | ||||||
| 					$("#cl-logout-button").show("fast"); |  | ||||||
| 					$("#cl-profile-button").show("fast"); |  | ||||||
| 					$("#cl-login-button").hide("fast"); |  | ||||||
| 				} else { |  | ||||||
| 					$("#cl-login-button").show("fast"); |  | ||||||
| 				} |  | ||||||
| 				$("body").show("fast"); |  | ||||||
| 			}); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
| 	</script> | 	</script> | ||||||
|  | 	<!-- socket.io scriot --> | ||||||
|  | 	<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script> | ||||||
|  |  | ||||||
| 	<body> |  | ||||||
| 		<nav |  | ||||||
| 			class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top"> |  | ||||||
| 			<div class="container"> |  | ||||||
| 				<a class="navbar-brand" href="/"> |  | ||||||
| 					<img src="images/logo.png" alt="logo" /> |  | ||||||
| 				</a> |  | ||||||
| 				<button |  | ||||||
| 					class="navbar-toggler" |  | ||||||
| 					type="button" |  | ||||||
| 					data-toggle="collapse" |  | ||||||
| 					data-target="#navbarResponsive" |  | ||||||
| 					aria-controls="navbarResponsive" |  | ||||||
| 					aria-expanded="false" |  | ||||||
| 					aria-label="Toggle navigation"> |  | ||||||
| 					<span class="fas fa-bars"></span> |  | ||||||
| 				</button> |  | ||||||
| 				<div class="collapse navbar-collapse" id="navbarResponsive"> |  | ||||||
| 					<ul class="navbar-nav ms-auto"> |  | ||||||
| 						<li jq-repeat="getUsername" class="nav-item"> |  | ||||||
|                             <a class="nav-link"> Welcome {{ user.username }} </a> |  | ||||||
| 						</li> |  | ||||||
| 						<li class="nav-item"> |  | ||||||
| 							<a class="nav-link" href="/">Home</a> |  | ||||||
| 						</li> |  | ||||||
| 						<li class="nav-item"> |  | ||||||
| 							<a class="nav-link" href="/news">News</a> |  | ||||||
| 						</li> |  | ||||||
| 						<li class="nav-item"> |  | ||||||
| 							<a class="nav-link" href="/contact">Contact</a> |  | ||||||
| 						</li> |  | ||||||
| 						<li class="nav-item"> |  | ||||||
| 							<a class="nav-link" href="/api">API Doc</a> |  | ||||||
| 						</li> |  | ||||||
| 						<!-- profile button --> |  | ||||||
| 						<div class="form-inline mt-2 mt-md-0"> |  | ||||||
| 							<!-- Profile Button --> |  | ||||||
| 							<a |  | ||||||
| 								id="cl-profile-button" |  | ||||||
| 								class="btn btn-outline-info btn-sm my-2 my-sm-0" |  | ||||||
| 								href="/profile" |  | ||||||
| 								style="display: none"> |  | ||||||
| 								<i class="fas fa-sign-out"></i> Profile |  | ||||||
| 							</a> |  | ||||||
|  |  | ||||||
| 							<!-- Login Button --> | 	<!-- jq-repeat --> | ||||||
| 							<a | 	<script src="js/jq-repeat.js"></script> | ||||||
| 								id="cl-login-button" |  | ||||||
| 								class="btn btn-outline-danger btn-sm my-2 my-sm-0" |  | ||||||
| 								onclick="app.auth.forceLogin()" |  | ||||||
| 								style="display: none"> |  | ||||||
| 								<i class="fas fa-sign-out"></i> Login |  | ||||||
| 							</a> |  | ||||||
|  |  | ||||||
| 							<!-- Logout Button --> | 	<!-- jquery app.js --> | ||||||
| 							<button | 	<script src="js/app.js"></script> | ||||||
| 								id="cl-logout-button" | </head> | ||||||
| 								class="btn btn-outline-danger btn-sm my-2 my-sm-0" | <!-- javascript function to check if user is auth --> | ||||||
| 								href="/" | <script> | ||||||
| 								onclick="app.auth.logOut(e => window.location.href='/')" | 	//make document ready | ||||||
| 								style="display: none"> | 	$(document).ready(function () { | ||||||
| 								<i class="fas fa-sign-out"></i> Logout | 		//check if user is logged in | ||||||
| 							</button> | 		app.auth.isLoggedIn(function (error, data) { | ||||||
| 						</div> | 			if (data) { | ||||||
| 					</ul> | 				$("#cl-logout-button").show("fast"); | ||||||
| 				</div> | 				$("#cl-api-button").show("fast"); | ||||||
|  | 				$("#cl-profile-button").show("fast"); | ||||||
|  | 				$("#cl-login-button").hide("fast"); | ||||||
|  | 			} else { | ||||||
|  | 				$("#cl-login-button").show("fast"); | ||||||
|  | 			} | ||||||
|  | 			$("body").show("fast"); | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <body> | ||||||
|  | 	<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top"> | ||||||
|  | 		<div class="container"> | ||||||
|  | 			<a class="navbar-brand" href="/"> | ||||||
|  | 				<img src="images/logo.png" alt="logo" /> | ||||||
|  | 			</a> | ||||||
|  | 			<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" | ||||||
|  | 				aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> | ||||||
|  | 				<span class="fas fa-bars"></span> | ||||||
|  | 			</button> | ||||||
|  | 			<div class="collapse navbar-collapse" id="navbarResponsive"> | ||||||
|  | 				<ul class="navbar-nav ms-auto"> | ||||||
|  | 					<li jq-repeat="getUsername" class="nav-item"> | ||||||
|  | 						<a class="nav-link"> Welcome {{ user.username }} </a> | ||||||
|  | 					</li> | ||||||
|  | 					<li class="nav-item"> | ||||||
|  | 						<a class="nav-link" href="/">Home</a> | ||||||
|  | 					</li> | ||||||
|  | 					<li class="nav-item"> | ||||||
|  | 						<a class="nav-link" href="/news">News</a> | ||||||
|  | 					</li> | ||||||
|  | 					<li class="nav-item"> | ||||||
|  | 						<a class="nav-link" href="/contact">Contact</a> | ||||||
|  | 					</li> | ||||||
|  | 					<!--  | ||||||
|  | 					<li class="nav-item"> | ||||||
|  | 						<a class="nav-link" href="/api">API Doc</a> | ||||||
|  | 					</li> | ||||||
|  |  | ||||||
|  | 					 --> | ||||||
|  | 					<!-- profile button --> | ||||||
|  | 					<div class="form-inline mt-2 mt-md-0"> | ||||||
|  | 						<a id="cl-api-button" class="btn btn-outline-info btn-sm my-2 my-sm-0" href="/api" | ||||||
|  | 							style="display: none"> | ||||||
|  | 							<i class="fas fa-sign-out"></i> API | ||||||
|  | 						</a> | ||||||
|  | 						<!-- Profile Button --> | ||||||
|  | 						<a id="cl-profile-button" class="btn btn-outline-info btn-sm my-2 my-sm-0" href="/profile" | ||||||
|  | 							style="display: none"> | ||||||
|  | 							<i class="fas fa-sign-out"></i> Profile | ||||||
|  | 						</a> | ||||||
|  |  | ||||||
|  | 						<!-- Login Button --> | ||||||
|  | 						<a id="cl-login-button" class="btn btn-outline-danger btn-sm my-2 my-sm-0" | ||||||
|  | 							onclick="app.auth.forceLogin()" style="display: none"> | ||||||
|  | 							<i class="fas fa-sign-out"></i> Login | ||||||
|  | 						</a> | ||||||
|  |  | ||||||
|  | 						<!-- Logout Button --> | ||||||
|  | 						<button id="cl-logout-button" class="btn btn-outline-danger btn-sm my-2 my-sm-0" href="/" | ||||||
|  | 							onclick="app.auth.logOut(e => window.location.href='/')" style="display: none"> | ||||||
|  | 							<i class="fas fa-sign-out"></i> Logout | ||||||
|  | 						</button> | ||||||
|  | 					</div> | ||||||
|  | 				</ul> | ||||||
| 			</div> | 			</div> | ||||||
| 		</nav> | 		</div> | ||||||
| 	</body> | 	</nav> | ||||||
| </html> |  | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ | |||||||
|     "bcrypt": "^5.1.1", |     "bcrypt": "^5.1.1", | ||||||
|     "body-parser": "^1.20.2", |     "body-parser": "^1.20.2", | ||||||
|     "cookie-parser": "^1.4.6", |     "cookie-parser": "^1.4.6", | ||||||
|  |     "cors": "^2.8.5", | ||||||
|     "csurf": "^1.11.0", |     "csurf": "^1.11.0", | ||||||
|     "date-fns": "^3.2.0", |     "date-fns": "^3.2.0", | ||||||
|     "date-fns-tz": "^2.0.0", |     "date-fns-tz": "^2.0.0", | ||||||
| @ -43,6 +44,8 @@ | |||||||
|     "sanitize-html": "^2.11.0", |     "sanitize-html": "^2.11.0", | ||||||
|     "sequelize": "^6.35.2", |     "sequelize": "^6.35.2", | ||||||
|     "sequelize-cli": "^6.6.2", |     "sequelize-cli": "^6.6.2", | ||||||
|  |     "socket.io": "^4.7.4", | ||||||
|  |     "socket.io-client": "^4.7.4", | ||||||
|     "validator": "^13.11.0" |     "validator": "^13.11.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|  | |||||||
| @ -1,65 +0,0 @@ | |||||||
| "use strict"; |  | ||||||
| const { Sequelize, DataTypes } = require("sequelize"); |  | ||||||
| const { sequelize } = require("../mySQL"); |  | ||||||
| const { userModel } = require("./userModel"); |  | ||||||
|  |  | ||||||
| //sequelize.sync(); |  | ||||||
| const apikeyModel = sequelize.define( |  | ||||||
| 	"apikey", |  | ||||||
| 	{ |  | ||||||
| 		id: { |  | ||||||
| 			type: DataTypes.INTEGER, |  | ||||||
| 			allowNull: true, |  | ||||||
| 			primaryKey: true, |  | ||||||
| 			autoIncrement: true, |  | ||||||
| 			validate: { |  | ||||||
| 				isNumeric: true, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		userid: { |  | ||||||
| 			type: DataTypes.INTEGER, |  | ||||||
| 			allowNull: false, |  | ||||||
| 			validate: { |  | ||||||
| 				isNumeric: true, |  | ||||||
| 			}, |  | ||||||
| 			//fk |  | ||||||
| 			references: { |  | ||||||
| 				model: userModel, |  | ||||||
| 				key: "id", |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		apikey: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: false, |  | ||||||
| 			length: 255, |  | ||||||
| 			unique: true, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 255], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		permission: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: false, |  | ||||||
| 			length: 255, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 255], |  | ||||||
| 				isIn: [["canRead", "canWrite" , "auto-generated"]], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		createdAt: { |  | ||||||
| 			type: DataTypes.DATE, |  | ||||||
| 			allowNull: true, |  | ||||||
| 		}, |  | ||||||
| 		updatedAt: { |  | ||||||
| 			type: DataTypes.DATE, |  | ||||||
| 			allowNull: true, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		timestamps: true, |  | ||||||
| 	} |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| module.exports = { apikeyModel }; |  | ||||||
| @ -1,94 +0,0 @@ | |||||||
| "use strict"; |  | ||||||
| const { Sequelize, DataTypes } = require("sequelize"); |  | ||||||
| const { sequelize } = require("../mySQL"); |  | ||||||
| const { |  | ||||||
| 	isAlphaNumericWithSpacesAndDash, |  | ||||||
| 	isAddress, |  | ||||||
| } = require("../../functions/validateData"); |  | ||||||
|  |  | ||||||
| //sequelize.sync(); |  | ||||||
| const userModel = sequelize.define( |  | ||||||
| 	"user", |  | ||||||
| 	{ |  | ||||||
| 		id: { |  | ||||||
| 			type: DataTypes.INTEGER, |  | ||||||
| 			allowNull: true, |  | ||||||
| 			primaryKey: true, |  | ||||||
| 			autoIncrement: true, |  | ||||||
| 			validate: { |  | ||||||
| 				isNumeric: true, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		username: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: false, |  | ||||||
| 			length: 60, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 60], |  | ||||||
| 				isAlphaNumericWithSpacesAndDash(value) { |  | ||||||
| 					if (!isAlphaNumericWithSpacesAndDash(value)) { |  | ||||||
| 						throw new Error("Invalid characters in username"); |  | ||||||
| 					} |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		password: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: false, |  | ||||||
| 			length: 255, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 255], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		email: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: false, |  | ||||||
| 			length: 60, |  | ||||||
| 			unique: true, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 60], |  | ||||||
| 				isEmail: true, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		address: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: true, |  | ||||||
| 			length: 255, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 255], |  | ||||||
| 				isAddress(value) { |  | ||||||
| 					if (!isAddress(value)) { |  | ||||||
| 						throw new Error("Invalid address"); |  | ||||||
| 					} |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		phone: { |  | ||||||
| 			type: DataTypes.STRING, |  | ||||||
| 			allowNull: true, |  | ||||||
| 			length: 20, |  | ||||||
| 			validate: { |  | ||||||
| 				notEmpty: true, |  | ||||||
| 				len: [1, 20], |  | ||||||
| 				isNumeric: true, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
|         //utc time |  | ||||||
| 		createdAt: { |  | ||||||
| 			type: DataTypes.DATE, |  | ||||||
| 			allowNull: true, |  | ||||||
| 		}, |  | ||||||
| 		updatedAt: { |  | ||||||
| 			type: DataTypes.DATE, |  | ||||||
| 			allowNull: true, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		timestamps: true, |  | ||||||
| 	} |  | ||||||
| ); |  | ||||||
| module.exports = { userModel }; |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| const dotenv = require("dotenv"); |  | ||||||
| const path = require('path') |  | ||||||
| require('dotenv').config({ path: path.resolve(__dirname, '../../.env') }) |  | ||||||
| const Sequelize = require("sequelize"); |  | ||||||
| const fs = require('fs'); |  | ||||||
| const { escape } = require("querystring"); |  | ||||||
|  |  | ||||||
| const sequelize = new Sequelize( |  | ||||||
|  "eco_saver", |  | ||||||
|  process.env.DB_USER, |  | ||||||
|  process.env.DB_PASS, |  | ||||||
|  { |  | ||||||
|     host: "mpsqldatabase.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')), |  | ||||||
|       }, |  | ||||||
|  |  | ||||||
|     }, |  | ||||||
|    }, |  | ||||||
|  |  | ||||||
|     |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| sequelize.authenticate().then(() => { |  | ||||||
|    console.log('Connection has been established successfully.'); |  | ||||||
| }).catch((error) => { |  | ||||||
|    console.error('Unable to connect to the database: ', error); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| module.exports = { sequelize }; |  | ||||||
|  |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| const { sequelize } = require("../Database/mySql.js"); |  | ||||||
| const { api_log_Model } = require("../Database/model/apiLogModel.js"); |  | ||||||
| const { sensorDataModel } = require("../Database/model/sensorDataModel.js"); |  | ||||||
| const { apikeyModel } = require("../Database/model/apiKeyModel.js"); |  | ||||||
| const { compareAPIKey } = require("./bcrypt.js"); |  | ||||||
|  |  | ||||||
| async function insertLogData(log) { |  | ||||||
| 	try { |  | ||||||
| 		api_log_Model.create({ |  | ||||||
| 			ip: log.ip, |  | ||||||
| 			time: log.time, |  | ||||||
| 			method: log.method, |  | ||||||
| 			host: log.host, |  | ||||||
| 			statusCode: log.statusCode, |  | ||||||
| 			Responsesize: log.Responsesize, |  | ||||||
| 			referrer: log.referrer, |  | ||||||
| 			userAgent: log.userAgent, |  | ||||||
| 		}); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function insertDatatoDB(data) { |  | ||||||
| 	try { |  | ||||||
| 		sensorDataModel.create({ |  | ||||||
| 			sensorid: data.sensorid, |  | ||||||
| 			locationid: data.locationid, |  | ||||||
| 			measurement: data.measurement, |  | ||||||
| 		}); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function checkAPikey(SuppliedKey, rowid) { |  | ||||||
| 	try { |  | ||||||
| 		const retrivedKey = await apikeyModel.findOne({ |  | ||||||
| 			raw: true, |  | ||||||
| 			attributes: ["apikey" , "permission"], |  | ||||||
| 			where: { |  | ||||||
| 				userid: rowid, |  | ||||||
| 			}, |  | ||||||
| 		}); |  | ||||||
| 		//console.log(retrivedKey.apikey); |  | ||||||
| 		if (compareAPIKey(SuppliedKey, retrivedKey.apikey)) { |  | ||||||
| 			//return true; |  | ||||||
|             return retrivedKey.permission; |  | ||||||
| 		} |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { insertLogData, insertDatatoDB, checkAPikey }; |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| const bcrypt = require('bcrypt'); |  | ||||||
| const saltRounds = 10; |  | ||||||
| //https://github.com/kelektiv/node.bcrypt.js#readme |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| // Load hash from your password DB. |  | ||||||
| bcrypt.compare(myPlaintextPassword, hash, function(err, result) { |  | ||||||
|     // result == true |  | ||||||
| }); |  | ||||||
| bcrypt.compare(someOtherPlaintextPassword, hash, function(err, result) { |  | ||||||
|     // result == false |  | ||||||
| }); |  | ||||||
| */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| //hash with salt |  | ||||||
| bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) { |  | ||||||
|     // Store hash in your password DB. |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| async function hashAPIKey(apikey) { |  | ||||||
|     return await bcrypt.hash(apikey, saltRounds); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function compareAPIKey(apikey, hash) { |  | ||||||
|     return await bcrypt.compare(apikey, hash); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = {  |  | ||||||
|     hashAPIKey, |  | ||||||
|     compareAPIKey |  | ||||||
| }; |  | ||||||
| @ -1,17 +0,0 @@ | |||||||
| //model for getting API key from database |  | ||||||
|  |  | ||||||
| async function getAPIKey() { |  | ||||||
|  |  | ||||||
|      |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = { getAPIKey } |  | ||||||
| @ -1,51 +0,0 @@ | |||||||
| var validator = require("validator"); |  | ||||||
|  |  | ||||||
| const dateRegex = /^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/; |  | ||||||
|  |  | ||||||
| function isValidDateString(value) { |  | ||||||
| 	return dateRegex.test(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function isAlphaNumericwithSpaces(value) { |  | ||||||
| 	return validator.isAlphanumeric(value, ["en-US"], { ignore: " " }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //allow alphanumeric and spaces and - |  | ||||||
| function isAlphaNumericWithSpacesAndDash(value) { |  | ||||||
| 	const alphanumeric = /^[a-zA-Z0-9]+$/; |  | ||||||
| 	const valid = value |  | ||||||
| 		.split("") |  | ||||||
| 		.every((char) => alphanumeric.test(char) || char === " " || char === "-"); |  | ||||||
| 	return valid; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function isMacAddress(value) { |  | ||||||
| 	//	Joi.string().regex(/^([0-9a-f]{2}-){5}([0-9a-f]{2})$/i).lowercase() |  | ||||||
| 	//return validator.isMACAddress(value, { no_separators: true, eui: 48 }); |  | ||||||
| 	const macAddress = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/; |  | ||||||
| 	const valid = macAddress.test(value); |  | ||||||
| 	return valid; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function isJson(value) { |  | ||||||
|   //check if its object |  | ||||||
|   if(typeof value === "object"){ |  | ||||||
|     return true  |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function isNumber(value) { |  | ||||||
| 	if (typeof value === "number") { |  | ||||||
| 		return true; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { |  | ||||||
| 	isValidDateString, |  | ||||||
| 	isAlphaNumericwithSpaces, |  | ||||||
| 	isAlphaNumericWithSpacesAndDash, |  | ||||||
| 	isMacAddress, |  | ||||||
| 	isJson, |  | ||||||
| 	isNumber, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| @ -1,80 +0,0 @@ | |||||||
| const express = require("express"); |  | ||||||
| const helmet = require("helmet"); |  | ||||||
| const { rateLimit } = require("express-rate-limit"); |  | ||||||
| const { APIlogger } = require('../middleware/apiLogger.js'); |  | ||||||
| const { apikeyCheck } = require('../middleware/apiKey.js'); |  | ||||||
|  |  | ||||||
| const app = express(); |  | ||||||
| app.use(helmet()); |  | ||||||
| const port = 80; |  | ||||||
|  |  | ||||||
| //express-rate-limit stolen from docs |  | ||||||
| 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 |  | ||||||
| 	legacyHeaders: false, // Disable the `X-RateLimit-*` headers. |  | ||||||
| }) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // Apply the rate limiting middleware to all requests. |  | ||||||
| app.use(limiter) |  | ||||||
|  |  | ||||||
| //disable x-powered-by header for security reasons |  | ||||||
| app.disable("x-powered-by"); |  | ||||||
|  |  | ||||||
| //parse json body format  |  | ||||||
| app.use(express.json()); |  | ||||||
| app.set("json spaces", 2); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| middleware logic ( called by next() ) |  | ||||||
| */ |  | ||||||
| app.use("/api/seed/v0", [ apikeyCheck , APIlogger] ,require("../routes/seed_route.js")); |  | ||||||
| app.use('/api/v0', [apikeyCheck, APIlogger] ,require("../routes/api_route.js"));  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // 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) { |  | ||||||
| 	var err = new Error("Not Found"); |  | ||||||
| 	err.message = "Page not found"; |  | ||||||
| 	err.status = 404; |  | ||||||
| 	next(err); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // 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){ |  | ||||||
| 		for(let item of err.errors){ |  | ||||||
| 			if(item.path){ |  | ||||||
| 				keyErrors[item.path] = item.message |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|    |  | ||||||
| 	res.status(err.status || 500); |  | ||||||
| 	console.log(keyErrors); |  | ||||||
| 	res.json({ |  | ||||||
| 	  name: err.name, |  | ||||||
| 	  message: err.message, |  | ||||||
| 	  keyErrors, |  | ||||||
| 	}); |  | ||||||
|   }); |  | ||||||
| app.listen(port, () => { |  | ||||||
| 	console.log(`app listening on port ${port}`); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| module.exports = { app }; |  | ||||||
| @ -1,77 +0,0 @@ | |||||||
| const { |  | ||||||
|  |  | ||||||
| } = require("../functions/apiDatabase.js"); |  | ||||||
|  |  | ||||||
| const express = require("express"); |  | ||||||
| const router = express.Router(); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = router; |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  |  | ||||||
| //get location |  | ||||||
| router.get("/", async (req, res, next) => { |  | ||||||
| 	try { |  | ||||||
| 		const location = await getLocation(); |  | ||||||
| 		//res send json and status code |  | ||||||
| 		res.status(200).json(location); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 		next(error); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //add location  |  | ||||||
| router.post("/new", async (req, res, next) => { |  | ||||||
| 	try { |  | ||||||
| 		const { name, added_by, description } = req.body; |  | ||||||
| 		await addLocation(name, added_by, description); |  | ||||||
| 		res.sendStatus(200) |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 		next(error); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| //update location |  | ||||||
| router.put("/update", async (req, res, next) => { |  | ||||||
| 	try { |  | ||||||
| 		const { id, name, added_by, description } = req.body; |  | ||||||
| 		await updateLocation(id, name, added_by, description); |  | ||||||
| 		res.status(200).json({ message: "Location " + id + " updated"  }); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 		next(error); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| //delete location |  | ||||||
| router.delete("/delete", async (req, res, next) => { |  | ||||||
| 	try { |  | ||||||
| 		const { id } = req.body; |  | ||||||
| 		await deleteLocation(id); |  | ||||||
| 		res.status(200).json({ message: "Location " + id + " deleted" }); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 		next(error); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //get location by id |  | ||||||
| router.get("/:id", async (req, res, next) => { |  | ||||||
| 	try { |  | ||||||
| 		//get params |  | ||||||
| 		const { id } = req.params; |  | ||||||
| 		const location = await getLocationById(id); |  | ||||||
| 		res.status(200).json(location); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		console.error(error); |  | ||||||
| 		next(error); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| */ |  | ||||||
| @ -1,37 +0,0 @@ | |||||||
| /* |  | ||||||
| 'use strict'; |  | ||||||
|  |  | ||||||
| const router = require('express').Router(); |  | ||||||
| const middleware = require('../middleware/auth'); |  | ||||||
|  |  | ||||||
| router.use('/runner', require('./runner')); |  | ||||||
| router.use('/worker', require('./worker')); |  | ||||||
| router.use('/auth', require('./auth')); |  | ||||||
| router.use('/user', middleware.auth, require('./user')); |  | ||||||
| router.use('/token',middleware.auth, require('./token')); |  | ||||||
|  |  | ||||||
| module.exports = router; |  | ||||||
|  |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| 'use strict'; |  | ||||||
| const router = require('express').Router(); |  | ||||||
|  |  | ||||||
| //location route |  | ||||||
| router.use('/location', require('./location')); |  | ||||||
|  |  | ||||||
| //sensor route |  | ||||||
| router.use('/sensor', require('./sensor')) |  | ||||||
|  |  | ||||||
| //sensor data route |  | ||||||
| router.use('/sensor-data', require('./sensorData')); |  | ||||||
|  |  | ||||||
| //log route |  | ||||||
| //router.use('/log', require('./logLog')); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = router; |  | ||||||
| @ -1,14 +0,0 @@ | |||||||
| 'use strict'; |  | ||||||
| const router = require('express').Router(); |  | ||||||
|  |  | ||||||
| //location route |  | ||||||
| router.use('/seedSensorData', require('./seedSensorData.js')); |  | ||||||
|  |  | ||||||
| router.use('/seed', require('./seedLocationAndSensor')); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = router; |  | ||||||
		Reference in New Issue
	
	Block a user