From 017e8b42d953136140e0ff6d12559b86d1a330d5 Mon Sep 17 00:00:00 2001 From: Bobby Date: Sat, 30 Apr 2022 23:20:29 -0400 Subject: user login api --- interface/config/db.config.js | 9 +- interface/controllers/users.controller.js | 18 +++ interface/functions/index.js | 5 + interface/models/index.js | 2 + interface/models/users.model.js | 20 +++ interface/package-lock.json | 223 ++++++++++++++++++++++++++++++ interface/package.json | 3 + interface/routes/api/index.js | 80 +++++++++++ interface/routes/index.js | 8 +- interface/views/partials/navbar.ejs | 40 ++++++ 10 files changed, 402 insertions(+), 6 deletions(-) create mode 100644 interface/controllers/users.controller.js create mode 100644 interface/functions/index.js create mode 100644 interface/models/users.model.js create mode 100644 interface/routes/api/index.js diff --git a/interface/config/db.config.js b/interface/config/db.config.js index 9118d6c..ea90d0c 100644 --- a/interface/config/db.config.js +++ b/interface/config/db.config.js @@ -1,14 +1,15 @@ +require('dotenv').config(); module.exports = { // The name of the database - database: 'WelfareSchemes', + database: process.env.DATABASE, // The username used to connect to the database - username: 'postgres', + username: process.env.USERNAME, // The password used to connect to the database - password: 'lucifer', + password: process.env.PASSWORD, // The dialect of the database you are connecting to dialect: 'postgres', // The host of the database - host: 'localhost', + host: process.env.HOST, // The port of the database port: 5432, // Setup pool of connections to the database diff --git a/interface/controllers/users.controller.js b/interface/controllers/users.controller.js new file mode 100644 index 0000000..fff4469 --- /dev/null +++ b/interface/controllers/users.controller.js @@ -0,0 +1,18 @@ +const { users } = require("../models"); +const db = require("../models"); +const citizens = db.citizens; +const op = db.Sequelize.Op; + +// Create a new user +exports.create = (username, password) => { + return users.create({ username, password }); +} + +// Get a user by their username +exports.findByUsername = (username) => { + return users.findOne({ + where: { + username: username + } + }); +} diff --git a/interface/functions/index.js b/interface/functions/index.js new file mode 100644 index 0000000..034dc80 --- /dev/null +++ b/interface/functions/index.js @@ -0,0 +1,5 @@ +const jwt = require('jsonwebtoken'); + +exports.verifyJWT = (jwtToken) => { + return jwt.verify(jwtToken, process.env.JWT_SECRET); +} diff --git a/interface/models/index.js b/interface/models/index.js index 852fb65..e799e1e 100644 --- a/interface/models/index.js +++ b/interface/models/index.js @@ -18,7 +18,9 @@ const sequelize = new Sequelize(databaseConfig.database, databaseConfig.username const db = {}; db.Sequelize = Sequelize; db.sequelize = sequelize; +db.users = require('./users.model')(Sequelize, sequelize); db.citizens = require('./citizens.model.js')(Sequelize, sequelize); db.village_master = require('./village_master.model.js')(Sequelize, sequelize); +db.bank_master = require('./bank_master.model.js')(Sequelize, sequelize); module.exports = db; diff --git a/interface/models/users.model.js b/interface/models/users.model.js new file mode 100644 index 0000000..df8b276 --- /dev/null +++ b/interface/models/users.model.js @@ -0,0 +1,20 @@ +module.exports = (Sequelize, sequelize) => { + const Users = sequelize.define("users", { + user_id: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true, + }, + username: { + type: Sequelize.STRING(155), + allowNull: false, + unique: true, + }, + password: { + type: Sequelize.STRING(155), + allowNull: false, + } + }); + return Users; +} \ No newline at end of file diff --git a/interface/package-lock.json b/interface/package-lock.json index e4be03a..2613ab1 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -9,10 +9,13 @@ "version": "1.0.0", "license": "GPL-3.0-or-later", "dependencies": { + "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cors": "^2.8.5", + "dotenv": "^16.0.0", "ejs": "^3.1.7", "express": "^4.17.3", + "jsonwebtoken": "^8.5.1", "pg": "^8.7.3", "pg-hstore": "^2.3.4", "sequelize": "^6.19.0" @@ -143,6 +146,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -283,6 +291,11 @@ "node": ">=8" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -585,6 +598,14 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", + "engines": { + "node": ">=12" + } + }, "node_modules/dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -596,6 +617,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1174,6 +1203,59 @@ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", "dev": true }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -1200,6 +1282,41 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -2499,6 +2616,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2603,6 +2725,11 @@ "fill-range": "^7.0.1" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -2824,6 +2951,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -2835,6 +2967,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3275,6 +3415,54 @@ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", "dev": true }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -3298,6 +3486,41 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", diff --git a/interface/package.json b/interface/package.json index 87ca23a..d421c00 100644 --- a/interface/package.json +++ b/interface/package.json @@ -12,10 +12,13 @@ "author": "Kumar Priyansh ", "license": "GPL-3.0-or-later", "dependencies": { + "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cors": "^2.8.5", + "dotenv": "^16.0.0", "ejs": "^3.1.7", "express": "^4.17.3", + "jsonwebtoken": "^8.5.1", "pg": "^8.7.3", "pg-hstore": "^2.3.4", "sequelize": "^6.19.0" diff --git a/interface/routes/api/index.js b/interface/routes/api/index.js new file mode 100644 index 0000000..bad2706 --- /dev/null +++ b/interface/routes/api/index.js @@ -0,0 +1,80 @@ +// API for logging in +const express = require("express"); +const router = express.Router(); +const jwt = require("jsonwebtoken"); +const bcyrpt = require("bcryptjs"); +const userController = require("../../controllers/users.controller"); +const { verifyJWT } = require("../../functions"); + +router.get("/verify", (req, res) => { + // get token from auth header + console.log(req.headers) + const token = req.headers.authorization; + // verify token + const decoded = verifyJWT(token.replace("Bearer ", "")); + if (decoded) { + res.status(200).json({ + message: "Token is valid", + decoded: decoded, + }); + } else { + res.status(401).json({ + message: "Token is invalid", + }); + } +}); + +router.post("/create", (req, res) => { + const { username, password } = req.body; + const saltRounds = 10; + const hash = bcyrpt.hashSync(password, saltRounds); + userController.create(username, hash).then((user) => { + const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { + expiresIn: "1h", + }); + res.json({ + token, + user, + }); + }); +}); + +router.post("/login", (req, res) => { + const { username, password } = req.body; + // get user by username + userController.findByUsername(username).then((user) => { + if (!user) { + return res.status(400).json({ + message: "User not found", + }); + } + // check if password is correct + bcyrpt.compare(password, user.password).then((isMatch) => { + if (!isMatch) { + return res.status(400).json({ + message: "Invalid credentials", + }); + } + // generate jwt + const payload = { + id: user.id, + username: user.username, + }; + jwt.sign( + payload, + process.env.SECRET_KEY, + { + expiresIn: 3600, + }, + (err, token) => { + if (err) throw err; + res.json({ + token, + }); + } + ); + }); + }); +}); + +module.exports = router; diff --git a/interface/routes/index.js b/interface/routes/index.js index 17c2021..057e1df 100644 --- a/interface/routes/index.js +++ b/interface/routes/index.js @@ -1,14 +1,18 @@ const express = require("express"); const router = express.Router(); const citizensController = require("../controllers/citizens.controller"); +const api = require('./api'); -// Setup Hello World route +// Setup api routes +router.use('/api', api); + +// Setup main route router.get("/", (req, res) => { // Get the citizens from the database citizensController.findXCitizens().then(citizens => { res.render("index", { citizens: citizens, - title: "Hello World" + title: "Home" }); }); }); diff --git a/interface/views/partials/navbar.ejs b/interface/views/partials/navbar.ejs index 6a46ff3..2939438 100644 --- a/interface/views/partials/navbar.ejs +++ b/interface/views/partials/navbar.ejs @@ -42,7 +42,47 @@ + + + -- cgit v1.2.3 From 50c8c294e2e23566887a47a3180c180675d64add Mon Sep 17 00:00:00 2001 From: Bobby Date: Sun, 1 May 2022 00:17:22 -0400 Subject: login function with a new main page --- interface/public/login.js | 39 +++++++++++++++ interface/public/logout.js | 5 ++ interface/public/router.js | 7 +++ interface/public/verify.js | 22 +++++++++ interface/routes/api/index.js | 5 +- interface/routes/index.js | 14 ++++-- interface/views/citizens.ejs | 51 +++++++++++++++++++ interface/views/index.ejs | 95 +++++++++++++++++++++--------------- interface/views/partials/head.ejs | 2 - interface/views/partials/navbar.ejs | 39 ++------------- interface/views/partials/scripts.ejs | 9 ++++ 11 files changed, 204 insertions(+), 84 deletions(-) create mode 100644 interface/public/login.js create mode 100644 interface/public/logout.js create mode 100644 interface/public/router.js create mode 100644 interface/public/verify.js create mode 100644 interface/views/citizens.ejs create mode 100644 interface/views/partials/scripts.ejs diff --git a/interface/public/login.js b/interface/public/login.js new file mode 100644 index 0000000..3396f81 --- /dev/null +++ b/interface/public/login.js @@ -0,0 +1,39 @@ +$(".ui.form").form({ + fields: { + username: "empty", + password: "empty", + }, +}); + +function login(event) { + event.preventDefault(); + const username = $("#username").val().trim(); + const password = $("#password").val().trim(); + + // make sure username is a-zA-Z0-9 + if (!username.match(/^[a-zA-Z0-9]+$/)) { + alert("Username must be alphanumeric"); + return; + } else { + // make request to /api/login + fetch("/api/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + username, + password, + }), + }).then((response) => { + if (response.status === 200) { + response.json().then((data) => { + localStorage.setItem("token", data.token); + window.location.href = "/"; + }); + } else { + alert("Invalid username or password"); + } + }); + } +} diff --git a/interface/public/logout.js b/interface/public/logout.js new file mode 100644 index 0000000..401f06d --- /dev/null +++ b/interface/public/logout.js @@ -0,0 +1,5 @@ +function logout(event) { + event.preventDefault(); + localStorage.removeItem("token"); + window.location.href = "/"; +} diff --git a/interface/public/router.js b/interface/public/router.js new file mode 100644 index 0000000..23f8115 --- /dev/null +++ b/interface/public/router.js @@ -0,0 +1,7 @@ +function route(page) { + if (!localStorage.getItem("token")) { + $("#loginButton").click(); + } else { + window.location.href = page; + } +} \ No newline at end of file diff --git a/interface/public/verify.js b/interface/public/verify.js new file mode 100644 index 0000000..ca7b47f --- /dev/null +++ b/interface/public/verify.js @@ -0,0 +1,22 @@ +const token = localStorage.getItem("token"); +if (token) { + fetch("/api/verify", { + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + } + }).then(response => { + if (response.status === 200) { + console.log(response.json()); + $('#loginButton').hide(); + $('#logoutButton').show(); + } else { + window.location.href = "/"; + $('#loginButton').show(); + $('#logoutButton').hide(); + } + }); +} else { + $('#loginButton').show(); + $('#logoutButton').hide(); +} diff --git a/interface/routes/api/index.js b/interface/routes/api/index.js index bad2706..27f9c98 100644 --- a/interface/routes/api/index.js +++ b/interface/routes/api/index.js @@ -5,8 +5,9 @@ const jwt = require("jsonwebtoken"); const bcyrpt = require("bcryptjs"); const userController = require("../../controllers/users.controller"); const { verifyJWT } = require("../../functions"); +require('dotenv').config(); -router.get("/verify", (req, res) => { +router.post("/verify", (req, res) => { // get token from auth header console.log(req.headers) const token = req.headers.authorization; @@ -62,7 +63,7 @@ router.post("/login", (req, res) => { }; jwt.sign( payload, - process.env.SECRET_KEY, + process.env.JWT_SECRET, { expiresIn: 3600, }, diff --git a/interface/routes/index.js b/interface/routes/index.js index 057e1df..fcc7c14 100644 --- a/interface/routes/index.js +++ b/interface/routes/index.js @@ -6,13 +6,19 @@ const api = require('./api'); // Setup api routes router.use('/api', api); -// Setup main route -router.get("/", (req, res) => { + +router.get('/', (req, res) => { + res.render('index', { + title: 'Home Page' + }); +}); + +router.get("/citizens", (req, res) => { // Get the citizens from the database citizensController.findXCitizens().then(citizens => { - res.render("index", { + res.render("citizens", { citizens: citizens, - title: "Home" + title: "Citizens Data" }); }); }); diff --git a/interface/views/citizens.ejs b/interface/views/citizens.ejs new file mode 100644 index 0000000..97c98fa --- /dev/null +++ b/interface/views/citizens.ejs @@ -0,0 +1,51 @@ + + + + <%- include('partials/head') %> + + + + <%- include('partials/navbar') %> + + + + + + + + + + + + + + + + + + + + <% for(var i=0; i < citizens.length; i++) { %> + + + + + + + + + + + + + + + + <% } %> + +
Citizen IDFirst NameMiddle NameLast NameAddressMobile NumberDate of BirthGenderMarital StatusDisabledDisabled PercentageCasteVillage ID
<%= citizens[i].citizen_id %><%= citizens[i].first_name %> + <%= citizens[i].middle_name ? citizens[i].middle_name : '-' %> + <%= citizens[i].last_name %><%= citizens[i].address %><%= citizens[i].mobile_num %><%= citizens[i].dob %><%= citizens[i].gender %><%= citizens[i].marital_status %><%= citizens[i].disabled %><%= citizens[i].disbaled_percentage %><%= citizens[i].caste %><%= citizens[i].village_id %>
+ + <%- include('partials/scripts') %> + diff --git a/interface/views/index.ejs b/interface/views/index.ejs index 827334b..6848aa3 100644 --- a/interface/views/index.ejs +++ b/interface/views/index.ejs @@ -5,46 +5,61 @@ + <%- include('partials/navbar') %> - - - - - - - - - - - - - - - - - - - - <% for(var i=0; i < citizens.length; i++) { %> - - - - - - - - - - - - - - - - <% } %> - -
Citizen IDFirst NameMiddle NameLast NameAddressMobile NumberDate of BirthGenderMarital StatusDisabledDisabled PercentageCasteVillage ID
<%= citizens[i].citizen_id %><%= citizens[i].first_name %> - <%= citizens[i].middle_name ? citizens[i].middle_name : '-' %> - <%= citizens[i].last_name %><%= citizens[i].address %><%= citizens[i].mobile_num %><%= citizens[i].dob %><%= citizens[i].gender %><%= citizens[i].marital_status %><%= citizens[i].disabled %><%= citizens[i].disbaled_percentage %><%= citizens[i].caste %><%= citizens[i].village_id %>
+
+
+
+
+
Citizens
+
+ Provides the details of all the citizens in the database +
+
+
+
+ View Data +
+
+
+
+
+ <%- include('partials/scripts') %> + + diff --git a/interface/views/partials/head.ejs b/interface/views/partials/head.ejs index c43233a..c4b963e 100644 --- a/interface/views/partials/head.ejs +++ b/interface/views/partials/head.ejs @@ -3,5 +3,3 @@ Welfare Schemes | <%= title %> - - diff --git a/interface/views/partials/navbar.ejs b/interface/views/partials/navbar.ejs index 2939438..91880fb 100644 --- a/interface/views/partials/navbar.ejs +++ b/interface/views/partials/navbar.ejs @@ -45,44 +45,11 @@ - - diff --git a/interface/views/partials/scripts.ejs b/interface/views/partials/scripts.ejs new file mode 100644 index 0000000..a90467a --- /dev/null +++ b/interface/views/partials/scripts.ejs @@ -0,0 +1,9 @@ + + + + + -- cgit v1.2.3 From 83fe4daf705e075b6afe275a4db8552ee61ab65b Mon Sep 17 00:00:00 2001 From: Bobby Date: Sun, 1 May 2022 00:18:00 -0400 Subject: remove console logs --- interface/routes/api/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/routes/api/index.js b/interface/routes/api/index.js index 27f9c98..f21720b 100644 --- a/interface/routes/api/index.js +++ b/interface/routes/api/index.js @@ -5,11 +5,10 @@ const jwt = require("jsonwebtoken"); const bcyrpt = require("bcryptjs"); const userController = require("../../controllers/users.controller"); const { verifyJWT } = require("../../functions"); -require('dotenv').config(); +require("dotenv").config(); router.post("/verify", (req, res) => { // get token from auth header - console.log(req.headers) const token = req.headers.authorization; // verify token const decoded = verifyJWT(token.replace("Bearer ", "")); -- cgit v1.2.3 From a31f92a2015fd5c5b4166c8c2fee42c3ec461ca8 Mon Sep 17 00:00:00 2001 From: Bobby Date: Sun, 1 May 2022 00:18:59 -0400 Subject: remove active --- interface/views/partials/navbar.ejs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/views/partials/navbar.ejs b/interface/views/partials/navbar.ejs index 91880fb..34116ea 100644 --- a/interface/views/partials/navbar.ejs +++ b/interface/views/partials/navbar.ejs @@ -1,5 +1,5 @@ Log in - Log out + + Log out -- cgit v1.2.3 From c79afe469347ce4f0cffa1ba268939fd00662e81 Mon Sep 17 00:00:00 2001 From: Bobby Date: Sun, 1 May 2022 01:01:22 -0400 Subject: added gender distribution to main page --- interface/controllers/citizens.controller.js | 27 +++++++++++++++++++++------ interface/package-lock.json | 1 + interface/package.json | 1 + interface/public/verify.js | 1 - interface/routes/index.js | 8 ++++++-- interface/views/index.ejs | 8 ++++++++ interface/views/partials/head.ejs | 5 +++++ 7 files changed, 42 insertions(+), 9 deletions(-) diff --git a/interface/controllers/citizens.controller.js b/interface/controllers/citizens.controller.js index 64522b1..b50ee74 100644 --- a/interface/controllers/citizens.controller.js +++ b/interface/controllers/citizens.controller.js @@ -1,11 +1,26 @@ const db = require("../models"); const citizens = db.citizens; -const op = db.Sequelize.Op; // Retrieve all citizens from the database. Limit the number of citizens returned to 10. exports.findXCitizens = () => { - const limit = 10; - return citizens.findAll({ - limit: limit - }); -} + const limit = 10; + return citizens.findAll({ + limit: limit, + }); +}; + +// Get total number of male and female citizens +exports.findGenderDistribution = () => { + // group by the 'gender' column + + /** + * This code is equivalent to the following SQL query: + * select count(gender), gender from citizens group by gender; + */ + + return citizens.findAll({ + group: ["gender"], + attributes: ["gender", [db.sequelize.fn("COUNT", "gender"), "genderCount"]], + raw: true + }); +}; diff --git a/interface/package-lock.json b/interface/package-lock.json index 2613ab1..dc4079f 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "GPL-3.0-or-later", "dependencies": { + "async": "^3.2.3", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cors": "^2.8.5", diff --git a/interface/package.json b/interface/package.json index d421c00..9cca33f 100644 --- a/interface/package.json +++ b/interface/package.json @@ -12,6 +12,7 @@ "author": "Kumar Priyansh ", "license": "GPL-3.0-or-later", "dependencies": { + "async": "^3.2.3", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cors": "^2.8.5", diff --git a/interface/public/verify.js b/interface/public/verify.js index ca7b47f..94025f8 100644 --- a/interface/public/verify.js +++ b/interface/public/verify.js @@ -7,7 +7,6 @@ if (token) { } }).then(response => { if (response.status === 200) { - console.log(response.json()); $('#loginButton').hide(); $('#logoutButton').show(); } else { diff --git a/interface/routes/index.js b/interface/routes/index.js index fcc7c14..12cd088 100644 --- a/interface/routes/index.js +++ b/interface/routes/index.js @@ -8,8 +8,12 @@ router.use('/api', api); router.get('/', (req, res) => { - res.render('index', { - title: 'Home Page' + Promise.all([citizensController.findGenderDistribution()]).then(results => { + const [genderDistribution] = results; + res.render('index', { + title: 'Home Page', + genderDistribution + }); }); }); diff --git a/interface/views/index.ejs b/interface/views/index.ejs index 6848aa3..99dc89b 100644 --- a/interface/views/index.ejs +++ b/interface/views/index.ejs @@ -44,6 +44,14 @@
Citizens
+
+                Gender Statistics:
+ =====================
+ Male: <%= genderDistribution[0].genderCount %>
+ Female: <%= genderDistribution[1].genderCount %>
+ ---------------------
+ Total: <%= genderDistribution[0].genderCount + genderDistribution[1].genderCount %> +
Provides the details of all the citizens in the database
diff --git a/interface/views/partials/head.ejs b/interface/views/partials/head.ejs index c4b963e..1296994 100644 --- a/interface/views/partials/head.ejs +++ b/interface/views/partials/head.ejs @@ -3,3 +3,8 @@ Welfare Schemes | <%= title %> + -- cgit v1.2.3