diff options
| author | Bobby <[email protected]> | 2022-06-03 14:36:30 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2022-06-03 14:36:30 +0530 |
| commit | 06e4ecd95bfd2817e56af83dbe9af1b6eba283bf (patch) | |
| tree | a2ec28bbab430e634b5c964d9e8c56e636e46062 | |
| parent | 1958098bdabf10f6b8ac9ea5851e08172dd8e10c (diff) | |
| download | thatcomputerscientist-06e4ecd95bfd2817e56af83dbe9af1b6eba283bf.tar.xz thatcomputerscientist-06e4ecd95bfd2817e56af83dbe9af1b6eba283bf.zip | |
complete login functionality
| -rw-r--r-- | package-lock.json | 237 | ||||
| -rw-r--r-- | package.json | 5 | ||||
| -rw-r--r-- | public/css/main.css | 4 | ||||
| -rw-r--r-- | routes/api/admin.js | 136 | ||||
| -rw-r--r-- | routes/api/user.js | 133 | ||||
| -rw-r--r-- | routes/auth.routes.js | 61 | ||||
| -rw-r--r-- | routes/basic.routes.js | 34 | ||||
| -rw-r--r-- | routes/index.js | 2 | ||||
| -rw-r--r-- | server.js | 11 | ||||
| -rw-r--r-- | views/partials/sidebar.ejs | 10 |
10 files changed, 476 insertions, 157 deletions
diff --git a/package-lock.json b/package-lock.json index 3ce51b02..e7379cf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,13 +12,16 @@ "@prisma/client": "^3.14.0", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", + "connect-flash": "^0.1.1", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.0.1", "ejs": "^3.1.8", "express": "^4.18.1", + "express-session": "^1.17.3", "jsonwebtoken": "^8.5.1", - "mysql2": "^2.3.3" + "mysql2": "^2.3.3", + "node-fetch": "^3.2.5" }, "devDependencies": { "nodemon": "^2.0.16" @@ -422,6 +425,14 @@ "node": ">=8" } }, + "node_modules/connect-flash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", + "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -495,6 +506,14 @@ "node": ">=8" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -694,6 +713,54 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -750,6 +817,17 @@ "node": ">= 0.8" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1433,6 +1511,41 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.5.tgz", + "integrity": "sha512-u7zCHdJp8JXBwF09mMfo2CL6kp37TslDl1KP3hRGTlCInBtag+UO3LGVy+NF0VzvnL3PVMpA2hXh1EtECFnyhQ==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/nodemon": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.16.tgz", @@ -1558,6 +1671,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1711,6 +1832,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2059,6 +2188,17 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -2156,6 +2296,14 @@ "node": ">= 0.8" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -2516,6 +2664,11 @@ "xdg-basedir": "^4.0.0" } }, + "connect-flash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", + "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2570,6 +2723,11 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2729,6 +2887,37 @@ "vary": "~1.1.2" } }, + "express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "requires": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + } + } + }, + "fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -2778,6 +2967,14 @@ "unpipe": "~1.0.0" } }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3305,6 +3502,21 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.5.tgz", + "integrity": "sha512-u7zCHdJp8JXBwF09mMfo2CL6kp37TslDl1KP3hRGTlCInBtag+UO3LGVy+NF0VzvnL3PVMpA2hXh1EtECFnyhQ==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, "nodemon": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.16.tgz", @@ -3394,6 +3606,11 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3508,6 +3725,11 @@ "side-channel": "^1.0.4" } }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -3773,6 +3995,14 @@ "is-typedarray": "^1.0.0" } }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -3845,6 +4075,11 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", diff --git a/package.json b/package.json index 31e0c4d3..625c1555 100644 --- a/package.json +++ b/package.json @@ -21,13 +21,16 @@ "@prisma/client": "^3.14.0", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", + "connect-flash": "^0.1.1", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.0.1", "ejs": "^3.1.8", "express": "^4.18.1", + "express-session": "^1.17.3", "jsonwebtoken": "^8.5.1", - "mysql2": "^2.3.3" + "mysql2": "^2.3.3", + "node-fetch": "^3.2.5" }, "devDependencies": { "nodemon": "^2.0.16" diff --git a/public/css/main.css b/public/css/main.css index 747fb352..c48c383d 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -73,3 +73,7 @@ nav > ul > li { margin-top: 0; margin-bottom: 10px; } + +.error { + color: red; +} diff --git a/routes/api/admin.js b/routes/api/admin.js index 080c6906..dd5d2744 100644 --- a/routes/api/admin.js +++ b/routes/api/admin.js @@ -1,82 +1,86 @@ const router = require("express").Router(); -const mysql = require('mysql2'); -const bcrypt = require('bcryptjs'); -const validateAuthorization = require('../../functions/validate'); +const mysql = require("mysql2"); +const bcrypt = require("bcryptjs"); +const validateAuthorization = require("../../functions/validate"); require("dotenv").config(); const connectionURL = process.env.DATABASE_URL; router.get("/", (req, res) => { - const validationHeader = req.headers.auth; - if (validateAuthorization(validationHeader)) { - res.status(200).json({ - message: "Welcome to the Admin API!" - }); - } else { - res.status(401).json({ - message: "Unauthorized" - }); - } + const validationHeader = req.headers.auth; + if (validateAuthorization(validationHeader)) { + res.status(200).json({ + message: "Welcome to the Admin API!", + }); + } else { + res.status(401).json({ + message: "Unauthorized", + }); + } }); router.post("/create", (req, res) => { - // Creates an admin user - const validationHeader = req.headers.auth; - if (validateAuthorization(validationHeader)) { - const connection = mysql.createConnection(connectionURL); - connection.connect(); - const sql = "INSERT INTO Users (username, password, admin) VALUES (?, ?, ?)"; - const username = req.body.username; - const password = req.body.password; - const hashedPassword = bcrypt.hashSync(password, 10); - const admin = 1; - connection.query(sql, [username, hashedPassword, admin], (err, results, fields) => { - if (err) { - res.status(500).json({ - message: "Error creating user", - error: err - }); - } else { - res.status(201).json({ - message: "User created" - }); - } - }); - connection.end(); - } else { - res.status(401).json({ - message: "Unauthorized" - }); - } + // Creates an admin user + const validationHeader = req.headers.auth; + if (validateAuthorization(validationHeader)) { + const connection = mysql.createConnection(connectionURL); + connection.connect(); + const sql = + "INSERT INTO Users (username, password, admin) VALUES (?, ?, ?)"; + const username = req.body.username; + const password = req.body.password; + const hashedPassword = bcrypt.hashSync(password, 10); + const admin = 1; + connection.query( + sql, + [username, hashedPassword, admin], + (err, results, fields) => { + if (err) { + res.status(500).json({ + message: "Error creating user", + error: err, + }); + } else { + res.status(201).json({ + message: "User created", + }); + } + } + ); + connection.end(); + } else { + res.status(401).json({ + message: "Unauthorized", + }); + } }); -router.post('/delete', (req, res) => { - // Deletes an admin user - const validationHeader = req.headers.auth; - if (validateAuthorization(validationHeader)) { - const connection = mysql.createConnection(connectionURL); - connection.connect(); - const sql = "DELETE FROM Users WHERE username = ?"; - const username = req.body.username; - connection.query(sql, [username], (err, results, fields) => { - if (err) { - res.status(500).json({ - message: "Error deleting user", - error: err - }); - } else { - res.status(200).json({ - message: "User deleted" - }); - } +router.post("/delete", (req, res) => { + // Deletes an admin user + const validationHeader = req.headers.auth; + if (validateAuthorization(validationHeader)) { + const connection = mysql.createConnection(connectionURL); + connection.connect(); + const sql = "DELETE FROM Users WHERE username = ?"; + const username = req.body.username; + connection.query(sql, [username], (err, results, fields) => { + if (err) { + res.status(500).json({ + message: "Error deleting user", + error: err, }); - connection.end(); - } else { - res.status(401).json({ - message: "Unauthorized" + } else { + res.status(200).json({ + message: "User deleted", }); - } + } + }); + connection.end(); + } else { + res.status(401).json({ + message: "Unauthorized", + }); + } }); - module.exports = router; diff --git a/routes/api/user.js b/routes/api/user.js index 5424619f..8874d2e5 100644 --- a/routes/api/user.js +++ b/routes/api/user.js @@ -1,77 +1,82 @@ const router = require("express").Router(); -const mysql = require('mysql2'); -const bcrypt = require('bcryptjs'); -const jwt = require('jsonwebtoken'); +const mysql = require("mysql2"); +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); require("dotenv").config(); const connectionURL = process.env.DATABASE_URL; const validationString = process.env.AUTHORIZATION_STRING; -router.post('/login', (req, res) => { - // Log in as user - const username = req.body.username; - const password = req.body.password; - const connection = mysql.createConnection(connectionURL); - connection.connect(); - const sql = "SELECT * FROM Users WHERE username = ?"; - connection.query(sql, [username], (err, results, fields) => { - if (err) { - res.status(500).json({ - message: "Error logging in", - error: err - }); +router.post("/login", (req, res) => { + // Log in as user + const username = req.body.username; + const password = req.body.password; + const connection = mysql.createConnection(connectionURL); + connection.connect(); + const sql = "SELECT * FROM Users WHERE username = ?"; + connection.query(sql, [username], (err, results, fields) => { + if (err) { + res.status(500).json({ + message: "Error logging in", + error: err, + }); + } else { + if (results.length > 0) { + const user = results[0]; + if (bcrypt.compareSync(password, user.password)) { + const token = jwt.sign( + { + username: user.username, + admin: user.admin, + }, + validationString + ); + res.status(200).json({ + message: "Logged in", + token: token, + }); } else { - if (results.length > 0) { - const user = results[0]; - if (bcrypt.compareSync(password, user.password)) { - const token = jwt.sign({ - username: user.username, - admin: user.admin - }, validationString); - res.status(200).json({ - message: "Logged in", - token: token - }); - } else { - res.status(401).json({ - message: "Incorrect password" - }); - } - } else { - res.status(401).json({ - message: "User not found" - }); - } + res.status(401).json({ + message: "Incorrect password", + }); } - }); - connection.end(); + } else { + res.status(401).json({ + message: "User not found", + }); + } + } + }); + connection.end(); }); -router.post('/create', (req, res) => { - // Creates a regular user - const username = req.body.username; - const password = req.body.password; - const connection = mysql.createConnection(connectionURL); - connection.connect(); - const sql = "INSERT INTO Users (username, password, admin) VALUES (?, ?, ?)"; - const hashedPassword = bcrypt.hashSync(password, 10); - const admin = 0; - connection.query(sql, [username, hashedPassword, admin], (err, results, fields) => { - if (err) { - res.status(500).json({ - message: "Error creating user", - error: err - }); - } else { - res.status(201).json({ - message: "User created" - }); - } - }); - connection.end(); +router.post("/create", (req, res) => { + // Creates a regular user + const username = req.body.username; + const password = req.body.password; + const connection = mysql.createConnection(connectionURL); + connection.connect(); + const sql = "INSERT INTO Users (username, password, admin) VALUES (?, ?, ?)"; + const hashedPassword = bcrypt.hashSync(password, 10); + const admin = 0; + connection.query( + sql, + [username, hashedPassword, admin], + (err, results, fields) => { + if (err) { + res.status(500).json({ + message: "Error creating user", + error: err, + }); + } else { + res.status(201).json({ + message: "User created", + }); + } + } + ); + connection.end(); }); - - -module.exports = router;
\ No newline at end of file +module.exports = router; diff --git a/routes/auth.routes.js b/routes/auth.routes.js new file mode 100644 index 00000000..da1f339f --- /dev/null +++ b/routes/auth.routes.js @@ -0,0 +1,61 @@ +const router = require("express").Router(); +const jwt = require("jsonwebtoken"); +const mysql = require('mysql2'); +const bcrypt = require('bcryptjs'); + +require("dotenv").config(); +const validationString = process.env.AUTHORIZATION_STRING; +const connectionURL = process.env.DATABASE_URL; + +router.get('/logout', (req, res) => { + res.clearCookie("token"); + res.redirect(req.get('referer')); +}) + +router.post('/login', (req, res) => { + // Log in as user + const username = req.body.username; + const password = req.body.password; + const connection = mysql.createConnection(connectionURL); + connection.connect(); + const sql = "SELECT * FROM Users WHERE username = ?"; + connection.query(sql, [username], (err, results, fields) => { + if (err) { + res.status(500).json({ + message: "Error logging in", + error: err + }); + } else { + if (results.length > 0) { + const user = results[0]; + if (bcrypt.compareSync(password, user.password)) { + // expires in 30 days + const token = jwt.sign({ + username: user.username, + admin: user.admin + }, validationString, { + expiresIn: '30d' + }); + // set cookie + res.cookie('token', token, { + maxAge: 30 * 24 * 60 * 60 * 1000, + httpOnly: true + }); + res.redirect(req.get('referer')); + } else { + // incorrect password, redirect to referer with error + req.flash('error', 'Incorrect password'); + res.redirect(req.get('referer')); + } + } else { + // user not found, redirect to referer with error + req.flash('error', 'User not found'); + res.redirect(req.get('referer')); + } + } + }); + connection.end(); +}); + + +module.exports = router;
\ No newline at end of file diff --git a/routes/basic.routes.js b/routes/basic.routes.js index 4049a974..143db16d 100644 --- a/routes/basic.routes.js +++ b/routes/basic.routes.js @@ -5,26 +5,20 @@ require("dotenv").config(); const validationString = process.env.AUTHORIZATION_STRING; router.get("/", (req, res) => { - if (req.cookies.token) { - jwt.verify(req.cookies.token, validationString, (err, decoded) => { - if (err) { - res.clearCookie("token"); - res.render("index", { - title: 'Home' - }); - } else { - res.render('index', { - title: 'Home', - username: decoded.username - }) - } - }); - } else { - res.render('index', { - title: 'Home' - }); - } + res.locals.messages = req.flash(); + jwt.verify(req.cookies.token, validationString, (err, decoded) => { + if (err) { + res.clearCookie("token"); + res.render("index", { + title: "Home" + }); + } else { + res.render("index", { + title: "Home", + username: decoded.username + }); + } + }); }); module.exports = router; - diff --git a/routes/index.js b/routes/index.js index ac3048f4..ad5506f0 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,8 +1,10 @@ const router = require("express").Router(); const home = require('./basic.routes'); +const auth = require('./auth.routes'); const api = require('./api'); router.use('/', home); +router.use('/auth', auth); router.use('/api', api); module.exports = router; @@ -2,13 +2,22 @@ const express = require("express"); const cors = require("cors"); const bodyParser = require("body-parser"); const cookieParser = require('cookie-parser'); +const flash = require('connect-flash'); +const expressSession = require('express-session'); const app = express(); const port = process.env.PORT || 3000; +require("dotenv").config(); // Middleware app.use(cors()); -app.use(bodyParser.json()); +app.use(express.json()); app.use(cookieParser()); +app.use(express.urlencoded({ extended: true })); +app.use(expressSession({ + cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 }, + secret: process.env.AUTHORIZATION_STRING, +})); +app.use(flash()); // Set Template Engine app.set("view engine", "ejs"); diff --git a/views/partials/sidebar.ejs b/views/partials/sidebar.ejs index 55b1412b..376a5552 100644 --- a/views/partials/sidebar.ejs +++ b/views/partials/sidebar.ejs @@ -3,21 +3,23 @@ <h1>That Computer Scientist</h1> <!-- Login Box --> </a> - <% if (username) { %> + <% if (locals.username) { %> <div class="login-box"> <p>Welcome, <%= username %>!</p> - <a href="/logout">Logout</a> + <a href="/auth/logout">Logout</a> </div> <% } else { %> - <form method="post" onsubmit="event.preventDefault();"> + <form method="post" action="/auth/login"> <fieldset> <legend>Login Area</legend> <label for="username">Username</label> <input type="text" id="username" name="username" placeholder="Username" autocomplete="off"> <label for="password">Password</label> <input type="password" id="password" name="password" placeholder="Password"> + <% if (locals.messages) { %> + <p class="error"><%= messages.error %></p> + <% } %> <input type="submit" value="Login"> - <a href="/register">Register</a> </fieldset> </form> <% } %> |
