Compare commits

..

No commits in common. "256e582ed0fa561a9a6e900a8fcd9af4b0c7b609" and "4aea6a8e4c67a178858d607581956eba5bf03a25" have entirely different histories.

57 changed files with 901 additions and 3914 deletions

View File

@ -1,4 +0,0 @@
DB_name="eco_saver"
DB_storage="database_test.sqlite"
DB_dialect="sqlite"
DB_logginf=false

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
node_modules node_modules
.env .env
cert cert
*.sqlite

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const { Sequelize, DataTypes, Op } = require("sequelize"); const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySql"); const { sequelize } = require("../mySQL");
const { userModel } = require("./userModel"); const { userModel } = require("./userModel");
//sequelize.sync(); //sequelize.sync();
@ -16,7 +16,7 @@ const apikeyModel = sequelize.define(
isNumeric: true, isNumeric: true,
}, },
}, },
userId: { userid: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
allowNull: false, allowNull: false,
validate: { validate: {
@ -63,8 +63,6 @@ const apikeyModel = sequelize.define(
); );
apikeyModel.belongsTo(userModel); apikeyModel.belongsTo(userModel);
apikeyModel.sync()
module.exports = { apikeyModel }; module.exports = { apikeyModel };
/* /*

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const { Sequelize, DataTypes } = require("sequelize"); const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySql"); const { sequelize } = require("../mySQL");
const { const {
isAlphaNumericWithSpacesAndDash, isAlphaNumericWithSpacesAndDash,
isAddress, isAddress,
@ -111,7 +111,4 @@ const userModel = sequelize.define(
timestamps: true, timestamps: true,
} }
); );
userModel.sync()
module.exports = { userModel }; module.exports = { userModel };

View File

@ -1,30 +1,31 @@
const dotenv = require("dotenv"); const dotenv = require("dotenv");
const path = require('path') const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') }); require('dotenv').config({ path: path.resolve(__dirname, '../../.env') })
const Sequelize = require("sequelize"); const Sequelize = require("sequelize");
const fs = require('fs'); const fs = require('fs');
const sequelize = new Sequelize( const sequelize = new Sequelize(
process.env.DB_name, "eco_saver",
process.env.DB_USER, process.env.DB_USER,
process.env.DB_PASS, process.env.DB_PASS,
{ {
host: process.env.host, //"mpsqldatabase.mysql.database.azure.com", host: "mpsqldatabase.mysql.database.azure.com",
dialect: process.env.DB_dialect, dialect: 'mysql',
storage: process.env.DB_storage,
logging: process.env.DB_logging,
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy'; // attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
attributeBehavior: 'escape', attributeBehavior: 'escape',
dialectOptions: { dialectOptions: {
ssl: { ssl: {
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')), ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')),
}, },
}, },
}, },
); );
sequelize.authenticate().then(() => { sequelize.authenticate().then(() => {
console.log(`Connection to ${process.env.DB_dialect} has been established successfully.`); console.log('Connection has been established successfully.');
}).catch((error) => { }).catch((error) => {
console.error('Unable to connect to the database: ', error); console.error('Unable to connect to the database: ', error);
}); });

View File

@ -1,23 +0,0 @@
const { hash, compareHash } = require("./bcrypt.js");
const { apikeyModel } = require("../database/model/apiKeyModel");
const { generateUUID } = require("./generateUUID.js");
//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;
}
module.exports = {
addAPIKey
};

View File

@ -1,45 +1,13 @@
const { sequelize } = require("../database/mySql.js");
const { Op } = require('sequelize') const { apikeyModel } = require("../database/model/apikeyModel.js");
const { hash, compareHash } = require("./bcrypt.js"); const { userModel } = require("../database/model/userModel.js");
const { addAPIKey } = require("./api"); const { Op, Sequelize } = require("sequelize");
const { userModel } = require("../database/model/userModel"); const { generateUUID } = require("../functions/generateUUID.js");
const {
hashPassword,
comparePassword,
//getuser hashAPIKey,
//api/v0/user/me } = require("../functions/bcrypt.js");
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;
}
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;
}
}
//getuser //getuser
//api/v0/user/me //api/v0/user/me
@ -64,13 +32,13 @@ async function getUserID(userid) {
*/ */
async function addUser(user) { async function addUser(user) {
//hash password //hash password
let hashed = await hash(user.password); let hash = await hashPassword(user.password);
const addRes = await userModel.create({ const addRes = await userModel.create({
firstname: user.firstname, firstname: user.firstname,
lastname: user.lastname, lastname: user.lastname,
username: user.username, username: user.username,
password: hashed, password: hash,
email: user.email, email: user.email,
address: user.address, address: user.address,
phone: user.phone, phone: user.phone,
@ -102,7 +70,7 @@ async function loginUser(user) {
if (!userRes) return false; if (!userRes) return false;
// Compare passwords // Compare passwords
let match = await compareHash(user.password, userRes.password); let match = await comparePassword(user.password, userRes.password);
if (!match) return false; if (!match) return false;
//console.log('loginUser', userRes.id, userRes.username); //console.log('loginUser', userRes.id, userRes.username);
@ -121,6 +89,20 @@ async function loginUser(user) {
6) store in database 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 //api/v0/user/update
async function updateProfile(user, body) { async function updateProfile(user, body) {
@ -143,7 +125,7 @@ async function updateProfile(user, body) {
if (!updateUser) return false; if (!updateUser) return false;
return true; return true;
} else { } else {
let hashed = await hash(body.password); let hash = await hashPassword(body.password);
let updateUser = await userModel.update( let updateUser = await userModel.update(
{ {
firstname: body.first_name, firstname: body.first_name,
@ -152,7 +134,7 @@ async function updateProfile(user, body) {
email: body.email, email: body.email,
address: body.address, address: body.address,
phone: body.phone, phone: body.phone,
password: hashed, password: hash,
}, },
{ {
where: { where: {
@ -170,4 +152,5 @@ module.exports = {
addUser, addUser,
loginUser, loginUser,
updateProfile, updateProfile,
addAPIKey,
}; };

View File

@ -23,18 +23,23 @@ bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
*/ */
//hash for pass or token lol doesnt matter //hash for pass or token lol doesnt matter
async function hash(password) { async function hashPassword(password) {
return await bcrypt.hash(password, saltRounds); return await bcrypt.hash(password, saltRounds);
} }
async function hashAPIKey(apikey) {
return await bcrypt.hash(apikey, saltRounds);
}
//can be used to compare password or token //can be used to compare password or token
async function compareHash(password, hash) { async function comparePassword(password, hash) {
return await bcrypt.compare(password, hash); return await bcrypt.compare(password, hash);
} }
module.exports = { module.exports = {
hash, hashPassword,
compareHash hashAPIKey,
comparePassword
}; };

View File

@ -1,55 +0,0 @@
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) {
//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,
};

View File

@ -1,23 +0,0 @@
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,
};

View File

@ -1,75 +0,0 @@
const {sensorModel} = require("../database/model/sensorModel");
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;
}
module.exports = {
getSensor,
addSensor,
updateSensor,
deleteSensor,
};

View File

@ -1,17 +0,0 @@
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;

View File

@ -1,27 +1,5 @@
var validator = require("validator"); var validator = require("validator");
const dateRegex = /^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/;
function isValidDateString(value) {
return dateRegex.test(value);
}
function isMacAddress(value) {
// Joi.string().regex(/^([0-9a-f]{2}-){5}([0-9a-f]{2})$/i).lowercase()
//return validator.isMACAddress(value, { no_separators: true, eui: 48 });
const macAddress = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
const valid = macAddress.test(value);
return valid;
}
function isNumber(value) {
if (typeof value === "number") {
return true;
}
}
function isAlphaNumericwithSpaces(value) { function isAlphaNumericwithSpaces(value) {
return validator.isAlphanumeric(value, ["en-US"], { ignore: " " }); return validator.isAlphanumeric(value, ["en-US"], { ignore: " " });
} }
@ -66,8 +44,6 @@ module.exports = {
isAlphaNumericwithSpaces, isAlphaNumericwithSpaces,
isAlphaNumericWithSpacesAndDash, isAlphaNumericWithSpacesAndDash,
isJson, isJson,
isAddress, isAddress
isValidDateString,
isMacAddress,
isNumber,
}; };

View File

@ -1,6 +1,6 @@
const { apikeyModel } = require("../database/model/apiKeyModel"); const { apikeyModel } = require("../database/model/apiKeyModel");
const { userModel } = require("../database/model/userModel"); const { userModel } = require("../database/model/userModel");
const { compareHash } = require("../functions/bcrypt"); const { comparePassword } = require("../functions/bcrypt");
async function auth(req, res, next){ async function auth(req, res, next){
try{ try{
@ -15,7 +15,7 @@ async function auth(req, res, next){
if (!token) return false; if (!token) return false;
//compare //compare
let isMatch = await compareHash(suppliedToken, token.apikey); let isMatch = await comparePassword(suppliedToken, token.apikey);
if (!isMatch) return false; if (!isMatch) return false;
//else do logic //else do logic

View File

@ -1,46 +1,29 @@
const express = require("express"); const express = require("express");
const { rateLimit } = require("express-rate-limit");
const path = require("path"); const path = require("path");
const app = express(); const app = express();
const port = 3000; const port = 3000;
const ejs = require("ejs"); const ejs = require("ejs");
module.exports = app;
app.use(express.json()); app.use(express.json());
app.set("json spaces", 2); app.set("json spaces", 2);
//express-rate-limit stolen from docs
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
limit: 600, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
standardHeaders: 'draft-7', // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
legacyHeaders: false, // Disable the `X-RateLimit-*` headers.
});
// Hold list of functions to run when the server is ready
app.onListen = [function(){console.log('Express is ready')}];
// Apply the rate limiting middleware to all requests.
app.use(limiter);
//disable x-powered-by header for security reasons
app.disable("x-powered-by");
// Set up the templating engine to build HTML for the front end. // Set up the templating engine to build HTML for the front end.
app.set("views", path.join(__dirname, "./views")); app.set("views", path.join(__dirname, "../views"));
app.set("view engine", "ejs"); app.set("view engine", "ejs");
// Have express server static content( images, CSS, browser JS) from the public // Have express server static content( images, CSS, browser JS) from the public
app.use(express.static(path.join(__dirname, "./public"))); app.use(express.static(path.join(__dirname, "../public")));
//middleware logic ( called by next() )
const auth = require("../middleware/authChecker");
//route logic //route logic
app.use("/api/seed/v0" ,require("./routes/seed_route.js")); app.use("/api/v0", require("../routes/api_routes"));
app.use("/api/v0", require("./routes/api_routes"));
//render logic //render logic
app.use("/", require("./routes/render")); app.use("/", require("../routes/render"));
// Catch 404 and forward to error handler. If none of the above routes are // Catch 404 and forward to error handler. If none of the above routes are
// used, this is what will be called. // used, this is what will be called.
@ -86,5 +69,8 @@ app.use(function (err, req, res, next) {
keyErrors, keyErrors,
}); });
}); });
app.listen(port, () => {
console.log(`app listening on port ${port}`);
});
module.exports = { app };

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
{
"name": "consumerwebsite",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start-dev": "nodemon bin/www"
},
"author": "",
"license": "ISC",
"devDependencies": {
"nodemon": "^3.0.3",
"sqlite3": "^5.1.7"
},
"dependencies": {
"bcrypt": "^5.1.1",
"date-fns": "^3.2.0",
"date-fns-tz": "^2.0.0",
"dotenv": "^16.3.1",
"ejs": "^3.1.9",
"express": "^4.18.2",
"express-rate-limit": "^7.1.5",
"mqtt": "^5.3.3",
"mysql2": "^3.7.1",
"nodemailer": "^6.9.8",
"sequelize": "^6.35.2",
"socket.io": "^4.7.4",
"validator": "^13.11.0"
}
}

View File

@ -10,24 +10,6 @@ app.util = (function (app) {
: decodeURIComponent(results[1].replace(/\+/g, " ")); : decodeURIComponent(results[1].replace(/\+/g, " "));
} }
function promisify(f) {
return function (...args) { // return a wrapper-function (*)
return new Promise((resolve, reject) => {
function callback(err, result) { // our custom callback for f (**)
if (err) {
reject(err);
} else {
resolve(result);
}
}
args.push(callback); // append our custom callback to the end of f arguments
f.call(this, ...args); // call the original function
});
};
}
function actionMessage(message, $target, type, callback) { function actionMessage(message, $target, type, callback) {
message = message || ""; message = message || "";
$target = $target.closest("div.iot-card").find(".actionMessage"); $target = $target.closest("div.iot-card").find(".actionMessage");
@ -70,13 +52,12 @@ app.util = (function (app) {
}; };
return { return {
getUrlParameter, getUrlParameter: getUrlParameter,
actionMessage, actionMessage: actionMessage,
promisify
}; };
})(app); })(app);
app.apiSync = (function (app) { app.api = (function (app) {
var baseURL = "/api/v0/"; var baseURL = "/api/v0/";
function post(url, data, callback) { function post(url, data, callback) {
@ -160,35 +141,20 @@ app.apiSync = (function (app) {
}); });
} }
return { return { post: post, get: get, put: put, delete: remove };
post: app.util.promisify(post),
get: app.util.promisify(get),
put: app.util.promisify(put),
delete: app.util.promisify(remove),
};
})(app);
app.api = (function (app) {
return {
post: app.util.promisify(app.apiSync.post),
get: app.util.promisify(app.apiSync.get),
put: app.util.promisify(app.apiSync.put),
delete: app.util.promisify(app.apiSync.remove),
};
})(app); })(app);
//socket.io //socket.io
app.socket = (function (app) { app.socket = (function (app) {
//need to replace with domain name of server when published //need to replace with domain name of server when published
var socket = io(); var socket = io("localhost", {
transports: ["websocket"],
'Access-Control-Allow-Origin': 'http://localhost:3000',
});
socket.on("disconnect", () => { socket.on("disconnect", () => {
console.log("disconnected"); console.log("disconnected");
}); });
socket.on('connect', ()=>{
console.info('WS connected');
})
socket.io.on("reconnect", () => { socket.io.on("reconnect", () => {
console.log("reconnected"); console.log("reconnected");
}); });
@ -217,7 +183,7 @@ app.auth = (function (app) {
function isLoggedIn(callback) { function isLoggedIn(callback) {
if (getToken()) { if (getToken()) {
return app.apiSync.get("user/me", function (error, data) { return app.api.get("user/me", function (error, data) {
if (!error) app.auth.user = data; if (!error) app.auth.user = data;
//for navbar to show username //for navbar to show username
if (!location.pathname === "/login") if (!location.pathname === "/login")
@ -301,7 +267,7 @@ app.auth = (function (app) {
app.user = (function (app) { app.user = (function (app) {
//delete profile //delete profile
function deleteProfile() { function deleteProfile() {
app.apiSync.delete("user/delete", function (error, data) { app.api.delete("user/delete", function (error, data) {
if (error) { if (error) {
app.util.actionMessage(error.message, $("#deleteProfile"), "danger"); app.util.actionMessage(error.message, $("#deleteProfile"), "danger");
} else { } else {
@ -327,7 +293,7 @@ function formAJAX(btn, del) {
//console.log('Data being sent to', $form.attr('action'), formData) //console.log('Data being sent to', $form.attr('action'), formData)
app.apiSync[method]($form.attr("action"), formData, function (error, data) { app.api[method]($form.attr("action"), formData, function (error, data) {
//console.log('Data back from the server', error, data) //console.log('Data back from the server', error, data)
app.util.actionMessage(data.message, $form, error ? "danger" : "success"); //re-populate table app.util.actionMessage(data.message, $form, error ? "danger" : "success"); //re-populate table
if (!error) { if (!error) {

View File

@ -1,22 +1,13 @@
'use strict'; 'use strict';
const router = require('express').Router(); const router = require('express').Router();
const { auth } = require("../middleware/authChecker") const { auth } = require("../middleware/authChecker")
const { APIlogger } = require('../middleware/apiLogger.js');
router.use('/auth', require('./auth')); router.use('/auth', require('./auth'));
router.use('/apikey', require('./apikey')); router.use('/apikey', require('./apikey'));
router.use('/user', [auth, APIlogger], require('./user')); router.use('/user', auth ,require('./user'));
//location route
router.use('/location', [auth, APIlogger], require('./location'));
//location route
router.use('/sensor', [auth, APIlogger], require('./sensor'));
//location route
router.use('/sensor-data', [auth, APIlogger], require('./sensorData'));
module.exports = router; module.exports = router;

View File

@ -1,4 +1,4 @@
const { addAPIKey } = require("../functions/api"); const { getAPIKey , addAPIKey } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");

View File

@ -1,4 +1,4 @@
const { addUser, loginUser } = require("../functions/user"); const { addUser, loginUser } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();

View File

@ -87,9 +87,5 @@ router.get("/api", function (req, res, next) {
res.render("api"); res.render("api");
}); });
// sensor data
router.get("/sensor-data", function (req, res, next) {
res.render("sensor-data");
});
module.exports = router; module.exports = router;

View File

@ -1,4 +1,4 @@
const { getUserID, updateProfile } = require("../functions/user"); const { getUserID, updateProfile } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();

View File

@ -24,7 +24,7 @@
<div class="error-contents"> <div class="error-contents">
<h3>Unauthorized Access!</h3> <h3>Unauthorized Access!</h3>
<div class="error-img"> <div class="error-img">
<img class="img-fluid" src="/images/401.png" alt="" /> <img class="img-fluid" src="images/401.png" alt="" />
</div> </div>
<p>Sorry, you don't have permission to access this resource. Please log in or provide valid credentials.</p> <p>Sorry, you don't have permission to access this resource. Please log in or provide valid credentials.</p>
<a class="btn btn-primary" href="/"> Back To Homepage </a> <a class="btn btn-primary" href="/"> Back To Homepage </a>

View File

@ -24,7 +24,7 @@
<div class="error-contents"> <div class="error-contents">
<h3>Oops! That page cant be found.</h3> <h3>Oops! That page cant be found.</h3>
<div class="error-img"> <div class="error-img">
<img class="img-fluid" src="/images/404.png" alt="" /> <img class="img-fluid" src="images/404.png" alt="" />
</div> </div>
<p>We cant find the page your are looking for. You can check out our <a href="/">Homepage</a>.</p> <p>We cant find the page your are looking for. You can check out our <a href="/">Homepage</a>.</p>
<a class="btn btn-primary" href="/"> Back To Homepage </a> <a class="btn btn-primary" href="/"> Back To Homepage </a>

View File

@ -45,7 +45,7 @@
<ul class="footer_ul_amrc"> <ul class="footer_ul_amrc">
<li class="media"> <li class="media">
<div class="media-left"> <div class="media-left">
<img class="img-fluid" src="/images/post-img-01.jpg" alt="" /> <img class="img-fluid" src="images/post-img-01.jpg" alt="" />
</div> </div>
<div class="media-body"> <div class="media-body">
<p>Singapore's air quality ...</p> <p>Singapore's air quality ...</p>
@ -55,7 +55,7 @@
<ul class="footer_ul_amrc"> <ul class="footer_ul_amrc">
<li class="media"> <li class="media">
<div class="media-left"> <div class="media-left">
<img class="img-fluid" src="/images/post-img-01.jpg" alt="" /> <img class="img-fluid" src="images/post-img-01.jpg" alt="" />
</div> </div>
<div class="media-body"> <div class="media-body">
<p>Singapore Government ...</p> <p>Singapore Government ...</p>
@ -65,7 +65,7 @@
<ul class="footer_ul_amrc"> <ul class="footer_ul_amrc">
<li class="media"> <li class="media">
<div class="media-left"> <div class="media-left">
<img class="img-fluid" src="/images/post-img-01.jpg" alt="" /> <img class="img-fluid" src="images/post-img-01.jpg" alt="" />
</div> </div>
<div class="media-body"> <div class="media-body">
<p>High risk of severe ...</p> <p>High risk of severe ...</p>
@ -81,7 +81,7 @@
</p> </p>
</div> </div>
</footer> </footer>
<script src="/js/search.js"></script> <script src="js/search.js"></script>
</body> </body>
</html> </html>

View File

@ -1,5 +1,5 @@
<%- include('top') %> <%- include('top') %>
<link href="/css/contact.css" rel="stylesheet" /> <link href="css/contact.css" rel="stylesheet" />
<!-- full Title --> <!-- full Title -->
<div class="full-title"> <div class="full-title">

View File

@ -1,5 +1,5 @@
<%- include('top') %> <%- include('top') %>
<link href="/css/learnmore.css" rel="stylesheet" /> <link href="css/learnmore.css" rel="stylesheet" />
<br> <br>
<br> <br>
@ -38,7 +38,7 @@
<br> <br>
<br> <br>
<script src="/js/learnmore.js"></script> <script src="js/learnmore.js"></script>
<%- include('bot') %> <%- include('bot') %>

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="shortcut icon" type="images/logo.ico" href="/images/logo.ico" /> <link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" />
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

View File

@ -1,41 +0,0 @@
<%- include('top') %>
<style>
#sensorDataList{
padding-top: 2.5em;
}
</style>
<ul id="sensorDataList">
<li jq-repeat='sensorData'>
rowid: {{ id }}
sensorId: {{ sensorid }}
created: {{ createdAt }}
location: {{ locationid }}
<br/ >
co: {{ measurement.co }}
humidity: {{ measurement.humidity }}
no2: {{ measurement.no2 }}
o3: {{ measurement.o3 }}
psi: {{ measurement.psi }}
so2: {{ measurement.so2 }}
temperature: {{ measurement.temperature }}
windspeed: {{ measurement.windspeed }}
<hr />
</li>
<li jq-repeat-defualt='sensorData'>
Loading...
</li>
</ul>
<script type="text/javascript">
$(document).ready(async function(){
$.scope.sensorData.push(...await app.api.get('sensor-data/data?order=DESC&limit=40'));
app.socket.on('sensordata:new', function(data){
$.scope.sensorData.unshift(data);
});
})
</script>
<%- include('bot') %>

View File

@ -9,7 +9,7 @@
<meta http-equiv="cleartype" content="on" /> <meta http-equiv="cleartype" content="on" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" type="/images/logo.ico" href="/images/logo.ico" /> <link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" />
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
@ -17,8 +17,8 @@
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" /> integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" />
<!-- Custom styles for this template --> <!-- Custom styles for this template -->
<link href="/css/all.css" rel="stylesheet" /> <link href="css/all.css" rel="stylesheet" />
<link href="/css/style.css" rel="stylesheet" /> <link href="css/style.css" rel="stylesheet" />
<!-- weird api page cdn --> <!-- weird api page cdn -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
@ -45,10 +45,10 @@
<!-- jq-repeat --> <!-- jq-repeat -->
<script src="/js/jq-repeat.js"></script> <script src="js/jq-repeat.js"></script>
<!-- jquery app.js --> <!-- jquery app.js -->
<script src="/js/app.js"></script> <script src="js/app.js"></script>
</head> </head>
<!-- javascript function to check if user is auth --> <!-- javascript function to check if user is auth -->
<script> <script>
@ -74,7 +74,7 @@
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top"> <nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
<div class="container"> <div class="container">
<a class="navbar-brand" href="/"> <a class="navbar-brand" href="/">
<img src="/images/logo.png" alt="logo" /> <img src="images/logo.png" alt="logo" />
</a> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive"
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
@ -128,3 +128,6 @@
</div> </div>
</div> </div>
</nav> </nav>
</body>
</html>

View File

@ -4,17 +4,16 @@
* Module dependencies. * Module dependencies.
*/ */
const app = require('../app'); var app = require('../../webserver/modules/express.js');
const debug = require('debug')('proxy-api:server'); const index = require("../index.js")
const http = require('http'); var debug = require('debug')('proxy-api:server');
const path = require('path'); var http = require('http');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env')})
/** /**
* Get port from environment and store in Express. * Get port from environment and store in Express.
*/ */
var port = normalizePort(process.env.NODE_PORT || '3000'); const port = normalizePort(process.env.PORT || '80');
app.set('port', port); app.set('port', port);
/** /**
@ -23,7 +22,18 @@ app.set('port', port);
var server = http.createServer(app); var server = http.createServer(app);
var io = require('socket.io')(server); const io = require('socket.io')(server
, {
cors: {
//replace with domain name when deployed
origin: 'http://localhost:3000', // client!
methods: ["GET"],
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
app.io = io; app.io = io;
/** /**
@ -93,7 +103,6 @@ function onListening() {
: 'port ' + addr.port; : 'port ' + addr.port;
console.log('Listening on ' + bind); console.log('Listening on ' + bind);
// execute list of functions when app is ready
for(let listener of app.onListen){ for(let listener of app.onListen){
listener() listener()
} }

View File

@ -0,0 +1,65 @@
"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 };

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const { Sequelize, DataTypes } = require("sequelize"); const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySql"); const { sequelize } = require("../mySQL");
//sequelize.sync(); //sequelize.sync();
const api_log_Model = sequelize.define( const api_log_Model = sequelize.define(
@ -68,6 +68,4 @@ const api_log_Model = sequelize.define(
} }
); );
api_log_Model.sync()
module.exports = { api_log_Model }; module.exports = { api_log_Model };

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const { Sequelize, DataTypes } = require("sequelize"); const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySql"); const { sequelize } = require("../mySQL");
const { isAlphaNumericwithSpaces } = require('../../functions/validateData') const { isAlphaNumericwithSpaces } = require('../../functions/validateData')
//sequelize.sync(); //sequelize.sync();
@ -72,6 +72,4 @@ const locationModel = sequelize.define(
} }
); );
locationModel.sync();
module.exports = { locationModel }; module.exports = { locationModel };

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const { Sequelize, DataTypes } = require("sequelize"); const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySql"); const { sequelize } = require("../mySQL");
const { locationModel } = require("./locationModel"); const { locationModel } = require("./locationModel");
const { sensorModel } = require("./sensorModel"); const { sensorModel } = require("./sensorModel");
const { isJson } = require('../../functions/validateData'); const { isJson } = require('../../functions/validateData');
@ -74,6 +74,4 @@ const sensorDataModel = sequelize.define(
} }
); );
sensorDataModel.sync()
module.exports = { sensorDataModel }; module.exports = { sensorDataModel };

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const { Sequelize, DataTypes } = require("sequelize"); const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySql"); const { sequelize } = require("../mySQL");
const { locationModel } = require("./locationModel"); const { locationModel } = require("./locationModel");
const { const {
isAlphaNumericwithSpaces, isAlphaNumericwithSpaces,
@ -107,6 +107,4 @@ const sensorModel = sequelize.define(
} }
); );
sensorModel.sync()
module.exports = { sensorModel }; module.exports = { sensorModel };

View File

@ -0,0 +1,94 @@
"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 };

View File

@ -0,0 +1,35 @@
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 };

View File

@ -1,8 +1,8 @@
const { sequelize } = require("../Database/mySql.js");
const { locationModel } = require("../Database/model/locationModel.js");
const { sensorModel } = require("../Database/model/sensorModel.js");
const { sensorDataModel } = require("../Database/model/sensorDataModel.js");
const { Op, Sequelize } = require("sequelize"); const { Op, Sequelize } = require("sequelize");
const { sequelize } = require("../database/mySql.js");
const { sensorDataModel } = require("../database/model/sensorDataModel.js");
const io = require('../functions/socket');
// const { io } = require('../app')
//helper function to convert month name to month number //helper function to convert month name to month number
//https://stackoverflow.com/questions/13566552/easiest-way-to-convert-month-name-to-month-number-in-js-jan-01 //https://stackoverflow.com/questions/13566552/easiest-way-to-convert-month-name-to-month-number-in-js-jan-01
@ -13,23 +13,130 @@ function getMonthFromString(mon) {
} }
return -1; return -1;
} }
async function getLocation() {
const location = await locationModel.findAll();
return location;
}
async function addLocation(name, added_by, description) {
const location = await locationModel.create({
name: name,
added_by: added_by,
description: description,
});
}
async function updateLocation(id, name, added_by, description) {
const location = await locationModel.update(
{
name: name,
added_by: added_by,
description: description,
},
{
where: {
id: id,
},
}
);
}
async function deleteLocation(id) {
//delete by id
const location = await locationModel.destroy({
where: {
id: id,
},
});
}
async function getLocationById(id) {
const location = await locationModel.findAll({
where: {
id: id,
},
});
return location;
}
async function getSensor() {
const sensor = await sensorModel.findAll();
return sensor;
console.error(error);
}
async function addSensor(
sensorname,
added_by,
mac_address,
description,
location
) {
const sensor = await sensorModel.create({
name: sensorname,
added_by: added_by,
mac_address: mac_address,
description: description,
location: location,
});
}
async function updateSensor(
id,
sensorname,
added_by,
mac_address,
description,
location
) {
const sensor = await sensorModel.update(
{
name: sensorname,
added_by: added_by,
mac_address: mac_address,
description: description,
location: location,
},
{
where: {
id: id,
},
}
);
}
async function deleteSensor(id) {
//delete by id
const sensor = await sensorModel.destroy({
where: {
id: id,
},
});
console.error(error);
}
async function getSensorById(id) {
const sensor = await sensorModel.findAll({
where: {
id: id,
},
});
return sensor;
}
async function getSensorData() { async function getSensorData() {
const sensorData = await sensorDataModel.findAll(); const sensorData = await sensorDataModel.findAll();
return sensorData; return sensorData;
} }
async function addSensorData(id_sensor, id_location, sensordata) { async function addSensorData(id, id_sensor, id_location, sensordata) {
const sensorData = await sensorDataModel.create({ const sensorData = await sensorDataModel.create({
id: id,
sensorid: id_sensor, sensorid: id_sensor,
locationid: id_location, locationid: id_location,
measurement: sensordata, measurement: sensordata,
}); });
io().emit('sensordata:new', sensorData)
return sensorData;
} }
async function updateSensorData(id, id_sensor, id_location, sensordata) { async function updateSensorData(id, id_sensor, id_location, sensordata) {
@ -719,6 +826,16 @@ async function getDatabyRange(queryString) {
} }
module.exports = { module.exports = {
getLocation,
addLocation,
updateLocation,
deleteLocation,
getLocationById,
getSensor,
addSensor,
updateSensor,
deleteSensor,
getSensorById,
getSensorData, getSensorData,
addSensorData, addSensorData,
updateSensorData, updateSensorData,
@ -726,5 +843,4 @@ module.exports = {
getSensorDataById, getSensorDataById,
getData, getData,
getDatabyRange, getDatabyRange,
}; };

View File

@ -0,0 +1,59 @@
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 {
const app = require("../modules/express.js");
sensorDataModel.create({
sensorid: data.sensorid,
locationid: data.locationid,
measurement: data.measurement,
});
//ws broadcast event except to the sender.
app.io.emit("sensorData:new", data);
} catch (error) {
console.error(error);
}
}
async function checkAPikey(SuppliedKey, rowid) {
try {
const retrivedKey = await apikeyModel.findOne({
raw: true,
attributes: ["apikey", "permission"],
where: {
id: 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 };

View File

@ -0,0 +1,38 @@
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
};

View File

@ -0,0 +1,17 @@
//model for getting API key from database
async function getAPIKey() {
}
module.exports = { getAPIKey }

View File

@ -0,0 +1,51 @@
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,
};

View File

@ -1,6 +1,6 @@
const client = require("./modules/mqtt"); const client = require("./modules/mqtt");
const { isJson, isNumber } = require("./functions/validateData.js"); const { isJson, isNumber } = require("./functions/validateData.js");
const { addSensorData } = require("./functions/sensors.js"); const { insertDatatoDB } = require("./functions/database.js");
// Event handlers // Event handlers
client.on("connect", () => { client.on("connect", () => {
@ -37,7 +37,7 @@ client.on("message", (topic, message) => {
if (isNumber(data)) { if (isNumber(data)) {
{ {
//pass datas to database //pass datas to database
insertDatatoDB(datas[key].sensorid, datas[key].locationid, datas[key]); insertDatatoDB(datas[key]);
} }
} else { } else {

View File

@ -0,0 +1,65 @@
const { checkAPikey } = require("../functions/database.js");
async function apikeyCheck(req, res, next) {
//const authHeader = req.headers.authorization
try {
let apikey = req.headers.authorization;
if (!apikey) {
res.status(401).json({
message: "No API key was supplied. Invalid request",
});
//throw new Error("No API key was supplied. Invalid request");
} else {
//split the string by the -
let splitAPIkey = apikey.split("-");
let rowid = splitAPIkey[0];
//rejoin withouth the rowid
let SuppliedKey = splitAPIkey.slice(1).join("-");
if (checkAPikey(SuppliedKey, rowid)) {
//get permission
let permission = await checkAPikey(SuppliedKey, rowid);
console.log(permission);
if (req.method === "GET" && permission === "canRead") {
return next();
}
//['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)
if (
["GET", "POST", "PUT", "DELETE"].includes(req.method) &&
permission === "canWrite"
) {
console.log("write");
return next();
}
//throw status 403
res.status(403).json({
message:
"Your API key does not have the correct permissions to access this resource",
});
}
}
} catch (error) {
next(error);
}
}
module.exports = { apikeyCheck };
/*
//web server microservice
1) take user supplied rowid-apikey
2) split the string by -
3) get the rowid or table id
4) get the apikey
5) compare the apikey with the one in database
6) if match, return true
*/
/*
I plan to seed some data in user and api
Than use the system info and my API middleware will somehow check the supplied API key and check
If it's correct API key and has canWrite perms
I allow it to access put and post
*/

View File

@ -1,5 +1,4 @@
const { insertLogData } = require("../functions/logger.js"); const { insertLogData } = require("../functions/database.js");
const APIlogger = (req, res, next) => { const APIlogger = (req, res, next) => {
try { try {
const log = { const log = {

View File

@ -0,0 +1,91 @@
const express = require("express");
//const helmet = require("helmet");
var cors = require('cors');
const { rateLimit } = require("express-rate-limit");
const { APIlogger } = require('../middleware/apiLogger.js');
const { apikeyCheck } = require('../middleware/apiKey.js');
const app = express();
//app.use(cors());
//allow cors from localhost:3000
//app.use(helmet({ crossOriginResourcePolicy: { policy: "cross-origin" } }));
const port = 80;
// Hold list of functions to run when the server is ready
app.onListen = [function(){console.log('hello')}];
module.exports = app;
//handle cors
//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}`);
});
*/

View File

@ -4,7 +4,7 @@ const {
getLocationById, getLocationById,
updateLocation, updateLocation,
deleteLocation, deleteLocation,
} = require("../functions/location"); } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();

View File

@ -1,6 +1,6 @@
const { sequelize } = require("../database/mySql.js"); const { sequelize } = require("../Database/mySql.js");
const { locationModel } = require("../database/model/locationModel.js"); const { locationModel } = require("../Database/model/locationModel.js");
const { sensorModel } = require("../database/model/sensorModel.js"); const { sensorModel } = require("../Database/model/sensorModel.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();

View File

@ -1,7 +1,7 @@
const { sequelize } = require("../database/mySql.js"); const { sequelize } = require("../Database/mySql.js");
const { locationModel } = require("../database/model/locationModel.js"); const { locationModel } = require("../Database/model/locationModel.js");
const { sensorModel } = require("../database/model/sensorModel.js"); const { sensorModel } = require("../Database/model/sensorModel.js");
const { sensorDataModel } = require("../database/model/sensorDataModel.js"); const { sensorDataModel } = require("../Database/model/sensorDataModel.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();

View File

@ -4,7 +4,7 @@ const {
updateSensor, updateSensor,
deleteSensor, deleteSensor,
getSensorById getSensorById
} = require("../functions/sensor.js"); } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();

View File

@ -6,9 +6,10 @@ const {
getSensorDataById, getSensorDataById,
getData, getData,
getDatabyRange, getDatabyRange,
} = require("../functions/sensorData"); } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");
const { json } = require("body-parser");
const router = express.Router(); const router = express.Router();
router.get("/", async (req, res, next) => { router.get("/", async (req, res, next) => {
@ -23,9 +24,9 @@ router.get("/", async (req, res, next) => {
router.post("/new", async (req, res, next) => { router.post("/new", async (req, res, next) => {
try { try {
const { id_sensor, id_location, sensordata } = req.body; const { id, id_sensor, id_location, sensordata } = req.body;
let data = await addSensorData(id_sensor, id_location, sensordata); await addSensorData(id, id_sensor, id_location, sensordata);
res.json({ message: "SensorData " + data.id + " added", ...data }); res.sendStatus(200).json({ message: "SensorData " + id + " added" });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
next(error); next(error);

View File

@ -0,0 +1,77 @@
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);
}
});
*/

View File

@ -0,0 +1,37 @@
/*
'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;

View File

@ -2,7 +2,7 @@
const router = require('express').Router(); const router = require('express').Router();
//location route //location route
router.use('/sensor-data', require('./seedSensorData.js')); router.use('/seedSensorData', require('./seedSensorData.js'));
router.use('/seed', require('./seedLocationAndSensor')); router.use('/seed', require('./seedLocationAndSensor'));