diff --git a/IoT-sensor/Database/locationModel.js b/IoT-sensor/Database/locationModel.js index 9163156..7bd55d2 100644 --- a/IoT-sensor/Database/locationModel.js +++ b/IoT-sensor/Database/locationModel.js @@ -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( diff --git a/IoT-sensor/Database/sensorModel.js b/IoT-sensor/Database/sensorModel.js index bed1d9b..1de32af 100644 --- a/IoT-sensor/Database/sensorModel.js +++ b/IoT-sensor/Database/sensorModel.js @@ -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( diff --git a/IoT-sensor/functions/dbFunctions.js b/IoT-sensor/functions/dbFunctions.js index f03c5a9..83993ec 100644 --- a/IoT-sensor/functions/dbFunctions.js +++ b/IoT-sensor/functions/dbFunctions.js @@ -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({ diff --git a/IoT-sensor/index.js b/IoT-sensor/index.js index 728cb30..a5cfb75 100644 --- a/IoT-sensor/index.js +++ b/IoT-sensor/index.js @@ -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); diff --git a/api.MD b/api.MD index b655bed..de38469 100644 --- a/api.MD +++ b/api.MD @@ -174,4 +174,4 @@ http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&p curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}' -curl localhost/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"}' diff --git a/consumerWebsite/modules/app.js b/consumerWebsite/app.js similarity index 60% rename from consumerWebsite/modules/app.js rename to consumerWebsite/app.js index 3b3d8ba..dc3c301 100644 --- a/consumerWebsite/modules/app.js +++ b/consumerWebsite/app.js @@ -1,29 +1,46 @@ 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; 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 +86,4 @@ app.use(function (err, req, res, next) { keyErrors, }); }); -app.listen(port, () => { - console.log(`app listening on port ${port}`); -}); -module.exports = { app }; diff --git a/consumerWebsite/bin/www b/consumerWebsite/bin/www new file mode 100644 index 0000000..ae5fa70 --- /dev/null +++ b/consumerWebsite/bin/www @@ -0,0 +1,102 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +const app = require('../app'); +const mqttApp = require('../mqttApp'); +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() + } +} \ No newline at end of file diff --git a/webserver/database/model/apiLogModel.js b/consumerWebsite/database/model/apiLogModel.js similarity index 100% rename from webserver/database/model/apiLogModel.js rename to consumerWebsite/database/model/apiLogModel.js diff --git a/webserver/database/model/locationModel.js b/consumerWebsite/database/model/locationModel.js similarity index 100% rename from webserver/database/model/locationModel.js rename to consumerWebsite/database/model/locationModel.js diff --git a/webserver/database/model/sensorDataModel.js b/consumerWebsite/database/model/sensorDataModel.js similarity index 100% rename from webserver/database/model/sensorDataModel.js rename to consumerWebsite/database/model/sensorDataModel.js diff --git a/webserver/database/model/sensorModel.js b/consumerWebsite/database/model/sensorModel.js similarity index 100% rename from webserver/database/model/sensorModel.js rename to consumerWebsite/database/model/sensorModel.js diff --git a/consumerWebsite/functions/api.js b/consumerWebsite/functions/api.js new file mode 100644 index 0000000..bbdbbe0 --- /dev/null +++ b/consumerWebsite/functions/api.js @@ -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 }; \ No newline at end of file diff --git a/consumerWebsite/functions/bcrypt.js b/consumerWebsite/functions/bcrypt.js index f0b72a3..8a6bc7a 100644 --- a/consumerWebsite/functions/bcrypt.js +++ b/consumerWebsite/functions/bcrypt.js @@ -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 }; \ No newline at end of file diff --git a/consumerWebsite/functions/location.js b/consumerWebsite/functions/location.js new file mode 100644 index 0000000..97fc0c4 --- /dev/null +++ b/consumerWebsite/functions/location.js @@ -0,0 +1,56 @@ +const {locationModel} = require("../database/model/locationModel"); + +async function getLocation() { + const location = await locationModel.findAll(); + return location; +} + +async function addLocation(name, added_by, description) { + console.log(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; +} + +module.exports = { + getLocation, + addLocation, + updateLocation, + deleteLocation, + getLocationById, +}; \ No newline at end of file diff --git a/consumerWebsite/functions/logger.js b/consumerWebsite/functions/logger.js new file mode 100644 index 0000000..57a9c24 --- /dev/null +++ b/consumerWebsite/functions/logger.js @@ -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, +}; \ No newline at end of file diff --git a/consumerWebsite/functions/sensor.js b/consumerWebsite/functions/sensor.js new file mode 100644 index 0000000..66994eb --- /dev/null +++ b/consumerWebsite/functions/sensor.js @@ -0,0 +1,75 @@ +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({ + where: { + id: id, + }, + }); + + console.error(error); +} + +async function getSensorById(id) { + const sensor = await sensorModel.findAll({ + where: { + id: id, + }, + }); + return sensor; +} + +module.exports = { + getSensor, + addSensor, + updateSensor, + deleteSensor, + getSensorById, +}; \ No newline at end of file diff --git a/webserver/functions/APIDatabase.js b/consumerWebsite/functions/sensorData.js similarity index 88% rename from webserver/functions/APIDatabase.js rename to consumerWebsite/functions/sensorData.js index d357188..f913ce0 100644 --- a/webserver/functions/APIDatabase.js +++ b/consumerWebsite/functions/sensorData.js @@ -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, -}; + +}; \ No newline at end of file diff --git a/consumerWebsite/functions/socket.js b/consumerWebsite/functions/socket.js new file mode 100644 index 0000000..acba88e --- /dev/null +++ b/consumerWebsite/functions/socket.js @@ -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; \ No newline at end of file diff --git a/consumerWebsite/functions/apiDatabase.js b/consumerWebsite/functions/user.js similarity index 70% rename from consumerWebsite/functions/apiDatabase.js rename to consumerWebsite/functions/user.js index 5cadaa5..9cfb6e0 100644 --- a/consumerWebsite/functions/apiDatabase.js +++ b/consumerWebsite/functions/user.js @@ -1,13 +1,9 @@ -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"); +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 @@ -24,6 +20,28 @@ async function getUserID(userid) { return userRes; } +//register +//api/v0/auth/register +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/register /* Registering new user 1) req.body is taken from html form or wtv @@ -32,13 +50,13 @@ async function getUserID(userid) { */ async function addUser(user) { //hash password - let hash = await hashPassword(user.password); + let hashed = await hash(user.password); const addRes = await userModel.create({ firstname: user.firstname, lastname: user.lastname, username: user.username, - password: hash, + password: hashed, email: user.email, address: user.address, phone: user.phone, @@ -70,7 +88,7 @@ async function loginUser(user) { if (!userRes) return false; // Compare passwords - let match = await comparePassword(user.password, userRes.password); + let match = await compareHash(user.password, userRes.password); if (!match) return false; //console.log('loginUser', userRes.id, userRes.username); @@ -89,20 +107,6 @@ async function loginUser(user) { 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/update async function updateProfile(user, body) { @@ -125,7 +129,7 @@ async function updateProfile(user, body) { if (!updateUser) return false; return true; } else { - let hash = await hashPassword(body.password); + let hashed = await hash(body.password); let updateUser = await userModel.update( { firstname: body.first_name, @@ -134,7 +138,7 @@ async function updateProfile(user, body) { email: body.email, address: body.address, phone: body.phone, - password: hash, + password: hashed, }, { where: { @@ -152,5 +156,4 @@ module.exports = { addUser, loginUser, updateProfile, - addAPIKey, -}; +}; \ No newline at end of file diff --git a/consumerWebsite/functions/validateData.js b/consumerWebsite/functions/validateData.js index d95fa58..d3f255f 100644 --- a/consumerWebsite/functions/validateData.js +++ b/consumerWebsite/functions/validateData.js @@ -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, +}; \ No newline at end of file diff --git a/webserver/middleware/apiKey.js b/consumerWebsite/middleware/apiKey.js similarity index 96% rename from webserver/middleware/apiKey.js rename to consumerWebsite/middleware/apiKey.js index 042514d..4d91dcb 100644 --- a/webserver/middleware/apiKey.js +++ b/consumerWebsite/middleware/apiKey.js @@ -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 { diff --git a/webserver/middleware/apiLogger.js b/consumerWebsite/middleware/apiLogger.js similarity index 93% rename from webserver/middleware/apiLogger.js rename to consumerWebsite/middleware/apiLogger.js index bfe7f2f..21c3e33 100644 --- a/webserver/middleware/apiLogger.js +++ b/consumerWebsite/middleware/apiLogger.js @@ -1,4 +1,4 @@ -const { insertLogData } = require("../functions/database.js"); +const { insertLogData } = require("../functions/logger.js"); const APIlogger = (req, res, next) => { try { const log = { diff --git a/consumerWebsite/middleware/authChecker.js b/consumerWebsite/middleware/authChecker.js index 3f77691..7855998 100644 --- a/consumerWebsite/middleware/authChecker.js +++ b/consumerWebsite/middleware/authChecker.js @@ -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{ @@ -15,7 +15,7 @@ async function auth(req, res, next){ 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 @@ -28,4 +28,4 @@ async function auth(req, res, next){ } } -module.exports = { auth }; +module.exports = { auth }; \ No newline at end of file diff --git a/webserver/modules/mqtt.js b/consumerWebsite/modules/mqtt.js similarity index 72% rename from webserver/modules/mqtt.js rename to consumerWebsite/modules/mqtt.js index 5266d7c..26b347b 100644 --- a/webserver/modules/mqtt.js +++ b/consumerWebsite/modules/mqtt.js @@ -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; - - +module.exports = client; \ No newline at end of file diff --git a/webserver/index.js b/consumerWebsite/mqttApp.js similarity index 87% rename from webserver/index.js rename to consumerWebsite/mqttApp.js index cf6da5d..2b13ef8 100644 --- a/webserver/index.js +++ b/consumerWebsite/mqttApp.js @@ -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(); }); + diff --git a/consumerWebsite/public/js/app.js b/consumerWebsite/public/js/app.js index 3d69ec5..5aed168 100644 --- a/consumerWebsite/public/js/app.js +++ b/consumerWebsite/public/js/app.js @@ -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,18 +182,20 @@ 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; //for navbar to show username - $.scope.getUsername.update(data); + 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") - { + if (location.pathname === "/profile") { $.scope.getUserDetails.update(data); } return callback(error, data); @@ -232,12 +262,9 @@ app.auth = (function (app) { logInRedirect, homeRedirect, profileRedirect, - //showUser, - //redirectIfLoggedIn, }; })(app); - app.user = (function (app) { //delete profile function deleteProfile() { @@ -250,12 +277,10 @@ app.user = (function (app) { }); } }); - } return { deleteProfile, }; - })(app); //ajax form submit and pass to api diff --git a/consumerWebsite/routes/api_routes.js b/consumerWebsite/routes/api_routes.js index 4edf988..080c427 100644 --- a/consumerWebsite/routes/api_routes.js +++ b/consumerWebsite/routes/api_routes.js @@ -1,3 +1,31 @@ +'use strict'; +const router = require('express').Router(); +const { auth } = require("../middleware/authChecker") +const { APIlogger } = require('../middleware/apiLogger.js'); +const { apikeyCheck } = require('../middleware/apiKey.js'); + +router.use('/auth', require('./auth')); + +router.use('/apikey', require('./apikey')); + +router.use('/user', [auth, APIlogger], require('./user')); + +//TO REFACTOR INTO ONE MIDDLWARE + +//location route +router.use('/location', [apikeyCheck , APIlogger], require('./location.js')); + +//location route +router.use('/sensor', [apikeyCheck , APIlogger], require('./sensor.js')); + +//location route +router.use('/sensor-data', [apikeyCheck, APIlogger], require('./sensorData.js')); + +module.exports = router; + + +/* + 'use strict'; const router = require('express').Router(); const { auth } = require("../middleware/authChecker") @@ -12,3 +40,4 @@ router.use('/user', auth ,require('./user')); module.exports = router; +*/ \ No newline at end of file diff --git a/consumerWebsite/routes/apikey.js b/consumerWebsite/routes/apikey.js index 3ee6c43..521cfdb 100644 --- a/consumerWebsite/routes/apikey.js +++ b/consumerWebsite/routes/apikey.js @@ -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; diff --git a/consumerWebsite/routes/auth.js b/consumerWebsite/routes/auth.js index 2484c16..863d863 100644 --- a/consumerWebsite/routes/auth.js +++ b/consumerWebsite/routes/auth.js @@ -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(); diff --git a/webserver/routes/Location.js b/consumerWebsite/routes/location.js similarity index 96% rename from webserver/routes/Location.js rename to consumerWebsite/routes/location.js index 486cff9..6551e5e 100644 --- a/webserver/routes/Location.js +++ b/consumerWebsite/routes/location.js @@ -4,7 +4,7 @@ const { getLocationById, updateLocation, deleteLocation, -} = require("../functions/apiDatabase.js"); +} = require("../functions/location"); const express = require("express"); const router = express.Router(); @@ -25,6 +25,7 @@ router.get("/", async (req, res, next) => { //add location router.post("/new", async (req, res, next) => { try { + console.log(req.body); const { name, added_by, description } = req.body; await addLocation(name, added_by, description); res.sendStatus(200) diff --git a/consumerWebsite/routes/render.js b/consumerWebsite/routes/render.js index 60eae5e..ad9f4ef 100644 --- a/consumerWebsite/routes/render.js +++ b/consumerWebsite/routes/render.js @@ -92,5 +92,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; +module.exports = router; \ No newline at end of file diff --git a/webserver/routes/SeedLocationAndSensor.js b/consumerWebsite/routes/seedLocationAndSensor.js similarity index 86% rename from webserver/routes/SeedLocationAndSensor.js rename to consumerWebsite/routes/seedLocationAndSensor.js index 11c2aa3..a092f9e 100644 --- a/webserver/routes/SeedLocationAndSensor.js +++ b/consumerWebsite/routes/seedLocationAndSensor.js @@ -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(); @@ -38,4 +38,4 @@ router.post("/new", async (req, res, next) => { -module.exports = router; +module.exports = router; \ No newline at end of file diff --git a/consumerWebsite/routes/seed_route.js b/consumerWebsite/routes/seed_route.js new file mode 100644 index 0000000..b10714d --- /dev/null +++ b/consumerWebsite/routes/seed_route.js @@ -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; \ No newline at end of file diff --git a/webserver/routes/SeedsensorData.js b/consumerWebsite/routes/seedsensorData.js similarity index 93% rename from webserver/routes/SeedsensorData.js rename to consumerWebsite/routes/seedsensorData.js index 7bfaec7..8504935 100644 --- a/webserver/routes/SeedsensorData.js +++ b/consumerWebsite/routes/seedsensorData.js @@ -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(); diff --git a/webserver/routes/Sensor.js b/consumerWebsite/routes/sensor.js similarity index 95% rename from webserver/routes/Sensor.js rename to consumerWebsite/routes/sensor.js index cc1c076..dea9ca9 100644 --- a/webserver/routes/Sensor.js +++ b/consumerWebsite/routes/sensor.js @@ -4,7 +4,7 @@ const { updateSensor, deleteSensor, getSensorById -} = require("../functions/apiDatabase.js"); +} = require("../functions/sensor.js"); const express = require("express"); const router = express.Router(); @@ -63,4 +63,4 @@ router.get("/:id", async (req, res, next) => { } }); -module.exports = router; +module.exports = router; \ No newline at end of file diff --git a/webserver/routes/SensorData.js b/consumerWebsite/routes/sensorData.js similarity index 86% rename from webserver/routes/SensorData.js rename to consumerWebsite/routes/sensorData.js index c54717d..c3862f5 100644 --- a/webserver/routes/SensorData.js +++ b/consumerWebsite/routes/sensorData.js @@ -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; - diff --git a/consumerWebsite/routes/user.js b/consumerWebsite/routes/user.js index 03913fd..474b905 100644 --- a/consumerWebsite/routes/user.js +++ b/consumerWebsite/routes/user.js @@ -1,4 +1,4 @@ -const { getUserID, updateProfile } = require("../functions/apiDatabase.js"); +const { getUserID, updateProfile } = require("../functions/user"); const express = require("express"); const router = express.Router(); diff --git a/consumerWebsite/views/index.ejs b/consumerWebsite/views/index.ejs index 1dfaaa4..921e105 100644 --- a/consumerWebsite/views/index.ejs +++ b/consumerWebsite/views/index.ejs @@ -1,5 +1,12 @@ <%- include('top') %> +
@@ -47,43 +54,55 @@
-

Services

- -
-
-
-

Humidity

-
-

70% - 75%

+

Services

+ +
+
+
+

Air Quality Index

+
+

15 - 18 PSI

+
+
- +
+
+

Humidity

+
+

70% - 75%

+
+
-
-
-
-
-

Air Quality Index

-
-

15 - 18 PSI

+
+
+
+

Temperature

+
+

30° - 37°

+
+
- +
+
+

Another Category

+
+

values

+
+
-
-
-
-
-

Temperature

-
-

30° - 37°

-
- -
-
-
+
+
+
@@ -121,4 +140,4 @@

-<%- include('bot') %> + <%- include('bot') %> \ No newline at end of file diff --git a/consumerWebsite/views/logintop.ejs b/consumerWebsite/views/logintop.ejs index e5dc928..80f9355 100644 --- a/consumerWebsite/views/logintop.ejs +++ b/consumerWebsite/views/logintop.ejs @@ -26,6 +26,8 @@ + + diff --git a/consumerWebsite/views/sensor-data.ejs b/consumerWebsite/views/sensor-data.ejs new file mode 100644 index 0000000..4013dc0 --- /dev/null +++ b/consumerWebsite/views/sensor-data.ejs @@ -0,0 +1,41 @@ +<%- include('top') %> + + + +
    +
  • + rowid: {{ id }} + sensorId: {{ sensorid }} + created: {{ createdAt }} + location: {{ locationid }} +
    + co: {{ measurement.co }} + humidity: {{ measurement.humidity }} + no2: {{ measurement.no2 }} + o3: {{ measurement.o3 }} + psi: {{ measurement.psi }} + so2: {{ measurement.so2 }} + temperature: {{ measurement.temperature }} + windspeed: {{ measurement.windspeed }} +
    +
  • +
  • + Loading... +
  • +
+ + +<%- include('bot') %> \ No newline at end of file diff --git a/consumerWebsite/views/top.ejs b/consumerWebsite/views/top.ejs index b3af246..276d928 100644 --- a/consumerWebsite/views/top.ejs +++ b/consumerWebsite/views/top.ejs @@ -1,144 +1,133 @@ - - - - - - - - - + + + + + + + + + + - - + + - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + - - + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8b75c59..391c6c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,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", @@ -35,6 +36,7 @@ "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": { @@ -1227,6 +1229,38 @@ "node": ">=10.2.0" } }, + "node_modules/engine.io-client": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/engine.io-parser": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", @@ -3606,6 +3640,20 @@ } } }, + "node_modules/socket.io-client": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz", + "integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -4091,6 +4139,14 @@ } } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index 28f6318..45eb5ce 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,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,7 @@ "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": { diff --git a/webserver/database/model/apiKeyModel.js b/webserver/database/model/apiKeyModel.js deleted file mode 100644 index 69e45d9..0000000 --- a/webserver/database/model/apiKeyModel.js +++ /dev/null @@ -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 }; diff --git a/webserver/database/model/userModel.js b/webserver/database/model/userModel.js deleted file mode 100644 index 561890c..0000000 --- a/webserver/database/model/userModel.js +++ /dev/null @@ -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 }; diff --git a/webserver/database/mySQL.js b/webserver/database/mySQL.js deleted file mode 100644 index 9b2f098..0000000 --- a/webserver/database/mySQL.js +++ /dev/null @@ -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 }; - diff --git a/webserver/functions/Database.js b/webserver/functions/Database.js deleted file mode 100644 index d18f7dd..0000000 --- a/webserver/functions/Database.js +++ /dev/null @@ -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 }; diff --git a/webserver/functions/bcrypt.js b/webserver/functions/bcrypt.js deleted file mode 100644 index 34afc86..0000000 --- a/webserver/functions/bcrypt.js +++ /dev/null @@ -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 -}; \ No newline at end of file diff --git a/webserver/functions/getAPIKey.js b/webserver/functions/getAPIKey.js deleted file mode 100644 index 4c62ddc..0000000 --- a/webserver/functions/getAPIKey.js +++ /dev/null @@ -1,17 +0,0 @@ -//model for getting API key from database - -async function getAPIKey() { - - -} - - - - - - - - - - -module.exports = { getAPIKey } \ No newline at end of file diff --git a/webserver/functions/validateData.js b/webserver/functions/validateData.js deleted file mode 100644 index 33ad8e1..0000000 --- a/webserver/functions/validateData.js +++ /dev/null @@ -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, -}; - diff --git a/webserver/modules/express.js b/webserver/modules/express.js deleted file mode 100644 index fcbbbba..0000000 --- a/webserver/modules/express.js +++ /dev/null @@ -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 }; diff --git a/webserver/routes/apiLog.js b/webserver/routes/apiLog.js deleted file mode 100644 index 80ed39a..0000000 --- a/webserver/routes/apiLog.js +++ /dev/null @@ -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); - } -}); -*/ \ No newline at end of file diff --git a/webserver/routes/api_route.js b/webserver/routes/api_route.js deleted file mode 100644 index 1144957..0000000 --- a/webserver/routes/api_route.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/webserver/routes/seed_route.js b/webserver/routes/seed_route.js deleted file mode 100644 index e89f904..0000000 --- a/webserver/routes/seed_route.js +++ /dev/null @@ -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; \ No newline at end of file