@ -18,7 +18,7 @@ client.on("connect", () => {
|
|||||||
|
|
||||||
client.on("end", () => {
|
client.on("end", () => {
|
||||||
console.log("Disconnected from MQTT broker");
|
console.log("Disconnected from MQTT broker");
|
||||||
client.reconnect = true;
|
client.reconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on("error", (err) => {
|
client.on("error", (err) => {
|
||||||
@ -32,3 +32,7 @@ setInterval(publishData, 900000);
|
|||||||
//setInterval(publishData, 60000);
|
//setInterval(publishData, 60000);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
66
consumerWebsite/database/model/apiKeyModel.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"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']],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
module.exports = { apikeyModel };
|
94
consumerWebsite/database/model/userModel.js
Normal 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 };
|
34
consumerWebsite/database/mySQL.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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 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 };
|
||||||
|
|
@ -9,7 +9,7 @@ function isAlphaNumericWithSpacesAndDash(value) {
|
|||||||
const alphanumeric = /^[a-zA-Z0-9]+$/;
|
const alphanumeric = /^[a-zA-Z0-9]+$/;
|
||||||
const valid = value
|
const valid = value
|
||||||
.split("")
|
.split("")
|
||||||
.every((char) => alphanumeric.test(char) || char === " " || char === "-");
|
.every((char) => alphanumeric.test(char) || char === " " || char === "-" || char === "_");
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,12 +22,25 @@ function isJson(value) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//https://stackoverflow.com/questions/35145838/regex-for-singapore-addresses
|
||||||
|
2 Orchard Turn #B4-47 ION ORCHARD Singapore 238801
|
||||||
|
|
||||||
|
68 Marine Parade Road #03-26B parkway Parade 449269
|
||||||
|
|
||||||
|
Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830
|
||||||
|
*/
|
||||||
|
function isAddress(value){
|
||||||
|
// (\d{1,3}.)?.+\s(\d{6})$
|
||||||
|
const addressRegex = /^(\d{1,3}.)?.+\s(\d{6})$/;
|
||||||
|
//return true if it matches
|
||||||
|
return addressRegex.test(value);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
validateData,
|
|
||||||
isValidDateString,
|
|
||||||
isAlphaNumericwithSpaces,
|
isAlphaNumericwithSpaces,
|
||||||
isAlphaNumericWithSpacesAndDash,
|
isAlphaNumericWithSpacesAndDash,
|
||||||
isMacAddress,
|
|
||||||
isJson,
|
isJson,
|
||||||
|
isAddress
|
||||||
};
|
};
|
||||||
|
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 399 KiB After Width: | Height: | Size: 399 KiB |
Before Width: | Height: | Size: 281 KiB After Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 633 KiB After Width: | Height: | Size: 633 KiB |
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 665 KiB After Width: | Height: | Size: 665 KiB |
@ -62,5 +62,5 @@ client.on("error", (err) => {
|
|||||||
|
|
||||||
client.on("end", () => {
|
client.on("end", () => {
|
||||||
console.log("Disconnected from MQTT broker");
|
console.log("Disconnected from MQTT broker");
|
||||||
client.reconnect = true;
|
client.reconnect();
|
||||||
});
|
});
|