Commit 88144f92 authored by M.V.S. SRIHARSHA's avatar M.V.S. SRIHARSHA

Initial commit

parents
node_modules
logs
.idea/
apidoc
req.http
.uploads/
package-lock.json
uploads
# Installation steps
Volunteer Management System Backend
## Prerequisites installing
### mongodb database
# [mongodb database](https://docs.mongodb.com/manual/installation/)
### nodejs
# [nodejs installtion](https://nodejs.org/en/download/package-manager/)
### redis
$ sudo apt install redis
## How to run
```
$ cd project_directory
$ npm install
$ node server.js
```
const async = require('async');
const userDbo = require('../../dbo/user.dbo');
const {success200, errorResponse} = require('../../../../utils/responses');
exports.createUser = (req, res) => {
let reqData = req.body;
async.waterfall([
(callback) => {
userDbo.saveUser(reqData, (err, resp) => {
if (err) {
console.log(err);
callback({
statusCode: 500,
message: "Internal Server Error"
})
} else {
callback(null, {
message: "User Created Successfully"
})
}
})
}
],
(err, result) => {
return err ? errorResponse(res, err) : success200(res, result)
})
};
\ No newline at end of file
const {createUser} = require('./createClient');
module.exports = {
createUser,
};
\ No newline at end of file
const {signin} = require('./signin');
module.exports = {
signin
};
\ No newline at end of file
exports.signin = (req, res) => {
console.log(req.body)
res.status(200).json({message : "Allow"})
};
\ No newline at end of file
const mongoose = require('mongoose'),
Session = mongoose.model('Session');
exports.findOne = function (query, projection, callback) {
Session.findOne(query, projection, callback);
};
exports.findAll = function (query, projection, callback) {
Session.find(query, projection, callback);
};
exports.saveSessions = function (data, callback) {
let newSessions = new Session(data);
newSessions.save(callback);
};
exports.findOneAndUpdate = function (query, update, options = {}, callback) {
Session.findOneAndUpdate(query, update, options, callback);
};
exports.updateMany = function (query, update, options = {}, callback) {
Session.updateMany(query, update, options, callback);
};
exports.findOneAndDelete = function (query, callback) {
Session.findOneAndDelete(query, callback);
};
exports.deleteMany = function (query, callback) {
Session.deleteMany(query, callback);
};
exports.countDocuments = function (query, callback) {
Session.countDocuments(query, callback);
};
const User = require('../models/user.model');
const _ = require('lodash');
exports.saveUser = function (userData, next) {
User.findOne({email: userData.email})
.then(function (res) {
if (res) {
next(res)
} else {
const newUser = new User(userData);
newUser.save(userData, next)
}
})
.catch(function (err) {
next(err)
})
};
exports.findOne = function (query, projection, cb) {
User.findOne(query, projection, cb)
};
\ No newline at end of file
var mongoose = require('mongoose');
const SessionSchema = new mongoose.Schema({
refreshToken: {
type: String,
required: true,
},
userId: {
type: String,
required: true,
minlength: 6
},
browserInfo: {
type: Object,
required: true
},
loginAt: {
type: Date,
required: true,
default: Date.now()
},
deletedAt: {
type: Date,
required: false,
default: null
},
logOutAt: {
type: Date,
required: false,
default: null
}
});
module.exports = mongoose.model('Session', SessionSchema, 'sessions');
const mongoose = require('mongoose');
const crypto = require('crypto');
const user = new mongoose.Schema({
name: {
type: String,
trim: true,
default: "",
required: "Please provide name"
},
userName: {
type: String,
trim: true,
default: "",
required: "Please provide fullName"
},
email: {
type: String,
trim: true,
default: "",
required: "Please provide Email"
},
salt: {
type: String
},
password: {
type: String,
required: "Please Provide Password"
},
mobileNumber: {
type: String,
trim: true,
required: "please provide the mobile number"
},
age: {
type: String,
trim: true,
required: "Please provide age"
},
location: {
type: String,
trim: true,
required: "Please provide Location"
}
});
user.pre("validate", function (next) {
if (this.password && this.isModified("password")) {
this.salt = crypto.randomBytes(16).toString("base64");
this.password = this.hashPassword(this.password);
}
next();
});
/**
* Create instance method for hashing a password
*/
user.methods.hashPassword = function (password) {
if (this.salt && password) {
return crypto
.pbkdf2Sync(password, new Buffer(this.salt, "base64"), 10000, 64, "SHA1")
.toString("base64");
} else {
return password;
}
};
/**
* Create instance method for authenticating user
*/
user.methods.authenticate = function (password) {
return this.password === this.hashPassword(password);
};
user.set("toJSON", {
getters: true,
virtuals: true
});
user.findById = async (id, cb) => {
console.log("object id", ObjectId(id));
const res = await this.findOne({_id: ObjectId(id)});
if (!res) {
cb(res);
}
cb(null);
};
module.exports = mongoose.model("user", user);
\ No newline at end of file
// const authMiddleware = require('../../../utils/middlewares/auth');
const clientControllers = require('../controllers/clients');
module.exports = function (app) {
app.route('/users/signup')
.post(
clientControllers.createUser
);
};
\ No newline at end of file
const userControllers = require('../controllers/users');
module.exports = function (app) {
app.route('/auth/signin')
.post(
userControllers.signin
)
};
\ No newline at end of file
const cors = require('cors');
function returnOrigins() {
let nodeEnv = process.env.NODE_ENV || 'dev';
if (nodeEnv === 'dev' || nodeEnv === 'test') {
return '*'
} else if (nodeEnv === 'stage') {
return ['http://localhost:3000']
} else if (nodeEnv === 'prod') {
return ['http://localhost:3000']
}
}
//Cors Options
let corsOptions = {
'origin': returnOrigins(),
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
};
//enable the cors
module.exports = cors(corsOptions);
\ No newline at end of file
const crypto = require('crypto');
const config = require('config');
const key = crypto.scryptSync(config.get('crypt.KEY'), 'salt', 24); // Generate key
const iv = Buffer.alloc(16, 0); // Initialization vector.
const algorithm = config.get('crypt.ALGO');
exports.encData = async (data, callback) => {
try {
let cipher = await crypto.createCipheriv(algorithm, key, iv);
let encrypted = await cipher.update(data, 'utf8', 'hex');
encrypted += await cipher.final('hex');
callback(null, encrypted);
} catch (e) {
callback(e)
}
};
exports.decData = async (encrypted, callback) => {
try {
const decipher = await crypto.createDecipheriv(algorithm, key, iv);
let decrypted = await decipher.update(encrypted, 'hex', 'utf8');
decrypted += await decipher.final('utf8');
callback(null, decrypted);
} catch (e) {
callback(e)
}
};
\ No newline at end of file
let redis = require('redis');
let bluebird = require('bluebird');
let config = require('config');
let async = require('async');
let chalk = require('chalk');
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
let app = require('../../../server');
function RedisFactory() {
this.client = redis.createClient();
this.client.on('connect', function () {
console.log(chalk.green('[+] Redis is connected'))
});
this.client.on('error', function (err) {
console.log(chalk('[X] Redis is Not Connected'))
process.exit(1);
app.close(() => {
})
})
}
RedisFactory.prototype.setToken = function (token, isRefresh = false) {
let tokenExpires = isRefresh
? config.get('JWT.refreshTokenExpiredAt')
: config.get('JWT.accessTokenExpireAt');
return this.client.setAsync(token, 'active', 'EX', tokenExpires)
};
RedisFactory.prototype.setString = function (KEY, value, callback) {
this.client.set(KEY, value, callback)
};
RedisFactory.prototype.existsKEY = function (KEY, callback) {
this.client.exists(KEY, callback);
};
RedisFactory.prototype.deleteToken = function (token, callback) {
this.client.del(token, function (err, resp) {
if (err) {
callback({error: err})
} else {
callback(null, {
resp: resp
})
}
})
};
RedisFactory.prototype.getToken = function (token, callback) {
this.client.getAsync(token, callback)
};
RedisFactory.prototype.setArray = function (KEY, data, callback) {
this.client.rpush(KEY, data, callback)
};
RedisFactory.prototype.setPermissions = function (KEY, data, callback) {
let expireThis = this;
async.waterfall(
[
function (callback) {
expireThis.client.rpush(KEY, data, function (err, res) {
if (err) {
callback(err)
} else {
callback(null, res)
}
})
},
function (setResp, callback) {
let tokenExpires = config.get('JWT.accessTokenExpireAt');
expireThis.client.expire(KEY, tokenExpires, function (err, resp) {
if (err) {
callback(err)
} else {
callback(null, resp)
}
})
}
],
function (err, result) {
if (err) {
callback(err)
} else {
callback(null, result)
}
}
)
};
RedisFactory.prototype.getArray = function (KEY, callback) {
this.client.lrange(KEY, 0, -1, callback)
};
module.exports = new RedisFactory();
const jwt = require('jsonwebtoken');
const config = require('config');
const redisFactory = require('./factory/redis.factory');
const {encData, decData} = require('./encryption');
exports.generateToken = function (data, isRefresh = false, callback) {
let tokenExpires = isRefresh
? Math.floor(Date.now() / 1000) + (60 * 60 * 24 * 30)
: Math.floor(Date.now() / 1000) + (60 * 60 * 3);
let SECRET_KEY = isRefresh
? config.get('JWT.REFRESH_SECRET_KEY')
: config.get('JWT.ACCESS_SECRET_KEY');
let token = jwt.sign({data: data, exp: tokenExpires}, SECRET_KEY);
if (token) {
// encrypting the generate token
encData(token, function (err, encHash) {
if (err) {
callback({message: 'Failed to enc the token.'})
} else {
if (!isRefresh) {
redisFactory.setString(encHash, data._id.toString(), function (err, result) {
if (err) callback({message: 'Failed to insert encrypt hash into redis server.'});
else callback(null, encHash)
}
)
} else callback(null, encHash)
}
})
} else callback('Failed to generate token')
};
// JWT verify method
module.exports.verifyJWTToken = async function (token, isRefreshToken = false, callback) {
await decData(token, function (err, decToken) {
if (err) callback('Failed to decrypt the token'); else {
let SECRET_KEY = isRefreshToken
? config.get('JWT.REFRESH_SECRET_KEY')
: config.get('JWT.ACCESS_SECRET_KEY');
jwt.verify(decToken, SECRET_KEY, callback)
}
})
};
// Generat two step verify token
module.exports.twoStepJWT = function (data, callback) {
jwt.sign({data: data}, config.get('JWT.TWO_STEP_KEY'), {
expiresIn: config.get('JWT.twoStepTokenExp')
}, callback
)
};
// Generat two step verify token
module.exports.verifyTwoStepJWT = function (token, callback) {
jwt.verify(token, config.get('JWT.TWO_STEP_KEY'), callback)
};
\ No newline at end of file
const redisFactory = require('../factory/redis.factory');
const jwt = require('jsonwebtoken');
const config = require('config');
const {decData} = require('../encryption');
const {verifyTwoStepJWT} = require('../jwt');
exports.isAuthenticated = async function (req, res, next) {
let token = null;
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
token = req.headers.authorization.split(' ')[1]
}
if (token === null) {
res.status(401).json({
success: false,
message: 'Unauthorized. Token missing.'
})
} else {
// decrypting the encrypted jwt token
decData(token, async function (err, decToken) {
if (err) {
res.status(400).json({
success: false,
message: 'Invalid token.'
})
} else {
await jwt.verify(
decToken,
config.get('JWT.ACCESS_SECRET_KEY'),
function (error, response) {
if (error) {
if (error.message === 'jwt expired') {
redisFactory.deleteToken(token, function (err, result) {
if (err) {
res.status(500).json({
success: false,
message: 'Internal server problem, please try again.'
})
} else {
res.status(400).json({
success: false,
message: 'Access token is expired.',
errors: error
})
}
})
} else {
res.status(400).json({
success: false,
message: error.message,
errors: error
})
}
} else {
redisFactory.existsKEY(token, function (err, result) {
if (err) {
res.status(500).json({
success: false,
message: 'Internal server problem, please try again.'
})
} else {
if (result) {
req.userDetails = response.data;
next()
} else res.status(400).json({success: false, message: 'Check your token.'})
}
})
}
}
)
}
})
}
};
// isAuthorized function for checking the user can have permission to access this route or not.
exports.isAuthorized = function (permission) {
return (req, res, next) => {
if (req.userDetails.role === "superAdmin") next();
else {
let permissions = req.userDetails.permissions;
if (permissions.indexOf(permission) !== -1) next(); else res.status(401).send({
success: false,
message: 'Not authorized to this routes'
})
}
}
};
// isAuthorized function for checking the user can have permission to access this route or not.
exports.isTwoStepProtection = function (req, res, next) {
let twoStepToken = req.body.protect_token || null;
if (twoStepToken === null) {
res.status(403).json({
success: false,
message: 'Unauthorized, PROTECT_TOKEN is missing.'
})
} else {
verifyTwoStepJWT(twoStepToken, function (err, result) {
if (err) {
res.status(403).json({
success: false,
message: 'Unauthorized, PROTECT_TOKEN is invalid.'
})
} else next()
})
}
};
\ No newline at end of file
module.exports.success200 = (resp, data) => {
if (data) {
data.success = true
} else {
data = {
message: 'no data',
success: true
}
}
return resp.status(200).json(data)
};
module.exports.success201 = (resp, data) => {
if (data) {