diff --git a/consumerWebsite/database/model/apiKeyModel.js b/consumerWebsite/database/model/apiKeyModel.js new file mode 100644 index 0000000..e9a2df4 --- /dev/null +++ b/consumerWebsite/database/model/apiKeyModel.js @@ -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 }; diff --git a/consumerWebsite/database/model/userModel.js b/consumerWebsite/database/model/userModel.js new file mode 100644 index 0000000..f9b3fee --- /dev/null +++ b/consumerWebsite/database/model/userModel.js @@ -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 }; diff --git a/consumerWebsite/database/mySQL.js b/consumerWebsite/database/mySQL.js new file mode 100644 index 0000000..255dc3a --- /dev/null +++ b/consumerWebsite/database/mySQL.js @@ -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 }; + diff --git a/consumerWebsite/functions/validateData.js b/consumerWebsite/functions/validateData.js index 11cbfe5..1849cb9 100644 --- a/consumerWebsite/functions/validateData.js +++ b/consumerWebsite/functions/validateData.js @@ -9,7 +9,7 @@ function isAlphaNumericWithSpacesAndDash(value) { const alphanumeric = /^[a-zA-Z0-9]+$/; const valid = value .split("") - .every((char) => alphanumeric.test(char) || char === " " || char === "-"); + .every((char) => alphanumeric.test(char) || char === " " || char === "-" || char === "_"); return valid; } @@ -22,9 +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 = { isAlphaNumericwithSpaces, isAlphaNumericWithSpacesAndDash, isJson, + isAddress };