Skip to content

Commit

Permalink
feat: user management
Browse files Browse the repository at this point in the history
Completed the basic user management system with server included
  • Loading branch information
ASEEMMUHAMMAD A. R committed Apr 23, 2021
1 parent 20b5e1e commit 677c0d8
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 0 deletions.
3 changes: 3 additions & 0 deletions server/app/config/auth.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
secret: "this-is-secret"
};
5 changes: 5 additions & 0 deletions server/app/db.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
HOST: "localhost",
PORT: 27017,
DB: "jwtauth"
}
9 changes: 9 additions & 0 deletions server/app/models/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

const db = {};

db.mongoose = mongoose;
db.user = require('./user.model');

module.exports = db;
15 changes: 15 additions & 0 deletions server/app/models/user.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const mongoose = require("mongoose");

const User = mongoose.model(
"User",
new mongoose.Schema({
firstName: String,
lastName: String,
username: String,
email: String,
password: String,
roles: String,
})
);

module.exports = User;
81 changes: 81 additions & 0 deletions server/controllers/auth.controllers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const config = require('../app/config/auth.config');
const db = require('../app/models');
const User = db.user;

var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');

exports.signup = (req, res) => {
const user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
username: req.body.username,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8)
});

user.save((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
// Role.findOne({ name: "user" }, (err, role) => {
// if (err) {
// res.status(500).send({ message: err });
// return;
// }

// user.roles = [role._id];
// user.save(err => {
// if (err) {
// res.status(500).send({ message: err });
// return;
// }

// res.send({ message: "User was registered successfully!" });
// });
// });
res.send({ message: "User was registered successfully!" });
});
};

exports.signin = (req, res) => {
console.log(req);
User.findOne({
username: req.body.username
})
.populate("role", "-__v")
.exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (!user) {
return res.send({ message: "User nor found!" });
}

var passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);

if (!passwordIsValid) {
return res.send({
accessToken: null,
message: "Invalid Password"
});
}

var token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400
});
res.status(200).send({
id: user._id,
fName: user.firstName,
lName: user.lastName,
username: user.username,
email: user.email,
accessToken: token
});
});
};
15 changes: 15 additions & 0 deletions server/controllers/user.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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!");
}
90 changes: 90 additions & 0 deletions server/middlewares/authJwt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const jwt = require('jsonwebtoken');
const config = require('../app/config/auth.config');
const db = require('../app/models');
const User = db.user;
const Role = db.role;

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, decode) => {
if(err){
return res.status(401).send({ message: "unautherized!" });
}
req.userId = decode.id;
next();
});
};

isAdmin = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if(err){
res.status(500).send({ message: err});
return;
}

Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if(err){
res.status(500).send({ message: err});
return;
}

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.findById(req.userId).exec((err, user) => {
if(err){
res.status(500).send({ message: err});
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if(err){
res.status(500).send({ message: err });
return;
}

for(let i = 0; i < roles.length; i++) {
if(roles[i].name === 'moderator') {
next();
return;
}
}

res.status(403).send({ message: "Require moderator role!" });
return;
}
);
});
};

const authJwt = {
verifyToken,
isAdmin,
isModerator
};

module.exports = authJwt;
7 changes: 7 additions & 0 deletions server/middlewares/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const authJwt = require('./authJwt');
const verifySignUp = require('./verifySignUp');

module.exports = {
authJwt,
verifySignUp
}
40 changes: 40 additions & 0 deletions server/middlewares/verifySignUp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const db = require('../app/models');
const User = db.user;



checkDuplicateUsernameOrEmail = (req, res, next) => {
User.findOne({
username: req.body.username
}).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}

if (user) {
res.status(400).send({ message: "Username already exists." });
return;
}

User.findOne({
email: req.body.email
}).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (user) {
res.status(400).send({ message: "Email already in use" });
return;
}
next();
});
});
};

const verifySignUp = {
checkDuplicateUsernameOrEmail
};

module.exports = verifySignUp;
20 changes: 20 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "login_demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.12.5"
}
}
22 changes: 22 additions & 0 deletions server/routes/auth.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { verifySignUp } = require('../middlewares');
const controller = require('../controllers/auth.controllers');

module.exports = function (app) {
app.use((req, res, next) => {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});

app.post(
"/api/auth/signup",
[
verifySignUp.checkDuplicateUsernameOrEmail
],
controller.signup
);

app.post('/api/auth/signin', controller.signin);
};
27 changes: 27 additions & 0 deletions server/routes/user.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { authJwt } = require('../middlewares');
const controller = require('../controllers/user.controller');

module.exports = function (app) {
app.use(function (req, res, next) {
res.header(
'Access-Control-Allow-Header',
'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
);
};

0 comments on commit 677c0d8

Please sign in to comment.