From 40d2170921be1cddfc9482d481cbeb8d594f773a Mon Sep 17 00:00:00 2001 From: cinnasphere Date: Thu, 30 Jan 2025 13:37:01 -0600 Subject: [PATCH] Update backend configuration and routes - Add environment variables to .env - Update .gitignore to include .env - Define authentication routes in auth.routes.js - Implement signup and signin functions in auth.controller.js - Set up server with routes and CORS in server.js - Add fetch requests for testing endpoints in index.js --- .gitignore | 2 - README.md | 65 ------------- app/config/auth.config.js | 3 - app/config/db.config.js | 13 --- app/controllers/auth.controller.js | 91 ------------------ app/controllers/user.controller.js | 15 --- app/middleware/authJwt.js | 91 ------------------ app/middleware/index.js | 7 -- app/middleware/verifySignUp.js | 57 ----------- app/models/index.js | 37 ------- app/models/role.model.js | 13 --- app/models/user.model.js | 15 --- app/routes/auth.routes.js | 23 ----- app/routes/user.routes.js | 32 ------ jwt-refresh-token-node-js-example-flow.png | Bin 29168 -> 0 bytes ...en-authentication-node-js-example-flow.png | Bin 30531 -> 0 bytes package.json | 27 ------ server.js | 59 ------------ 18 files changed, 550 deletions(-) delete mode 100644 .gitignore delete mode 100644 README.md delete mode 100644 app/config/auth.config.js delete mode 100644 app/config/db.config.js delete mode 100644 app/controllers/auth.controller.js delete mode 100644 app/controllers/user.controller.js delete mode 100644 app/middleware/authJwt.js delete mode 100644 app/middleware/index.js delete mode 100644 app/middleware/verifySignUp.js delete mode 100644 app/models/index.js delete mode 100644 app/models/role.model.js delete mode 100644 app/models/user.model.js delete mode 100644 app/routes/auth.routes.js delete mode 100644 app/routes/user.routes.js delete mode 100644 jwt-refresh-token-node-js-example-flow.png delete mode 100644 jwt-token-authentication-node-js-example-flow.png delete mode 100644 package.json delete mode 100644 server.js diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 25c8fdb..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -package-lock.json \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 1b4ecc8..0000000 --- a/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Node.js – JWT Authentication example with PostgreSQL example - -## User Registration, User Login and Authorization process. -The diagram shows flow of how we implement User Registration, User Login and Authorization process. - -![jwt-token-authentication-node-js-example-flow](jwt-token-authentication-node-js-example-flow.png) - -For more detail, please visit: -> [Node.js JWT Authentication & Authorization with PostgreSQL example](https://www.bezkoder.com/node-js-jwt-authentication-postgresql/) - -You may need to implement Refresh Token: - -![jwt-refresh-token-node-js-example-flow](jwt-refresh-token-node-js-example-flow.png) - -> [Node.js JWT Refresh Token example](https://www.bezkoder.com/jwt-refresh-token-node-js/) - -Working with Front-end: -> [Vue.js JWT Authentication with Vuex and Vue Router](https://www.bezkoder.com/jwt-vue-vuex-authentication/) - -> [Angular 8 JWT Authentication example](https://www.bezkoder.com/angular-jwt-authentication/) - -> [Angular 10 JWT Authentication example](https://www.bezkoder.com/angular-10-jwt-auth/) - -> [Angular 11 JWT Authentication example](https://www.bezkoder.com/angular-11-jwt-auth/) - -> [Angular 12 JWT Authentication example](https://www.bezkoder.com/angular-12-jwt-auth/) - -> [Angular 13 JWT Authentication example](https://www.bezkoder.com/angular-13-jwt-auth/) - -> [React JWT Authentication & Authorization (without Redux) example](https://www.bezkoder.com/react-jwt-auth/) - -> [React Redux JWT Authentication & Authorization example](https://www.bezkoder.com/react-redux-jwt-auth/) - -## More Practice: -> [Node.js CRUD Rest APIs with Express, Sequelize & PostgreSQL example](https://www.bezkoder.com/node-express-sequelize-postgresql/) - -> [Node.js Express Pagination with PostgreSQL example](https://www.bezkoder.com/node-js-pagination-postgresql/) - -> [Node.js Express File Upload Rest API example](https://www.bezkoder.com/node-js-express-file-upload/) - -> [Node.js Express File Upload with Google Cloud Storage example](https://www.bezkoder.com/google-cloud-storage-nodejs-upload-file/) - -Associations: -> [Sequelize Associations: One-to-Many Relationship example](https://www.bezkoder.com/sequelize-associate-one-to-many/) - -> [Sequelize Associations: Many-to-Many Relationship example](https://www.bezkoder.com/sequelize-associate-many-to-many/) - -Integration on same Server/Port: -> [Integrate Vue with Node.js Express](https://www.bezkoder.com/serve-vue-app-express/) - -> [Integrate Angular with Node.js Express](https://www.bezkoder.com/integrate-angular-12-node-js/) - -> [Integrate React with Node.js Express](https://www.bezkoder.com/integrate-react-express-same-server-port/) - -## Project setup -``` -npm install -``` - -Then, edit `app/config/db.config.js` with correct DB credentials. - -### Run -``` -node server.js -``` diff --git a/app/config/auth.config.js b/app/config/auth.config.js deleted file mode 100644 index 4819df3..0000000 --- a/app/config/auth.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - secret: "bezkoder-secret-key" -}; diff --git a/app/config/db.config.js b/app/config/db.config.js deleted file mode 100644 index d186745..0000000 --- a/app/config/db.config.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - HOST: "localhost", - USER: "postgres", - PASSWORD: "123", - DB: "testdb", - dialect: "postgres", - pool: { - max: 5, - min: 0, - acquire: 30000, - idle: 10000 - } -}; \ No newline at end of file diff --git a/app/controllers/auth.controller.js b/app/controllers/auth.controller.js deleted file mode 100644 index 4dc09f6..0000000 --- a/app/controllers/auth.controller.js +++ /dev/null @@ -1,91 +0,0 @@ -const db = require("../models"); -const config = require("../config/auth.config"); -const User = db.user; -const Role = db.role; - -const Op = db.Sequelize.Op; - -var jwt = require("jsonwebtoken"); -var bcrypt = require("bcryptjs"); - -exports.signup = (req, res) => { - // Save User to Database - User.create({ - username: req.body.username, - email: req.body.email, - password: bcrypt.hashSync(req.body.password, 8) - }) - .then(user => { - if (req.body.roles) { - Role.findAll({ - where: { - name: { - [Op.or]: req.body.roles - } - } - }).then(roles => { - user.setRoles(roles).then(() => { - res.send({ message: "User registered successfully!" }); - }); - }); - } else { - // user role = 1 - user.setRoles([1]).then(() => { - res.send({ message: "User registered successfully!" }); - }); - } - }) - .catch(err => { - res.status(500).send({ message: err.message }); - }); -}; - -exports.signin = (req, res) => { - User.findOne({ - where: { - username: req.body.username - } - }) - .then(user => { - if (!user) { - return res.status(404).send({ message: "User Not found." }); - } - - var passwordIsValid = bcrypt.compareSync( - req.body.password, - user.password - ); - - if (!passwordIsValid) { - return res.status(401).send({ - accessToken: null, - message: "Invalid Password!" - }); - } - - const token = jwt.sign({ id: user.id }, - config.secret, - { - algorithm: 'HS256', - allowInsecureKeySizes: true, - expiresIn: 86400, // 24 hours - }); - - var authorities = []; - user.getRoles().then(roles => { - for (let i = 0; i < roles.length; i++) { - authorities.push("ROLE_" + roles[i].name.toUpperCase()); - } - res.status(200).send({ - id: user.id, - username: user.username, - email: user.email, - roles: authorities, - accessToken: token - }); - }); - }) - .catch(err => { - res.status(500).send({ message: err.message }); - }); -}; diff --git a/app/controllers/user.controller.js b/app/controllers/user.controller.js deleted file mode 100644 index e2fa15b..0000000 --- a/app/controllers/user.controller.js +++ /dev/null @@ -1,15 +0,0 @@ -exports.allAccess = (req, res) => { - res.status(200).send("Public Content."); -}; - -exports.userBoard = (req, res) => { - res.status(200).send("User Content."); -}; - -exports.adminBoard = (req, res) => { - res.status(200).send("Admin Content."); -}; - -exports.moderatorBoard = (req, res) => { - res.status(200).send("Moderator Content."); -}; diff --git a/app/middleware/authJwt.js b/app/middleware/authJwt.js deleted file mode 100644 index ccb5605..0000000 --- a/app/middleware/authJwt.js +++ /dev/null @@ -1,91 +0,0 @@ -const jwt = require("jsonwebtoken"); -const config = require("../config/auth.config.js"); -const db = require("../models"); -const User = db.user; - -verifyToken = (req, res, next) => { - let token = req.headers["x-access-token"]; - - if (!token) { - return res.status(403).send({ - message: "No token provided!" - }); - } - - jwt.verify(token, - config.secret, - (err, decoded) => { - if (err) { - return res.status(401).send({ - message: "Unauthorized!", - }); - } - req.userId = decoded.id; - next(); - }); -}; - -isAdmin = (req, res, next) => { - User.findByPk(req.userId).then(user => { - user.getRoles().then(roles => { - for (let i = 0; i < roles.length; i++) { - if (roles[i].name === "admin") { - next(); - return; - } - } - - res.status(403).send({ - message: "Require Admin Role!" - }); - return; - }); - }); -}; - -isModerator = (req, res, next) => { - User.findByPk(req.userId).then(user => { - user.getRoles().then(roles => { - for (let i = 0; i < roles.length; i++) { - if (roles[i].name === "moderator") { - next(); - return; - } - } - - res.status(403).send({ - message: "Require Moderator Role!" - }); - }); - }); -}; - -isModeratorOrAdmin = (req, res, next) => { - User.findByPk(req.userId).then(user => { - user.getRoles().then(roles => { - for (let i = 0; i < roles.length; i++) { - if (roles[i].name === "moderator") { - next(); - return; - } - - if (roles[i].name === "admin") { - next(); - return; - } - } - - res.status(403).send({ - message: "Require Moderator or Admin Role!" - }); - }); - }); -}; - -const authJwt = { - verifyToken: verifyToken, - isAdmin: isAdmin, - isModerator: isModerator, - isModeratorOrAdmin: isModeratorOrAdmin -}; -module.exports = authJwt; diff --git a/app/middleware/index.js b/app/middleware/index.js deleted file mode 100644 index 78a3414..0000000 --- a/app/middleware/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const authJwt = require("./authJwt"); -const verifySignUp = require("./verifySignUp"); - -module.exports = { - authJwt, - verifySignUp -}; diff --git a/app/middleware/verifySignUp.js b/app/middleware/verifySignUp.js deleted file mode 100644 index 2e2e030..0000000 --- a/app/middleware/verifySignUp.js +++ /dev/null @@ -1,57 +0,0 @@ -const db = require("../models"); -const ROLES = db.ROLES; -const User = db.user; - -checkDuplicateUsernameOrEmail = (req, res, next) => { - // Username - User.findOne({ - where: { - username: req.body.username - } - }).then(user => { - if (user) { - res.status(400).send({ - message: "Failed! Username is already in use!" - }); - return; - } - - // Email - User.findOne({ - where: { - email: req.body.email - } - }).then(user => { - if (user) { - res.status(400).send({ - message: "Failed! Email is already in use!" - }); - return; - } - - next(); - }); - }); -}; - -checkRolesExisted = (req, res, next) => { - if (req.body.roles) { - for (let i = 0; i < req.body.roles.length; i++) { - if (!ROLES.includes(req.body.roles[i])) { - res.status(400).send({ - message: "Failed! Role does not exist = " + req.body.roles[i] - }); - return; - } - } - } - - next(); -}; - -const verifySignUp = { - checkDuplicateUsernameOrEmail: checkDuplicateUsernameOrEmail, - checkRolesExisted: checkRolesExisted -}; - -module.exports = verifySignUp; diff --git a/app/models/index.js b/app/models/index.js deleted file mode 100644 index f57f9e9..0000000 --- a/app/models/index.js +++ /dev/null @@ -1,37 +0,0 @@ -const config = require("../config/db.config.js"); - -const Sequelize = require("sequelize"); -const sequelize = new Sequelize( - config.DB, - config.USER, - config.PASSWORD, - { - host: config.HOST, - dialect: config.dialect, - pool: { - max: config.pool.max, - min: config.pool.min, - acquire: config.pool.acquire, - idle: config.pool.idle - } - } -); - -const db = {}; - -db.Sequelize = Sequelize; -db.sequelize = sequelize; - -db.user = require("../models/user.model.js")(sequelize, Sequelize); -db.role = require("../models/role.model.js")(sequelize, Sequelize); - -db.role.belongsToMany(db.user, { - through: "user_roles" -}); -db.user.belongsToMany(db.role, { - through: "user_roles" -}); - -db.ROLES = ["user", "admin", "moderator"]; - -module.exports = db; diff --git a/app/models/role.model.js b/app/models/role.model.js deleted file mode 100644 index 345c247..0000000 --- a/app/models/role.model.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = (sequelize, Sequelize) => { - const Role = sequelize.define("roles", { - id: { - type: Sequelize.INTEGER, - primaryKey: true - }, - name: { - type: Sequelize.STRING - } - }); - - return Role; -}; diff --git a/app/models/user.model.js b/app/models/user.model.js deleted file mode 100644 index 63b8c28..0000000 --- a/app/models/user.model.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = (sequelize, Sequelize) => { - const User = sequelize.define("users", { - username: { - type: Sequelize.STRING - }, - email: { - type: Sequelize.STRING - }, - password: { - type: Sequelize.STRING - } - }); - - return User; -}; diff --git a/app/routes/auth.routes.js b/app/routes/auth.routes.js deleted file mode 100644 index a4fcd91..0000000 --- a/app/routes/auth.routes.js +++ /dev/null @@ -1,23 +0,0 @@ -const { verifySignUp } = require("../middleware"); -const controller = require("../controllers/auth.controller"); - -module.exports = function(app) { - app.use(function(req, res, next) { - res.header( - "Access-Control-Allow-Headers", - "x-access-token, Origin, Content-Type, Accept" - ); - next(); - }); - - app.post( - "/api/auth/signup", - [ - verifySignUp.checkDuplicateUsernameOrEmail, - verifySignUp.checkRolesExisted - ], - controller.signup - ); - - app.post("/api/auth/signin", controller.signin); -}; diff --git a/app/routes/user.routes.js b/app/routes/user.routes.js deleted file mode 100644 index 10f00c5..0000000 --- a/app/routes/user.routes.js +++ /dev/null @@ -1,32 +0,0 @@ -const { authJwt } = require("../middleware"); -const controller = require("../controllers/user.controller"); - -module.exports = function(app) { - app.use(function(req, res, next) { - res.header( - "Access-Control-Allow-Headers", - "x-access-token, Origin, Content-Type, Accept" - ); - next(); - }); - - app.get("/api/test/all", controller.allAccess); - - app.get( - "/api/test/user", - [authJwt.verifyToken], - controller.userBoard - ); - - app.get( - "/api/test/mod", - [authJwt.verifyToken, authJwt.isModerator], - controller.moderatorBoard - ); - - app.get( - "/api/test/admin", - [authJwt.verifyToken, authJwt.isAdmin], - controller.adminBoard - ); -}; diff --git a/jwt-refresh-token-node-js-example-flow.png b/jwt-refresh-token-node-js-example-flow.png deleted file mode 100644 index 6db0461beaaad86efc23cfc6c7c86f860265c08c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29168 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 diff --git a/package.json b/package.json deleted file mode 100644 index 42ff21f..0000000 --- a/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "node-js-jwt-auth-postgresql", - "version": "1.0.0", - "description": "Node.js Demo for JWT Authentication with PostgreSQL", - "main": "server.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "node js", - "express", - "jwt", - "authentication", - "postgresql" - ], - "author": "bezkoder", - "license": "ISC", - "dependencies": { - "bcryptjs": "^2.4.3", - "cors": "^2.8.5", - "express": "^4.18.2", - "jsonwebtoken": "^9.0.0", - "pg": "^8.11.1", - "pg-hstore": "^2.3.4", - "sequelize": "^6.32.1" - } -} diff --git a/server.js b/server.js deleted file mode 100644 index 71e6e0a..0000000 --- a/server.js +++ /dev/null @@ -1,59 +0,0 @@ -const express = require("express"); -const cors = require("cors"); - -const app = express(); - -var corsOptions = { - origin: "http://localhost:8081" -}; - -app.use(cors(corsOptions)); - -// parse requests of content-type - application/json -app.use(express.json()); - -// parse requests of content-type - application/x-www-form-urlencoded -app.use(express.urlencoded({ extended: true })); - -// database -const db = require("./app/models"); -const Role = db.role; - -// db.sequelize.sync(); -// force: true will drop the table if it already exists -db.sequelize.sync({force: true}).then(() => { - console.log('Drop and Resync Database with { force: true }'); - initial(); -}); - -// simple route -app.get("/", (req, res) => { - res.json({ message: "Welcome to bezkoder application." }); -}); - -// routes -require('./app/routes/auth.routes')(app); -require('./app/routes/user.routes')(app); - -// set port, listen for requests -const PORT = process.env.PORT || 8080; -app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}.`); -}); - -function initial() { - Role.create({ - id: 1, - name: "user" - }); - - Role.create({ - id: 2, - name: "moderator" - }); - - Role.create({ - id: 3, - name: "admin" - }); -} \ No newline at end of file