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/README.md b/README.md index 022ac48..3eaadc6 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/api.MD b/api.MD index b655bed..2f590e4 100644 --- a/api.MD +++ b/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"}' diff --git a/consumerWebsite/modules/app.js b/consumerWebsite/app.js similarity index 59% rename from consumerWebsite/modules/app.js rename to consumerWebsite/app.js index 3b3d8ba..ce7fee1 100644 --- a/consumerWebsite/modules/app.js +++ b/consumerWebsite/app.js @@ -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 }; diff --git a/consumerWebsite/bin/www b/consumerWebsite/bin/www new file mode 100644 index 0000000..dad62b9 --- /dev/null +++ b/consumerWebsite/bin/www @@ -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() + } +} \ 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/apiDatabase.js b/consumerWebsite/functions/apiDatabase.js deleted file mode 100644 index 1114c37..0000000 --- a/consumerWebsite/functions/apiDatabase.js +++ /dev/null @@ -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, -}; 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..4b5baf2 --- /dev/null +++ b/consumerWebsite/functions/location.js @@ -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, +}; \ 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..a72512b --- /dev/null +++ b/consumerWebsite/functions/sensor.js @@ -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, +}; 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..28cf3a0 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/user.js b/consumerWebsite/functions/user.js new file mode 100644 index 0000000..ee5cdb0 --- /dev/null +++ b/consumerWebsite/functions/user.js @@ -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, +}; \ 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 b12ffe2..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{ @@ -12,19 +12,20 @@ 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); } } -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/css/all.css b/consumerWebsite/public/css/all.css index d3173e3..a213d9c 100644 --- a/consumerWebsite/public/css/all.css +++ b/consumerWebsite/public/css/all.css @@ -3813,3 +3813,12 @@ .card-text { color: #000000; } + +/* edit profile */ +.profile { + margin: auto; + width: 40%; + border: 1px solid #000000; + padding: 10px; +} + diff --git a/consumerWebsite/public/css/api.css b/consumerWebsite/public/css/api.css index d3d44b1..f5d527e 100644 --- a/consumerWebsite/public/css/api.css +++ b/consumerWebsite/public/css/api.css @@ -523,4 +523,27 @@ body.one-content-column-version .content thead { .cf:before, .cf:after { content: ""; display: block; } .cf:after { clear: both; } -.ie6 .cf { zoom: 1 } \ No newline at end of file +.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 */ +} \ No newline at end of file diff --git a/consumerWebsite/public/css/contact.css b/consumerWebsite/public/css/contact.css index 2137c19..524a5e4 100644 --- a/consumerWebsite/public/css/contact.css +++ b/consumerWebsite/public/css/contact.css @@ -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%; diff --git a/consumerWebsite/public/images/404.png b/consumerWebsite/public/images/404.png index bcf5936..6b34292 100644 Binary files a/consumerWebsite/public/images/404.png and b/consumerWebsite/public/images/404.png differ diff --git a/consumerWebsite/public/images/4044.png b/consumerWebsite/public/images/4044.png deleted file mode 100644 index 6b34292..0000000 Binary files a/consumerWebsite/public/images/4044.png and /dev/null differ diff --git a/consumerWebsite/public/images/logo.ico b/consumerWebsite/public/images/logo.ico new file mode 100644 index 0000000..8b55d25 Binary files /dev/null and b/consumerWebsite/public/images/logo.ico differ diff --git a/consumerWebsite/public/js/app.js b/consumerWebsite/public/js/app.js index b5a1a3d..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,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(); - } - logInRedirect(); + function profileRedirect() { + location.replace(`/profile`); } - */ - - 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) diff --git a/consumerWebsite/public/js/learnmore.js b/consumerWebsite/public/js/learnmore.js index c965824..2e4a440 100644 --- a/consumerWebsite/public/js/learnmore.js +++ b/consumerWebsite/public/js/learnmore.js @@ -1,28 +1,60 @@ document.addEventListener("DOMContentLoaded", function () { function updateAdditionalInfo(region) { const infoContainer = document.getElementById("additional-info"); - // Replace the following with actual data retrieval based on the region - const aqi = "15"; - const temperature = "25°C"; - const humidity = "60%"; +// Replace the following with actual data retrieval based on the region +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 = ` +
+

Additional Information - ${region}

+ +
+ Air Quality Index: + ${aqi} +
+
+ Temperature: + ${temperature} +
+
+ Humidity: + ${humidity} +
+
+ PM2.5: + ${pm25} +
+
+ PM10: + ${pm10} +
+
+ SO2: + ${so2} +
+
+ O3: + ${o3} +
+
+ CO: + ${co} +
+
+ NO2: + ${no2} +
+
+`; - infoContainer.innerHTML = ` -
-

Additional Information - ${region}

