This commit is contained in:
newtbot 2024-01-24 14:21:13 +08:00
parent 4aea6a8e4c
commit e710fa15a1
45 changed files with 463 additions and 828 deletions

View File

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

View File

@ -4,36 +4,28 @@
* Module dependencies.
*/
var app = require('../../webserver/modules/express.js');
const index = require("../index.js")
var debug = require('debug')('proxy-api:server');
var http = require('http');
const app = require('../app');
const mqttApp = require('../mqttApp');
const debug = require('debug')('proxy-api:server');
const http = require('http');
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env')})
/**
* Get port from environment and store in Express.
*/
const port = normalizePort(process.env.PORT || '80');
var port = normalizePort(process.env.NODE_PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
//create server with app
var server = http.createServer(app);
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
}
});
var io = require('socket.io')(server);
app.io = io;
/**
@ -103,7 +95,8 @@ function onListening() {
: 'port ' + addr.port;
console.log('Listening on ' + bind);
// execute list of functions when app is ready
for(let listener of app.onListen){
listener()
}
}
}

View File

@ -0,0 +1,47 @@
const { hash, compareHash } = require("./bcrypt.js");
const { apikeyModel } = require("../database/model/apiKeyModel");
const { generateUUID } = require("./generateUUID.js");
/*
1) take userid
2) generate random api key
3) hash the api key
4) append userid with - and api key
5) you give the user rowid-uuidv4
6) store in database
*/
//can be used for api key or token. Both are the same logic
async function addAPIKey(userId, permission) {
let hashtoken = await generateUUID();
let apikey = await hashAPIKey(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 };

View File

@ -23,23 +23,18 @@ bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
*/
//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
};

View File

@ -0,0 +1,55 @@
const {locationModel} = require("../database/model/locationModel");
async function getLocation() {
const location = await locationModel.findAll();
return location;
}
async function addLocation(name, added_by, description) {
const location = await locationModel.create({
name: name,
added_by: added_by,
description: description,
});
}
async function updateLocation(id, name, added_by, description) {
const location = await locationModel.update(
{
name: name,
added_by: added_by,
description: description,
},
{
where: {
id: id,
},
}
);
}
async function deleteLocation(id) {
//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

@ -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,
};

View File

@ -0,0 +1,75 @@
const {sensorModel} = require("../database/model/sensorModel");
async function getSensor() {
const sensor = await sensorModel.findAll();
return sensor;
}
async function addSensor(
sensorname,
added_by,
mac_address,
description,
location
) {
const sensor = await sensorModel.create({
name: sensorname,
added_by: added_by,
mac_address: mac_address,
description: description,
location: location,
});
}
async function updateSensor(
id,
sensorname,
added_by,
mac_address,
description,
location
) {
const sensor = await sensorModel.update(
{
name: sensorname,
added_by: added_by,
mac_address: mac_address,
description: description,
location: location,
},
{
where: {
id: id,
},
}
);
}
async function deleteSensor(id) {
//delete by id
const sensor = await sensorModel.destroy({
where: {
id: id,
},
});
console.error(error);
}
async function getSensorById(id) {
const sensor = await sensorModel.findAll({
where: {
id: id,
},
});
return sensor;
}
module.exports = {
getSensor,
addSensor,
updateSensor,
deleteSensor,
getSensorById,
};

View File

@ -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,
};
};

View File

@ -0,0 +1,17 @@
const app = require("../app");
const io = ()=> app.io;
// We have to wait for the express HTTP server to be finished starting before we
// can use any of the socket.io stuff.
app.onListen.push(function(){
app.io.on('connection', (socket) => {
console.log('User connected via WebsSocket')
socket.on('disconnect', (socket) => {
console.log('User disconnect via WebsSocket')
});
});
});
module.exports = io;

View File

