Files
ostandari/server/controllers/userController.js
T
2024-10-21 10:22:26 +03:30

1188 lines
35 KiB
JavaScript

const User = require('../models/User');
const {body, validationResult} = require('express-validator');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const sharp = require('sharp');
const {secretKey} = require('./../authentication');
const {_sr} = require('../plugins/serverResponses');
const {res404, res500, hasWhiteSpaces, isLatinCharactersWithSymbol, generateRandomDigits} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const nodemailer = require('nodemailer');
const Category = require('../models/Category');
const Logger = require('../models/Logger')
////// variables
const profileWidth = 500;
const profileHeight = 500;
const profileQuality = 100;
const hostURL = 'localhost:6688';
const limit = 20;
const select = '-password -token';
/** @todo add private to query */
/** auth --------------------------------------------- */
/////////////////////////////////////////////////////////////////////// login
module.exports.login = [
[
body('username')
.if((value, {req}) => {
return req.body.password && req.body.password.length >= 4
})
.custom((value, {req}) => {
var test = value;
return User.findOne({username: value})
.then(user => {
if (!user) return Promise.reject(_sr['fa'].not_found.password)
else return true
})
}),
body('password')
.notEmpty().withMessage(_sr['fa'].required.password)
.bail()
.isLength({min: 4}).withMessage(_sr['fa'].min_char.min4),
body('remember_me')
.exists().withMessage(_sr['fa'].required.remember_me)
.bail()
.isBoolean().withMessage(_sr['fa'].format.boolean)
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
var {username, password, remember_me} = req.body;
/** get user */
var user = await User.findOne({$or: [{username: username}, {email: username}]});
const logger = await Logger.findOne({user:user._id})
if (!user.registration_done) {
return res.status(403).json({message: `اکانت شما غیرفعال می باشد لطفا با ادمین تماس بگیرید`});
}
const isMatch = await bcrypt.compare(password,user.password)
/**check user */
if (user) {
/** check password */
if (isMatch) {
if(logger){
await Logger.findOneAndUpdate({user:user._id},{$set:{LastLogin:new Date()}},{new:true})
}else {
const newLogger = new Logger({
user:user,
LastLogin:new Date()
})
await newLogger.save();
}
/** if have token and it true show result else generate new token */
if (user.token) {
jwt.verify(user.token.replace(/^Bearer\s/, ''), secretKey, async (err, decoeded) => {
if (err || !decoeded) {
/** generate new token */
var token = await jwt.sign({_id: user._id}, secretKey, {expiresIn: remember_me ? '7d' : '1h'});
user.token = token;
await user.save();
return res.json({token: user.token});
} else {
return res.json({token: user.token});
}
});
} else {
/** generate new token */
var token = await jwt.sign({_id: user._id}, secretKey, {expiresIn: remember_me ? '7d' : '1h'});
user.token = token;
await user.save();
return res.json({token: user.token});
}
} else {
return res.status(422).json({validation: {username: {msg: _sr['fa'].not_found.password}}});
}
} else {
return res.status(422).json({validation: {username: {msg: _sr['fa'].not_found.password}}});
}
} catch (error) {
return res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// logout
module.exports.logout = [
async (req, res) => {
const token = req.headers.authorization?.replace(/^Bearer\s/, '');
if (token) {
User.findOneAndUpdate({token: token}, {token: null}, (err, oldData) => {
if (err || !oldData) res.status(401).json({message: 'Your not logged in'})
else return res.json({message: 'You are logged out.'})
})
} else {
return res.status(401).json({message: 'Your not logged in'})
}
}
]
/////////////////////////////////////////////////////////////////////// get user
module.exports.getuser = [
async (req, res) => {
const token = req.headers.authorization?.replace(/^Bearer\s/, '');
// check if token is not destroyed
var user = await User.findOne({token: token}).select('-password');
if (!user) {
return res.status(401).json({message: 'unauthorized'});
}
if (!user.registration_done) {
return res.status(401).json({message: `اکانت شما غیرفعال می باشد لطفا با ادمین تماس بگیرید`});
}
//verifies secret and checks if the token is expired
try {
var checkToken = await jwt.verify(user.token.replace(/^Bearer\s/, ''), secretKey);
if (!checkToken) {
return res.status(401).json({message: 'unauthorized'});
}
return res.json({user: user});
} catch (error) {
return res.status(401).json({message: 'unauthorized'});
}
}
]
/** end auth --------------------------------------------- */
/////////////////////////////////////////////////////////////////////// admin
module.exports.registerAdmin = [
[
body('firstName')
.notEmpty().withMessage(_sr['fa'].required.first_name),
body('lastName')
.notEmpty().withMessage(_sr['fa'].required.last_name),
body('mobileNumber')
.if((value, {req}) => {
return req.body.mobileNumber
})
.custom((value, {req}) => {
if (!_.isEmpty(value) && !lodash.isNumeric(value)) {
return Promise.reject(_sr['fa'].format.number);
}
return User.findOne({mobileNumber: value})
.then(user => {
if (user) return Promise.reject(_sr['fa'].duplicated.phoneNumber);
else return true
})
}),
// body('email')
// .optional().isEmail().withMessage(_sr['fa'].format.email)
// .if((value, {req}) => {
// return req.body.email
// })
// .custom((value, {req}) => {
// return User.findOne({email: value})
// .then(user => {
// if (user) return Promise.reject(_sr['fa'].duplicated.email)
// else return true
// })
// }),
body('username')
.isLength({min: 4}).withMessage(_sr['fa'].min_char.min4)
.bail()
.custom((value, {req}) => {
if (hasWhiteSpaces(value)) return Promise.reject(_sr['fa'].response.whiteSpace)
else return true
})
.bail()
.custom((value, {req}) => {
if (!isLatinCharactersWithSymbol(value)) return Promise.reject(_sr['fa'].response.latinChar)
else return true
})
.bail()
.custom((value, {req}) => {
return User.findOne({username: value})
.then(user => {
if (user) return Promise.reject(_sr['fa'].duplicated.username)
else return true
})
}),
body('password')
.isLength({min: 4}).withMessage(_sr['fa'].min_char.min4)
.custom((value, {req}) => {
if (value === req.body.password_confirmation) return Promise.resolve()
else return Promise.reject(_sr['fa'].response.passwords_not_match)
}),
body('permissions')
.if((value, {req}) => {
return req.body.specialPermissions;
})
.custom((value, {req}) => {
var permission = _.isString(value) ? JSON.parse(value) : value;
if (!_.isArray(permission)) {
return Promise.reject(`این فیلد باید از نوع آرایه باشد`);
}
if (!permission.length) {
return Promise.reject(`شما باید یک دسترسی انتخاب کنید`);
}
if (permission.length && !permission.includes('superAdmin') && (!permission.includes('news') && !permission.includes('categories'))) {
return Promise.reject(`شما باید همراه با دسترسی مخصوص، دسترسی مدیریت صفحات یا اخبار را ارسال کنید`);
} else {
return true
}
}),
body('specialPermissions')
.optional()
.custom((value, {req}) => {
var specialPermissions = _.isString(value) && !_.isEmpty(value) ? JSON.parse(value) : value;
if (!_.isArray(specialPermissions)) {
return Promise.reject(`این فیلد باید از نوع آرایه باشد`);
}
return true
}),
body('portals')
.custom((value, {req}) => {
var portals = _.isString(value) ? JSON.parse(value) : value;
if (!_.isArray(portals)) {
return Promise.reject(`این فیلد باید از نوع آرایه باشد`);
}
if (!portals.length) {
return Promise.reject(`شما باید محدوده دسترسی را مشخص کنید`);
}
let isValid = portals.every((item) => {
return portal.includes(item);
});
if (isValid) {
return true;
} else {
return Promise.reject(`${_sr['fa'].optional.onlyValid} => ${portal}`);
}
}),
body('registration_done')
.isBoolean().withMessage(_sr['fa'].format.boolean),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
var {
username,
password,
firstName,
lastName,
email,
mobileNumber,
permissions,
specialPermissions,
registration_done,
portals
} = req.body;
/** this code fix problem with array in form data */
permissions = _.isString(permissions) ? JSON.parse(permissions) : permissions;
specialPermissions = _.isString(specialPermissions) ? JSON.parse(specialPermissions) : specialPermissions;
portals = _.isString(portals) ? JSON.parse(portals) : portals;
var data = {
username,
firstName,
lastName,
email,
mobileNumber,
permissions,
registration_done,
private: false,
_creator: req.user?._id || null,
_updatedBy: req.user?._id || null,
specialPermissions: permissions.includes('superAdmin') ? [] : specialPermissions,
portals: [...new Set(portals)]
};
/**
* if we have pic upload to server
*/
if (req.files && req.files.profilePic) {
const image = req.files.profilePic;
if (!_sr.supportedImageFormats.includes(image.mimetype.split('/')[1])) {
return res.status(422).json({validation: {profilePic: {msg: _sr['fa'].format.image}}});
}
const imageName = 'user_' + Date.now() + '_' + username + '.' + image.mimetype.split('/')[1];
data.profilePic = imageName
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/users/${imageName}`)
} catch (e) {
return res500(res, e?.message)
}
}
/**
* generate salt
*/
var salt = bcrypt.genSaltSync(10);
/**
* hash password with salt
*/
var hashPassword = bcrypt.hashSync(password, salt);
if (!hashPassword) {
return res500(res, `error in hash`);
}
data.password = hashPassword;
/**
* create new admin
*/
const newAdmin = await User.create(data);
/**
* if we have error show him
*/
if (!newAdmin) {
return res500(`error in register admin`);
}
/**
* show result
*/
return res.status(201).json({
message: _sr['fa'].response.success_save
})
} catch (error) {
return res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// get user
module.exports.getUserByAdmin = [
async (req, res) => {
try {
const userId = req.params.id;
/** get one user */
const user = await User.findById(userId).populate('specialPermissions').select(select);
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
/** show result */
return res.json(user);
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// get all user
module.exports.getAllUsers = [
async (req, res) => {
try {
/** get all user */
const users = await User.paginate({private: false}, {page: req.query.page, limit, select});
/** if not exist show message to client */
if (!users) {
return res500(res, `مشکلی در گرفتن اطلاعات پیش آمده لطفا دوباره تلاش کنید`);
}
/** show result */
return res.json(users);
} catch (error) {
return res500(res, error?.message);
}
}
]
module.exports.changeUserStatus = [
async (req, res) => {
try {
const userId = req.params.id
let user = await User.findOne({private: false , _id : userId});
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
user.registration_done = !user.registration_done;
user.save();
/** show result */
return res.json(_sr['fa'].response.success_save);
} catch (error) {
return res500(res, `مشکلی در اجرای درخواست شما بوجود امده است`);
}
}
]
/////////////////////////////////////////////////////////////////////// delete one user
module.exports.deleteOneUser = [
async (req, res) => {
try {
const userId = req.params.id;
/** get one user */
const user = await User.findOne({_id: userId});
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
if (user.private) {
return res.status(403).json({message: `شما نمیتوانید این کاربر را حذف کنید`});
}
/**
* if exist old pic delete it from file
*/
if (user.profilePic) {
var oldPic = `./static${user.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
/** delete user */
await user.deleteOne();
/** show result */
return res.json(user);
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// update user
module.exports.updateUser = [
[
body('firstName')
.notEmpty().withMessage(_sr['fa'].required.first_name),
body('lastName')
.notEmpty().withMessage(_sr['fa'].required.last_name),
body('mobileNumber')
.if((value, {req}) => {
return req.body.mobileNumber
})
.custom((value, {req}) => {
if (!_.isEmpty(value) && !lodash.isNumeric(value)) {
return Promise.reject(_sr['fa'].format.number);
}
return true;
}),
// body('email')
// .optional().isEmail().withMessage(_sr['fa'].format.email),
body('permissions')
.if((value, {req}) => {
return req.body.specialPermissions;
})
.custom((value, {req}) => {
let permission = _.isString(value) ? JSON.parse(value) : value;
let specialPermissions = _.isString(req.body.specialPermissions) ? JSON.parse(req.body.specialPermissions) : req.body.specialPermissions;
if (!_.isArray(permission)) {
return Promise.reject(`این فیلد باید از نوع آرایه باشد`);
}
if (!permission.length) {
return Promise.reject(`شما باید یک دسترسی انتخاب کنید`);
}
if (specialPermissions.length !== 0 && !permission.includes('superAdmin') && (!permission.includes('news') && !permission.includes('categories'))) {
return Promise.reject(`شما باید همراه با دسترسی مخصوص، دسترسی مدیریت صفحات یا اخبار را ارسال کنید`);
} else {
return true
}
}),
body('specialPermissions')
.optional()
.custom((value, {req}) => {
var specialPermissions = _.isString(value) && !_.isEmpty(value) ? JSON.parse(value) : value;
if (!_.isArray(specialPermissions)) {
return Promise.reject(`این فیلد باید از نوع آرایه باشد`);
}
return true
}),
body('portals')
.custom((value, {req}) => {
var portals = _.isString(value) ? JSON.parse(value) : value;
if (!_.isArray(portals)) {
return Promise.reject(`این فیلد باید از نوع آرایه باشد`);
}
if (!portals.length) {
return Promise.reject(`شما باید محدوده دسترسی را مشخص کنید`);
}
let isValid = portals.every((item) => {
return portal.includes(item);
});
if (isValid) {
return true;
} else {
return Promise.reject(`${_sr['fa'].optional.onlyValid} => ${portal}`);
}
}),
body('registration_done')
.isBoolean().withMessage(_sr['fa'].format.boolean),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
const userId = req.params.id;
var {
firstName,
lastName,
email,
mobileNumber,
permissions,
specialPermissions,
registration_done,
portals
} = req.body;
/** this code fix problem with array in form data */
permissions = _.isString(permissions) ? JSON.parse(permissions) : permissions;
specialPermissions = _.isString(specialPermissions) ? JSON.parse(specialPermissions) : specialPermissions;
portals = _.isString(portals) ? JSON.parse(portals) : portals;
/** get one user */
var user = await User.findById(userId);
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
if (!user.private && !req.user.private) {
return res.status(403).json({message: `شما نمیتوانید این کاربر را آپدیت کنید`});
}
/** check new email is dupllicate or not */
if (user.email !== email) {
var checkDupplicate = await User.find({email: email});
if (checkDupplicate.length) {
return res.status(422).json({validation: {email: {msg: `${_sr['fa'].duplicated.email}`}}});
}
}
/** check new mobileNumber is dupllicate or not */
if (user.mobileNumber !== mobileNumber) {
var checkDupplicate = await User.find({mobileNumber: mobileNumber});
if (checkDupplicate.length) {
return res.status(422).json({validation: {mobileNumber: {msg: `${_sr['fa'].duplicated.phoneNumber}`}}});
}
}
user.firstName = firstName;
user.lastName = lastName;
user.password = user.password;
user.scope = user.scope;
user.token = user.token;
user.mobileNumber = mobileNumber;
user.email = email;
user.registration_done = registration_done;
user._creator = req.user._id;
user.username = user.username;
user.permissions = permissions;
user.specialPermissions = permissions?.includes('superAdmin') ? [] : specialPermissions;
user.private = user.private;
user.portals = [...new Set(portals)]
if (req.files && req.files.profilePic) {
const image = req.files.profilePic;
if (!_sr.supportedImageFormats.includes(image.mimetype.split('/')[1])) {
return res.status(422).json({validation: {profilePic: {msg: _sr['fa'].format.image}}});
}
const imageName = 'user_' + Date.now() + '_' + user.username + '.' + image.mimetype.split('/')[1];
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/users/${imageName}`);
/**
* if exist old pic delete it from file
*/
if (user.profilePic) {
var oldPic = `./static${user.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
} catch (e) {
return res500(res, e?.message);
}
user.profilePic = imageName;
}
await user.save();
/** show result */
return res.json(user);
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// change password
module.exports.changePassword = [
[
body('password')
.isLength({min: 4}).withMessage(_sr['fa'].min_char.min4)
.custom((value, {req}) => {
if (value === req.body.password_confirmation) return Promise.resolve()
else return Promise.reject(_sr['fa'].response.passwords_not_match)
}),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
const userId = req.params.id;
const password = req.body.password;
/** get one user */
var user = await User.findById(userId);
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
if (!user.private && !req.user.private) {
return res.status(403).json({message: `شما نمی توانید رمز عبور این کاربر را تغییر دهید`});
}
/**
* generate salt
*/
var salt = bcrypt.genSaltSync(10);
/**
* hash password with salt
*/
var hashPassword = bcrypt.hashSync(password, salt);
if (!hashPassword) {
return res500(res, `error in hash`);
}
user.password = hashPassword;
user.token = null
await user.save();
/** show result */
return res.json({message: _sr['fa'].response.success_save});
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// get profile(get self)
module.exports.getProfile = [
async (req, res) => {
try {
const userId = req.user._id;
/** get one user */
const user = await User.findById(userId).select(select);
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
/** show result */
return res.json(user);
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// update profile(get self)
module.exports.updateProfile = [
[
body('firstName')
.notEmpty().withMessage(_sr['fa'].required.first_name),
body('lastName')
.notEmpty().withMessage(_sr['fa'].required.last_name),
body('mobileNumber')
.isNumeric().withMessage(_sr['fa'].format.number),
// body('email')
// .isEmail().withMessage(_sr['fa'].format.email),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
const userId = req.user._id;
const {
firstName,
lastName,
email,
mobileNumber,
} = req.body;
/** get one user */
var user = await User.findById(userId);
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
/** check new email is dupllicate or not */
if (user.email != email) {
var checkDupplicate = await User.find({email: email});
if (checkDupplicate.length) {
return res.status(422).json({validation: {email: {msg: `${_sr['fa'].duplicated.email}`}}});
}
}
/** check new mobileNumber is dupllicate or not */
if (user.mobileNumber != mobileNumber) {
var checkDupplicate = await User.find({mobileNumber: mobileNumber});
if (checkDupplicate.length) {
return res.status(422).json({validation: {mobileNumber: {msg: `${_sr['fa'].duplicated.phoneNumber}`}}});
}
}
user.firstName = firstName;
user.lastName = lastName;
user.password = user.password;
user.scope = user.scope;
user.token = user.token;
user.mobileNumber = mobileNumber;
user.email = email;
user.registration_done = user.registration_done;
user._creator = req.user._id;
user.username = user.username;
user.permissions = user.permissions;
user.specialPermissions = user.specialPermissions;
user.private = user.private;
/** if exist a picture */
if (req.files && req.files.profilePic) {
const image = req.files.profilePic;
if (!_sr.supportedImageFormats.includes(image.mimetype.split('/')[1])) {
return res.status(422).json({validation: {profilePic: {msg: _sr['fa'].format.image}}});
}
const imageName = 'user_' + Date.now() + '_' + user.username + '.' + image.mimetype.split('/')[1];
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/users/${imageName}`);
/**
* if exist old pic delete it from file
*/
if (user.profilePic) {
var oldPic = `./static${user.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
} catch (e) {
return res500(res, e?.message);
}
user.profilePic = imageName;
}
await user.save();
/** show result */
return res.json(user);
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// change password (profile)
module.exports.changePasswordProfile = [
[
body('password')
.isLength({min: 4}).withMessage(_sr['fa'].min_char.min4)
.custom((value, {req}) => {
if (value === req.body.password_confirmation) return Promise.resolve()
else return Promise.reject(_sr['fa'].response.passwords_not_match)
}),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
const userId = req.user._id;
const password = req.body.password;
/** get one user */
var user = await User.findById(userId);
/** if not exist show message to client */
if (!user) {
return res404(res, `کاربر مورد نظر پیدا نشد`);
}
/**
* generate salt
*/
var salt = bcrypt.genSaltSync(10);
/**
* hash password with salt
*/
var hashPassword = bcrypt.hashSync(password, salt);
if (!hashPassword) {
return res500(res, `مشکلی در تغییر پسورد پیش آمده است`);
}
user.password = hashPassword;
user.token = null
await user.save();
/** show result */
return res.json({message: _sr['fa'].response.success_save});
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// forget password generate token
module.exports.forgetPassGenerateToken = [
[
body('email')
.optional().isEmail().withMessage(_sr['fa'].format.email)
.if((value, {req}) => {
return req.body.email
})
.custom((value, {req}) => {
return User.findOne({email: value})
.then(user => {
if (!user) return Promise.reject(_sr['fa'].not_found.email)
else return true
})
}),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
try {
const email = req.body.email;
/** get one user */
var user = await User.findOne({email: email});
/** if not exist show message to client */
if (!user) {
return res404(res, `کابر مورد نظر پیدا نشد`);
}
const token = crypto.randomBytes(20).toString('hex');
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let transporter = nodemailer.createTransport({
host: "www.rubynaturalco.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'recovery@rubynaturalco.com',
pass: 'jd-m2?3ao?b('
},
tls: {
rejectUnauthorized: false
}
})
const emailHTMLTemplate = `
<div style="direction: rtl;background-color: #065495;overflow: hidden;">
<div style="width: 50%;border-radius: 10px;margin: 150px auto;background: #fff;text-align: center;padding: 20px;box-shadow: 0 15px 30px #000;">
<H1 style="color: #000;">برای بازیابی کلمه عبور خود روی لینک زیر کلیک کنید.</H1>
<div style="text-align: center;margin-top: 20px;">
<a href="http://${hostURL}/auth/resetpass-newpass/${token}"
target="_blank"
style="display: inline-block;padding: 15px;background: #065495;color: #fff;border-radius: 5px;text-decoration: none;">بازیابی کلمه عبور</a>
</div>
</div>
<span style="opacity: 0">${Date.now()}</span>
</div>
`
// send mail with defined transport object
let info = await transporter.sendMail({
from: '"Ostandari Portal" <recovery@rubynaturalco.com>', // sender address
to: user.email, // list of receivers
subject: 'لینک بازیابی کلمه عبور',
text: 'کلمه عبور خود را بازیابی کنید',
html: emailHTMLTemplate
});
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
user.token = token;
await user.save();
/** show result */
return res.json(token);
} catch (error) {
res500(res, error?.message);
}
}
]
/////////////////////////////////////////////////////////////////////// forget password get token and change pass
module.exports.forgetPassGetToken = [
[
body('password')
.isLength({min: 4}).withMessage(_sr['fa'].min_char.min4)
.custom((value, {req}) => {
if (value === req.body.password_confirmation) return Promise.resolve()
else return Promise.reject(_sr['fa'].response.passwords_not_match)
}),
],
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()});
try {
var token = req.params.token;
var password = req.body.password;
var user = await User.findOne({token: token});
if (!user) {
return res500(res, _sr['fa'].response.expired_reset_link); /** @todo change response */
}
/**
* generate salt
*/
var salt = bcrypt.genSaltSync(10);
/**
* hash password with salt
*/
var hashPassword = bcrypt.hashSync(password, salt);
if (!hashPassword) {
return res500(res, `مشکلی در تغییر رمز عبور پیش آمده است`); /** @todo change response */
}
user.password = hashPassword;
user.token = null;
await user.save();
/** show result */
return res.json({message: _sr['fa'].response.success_save});
} catch (error) {
res500(res, error?.message);
}
}
]
////////////////////////////////////////////////////////////////////// search
module.exports.search = [
async (req, res) => {
try {
var query = {private: false};
query['$and'] = [];
var {
name,
email,
phone,
permissions,
specialPermissions,
portals,
status,
username
} = req.body;
/** search by name and family */
if (name && !_.isEmpty(name)) {
query['$and'].push({
$or: [{
firstName: {
$regex: '.*' + name + '.*'
},
lastName: {
$regex: '.*' + name + '.*'
}
}]
});
}
/** search by email */
if (email && !_.isEmpty(email)) {
query['$and'].push({
email: email
});
}
/** search by phone */
if (phone && !_.isEmpty(phone)) {
query['$and'].push({
mobileNumber: phone
});
}
/** search by permissions */
if (permissions && !_.isEmpty(permissions)) {
query['$and'].push({
permissions: {
$in: permissions
}
});
}
/** search by specialPermissions */
if (specialPermissions && !_.isEmpty(specialPermissions)) {
query['$and'].push({
specialPermissions: {
$in: specialPermissions
}
});
}
/** search by portals */
if (portals && !_.isEmpty(portals)) {
query['$and'].push({
portals: {
$in: portals
}
})
}
/** search by status */
if (!_.isUndefined(status) && _.isBoolean(status)) {
query['$and'].push({
registration_done: status
})
}
/** search by username */
if (username && !_.isEmpty(username)) {
query['$and'].push({
username: username
});
}
_.isEmpty(query['$and']) && delete query['$and'];
// _.isEmpty(input['$or']) && delete input['$or'];
/** get users */
var users = await User.paginate(query, {page: req.query.page, limit, select});
/** show result */
return res.json(users);
} catch (error) {
return res500(res, error?.message);
}
}
]