-
- Air Quality Index: - ${aqi} -
-
- Temperature: - ${temperature} -
-
- Humidity: - ${humidity} -
-
- `; // Remove the 'active' class from all info-box elements const infoBoxes = document.querySelectorAll('.info-box'); diff --git a/consumerWebsite/routes/api_routes.js b/consumerWebsite/routes/api_routes.js index 4edf988..ebd16ed 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')); + +//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") @@ -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 97% rename from webserver/routes/Location.js rename to consumerWebsite/routes/location.js index 486cff9..cc7ce2b 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(); diff --git a/consumerWebsite/routes/render.js b/consumerWebsite/routes/render.js index f2c52e7..8c98d9f 100644 --- a/consumerWebsite/routes/render.js +++ b/consumerWebsite/routes/render.js @@ -1,42 +1,3 @@ -/* -'use strict'; - -var router = require('express').Router(); -const conf = require('../conf') - -const values ={ - title: conf.environment !== 'production' ? `` : '' -} - -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; +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 2d4cdca..474b905 100644 --- a/consumerWebsite/routes/user.js +++ b/consumerWebsite/routes/user.js @@ -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(); @@ -6,27 +6,25 @@ const router = express.Router(); //api/v0/user/me //getbyid router.get("/me", async function (req, res, next) { - try { - let user = await getUserID(req.user); - if (!user) { - let error = new Error("User not found"); - error.status = 400; - return next(error); - } - res.json({ - user: user, - }); - - } catch (error) { - next(error); - } + try { + let user = await getUserID(req.user); + if (!user) { + let error = new Error("User not found"); + error.status = 400; + return next(error); + } + res.json({ + user: user, + }); + } catch (error) { + next(error); + } }); - -//logout -router.delete('/logout', async function(req, res, next){ - try{ - /* +//logout +router.delete("/logout", async function (req, res, next) { + try { + /* let authToken = req.header('auth-token'); let userDel = await deleteUserToken(authToken); if (!userDel) { @@ -35,23 +33,51 @@ router.delete('/logout', async function(req, res, next){ return next(error); } */ - //destroy method call on seq object - req.token.destroy(); - // DO NOT CALL THIS!!! IT WILL DESTROY USERMODEL SEQ OBJ - //req.user.destroy(); - res.json({ - message: "User logged out successfully", - }); - - }catch(error){ - next(error); - } - }); + //destroy method call on seq object + req.token.destroy(); + // DO NOT CALL THIS!!! IT WILL DESTROY USERMODEL SEQ OBJ + //req.user.destroy(); + 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; - - - diff --git a/consumerWebsite/views/api.ejs b/consumerWebsite/views/api.ejs index eeabf16..73b6f6e 100644 --- a/consumerWebsite/views/api.ejs +++ b/consumerWebsite/views/api.ejs @@ -6,6 +6,7 @@ !--> <%- include('top') %> +
@@ -38,8 +39,8 @@ -
- - - - - - - - - - - - - - - - - -

Errors

@@ -359,9 +358,41 @@

+
+
+

API Keys

+ +

+ You can generate API Keys here: +

+ + + + + + + + + + + + + + + + + + + +
NamePublic KeyPrivate KeyKey TypeCreated
API KeyGR234-We34greR-234-fEGType2024-01-22
+
+
+ + + - - \ No newline at end of file + + diff --git a/consumerWebsite/views/bot.ejs b/consumerWebsite/views/bot.ejs index 04adff0..c383677 100644 --- a/consumerWebsite/views/bot.ejs +++ b/consumerWebsite/views/bot.ejs @@ -81,12 +81,7 @@

- - - - - \ No newline at end of file diff --git a/consumerWebsite/views/contact.ejs b/consumerWebsite/views/contact.ejs index f93c0f2..edc98f5 100644 --- a/consumerWebsite/views/contact.ejs +++ b/consumerWebsite/views/contact.ejs @@ -1,4 +1,5 @@ <%- include('top') %> +
diff --git a/consumerWebsite/views/forgotPassword.ejs b/consumerWebsite/views/forgotPassword.ejs index 4018890..ca37f61 100644 --- a/consumerWebsite/views/forgotPassword.ejs +++ b/consumerWebsite/views/forgotPassword.ejs @@ -4,7 +4,7 @@
Reset Password
-
+ 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/learnmore.ejs b/consumerWebsite/views/learnmore.ejs index 70cfd55..5ef406f 100644 --- a/consumerWebsite/views/learnmore.ejs +++ b/consumerWebsite/views/learnmore.ejs @@ -1,4 +1,5 @@ <%- include('top') %> +

@@ -37,5 +38,7 @@

+ -<%- include('bot') %> \ No newline at end of file + +<%- include('bot') %> diff --git a/consumerWebsite/views/logintop.ejs b/consumerWebsite/views/logintop.ejs index 3c5eb62..80f9355 100644 --- a/consumerWebsite/views/logintop.ejs +++ b/consumerWebsite/views/logintop.ejs @@ -6,7 +6,7 @@ - + @@ -26,6 +26,8 @@ + + diff --git a/consumerWebsite/views/profile.ejs b/consumerWebsite/views/profile.ejs index 03f9351..0670852 100644 --- a/consumerWebsite/views/profile.ejs +++ b/consumerWebsite/views/profile.ejs @@ -1,64 +1,111 @@ <%- include('top') %> - +
+
+
+
+ +
+ + +

Edit Personal Information

+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + -
-
-

Profile -

-
-
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ -
-<%- include('bot') %> - - + <%- include('bot') %> \ No newline at end of file diff --git a/consumerWebsite/public/resetpassword.html b/consumerWebsite/views/resetpassword.ejs similarity index 100% rename from consumerWebsite/public/resetpassword.html rename to consumerWebsite/views/resetpassword.ejs diff --git a/consumerWebsite/views/sensor-data.ejs b/consumerWebsite/views/sensor-data.ejs new file mode 100644 index 0000000..c46510b --- /dev/null +++ b/consumerWebsite/views/sensor-data.ejs @@ -0,0 +1,39 @@ +<%- 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/signuplogin.ejs b/consumerWebsite/views/signuplogin.ejs index f0ca40f..8543704 100644 --- a/consumerWebsite/views/signuplogin.ejs +++ b/consumerWebsite/views/signuplogin.ejs @@ -9,6 +9,7 @@