@ -1,13 +1,44 @@
const { sequelize } = require("../database/mySql.js");
const { apikeyModel } = require("../database/model/apikeyModel.js");
const { userModel } = require("../database/model/userModel.js");
const { Op, Sequelize } = require("sequelize");
const { generateUUID } = require("../functions/generateUUID.js");
const {
hashPassword,
comparePassword,
hashAPIKey,
} = require("../functions/bcrypt.js");
const { Op } = require('sequelize')
const { hash, compareHash } = require("./bcrypt.js");
const { addAPIKey } = require("./api");
const { userModel } = require("../database/model/userModel");
//getuser
//api/v0/user/me
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
//api/v0/user/me
@ -32,13 +63,13 @@ async function getUserID(userid) {
*/
async function addUser(user) {
//hash password
let hash = await hashPassword(user.password);
let hashed = await hash(user.password);
const addRes = await userModel.create({
firstname: user.firstname,
lastname: user.lastname,
username: user.username,
password: hash,
password: hashed,
email: user.email,
address: user.address,
phone: user.phone,
@ -70,7 +101,7 @@ async function loginUser(user) {
if (!userRes) return false;
// Compare passwords
let match = await comparePassword(user.password, userRes.password);
let match = await compareHash(user.password, userRes.password);
if (!match) return false;
//console.log('loginUser', userRes.id, userRes.username);
@ -89,20 +120,6 @@ async function loginUser(user) {
6) store in database
*/
//can be used for api key or token. Both are the same logic
async function addAPIKey(userId, permission) {
let hashtoken = await generateUUID();
let apikey = await hashAPIKey(hashtoken);
let token = await apikeyModel.create({
userid: userId,
apikey: apikey,
permission: permission,
});
//user token with - tokenid is table id
return token.id + "-" + hashtoken;
}
//api/v0/user/update
async function updateProfile(user, body) {
@ -125,7 +142,7 @@ async function updateProfile(user, body) {
if (!updateUser) return false;
return true;
} else {
let hash = await hashPassword(body.password);
let hashed = await hash(body.password);
let updateUser = await userModel.update(
{
firstname: body.first_name,
@ -134,7 +151,7 @@ async function updateProfile(user, body) {
email: body.email,
address: body.address,
phone: body.phone,
password: hash,
password: hashed,
},
{
where: {
@ -152,5 +169,4 @@ module.exports = {
addUser,
loginUser,
updateProfile,
addAPIKey,
};
};

View File

@ -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,
};

View File

@ -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 {

View File

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

View File

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

View File

@ -17,6 +17,4 @@ const options = {
const client = mqtt.connect(brokerUrl, options);
module.exports = client;
module.exports = client;

View File

@ -1,6 +1,6 @@
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", () => {
@ -37,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 {
@ -63,3 +63,4 @@ client.on("end", () => {
console.log("Disconnected from MQTT broker");
client.reconnect();
});

View File

@ -144,17 +144,19 @@ 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("localhost", {
transports: ["websocket"],
'Access-Control-Allow-Origin': 'http://localhost:3000',
});
var socket = io();
socket.on("disconnect", () => {
console.log("disconnected");
});
socket.on('connect', ()=>{
console.info('WS connected');
})
socket.io.on("reconnect", () => {
console.log("reconnected");
});
@ -163,7 +165,6 @@ app.socket = (function (app) {
});
return socket;
})(app);
//sensor data
app.sensordata = (function (app) {

View File

@ -1,3 +1,31 @@
'use strict';
const router = require('express').Router();
const { auth } = require("../middleware/authChecker")
const { APIlogger } = require('../middleware/apiLogger.js');
const { apikeyCheck } = require('../middleware/apiKey.js');
router.use('/auth', require('./auth'));
router.use('/apikey', require('./apikey'));
router.use('/user', [auth, APIlogger], require('./user'));
//TO REFACTOR INTO ONE MIDDLWARE
//location route
router.use('/location', [apikeyCheck , APIlogger], require('./location.js'));
//location route
router.use('/sensor', [apikeyCheck , APIlogger], require('./sensor.js'));
//location route
router.use('/sensor-data', [apikeyCheck, APIlogger], require('./sensorData.js'));
module.exports = router;
/*
'use strict';
const router = require('express').Router();
const { auth } = require("../middleware/authChecker")
@ -12,3 +40,4 @@ router.use('/user', auth ,require('./user'));
module.exports = router;
*/

View File

@ -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;

View File

@ -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();

View File

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

View File

@ -87,5 +87,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;

View File

@ -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;

View File

@ -0,0 +1,14 @@
'use strict';
const router = require('express').Router();
//location route
router.use('/seedSensorData', require('./seedsensorData.js'));
router.use('/seed', require('./seedLocationAndSensor.js'));
module.exports = router;

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -2,6 +2,7 @@
<script>
//call socket.io
app.socket.on("sensorData:new", function (data) {
console.log("new data!!")
console.log(data);
});

View File

@ -0,0 +1,41 @@
<%- 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

@ -1,65 +0,0 @@
"use strict";
const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySQL");
const { userModel } = require("./userModel");
//sequelize.sync();
const apikeyModel = sequelize.define(
"apikey",
{
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true,
autoIncrement: true,
validate: {
isNumeric: true,
},
},
userid: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
isNumeric: true,
},
//fk
references: {
model: userModel,
key: "id",
},
},
apikey: {
type: DataTypes.STRING,
allowNull: false,
length: 255,
unique: true,
validate: {
notEmpty: true,
len: [1, 255],
},
},
permission: {
type: DataTypes.STRING,
allowNull: false,
length: 255,
validate: {
notEmpty: true,
len: [1, 255],
isIn: [["canRead", "canWrite" , "auto-generated"]],
},
},
createdAt: {
type: DataTypes.DATE,
allowNull: true,
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true,
},
},
{
timestamps: true,
}
);
module.exports = { apikeyModel };

View File

@ -1,94 +0,0 @@
"use strict";
const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySQL");
const {
isAlphaNumericWithSpacesAndDash,
isAddress,
} = require("../../functions/validateData");
//sequelize.sync();
const userModel = sequelize.define(
"user",
{
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true,
autoIncrement: true,
validate: {
isNumeric: true,
},
},
username: {
type: DataTypes.STRING,
allowNull: false,
length: 60,
validate: {
notEmpty: true,
len: [1, 60],
isAlphaNumericWithSpacesAndDash(value) {
if (!isAlphaNumericWithSpacesAndDash(value)) {
throw new Error("Invalid characters in username");
}
},
},
},
password: {
type: DataTypes.STRING,
allowNull: false,
length: 255,
validate: {
notEmpty: true,
len: [1, 255],
},
},
email: {
type: DataTypes.STRING,
allowNull: false,
length: 60,
unique: true,
validate: {
notEmpty: true,
len: [1, 60],
isEmail: true,
},
},
address: {
type: DataTypes.STRING,
allowNull: true,
length: 255,
validate: {
notEmpty: true,
len: [1, 255],
isAddress(value) {
if (!isAddress(value)) {
throw new Error("Invalid address");
}
},
},
},
phone: {
type: DataTypes.STRING,
allowNull: true,
length: 20,
validate: {
notEmpty: true,
len: [1, 20],
isNumeric: true,
},
},
//utc time
createdAt: {
type: DataTypes.DATE,
allowNull: true,
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true,
},
},
{
timestamps: true,
}
);
module.exports = { userModel };

View File

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

View File

@ -1,59 +0,0 @@
const { sequelize } = require("../Database/mySql.js");
const { api_log_Model } = require("../Database/model/apiLogModel.js");
const { sensorDataModel } = require("../Database/model/sensorDataModel.js");
const { apikeyModel } = require("../Database/model/apiKeyModel.js");
const { compareAPIKey } = require("./bcrypt.js");
async function insertLogData(log) {
try {
api_log_Model.create({
ip: log.ip,
time: log.time,
method: log.method,
host: log.host,
statusCode: log.statusCode,
Responsesize: log.Responsesize,
referrer: log.referrer,
userAgent: log.userAgent,
});
} catch (error) {
console.error(error);
}
}
async function insertDatatoDB(data) {
try {
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

@ -1,38 +0,0 @@
const bcrypt = require('bcrypt');
const saltRounds = 10;
//https://github.com/kelektiv/node.bcrypt.js#readme
/*
// Load hash from your password DB.
bcrypt.compare(myPlaintextPassword, hash, function(err, result) {
// result == true
});
bcrypt.compare(someOtherPlaintextPassword, hash, function(err, result) {
// result == false
});
*/
/*
//hash with salt
bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
// Store hash in your password DB.
});
*/
async function hashAPIKey(apikey) {
return await bcrypt.hash(apikey, saltRounds);
}
async function compareAPIKey(apikey, hash) {
return await bcrypt.compare(apikey, hash);
}
module.exports = {
hashAPIKey,
compareAPIKey
};

View File

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

View File

@ -1,51 +0,0 @@
var validator = require("validator");
const dateRegex = /^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/;
function isValidDateString(value) {
return dateRegex.test(value);
}
function isAlphaNumericwithSpaces(value) {
return validator.isAlphanumeric(value, ["en-US"], { ignore: " " });
}
//allow alphanumeric and spaces and -
function isAlphaNumericWithSpacesAndDash(value) {
const alphanumeric = /^[a-zA-Z0-9]+$/;
const valid = value
.split("")
.every((char) => alphanumeric.test(char) || char === " " || char === "-");
return valid;
}
function isMacAddress(value) {
// Joi.string().regex(/^([0-9a-f]{2}-){5}([0-9a-f]{2})$/i).lowercase()
//return validator.isMACAddress(value, { no_separators: true, eui: 48 });
const macAddress = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
const valid = macAddress.test(value);
return valid;
}
function isJson(value) {
//check if its object
if(typeof value === "object"){
return true
}
}
function isNumber(value) {
if (typeof value === "number") {
return true;
}
}
module.exports = {
isValidDateString,
isAlphaNumericwithSpaces,
isAlphaNumericWithSpacesAndDash,
isMacAddress,
isJson,
isNumber,
};

View File

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

@ -1,77 +0,0 @@
const {
} = require("../functions/apiDatabase.js");
const express = require("express");
const router = express.Router();
module.exports = router;
/*
//get location
router.get("/", async (req, res, next) => {
try {
const location = await getLocation();
//res send json and status code
res.status(200).json(location);
} catch (error) {
console.error(error);
next(error);
}
});
//add location
router.post("/new", async (req, res, next) => {
try {
const { name, added_by, description } = req.body;
await addLocation(name, added_by, description);
res.sendStatus(200)
} catch (error) {
console.error(error);
next(error);
}
});
//update location
router.put("/update", async (req, res, next) => {
try {
const { id, name, added_by, description } = req.body;
await updateLocation(id, name, added_by, description);
res.status(200).json({ message: "Location " + id + " updated" });
} catch (error) {
console.error(error);
next(error);
}
});
//delete location
router.delete("/delete", async (req, res, next) => {
try {
const { id } = req.body;
await deleteLocation(id);
res.status(200).json({ message: "Location " + id + " deleted" });
} catch (error) {
console.error(error);
next(error);
}
});
//get location by id
router.get("/:id", async (req, res, next) => {
try {
//get params
const { id } = req.params;
const location = await getLocationById(id);
res.status(200).json(location);
} catch (error) {
console.error(error);
next(error);
}
});
*/

View File

@ -1,37 +0,0 @@
/*
'use strict';
const router = require('express').Router();
const middleware = require('../middleware/auth');
router.use('/runner', require('./runner'));
router.use('/worker', require('./worker'));
router.use('/auth', require('./auth'));
router.use('/user', middleware.auth, require('./user'));
router.use('/token',middleware.auth, require('./token'));
module.exports = router;
*/
'use strict';
const router = require('express').Router();
//location route
router.use('/location', require('./location'));
//sensor route
router.use('/sensor', require('./sensor'))
//sensor data route
router.use('/sensor-data', require('./sensorData'));
//log route
//router.use('/log', require('./logLog'));
module.exports = router;

View File

@ -1,14 +0,0 @@
'use strict';
const router = require('express').Router();
//location route
router.use('/seedSensorData', require('./seedSensorData.js'));
router.use('/seed', require('./seedLocationAndSensor'));
module.exports = router;