Merge branch 'main' into sensor
This commit is contained in:
		| @ -1,7 +1,6 @@ | ||||
| "use strict"; | ||||
| const { Sequelize, DataTypes } = require("sequelize"); | ||||
| const { sequelize } = require("./mySQL"); | ||||
| const { isAlphaNumericwithSpaces } = require('../../Web-Server/functions/validateData') | ||||
|  | ||||
| //sequelize.sync(); | ||||
| const locationModel = sequelize.define( | ||||
|  | ||||
| @ -2,11 +2,7 @@ | ||||
| const { Sequelize, DataTypes } = require("sequelize"); | ||||
| const { sequelize } = require("./mySQL"); | ||||
| const { locationModel } = require("./locationModel"); | ||||
| const { | ||||
| 	isAlphaNumericwithSpaces, | ||||
| 	isAlphaNumericWithSpacesAndDash, | ||||
| 	isMacAddress, | ||||
| } = require("../../Web-Server/functions/validateData"); | ||||
|  | ||||
|  | ||||
| //sequelize.sync(); | ||||
| const sensorModel = sequelize.define( | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| const { locationModel } = require("../Database/locationModel"); | ||||
| const { sensorModel } = require("../Database/sensorModel"); | ||||
| const { locationModel } = require("../database/locationModel"); | ||||
| const { sensorModel } = require("../database/sensorModel"); | ||||
|  | ||||
| async function getLocation() { | ||||
| 	const location = locationModel.findAll({ | ||||
|  | ||||
| @ -27,9 +27,9 @@ client.on("error", (err) => { | ||||
| }); | ||||
|  | ||||
| //every 15 minutes | ||||
| setInterval(publishData, 900000); | ||||
| //setInterval(publishData, 900000); | ||||
| //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 | ||||
| 2) Sean | ||||
| * 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 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 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 { rateLimit } = require("express-rate-limit"); | ||||
| const path = require("path"); | ||||
| const app = express(); | ||||
| const port = 3000; | ||||
| const ejs = require("ejs"); | ||||
| 
 | ||||
| module.exports = app; | ||||
| 
 | ||||
| process.nextTick(() => require('./mqttApp')); | ||||
| 
 | ||||
| app.use(express.json()); | ||||
| 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.
 | ||||
| app.set("views", path.join(__dirname, "../views")); | ||||
| app.set("views", path.join(__dirname, "./views")); | ||||
| app.set("view engine", "ejs"); | ||||
| 
 | ||||
| // Have express server static content( images, CSS, browser JS) from the public
 | ||||
| app.use(express.static(path.join(__dirname, "../public"))); | ||||
| 
 | ||||
| //middleware logic ( called by next() )
 | ||||
| const auth = require("../middleware/authChecker");  | ||||
| app.use(express.static(path.join(__dirname, "./public"))); | ||||
| 
 | ||||
| 
 | ||||
| //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
 | ||||
| app.use("/", require("../routes/render")); | ||||
| app.use("/", require("./routes/render")); | ||||
| 
 | ||||
| // Catch 404 and forward to error handler. If none of the above routes are
 | ||||
| // used, this is what will be called.
 | ||||
| @ -69,8 +88,4 @@ app.use(function (err, req, res, next) { | ||||
| 		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; | ||||
| //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 | ||||
| async function hashPassword(password) { | ||||
| async function hash(password) { | ||||
|     return await bcrypt.hash(password, saltRounds); | ||||
| } | ||||
|  | ||||
| async function hashAPIKey(apikey) { | ||||
|     return await bcrypt.hash(apikey, saltRounds); | ||||
| } | ||||
|  | ||||
| //can be used to compare password or token | ||||
| async function comparePassword(password, hash) { | ||||
| async function compareHash(password, hash) { | ||||
|     return await bcrypt.compare(password, hash); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| module.exports = {  | ||||
|     hashPassword, | ||||
|     hashAPIKey, | ||||
|     comparePassword | ||||
|     hash, | ||||
|     compareHash | ||||
| }; | ||||
							
								
								
									
										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 { 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
 | ||||
| //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; | ||||
| } | ||||
| 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() { | ||||
| 	const sensorData = await sensorDataModel.findAll(); | ||||
| 	return sensorData; | ||||
| } | ||||
| 
 | ||||
| async function addSensorData(id, id_sensor, id_location, sensordata) { | ||||
| async function addSensorData(id_sensor, id_location, sensordata) { | ||||
| 	const sensorData = await sensorDataModel.create({ | ||||
| 		id: id, | ||||
| 		sensorid: id_sensor, | ||||
| 		locationid: id_location, | ||||
| 		measurement: sensordata, | ||||
| 	}); | ||||
| 	io().emit('sensorData:new', sensorData) | ||||
| 
 | ||||
| 	return sensorData; | ||||
| } | ||||
| 
 | ||||
| async function updateSensorData(id, id_sensor, id_location, sensordata) { | ||||
| @ -826,16 +717,6 @@ async function getDatabyRange(queryString) { | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	getLocation, | ||||
| 	addLocation, | ||||
| 	updateLocation, | ||||
| 	deleteLocation, | ||||
| 	getLocationById, | ||||
| 	getSensor, | ||||
| 	addSensor, | ||||
| 	updateSensor, | ||||
| 	deleteSensor, | ||||
| 	getSensorById, | ||||
| 	getSensorData, | ||||
| 	addSensorData, | ||||
| 	updateSensorData, | ||||
| @ -843,4 +724,5 @@ module.exports = { | ||||
| 	getSensorDataById, | ||||
| 	getData, | ||||
| 	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"); | ||||
|  | ||||
| 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) { | ||||
| 	return validator.isAlphanumeric(value, ["en-US"], { ignore: " " }); | ||||
| } | ||||
| @ -16,7 +38,6 @@ function isAlphaNumericWithSpacesAndDash(value) { | ||||
| function isJson(value) { | ||||
|   //check if its object | ||||
|   if(typeof value === "object"){ | ||||
|     console.log("its an object") | ||||
|     return true  | ||||
|   } | ||||
|  | ||||
| @ -44,6 +65,8 @@ module.exports = { | ||||
| 	isAlphaNumericwithSpaces, | ||||
| 	isAlphaNumericWithSpacesAndDash, | ||||
| 	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) { | ||||
| 	//const authHeader = req.headers.authorization
 | ||||
| 	try { | ||||
| @ -1,4 +1,4 @@ | ||||
| const { insertLogData } = require("../functions/database.js"); | ||||
| const { insertLogData } = require("../functions/logger.js"); | ||||
| const APIlogger = (req, res, next) => { | ||||
|   try { | ||||
|     const log = { | ||||
| @ -1,6 +1,6 @@ | ||||
| const { apikeyModel } = require("../database/model/apiKeyModel"); | ||||
| const { userModel } = require("../database/model/userModel"); | ||||
| const { comparePassword } = require("../functions/bcrypt"); | ||||
| const { compareHash } = require("../functions/bcrypt"); | ||||
|  | ||||
| async function auth(req, res, next){ | ||||
|     try{  | ||||
| @ -12,15 +12,16 @@ async function auth(req, res, next){ | ||||
|  | ||||
|         //get from db | ||||
|         let token = await apikeyModel.findByPk(rowid, {include: userModel}); | ||||
|         if (!token) return false; | ||||
|  | ||||
|         //compare | ||||
|         let isMatch = await comparePassword(suppliedToken, token.apikey); | ||||
|         let isMatch = await compareHash(suppliedToken, token.apikey); | ||||
|         if (!isMatch) return false; | ||||
|  | ||||
|         //else do logic | ||||
|         //pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT) | ||||
|         req.token = token | ||||
|         req.user = await token.getUser(); | ||||
|         req.user = await token.getUser(); //taking user seq obj from usermodel | ||||
|         next(); | ||||
|     }catch(error){ | ||||
|         next(error); | ||||
|  | ||||
| @ -10,13 +10,11 @@ const options = { | ||||
|   username: process.env.MQTT_USER,  | ||||
|   password: process.env.MQTT_PASS,  | ||||
|   protocol: 'mqtts', // Use MQTT over TLS
 | ||||
|   key: fs.readFileSync(path.resolve(__dirname, '../../cert/privkey.pem')),  | ||||
|   cert: fs.readFileSync(path.resolve(__dirname, '../../cert/cert.pem')),  | ||||
|   key: fs.readFileSync(path.resolve(__dirname, '../cert/privkey.pem')),  | ||||
|   cert: fs.readFileSync(path.resolve(__dirname, '../cert/cert.pem')),  | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| const client = mqtt.connect(brokerUrl, options); | ||||
| 
 | ||||
| module.exports = client; | ||||
| 
 | ||||
| 
 | ||||
| @ -1,7 +1,6 @@ | ||||
| const { app } = require("./modules/express.js"); | ||||
| const client = require("./modules/mqtt"); | ||||
| const client = require("./modules/mqtt.js"); | ||||
| const { isJson, isNumber } = require("./functions/validateData.js"); | ||||
| const { insertDatatoDB } = require("./functions/database.js"); | ||||
| const { addSensorData } = require("./functions/sensorData"); | ||||
| 
 | ||||
| // Event handlers
 | ||||
| client.on("connect", () => { | ||||
| @ -38,7 +37,7 @@ client.on("message", (topic, message) => { | ||||
| 				if (isNumber(data)) { | ||||
| 					{ | ||||
| 						//pass datas to database
 | ||||
| 						insertDatatoDB(datas[key]); | ||||
| 						addSensorData(datas[key].sensorid, datas[key].locationid, datas[key]); | ||||
| 
 | ||||
| 					} | ||||
| 				} else { | ||||
| @ -64,3 +63,4 @@ client.on("end", () => { | ||||
| 	console.log("Disconnected from MQTT broker"); | ||||
| 	client.reconnect(); | ||||
| }); | ||||
| 
 | ||||
| @ -3813,3 +3813,12 @@ | ||||
| .card-text { | ||||
|     color: #000000; | ||||
| } | ||||
|  | ||||
| /* edit profile */ | ||||
| .profile { | ||||
|   margin: auto; | ||||
|   width: 40%; | ||||
|   border: 1px solid #000000; | ||||
|   padding: 10px; | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -524,3 +524,26 @@ body.one-content-column-version .content thead { | ||||
| .cf:before, .cf:after { content: ""; display: block; } | ||||
| .cf:after { clear: both; } | ||||
| .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 { | ||||
|     background-color: #fff; | ||||
|     padding: 20px; | ||||
|     padding: 25px; | ||||
|     border-radius: 8px; | ||||
|     box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | ||||
|     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 }; | ||||
| })(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) { | ||||
| 	var user = {}; | ||||
| 	function setToken(token) { | ||||
| @ -154,12 +182,22 @@ app.auth = (function (app) { | ||||
| 		return localStorage.getItem("APIToken"); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	function isLoggedIn(callback) { | ||||
| 		if (getToken()) { | ||||
| 			return app.api.get("user/me", function (error, 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); | ||||
| 			}); | ||||
| 		} 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) { | ||||
| 		//call logout route | ||||
| 		$.ajax({ | ||||
| @ -217,19 +245,13 @@ app.auth = (function (app) { | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 	function profileRedirect() { | ||||
| 		location.replace(`/profile`); | ||||
| 	} | ||||
| 		logInRedirect(); | ||||
|  | ||||
| 	} | ||||
| 	*/ | ||||
|  | ||||
|  | ||||
|  | ||||
| 	return { | ||||
| 		getToken: getToken, | ||||
| @ -239,8 +261,25 @@ app.auth = (function (app) { | ||||
| 		forceLogin, | ||||
| 		logInRedirect, | ||||
| 		homeRedirect, | ||||
| 		showUser, | ||||
| 		//redirectIfLoggedIn, | ||||
| 		profileRedirect, | ||||
| 	}; | ||||
| })(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); | ||||
|  | ||||
| @ -251,11 +290,6 @@ function formAJAX(btn, del) { | ||||
| 	var formData = $form.find("[name]").serializeObject(); // builds query formDataing | ||||
| 	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"); | ||||
|  | ||||
| 	//console.log('Data being sent to', $form.attr('action'), formData) | ||||
|  | ||||
| @ -5,10 +5,17 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
| const aqi = "15"; | ||||
| const temperature = "25°C"; | ||||
| 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> | ||||
| @ -21,9 +28,34 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|             <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> | ||||
| `; | ||||
|  | ||||
|  | ||||
|         // Remove the 'active' class from all info-box elements | ||||
|         const infoBoxes = document.querySelectorAll('.info-box'); | ||||
|         infoBoxes.forEach(box => box.classList.remove('active')); | ||||
|  | ||||
| @ -1,6 +1,34 @@ | ||||
| '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'; | ||||
| const router = require('express').Router(); | ||||
| const { auth }   = require("../middleware/authChecker") | ||||
|  | ||||
|  | ||||
| router.use('/auth', require('./auth')); | ||||
| @ -12,3 +40,4 @@ router.use('/user', auth ,require('./user')); | ||||
| module.exports = router; | ||||
|  | ||||
|  | ||||
| */ | ||||
| @ -1,19 +1,9 @@ | ||||
| const { getAPIKey , addAPIKey } = require("../functions/apiDatabase.js"); | ||||
| const { addAPIKey } = require("../functions/api"); | ||||
|  | ||||
|  | ||||
| const express = require("express"); | ||||
| 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) | ||||
| 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; | ||||
|  | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| const { addUser, loginUser } = require("../functions/apiDatabase.js"); | ||||
| const { addUser, loginUser } = require("../functions/user"); | ||||
|  | ||||
| const express = require("express"); | ||||
| const router = express.Router(); | ||||
|  | ||||
| @ -4,7 +4,7 @@ const { | ||||
| 	getLocationById, | ||||
| 	updateLocation, | ||||
| 	deleteLocation, | ||||
| } = require("../functions/apiDatabase.js"); | ||||
| } = require("../functions/location"); | ||||
| 
 | ||||
| const express = require("express"); | ||||
| 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"; | ||||
|  | ||||
| var router = require("express").Router(); | ||||
| @ -66,11 +27,17 @@ router.get("/profile", function (req, res, next) { | ||||
| 	res.render("profile"); | ||||
| }); | ||||
|  | ||||
|  | ||||
| //forgot password page | ||||
| router.get("/forgotpassword", function (req, res, next) { | ||||
| 	res.render("forgotpassword"); | ||||
| }); | ||||
|  | ||||
| //resetted password page | ||||
| router.get("/resetpassword", function (req, res, next) { | ||||
| 	res.render("resetpassword"); | ||||
| }); | ||||
|  | ||||
| //contact page | ||||
| router.get("/contact", function (req, res, next) { | ||||
| 	res.render("contact"); | ||||
| @ -81,6 +48,9 @@ router.get("/api", function (req, res, next) { | ||||
| 	res.render("api"); | ||||
| }); | ||||
|  | ||||
|  | ||||
| // sensor data | ||||
| router.get("/sensor-data", function (req, res, next) { | ||||
| 	res.render("sensor-data"); | ||||
| }); | ||||
|  | ||||
| module.exports = router; | ||||
| @ -1,6 +1,6 @@ | ||||
| const { sequelize } = require("../Database/mySql.js"); | ||||
| const { locationModel } = require("../Database/model/locationModel.js"); | ||||
| const { sensorModel } = require("../Database/model/sensorModel.js"); | ||||
| const { sequelize } = require("../database/mySQL.js"); | ||||
| const { locationModel } = require("../database/model/locationModel.js"); | ||||
| const { sensorModel } = require("../database/model/sensorModel.js"); | ||||
| 
 | ||||
| const express = require("express"); | ||||
| const router = express.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 { locationModel } = require("../Database/model/locationModel.js"); | ||||
| const { sensorModel } = require("../Database/model/sensorModel.js"); | ||||
| const { sensorDataModel } = require("../Database/model/sensorDataModel.js"); | ||||
| 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 express = require("express"); | ||||
| const router = express.Router(); | ||||
| @ -4,7 +4,7 @@ const { | ||||
| 	updateSensor, | ||||
|     deleteSensor, | ||||
|     getSensorById | ||||
| } = require("../functions/apiDatabase.js"); | ||||
| } = require("../functions/sensor.js"); | ||||
| 
 | ||||
| const express = require("express"); | ||||
| const router = express.Router(); | ||||
| @ -6,10 +6,9 @@ const { | ||||
| 	getSensorDataById, | ||||
| 	getData, | ||||
| 	getDatabyRange, | ||||
| } = require("../functions/apiDatabase.js"); | ||||
| } = require("../functions/sensorData"); | ||||
| 
 | ||||
| const express = require("express"); | ||||
| const { json } = require("body-parser"); | ||||
| const router = express.Router(); | ||||
| 
 | ||||
| router.get("/", async (req, res, next) => { | ||||
| @ -24,9 +23,9 @@ router.get("/", async (req, res, next) => { | ||||
| 
 | ||||
| router.post("/new", async (req, res, next) => { | ||||
| 	try { | ||||
| 		const { id, id_sensor, id_location, sensordata } = req.body; | ||||
| 		await addSensorData(id, id_sensor, id_location, sensordata); | ||||
| 		res.sendStatus(200).json({ message: "SensorData " + id + " added" }); | ||||
| 		const { id_sensor, id_location, sensordata } = req.body; | ||||
| 		let data = await addSensorData(id_sensor, id_location, sensordata); | ||||
| 		res.json({ message: "SensorData " + data.id + " added", ...data }); | ||||
| 	} catch (error) { | ||||
| 		console.error(error); | ||||
| 		next(error); | ||||
| @ -91,4 +90,3 @@ router.get("/:id", async (req, res, next) => { | ||||
| }); | ||||
| 
 | ||||
| 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 router = express.Router(); | ||||
| @ -16,15 +16,13 @@ router.get("/me", async function (req, res, next) { | ||||
| 		res.json({ | ||||
| 			user: user, | ||||
| 		}); | ||||
|  | ||||
| 	} catch (error) { | ||||
| 		next(error); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
|  | ||||
| //logout | ||||
| router.delete('/logout', async function(req, res, next){ | ||||
| router.delete("/logout", async function (req, res, next) { | ||||
| 	try { | ||||
| 		/* | ||||
|         let authToken = req.header('auth-token'); | ||||
| @ -42,16 +40,44 @@ router.delete('/logout', async function(req, res, next){ | ||||
| 		res.json({ | ||||
| 			message: "User logged out successfully", | ||||
| 		}); | ||||
|  | ||||
| 	} catch (error) { | ||||
| 		next(error); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| //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 | ||||
| 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; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
|  !--> | ||||
|  | ||||
| <%- include('top') %> | ||||
|     <link rel="stylesheet" href="css/api.css" media="all"> | ||||
|  | ||||
|     <body class="one-content-column-version"> | ||||
|         <div class="left-menu"> | ||||
| @ -38,8 +39,8 @@ | ||||
|                     <li class="scroll-to-link active" data-target="content-get-started"> | ||||
|                         <a>GET STARTED</a> | ||||
|                     </li> | ||||
|                     <li class="scroll-to-link" data-target="content-get-characters"> | ||||
|                         <a>Get Data From API</a> | ||||
|                     <li class="scroll-to-link" data-target="content-get-api"> | ||||
|                         <a>Generate API</a> | ||||
|                     </li> | ||||
|                     <li class="scroll-to-link" data-target="content-errors"> | ||||
|                         <a>Errors</a> | ||||
| @ -86,7 +87,8 @@ | ||||
|                                 <td>Authorization</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -118,7 +120,8 @@ | ||||
|                                 <td>Authorization</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -133,7 +136,8 @@ | ||||
|                         <br> | ||||
|                         <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> | ||||
|                         Return Response :<br> | ||||
| @ -154,7 +158,8 @@ | ||||
|                                 <td>Authorization</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -162,7 +167,8 @@ | ||||
|                                 <td>Location name</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -170,7 +176,8 @@ | ||||
|                                 <td>Added by </td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -178,7 +185,8 @@ | ||||
|                                 <td>Description</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -194,7 +202,8 @@ | ||||
|                         <br> | ||||
|                         <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> | ||||
|                         Return Response :<br> | ||||
| @ -215,7 +224,8 @@ | ||||
|                                 <td>Authorization</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -223,7 +233,8 @@ | ||||
|                                 <td>ID</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -231,7 +242,8 @@ | ||||
|                                 <td>Location name</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -239,7 +251,8 @@ | ||||
|                                 <td>Added by </td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -247,7 +260,8 @@ | ||||
|                                 <td>Description</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -263,7 +277,8 @@ | ||||
|                         <br> | ||||
|                         <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> | ||||
|                     <br> | ||||
|                     <h4>QUERY PARAMETERS</h4> | ||||
| @ -280,7 +295,8 @@ | ||||
|                                 <td>Authorization</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -288,7 +304,8 @@ | ||||
|                                 <td>ID</td> | ||||
|                                 <td>JSON</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> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
| @ -296,24 +313,6 @@ | ||||
|                     </table> | ||||
|                 </div> | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|                 <div class="overflow-hidden content-section" id="content-errors"> | ||||
|                     <h2>Errors</h2> | ||||
|                     <p> | ||||
| @ -359,9 +358,41 @@ | ||||
|                         </tbody> | ||||
|                     </table> | ||||
|                 </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> | ||||
|  | ||||
|     </body> | ||||
|  | ||||
|     <script src="js/api.js"></script> | ||||
|     </html> | ||||
| @ -81,12 +81,7 @@ | ||||
|       </p> | ||||
|    </div> | ||||
| </footer> | ||||
|  | ||||
| <script src="js/learnmore.js"></script> | ||||
| <script src="js/search.js"></script> | ||||
| <script src="js/api.js"></script> | ||||
|  | ||||
|  | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
| @ -1,4 +1,5 @@ | ||||
| <%- include('top') %> | ||||
| <link href="css/contact.css" rel="stylesheet" /> | ||||
|  | ||||
|   <!-- full Title --> | ||||
|   <div class="full-title"> | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
|     <section class="wrapper"> | ||||
|         <div class="form"> | ||||
|             <header>Reset Password</header> | ||||
|             <form action="resetpassword.html"> | ||||
|             <form action="/resetpassword"> | ||||
|                 <input type="text" id="email" placeholder="Email" required /> | ||||
|                 <input type="password" id="password" placeholder="Password" required /> | ||||
|                 <input type="password" id="confirmPassword" placeholder="Confirm Password" required /> | ||||
|  | ||||
| @ -1,5 +1,12 @@ | ||||
| <%- 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"> | ||||
| @ -50,18 +57,7 @@ | ||||
|           <h1 class="my-4">Services</h1> | ||||
|           <!-- Services Section --> | ||||
|           <div class="row"> | ||||
|             <div class="col-lg-4 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 class="col-lg-4 mb-4"> | ||||
|               <div class="col-lg-3 mb-4"> | ||||
|                   <div class="card"> | ||||
|                       <h4 class="card-header">Air Quality Index</h4> | ||||
|                       <div class="card-body text-center"> | ||||
| @ -72,7 +68,18 @@ | ||||
|                       </div> | ||||
|                   </div> | ||||
|               </div> | ||||
|             <div class="col-lg-4 mb-4"> | ||||
|               <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 class="col-lg-3 mb-4"> | ||||
|                   <div class="card"> | ||||
|                       <h4 class="card-header">Temperature</h4> | ||||
|                       <div class="card-body text-center"> | ||||
| @ -83,7 +90,19 @@ | ||||
|                       </div> | ||||
|                   </div> | ||||
|               </div> | ||||
|               <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> | ||||
|    | ||||
|          <!-- /.row --> | ||||
|       </div> | ||||
|       <!-- About Section --> | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| <%- include('top') %> | ||||
| <link href="css/learnmore.css" rel="stylesheet" /> | ||||
|  | ||||
| <br> | ||||
| <br> | ||||
| @ -37,5 +38,7 @@ | ||||
|  | ||||
| <br> | ||||
| <br> | ||||
| <script src="js/learnmore.js"></script> | ||||
|  | ||||
|  | ||||
| <%- include('bot') %> | ||||
| @ -6,7 +6,7 @@ | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||||
|     <meta name="description" content=""> | ||||
|     <meta name="author" content=""> | ||||
|  | ||||
|     <link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" /> | ||||
|     <!-- Bootstrap core CSS --> | ||||
|     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" | ||||
|         integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> | ||||
| @ -26,6 +26,8 @@ | ||||
|     <!-- 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.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 --> | ||||
|     <script src="js/app.js"></script> | ||||
|  | ||||
| @ -1,64 +1,111 @@ | ||||
| <%- include('top') %> | ||||
| <script type="text/javascript"> | ||||
| 	// Require login to see this page. | ||||
| 	app.auth.forceLogin() | ||||
|     <br> | ||||
|     <br> | ||||
|     <br> | ||||
|     <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> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <br> | ||||
|                 <div class="row justify-content-center mt-3"> | ||||
|                     <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; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|     </script> | ||||
|  | ||||
| 	<div class="full-title"> | ||||
| 		<div class="container"> | ||||
| 			<h1 class="mt-4 mb-3">Profile | ||||
| 			</h1> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | ||||
| 	<br> | ||||
| 	<br> | ||||
|  | ||||
| 	<div class="centered-content"> | ||||
| 		<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') %> | ||||
|  | ||||
| 	 | ||||
|  | ||||
							
								
								
									
										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 card" --> | ||||
|                 <header>Signup</header> | ||||
|                 <div class="card-header shadow actionMessage" style="display:none"></div> | ||||
|                 <!-- localhost/api/v0/user/register --> | ||||
|                 <!-- evalAjax Fires when status 200 is returned  --> | ||||
|                 <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(); | ||||
|                 app.auth.setToken(data.token);"> | ||||
|                     <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 /> | ||||
|                     <a href="/forgotpassword">Forgot password?</a> | ||||
|                     <input type="submit" value="Login" /> | ||||
|  | ||||
| @ -1,29 +1,24 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
|  | ||||
| <head> | ||||
| 	<meta charset="utf-8" /> | ||||
| 		<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="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" /> | ||||
| 	<link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" /> | ||||
|  | ||||
|  | ||||
| 	<!-- Bootstrap core CSS --> | ||||
| 		<link | ||||
| 			href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" | ||||
| 			rel="stylesheet" | ||||
| 			integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" | ||||
| 			crossorigin="anonymous" /> | ||||
| 	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" | ||||
| 		integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" /> | ||||
|  | ||||
| 	<!-- 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 /> | ||||
| @ -34,10 +29,8 @@ | ||||
| 	<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" | ||||
| 	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" | ||||
| 		integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" | ||||
| 		crossorigin="anonymous"></script> | ||||
|  | ||||
| @ -47,6 +40,9 @@ | ||||
| 	<script> | ||||
| 		hljs.initHighlightingOnLoad(); | ||||
| 	</script> | ||||
| 	<!-- socket.io scriot --> | ||||
| 	<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script> | ||||
|  | ||||
|  | ||||
| 	<!-- jq-repeat --> | ||||
| 	<script src="js/jq-repeat.js"></script> | ||||
| @ -61,8 +57,8 @@ | ||||
| 		//check if user is logged in | ||||
| 		app.auth.isLoggedIn(function (error, data) { | ||||
| 			if (data) { | ||||
|                     app.auth.showUser(); | ||||
| 				$("#cl-logout-button").show("fast"); | ||||
| 				$("#cl-api-button").show("fast"); | ||||
| 				$("#cl-profile-button").show("fast"); | ||||
| 				$("#cl-login-button").hide("fast"); | ||||
| 			} else { | ||||
| @ -75,20 +71,13 @@ | ||||
| </script> | ||||
|  | ||||
| <body> | ||||
| 		<nav | ||||
| 			class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top"> | ||||
| 	<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"> | ||||
| 			<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"> | ||||
| @ -105,36 +94,33 @@ | ||||
| 					<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" | ||||
| 						<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"> | ||||
| 						<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"> | ||||
| 						<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> | ||||
| @ -142,5 +128,3 @@ | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</nav> | ||||
| 	</body> | ||||
| </html> | ||||
|  | ||||
| @ -21,6 +21,7 @@ | ||||
|     "bcrypt": "^5.1.1", | ||||
|     "body-parser": "^1.20.2", | ||||
|     "cookie-parser": "^1.4.6", | ||||
|     "cors": "^2.8.5", | ||||
|     "csurf": "^1.11.0", | ||||
|     "date-fns": "^3.2.0", | ||||
|     "date-fns-tz": "^2.0.0", | ||||
| @ -43,6 +44,8 @@ | ||||
|     "sanitize-html": "^2.11.0", | ||||
|     "sequelize": "^6.35.2", | ||||
|     "sequelize-cli": "^6.6.2", | ||||
|     "socket.io": "^4.7.4", | ||||
|     "socket.io-client": "^4.7.4", | ||||
|     "validator": "^13.11.0" | ||||
|   }, | ||||
|   "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