Compare commits

...

3 Commits

24 changed files with 1544 additions and 1989 deletions

View File

@ -2,4 +2,9 @@ JWT_ACCESS_TIME=
JWT_REFRESH_TIME=
REDIS_PORT=
REDIS_HOST=
DB_CONN_STRING=
DB_CONN_STRING=
MAIL_HOST=
MAIL_PORT=
MAIL_USER=
MAIL_PASS=
MAIL_FROM=

8
.eslintrc.yml Normal file
View File

@ -0,0 +1,8 @@
env:
commonjs: true
es2021: true
node: true
extends: eslint:recommended
parserOptions:
ecmaVersion: latest
rules: {}

5
.husky/pre-commit Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx pretty-quick --staged
npm run lint --fix

4
.prettierignore Normal file
View File

@ -0,0 +1,4 @@
*.key
yarn.lock
package-lock.json
*.log

6
.prettierrc Normal file
View File

@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true
}

View File

@ -1,23 +1,48 @@
# jwt-auth-nodejs
Template to get started with Backend auth module for REST API
[![imgshields](https://img.shields.io/badge/Version-3-yellowgreen?style=for-the-badge)](https://shields.io/)
[![imgshields](<https://img.shields.io/badge/NodeJS-16(JS)-yellow?style=for-the-badge>)](https://shields.io/)
[![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com)
[![forthebadge](https://forthebadge.com/images/badges/open-source.svg)](https://forthebadge.com)
[![forthebadge](https://forthebadge.com/images/badges/made-with-javascript.svg)](https://forthebadge.com)
[![forthebadge](https://forthebadge.com/images/badges/0-percent-optimized.svg)](https://forthebadge.com)
## Fetures :-
- MongoDB as Database
- JWT as Authentication
- Nodemailer as Email Service
- Express as Web Server
- Error Handling with Express
- RSA Key Value Pair for Encryption
- Husky as Prettier ESLint and Git Hooks
- Ready to Deploy
# Setup
After pulling this project, create a file named .env in the root of the project and add below information. Change the values of below keys as per your requirement.
After pulling this project, create a file named .env in the root of the project and add below configuration. Change the values of below keys as per your requirement.
- .env example
- .env example
```
JWT_ACCESS_TIME=30s
JWT_ACCESS_TIME=7h
JWT_REFRESH_TIME=30d
REDIS_HOST=192.168.100.101
REDIS_PORT=6379
DB_CONN_STRING=mongodb://127.0.0.1:27017/nodejsjwtauth
MAIL_HOST=smtp.ethereal.email
MAIL_PORT=587
MAIL_USER=cecile.leffler67@ethereal.email
MAIL_PASS=7TfEXqF2GQcmDRGN82
MAIL_FROM="Cecile Leffler <cecile.leffler67@ethereal.email>"
```
- Deffi-Hellman key exchange setup
- Deffi-Hellman key exchange setup
```bash
ssh-keygen -t rsa -P "" -b 4096 -m PEM -f jwtRS256.key
ssh-keygen -e -m PEM -f jwtRS256.key > jwtRS256.key.pub
```
```

View File

@ -0,0 +1,170 @@
const User = require('../models/user.model')
const redis_client = require('../helpers/redis_connect')
const {
GenerateAccessToken,
GenerateRefreshToken,
} = require('../services/auth.service')
const Mailer = require('../services/mail.service')
async function Register(req, res, next) {
// encrypt password
const checkIfUsernameExists = await User.findOne({
username: req.body.username,
}).exec()
const checkIfEmailExists = await User.findOne({
email: req.body.email,
}).exec()
if (checkIfUsernameExists !== null || checkIfEmailExists !== null)
throw new Error('Username or Email already exists')
const user = new User({
username: req.body.username,
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
phone: req.body.phone,
address: {
street: req.body.address,
city: req.body.city,
state: req.body.state,
zip: req.body.zip,
country: req.body.country,
},
birthday: req.body.birthday,
})
user.setPassword(req.body.password)
try {
const saved_user = await user.save()
Mailer.sendMail({
to: saved_user.email,
subject: 'Welcome to the app',
text: `Welcome to the app, ${saved_user.username}`,
})
res.json({
status: true,
message: 'Registered successfully.',
data: saved_user,
})
} catch (error) {
// do logging in DB or file.
next(error)
}
}
async function Login(req, res, next) {
const username = req.body.username
try {
const user = await User.findOne({
username: username,
}).exec()
if (user === null || !user.validatePassword(req.body.password))
throw new Error('Username or Password is not valid')
const access_token = GenerateAccessToken(user._id)
const refresh_token = GenerateRefreshToken(user._id)
return res.json({
status: true,
message: 'Login Successfully.',
data: {
access_token,
refresh_token,
},
})
} catch (error) {
next(error)
}
}
async function Logout(req, res, next) {
try {
const user_id = req.userData.user
const token = req.token
await redis_client.del(user_id.toString())
await redis_client.set('BL_' + user_id.toString(), token)
return res.json({
status: true,
message: 'Successfully Logged out',
})
} catch (error) {
next(error)
}
}
async function checkUsernameAvaiblity(req, res, next) {
const username = req.params.username
try {
const user = await User.findOne({
username: username,
}).exec()
if (user === null)
return res.status(200).json({
status: true,
message: 'Username is available',
})
return res.status(200).json({
status: false,
message: 'Username is not available',
})
} catch (error) {
next(error)
}
}
async function GetOnlyNewAccessToken(req, res, next) {
try {
const userData = req.userData.user
const access_token = GenerateAccessToken(userData)
return res.json({
status: true,
message: 'Successfully generated new access token.',
data: {
access_token,
},
})
} catch (error) {
next(error)
}
}
async function GetNewToken(req, res, next) {
try {
const userData = req.userData.user
const access_token = GenerateAccessToken(userData)
const refresh_token = GenerateRefreshToken(userData)
return res.json({
status: true,
message:
'Successfully generated new access token and refresh token.',
data: {
access_token,
refresh_token,
},
})
} catch (error) {
next(error)
}
}
module.exports = {
Register,
Login,
Logout,
checkUsernameAvaiblity,
GetOnlyNewAccessToken,
GetNewToken,
}

View File

@ -1,138 +1,119 @@
const User = require("../models/user.model");
const jwt = require("jsonwebtoken");
const redis_client = require("../redis_connect");
const User = require('../models/user.model')
async function Register(req, res) {
// encrypt password
const user = new User({
username: req.body.username,
});
user.setPassword(req.body.password);
async function GetUserById(req, res, next) {
const user_id = req.params.user_id
try {
const saved_user = await user.save();
res.json({
status: true,
message: "Registered successfully.",
data: saved_user,
});
} catch (error) {
// do logging in DB or file.
res.status(400).json({
status: false,
message: "Something went wrong.",
data: error,
});
}
}
try {
const user = await User.findById(user_id).exec()
async function Login(req, res) {
const username = req.body.username;
if (user === null) throw new Error('User not found')
try {
const user = await User.findOne({
username: username,
}).exec();
if (user === null || !user.validatePassword(req.body.password))
return res.status(401).json({
status: false,
message: "Username or Password is not valid.",
});
// console.log("user", user);
const access_token = jwt.sign(
{
sub: user._id,
},
process.env.JWT_ACCESS_SECRET,
{
expiresIn: process.env.JWT_ACCESS_TIME,
}
);
// console.log("access_token", access_token);
const refresh_token = GenerateRefreshToken(user._id);
return res.json({
status: true,
message: "Login Successfully.",
data: {
access_token,
refresh_token,
},
});
} catch (error) {
return res.status(401).json({
status: true,
message: "Login Failiure.",
data: error,
});
}
}
async function Logout(req, res) {
const user_id = req.userData.sub;
const token = req.token;
await redis_client.del(user_id.toString());
await redis_client.set("BL_" + user_id.toString(), token);
return res.json({
status: true,
message: "Successfully Logged out.",
});
}
function GetAccessToken(req, res) {
const user_id = req.userData.sub;
const access_token = jwt.sign(
{
sub: user_id,
},
process.env.JWT_ACCESS_SECRET,
{
expiresIn: process.env.JWT_ACCESS_TIME,
return res.json({
status: true,
message: 'User found.',
data: user,
})
} catch (error) {
next(error)
}
);
const refresh_token = GenerateRefreshToken(user_id);
return res.json({
status: true,
message: "Success successfully Generated RefreshToken",
data: {
access_token,
refresh_token,
},
});
}
function GenerateRefreshToken(user_id) {
const refresh_token = jwt.sign(
{
sub: user_id,
},
process.env.JWT_REFRESH_SECRET,
{
expiresIn: process.env.JWT_REFRESH_TIME,
async function GetUserByUsername(req, res, next) {
const username = req.params.username
try {
const user = await User.findOne({
username: username,
}).exec()
if (user === null) throw new Error('User not found')
return res.json({
status: true,
message: 'User found.',
data: user,
})
} catch (error) {
next(error)
}
);
}
redis_client.get(user_id.toString(), (err, data) => {
if (err) throw err;
async function GetAllUsers(_req, res, next) {
try {
const users = await User.find().exec()
redis_client.set(
user_id.toString(),
JSON.stringify({
token: refresh_token,
})
);
});
if (users === null) throw new Error('User not found')
return refresh_token;
return res.json({
status: true,
message: 'Users found.',
data: users,
})
} catch (error) {
next(error)
}
}
async function UpdateUser(req, res, next) {
const user_id = req.userData.user
const userData = req.body
try {
const user = await User.findById(user_id).exec()
if (user === null) throw new Error('User not found')
const updatedUser = await User.findByIdAndUpdate(user_id, userData, {
new: true,
}).exec()
return res.json({
status: true,
message: 'User updated.',
data: updatedUser,
})
} catch (error) {
next(error)
}
}
async function Dashboard(req, res, next) {
const user_id = req.userData.user
try {
return res.json({
status: true,
message: 'Hello ' + user_id + ' from dashboard.',
})
} catch (error) {
next(error)
}
}
async function DeleteUser(req, res, next) {
const user_id = req.userData.user
try {
const user = await User.findById(user_id).exec()
if (user === null) throw new Error('User not found')
await User.findByIdAndDelete(user_id).exec()
return res.json({
status: true,
message: 'User deleted.',
})
} catch (error) {
next(error)
}
}
module.exports = {
Register,
Login,
Logout,
GetAccessToken,
};
GetUserById,
GetAllUsers,
GetUserByUsername,
UpdateUser,
Dashboard,
DeleteUser,
}

13
helpers/mongo_connect.js Normal file
View File

@ -0,0 +1,13 @@
const mongoose = require('mongoose')
module.exports = async () => {
await mongoose.connect(
process.env.DB_CONN_STRING,
{
useUnifiedTopology: true,
useNewUrlParser: true,
useFindAndModify: false,
},
() => console.log('Connected to MongoDB 🍀')
)
}

12
helpers/redis_connect.js Normal file
View File

@ -0,0 +1,12 @@
const redis = require('redis')
const redis_client = redis.createClient(
process.env.REDIS_PORT,
process.env.REDIS_HOST
)
redis_client.on('connect', function () {
console.log('Redis Client connected 🍒')
})
module.exports = redis_client

View File

@ -1,22 +1,45 @@
require("dotenv").config();
const express = require("express");
const app = express();
require('dotenv').config()
const express = require('express')
const fs = require('fs')
const morgan = require('morgan')
const cors = require('cors')
const mongoose = require("mongoose");
const app = express()
const connectMongo = require('./helpers/mongo_connect')
const checkENV = require('./utils/checkENV.utils')
const err_routes = require('./utils/errorHandler.utils')
mongoose.connect(
process.env.DB_CONN_STRING,
{ useUnifiedTopology: true, useNewUrlParser: true },
() => console.log("Connected to MongoDB 🍀")
);
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(morgan('tiny'))
app.use(cors())
app.use(express.json());
// Connect to MongoDB and Config Checking
;(async () => {
try {
setTimeout(async () => {
console.log('Connecting to MongoDB ...')
await connectMongo()
console.log('Checking Config ...')
await checkENV()
}, 1000)
} catch (error) {
console.log(error.message)
process.exit(1)
}
})()
const auth_routes = require("./routes/auth.route");
const user_routes = require("./routes/user.route");
console.log('Auto Loading routes 🎩 ...')
fs.readdirSync('./routes/').forEach(function (file) {
console.log('Loading route: /' + file.split('.')[0])
app.use(`/${file.split('.')[0]}`, require('./routes/' + file))
})
console.log('Loaded all routes 🎩 ...')
app.use("/auth", auth_routes);
app.use("/user", user_routes);
app.use('*', err_routes.notFound)
app.use(err_routes.logErrors)
app.use(err_routes.clientErrorHandler)
app.use(err_routes.errorHandler)
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`🤖 API Server is running at ${port} ...`));
const port = process.env.PORT || 5000
app.listen(port, () => console.log(`🤖 API Server is running at ${port} ...`))

11
jsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2020",
"jsx": "preserve",
"strictNullChecks": true,
"strictFunctionTypes": true
},
"exclude": ["node_modules", "**/node_modules/*"]
}

View File

@ -1,75 +1,63 @@
const jwt = require("jsonwebtoken");
const redis_client = require("../redis_connect");
const jwt = require('jsonwebtoken')
const redis_client = require('../helpers/redis_connect')
const fs = require('fs')
const publicKey = fs.readFileSync('jwtRS256.key.pub')
function verifyToken(req, res, next) {
try {
// Bearer tokenstring
const token = req.headers.authorization.split(" ")[1];
function verifyToken(req, _res, next) {
try {
// Bearer tokenstring
if (req.headers.authorization === undefined)
throw new Error('Invalid request')
const decoded = jwt.verify(token, process.env.JWT_ACCESS_SECRET);
req.userData = decoded;
const token = req.headers.authorization.split(' ')[1]
req.token = token;
const decoded = jwt.verify(token, publicKey)
// varify blacklisted access token.
redis_client.get("BL_" + decoded.sub.toString(), (err, data) => {
if (err) throw err;
if (decoded.tokenType !== 'access_token')
throw new Error('Invalid token')
if (data === token)
return res.status(401).json({
status: false,
message: "blacklisted token.",
});
next();
});
} catch (error) {
return res.status(401).json({
status: false,
message: "Your session is not valid.",
data: error,
});
}
req.userData = decoded
req.token = token
// verify blacklisted access token.
redis_client.get('BL_' + decoded.user.toString(), (err, data) => {
if (err) throw err
if (data === token) throw new Error('Blacklisted token')
next()
})
} catch (error) {
next(error)
}
}
function verifyRefreshToken(req, res, next) {
const token = req.body.token;
function verifyRefreshToken(req, _res, next) {
const token = req.body.token
if (token === null)
return res.status(401).json({
status: false,
message: "Invalid request.",
});
try {
const decoded = jwt.verify(token, process.env.JWT_REFRESH_SECRET);
req.userData = decoded;
if (token === null) throw new Error('Invalid request')
try {
const decoded = jwt.verify(token, publicKey)
req.userData = decoded
if (decoded.tokenType !== 'refresh_token')
throw new Error('Invalid token.')
// verify if token is in store or not
redis_client.get(decoded.user.toString(), (err, data) => {
if (err) throw err
// verify if token is in store or not
redis_client.get(decoded.sub.toString(), (err, data) => {
if (err) throw err;
if (data === null)
throw new Error('Invalid request :- Token is not in store')
if (JSON.parse(data).token != token)
throw new Error('Invalid request :- Token is not in store')
if (data === null)
return res.status(401).json({
status: false,
message: "Invalid request. Token is not in store.",
});
if (JSON.parse(data).token != token)
return res.status(401).json({
status: false,
message: "Invalid request. Token is not same in store.",
});
next();
});
} catch (error) {
return res.status(401).json({
status: true,
message: "Your session is not valid.",
data: error,
});
}
next()
})
} catch (error) {
next(error)
}
}
module.exports = {
verifyToken,
verifyRefreshToken,
};
verifyToken,
verifyRefreshToken,
}

View File

@ -1,38 +1,97 @@
const mongoose = require("mongoose");
const crypto = require("crypto");
const mongoose = require('mongoose')
const crypto = require('crypto')
const { nanoid } = require('napi-nanoid')
const userSchema = new mongoose.Schema({
username: {
type: String,
require: true,
min: 6,
max: 255,
},
password: {
type: String,
require: true,
},
email: {
type: String,
require: true,
},
name: { type: String },
salt: { type: String },
hash: { type: String },
});
username: {
type: String,
require: true,
min: 6,
max: 255,
},
password: {
type: String,
require: true,
},
email: {
type: String,
require: true,
},
name: {
first_name: {
type: String,
require: true,
},
last_name: {
type: String,
require: true,
},
},
phone: {
type: String,
},
address: {
street: {
type: String,
},
city: {
type: String,
},
state: {
type: String,
},
zip: {
type: String,
},
country: {
type: String,
},
},
birthday: {
type: Date,
},
salt: {
type: String,
},
hash: {
type: String,
},
attributes: {
isVerified: {
type: Boolean,
default: false,
},
emailVerificationToken: {
type: String,
default: nanoid(),
},
isAdmin: {
type: Boolean,
default: false,
},
isActive: {
type: Boolean,
default: false,
},
isDeleted: {
type: Boolean,
default: false,
},
},
})
userSchema.methods.setPassword = function (password) {
this.salt = crypto.randomBytes(16).toString("hex");
this.hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, "sha512")
.toString("hex");
};
this.salt = crypto.randomBytes(16).toString('hex')
this.hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
.toString('hex')
}
userSchema.methods.validatePassword = function (password) {
const hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, "sha512")
.toString("hex");
return this.hash === hash;
};
const hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
.toString('hex')
return this.hash === hash
}
module.exports = mongoose.model("User", userSchema);
module.exports = mongoose.model('User', userSchema)

1693
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,35 @@
{
"name": "jwt-auth-nodejs",
"version": "2.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"crypto": "^1.0.1",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.11.17",
"redis": "^3.0.2"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
"name": "jwt-auth-nodejs",
"version": "2.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"pretty": "prettier --write .",
"prepare": "husky install",
"lint": "eslint ."
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"crypto": "^1.0.1",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.11.17",
"morgan": "^1.10.0",
"napi-nanoid": "^0.0.3",
"nodemailer": "^6.7.6",
"redis": "^3.0.2"
},
"devDependencies": {
"eslint": "^8.19.0",
"husky": "^8.0.0",
"nodemon": "^2.0.7",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3"
}
}

View File

@ -1,12 +0,0 @@
const redis = require("redis");
const redis_client = redis.createClient(
process.env.REDIS_PORT,
process.env.REDIS_HOST
);
redis_client.on("connect", function () {
console.log("Redis Client connected 🍒");
});
module.exports = redis_client;

View File

@ -1,12 +1,20 @@
const route = require('express').Router();
const user_controller = require('../controllers/user.controller');
const auth_middleware = require('../middlewares/auth.middleware');
const route = require('express').Router()
const user_controller = require('../controllers/auth.controller')
const auth_middleware = require('../middlewares/auth.middleware')
route.post('/register', user_controller.Register)
route.post('/login', user_controller.Login)
route.get('/status/:username', user_controller.checkUsernameAvaiblity)
route.post(
'/token',
auth_middleware.verifyRefreshToken,
user_controller.GetOnlyNewAccessToken
)
route.post(
'/token/reset',
auth_middleware.verifyRefreshToken,
user_controller.GetNewToken
)
route.get('/logout', auth_middleware.verifyToken, user_controller.Logout)
route.post('/register', user_controller.Register);
route.post('/login', user_controller.Login);
route.post('/token', auth_middleware.verifyRefreshToken, user_controller.GetAccessToken);
route.get('/logout', auth_middleware.verifyToken, user_controller.Logout);
module.exports = route;
module.exports = route

View File

@ -1,8 +1,20 @@
const route = require('express').Router();
const auth_middleware = require('../middlewares/auth.middleware');
const route = require('express').Router()
const auth_middleware = require('../middlewares/auth.middleware')
const user_controller = require('../controllers/user.controller')
route.get('/dashboard', auth_middleware.verifyToken, (req, res) => {
return res.json({status: true, message: "Hello from dashboard."});
});
route.get('/dashboard', auth_middleware.verifyToken, user_controller.Dashboard)
route.get('/all', auth_middleware.verifyToken, user_controller.GetAllUsers)
route.get(
'/:username',
auth_middleware.verifyToken,
user_controller.GetUserByUsername
)
route.get(
'/id/:user_id',
auth_middleware.verifyRefreshToken,
user_controller.GetUserById
)
route.patch('/', auth_middleware.verifyToken, user_controller.UpdateUser)
route.delete('/', auth_middleware.verifyToken, user_controller.DeleteUser)
module.exports = route;
module.exports = route

View File

@ -0,0 +1,40 @@
const jwt = require('jsonwebtoken')
const redis_client = require('../helpers/redis_connect')
const fs = require('fs')
const privateKey = fs.readFileSync('jwtRS256.key')
function GenerateAccessToken(user_id) {
let userData = {
tokenType: 'access_token',
user: user_id,
}
return jwt.sign(userData, privateKey, {
algorithm: 'RS256',
expiresIn: '1d',
})
}
function GenerateRefreshToken(user_id) {
const setReferesh = {
tokenType: 'refresh_token',
user: user_id,
}
const refresh_token = jwt.sign(setReferesh, privateKey, {
algorithm: 'RS256',
expiresIn: '7d',
})
redis_client.set(
setReferesh.user.toString(),
JSON.stringify({
token: refresh_token,
})
)
return refresh_token
}
module.exports = {
GenerateAccessToken,
GenerateRefreshToken,
}

30
services/mail.service.js Normal file
View File

@ -0,0 +1,30 @@
const nodemailer = require('nodemailer')
let mailClient = nodemailer.createTransport({
host: process.env.MAIL_HOST,
port: process.env.MAIL_PORT,
secure: false, // true for 465, false for other ports
auth: {
user: process.env.MAIL_USER, // generated ethereal user
pass: process.env.MAIL_PASS, // generated ethereal password
},
})
async function sendMail(body, next) {
const { to, subject, text } = body
const mailOptions = {
from: process.env.MAIL_FROM,
to: to,
subject: subject,
text: text,
}
try {
await mailClient.sendMail(mailOptions)
} catch (error) {
next(error)
}
}
module.exports = {
sendMail,
}

View File

@ -0,0 +1,33 @@
const { exists } = require('fs')
module.exports = async (fn) => {
const notDiffVars = []
exists('jwtRS256.key', (chk) => {
if (!chk) {
throw new Error('Please generate jwtRS256.key ("Private Key")')
}
})
exists('jwtRS256.key.pub', (chk) => {
if (!chk) {
throw new Error('Please generate jwtRS256.key.pub ("Public Key")')
}
})
console.log('Development environment detected.')
;[
'JWT_ACCESS_TIME',
'JWT_REFRESH_TIME',
'REDIS_PORT',
'REDIS_HOST',
'DB_CONN_STRING',
].forEach((envVar) => {
if (process.env[envVar] === undefined) {
notDiffVars.push(envVar)
}
})
if (notDiffVars.length > 0) {
throw new Error(`${notDiffVars.join(', ')} is not defined`)
}
if (typeof fn === 'function') {
fn()
}
}

View File

@ -0,0 +1,89 @@
async function notFound(_req, _res, next) {
try {
throw new Error('Not Found')
} catch (err) {
next(err)
}
}
async function logErrors(err, _req, _res, next) {
console.error('\n')
console.log('------------Error Log------------')
console.error(err.stack)
console.log('---------------------------------')
next(err)
}
async function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.send({
error: 'Something failed!',
})
} else {
next(err)
}
}
// eslint-disable-next-line no-unused-vars
async function errorHandler(err, _req, res, _next) {
if (err.message === 'Invalid request') {
return res.status(400).send({
status: false,
message: err.message,
error: err.stack,
})
} else if (err.message === 'Not Found') {
return res.status(404).send({
status: false,
message: err.message,
})
} else if (err.message === 'Invalid token') {
return res.status(403).send({
status: false,
message: err.message,
error: err.stack,
})
} else if (err.message === 'Blacklisted token') {
return res.status(403).send({
status: false,
message: err.message,
error: err.stack,
})
} else if (err.message === 'Invalid token :- Token is not in store') {
return res.status(403).send({
status: false,
message: err.message,
error: err.stack,
})
} else if (err.message === 'User not found') {
return res.status(404).send({
status: false,
message: err.message,
error: err.stack,
})
} else if (err.message === 'Username or Email already exists') {
return res.status(400).send({
status: false,
message: err.message,
error: err.stack,
})
} else if (err.message === 'Username or Password is not valid') {
return res.status(401).send({
status: false,
message: err.message,
error: err.stack,
})
} else {
return res.status(500).send({
status: false,
message: err.message,
error: err.stack,
})
}
}
module.exports = {
notFound,
logErrors,
clientErrorHandler,
errorHandler,
}

740
yarn.lock

File diff suppressed because it is too large Load Diff