Files
arakrail/api/controllers/userController.js
T
2020-11-23 19:39:26 +03:30

690 lines
24 KiB
JavaScript

const User = require('../models/user/User')
const v_m = require('../validation_messages')
const {body, validationResult} = require('express-validator')
const dateformat = require('dateformat')
const bcrypt = require('bcryptjs')
const crypto = require('crypto')
const jwt = require('jsonwebtoken')
const config = require('../config')
const nodemailer = require('nodemailer')
/////////////////////////////////////////////////////////////////////// register
module.exports.register = [
[
body('first_name')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.first_name
})
.bail()
.isLength({min: 2})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min2
}),
body('last_name')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.last_name
})
.bail()
.isLength({min: 2})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min2
}),
body('company_name')
.if((value, {req}) => req.body.type === 'company')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.company_name
}),
body('email_personal')
.if((value, {req}) => req.body.type === 'personal')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.email_personal
}),
body('email_personal')
.if(body('email_personal').notEmpty())
.isEmail()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.email
})
.custom((value, {req}) => {
return User.findOne({$or: [{email_personal: value}, {email_company: value}]})
.then(user => {
if (user) return Promise.reject(v_m[req.body.locale].duplicated.email)
else return true
})
}),
body('email_company')
.if((value, {req}) => req.body.type === 'company')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.email_company
})
.bail()
.isEmail()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.email
})
.custom((value, {req}) => {
return User.findOne({$or: [{email_personal: value}, {email_company: value}]})
.then(user => {
if (user) return Promise.reject(v_m[req.body.locale].duplicated.email)
else return true
})
}),
body('password')
.isLength({min: 4})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min4
}),
body('phone_number')
.isNumeric()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.phone_number
}),
body('password_confirmation')
.isLength({min: 4})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min4
})
.bail()
.custom((value, {req}) => {
if (value !== req.body.password) return Promise.reject(v_m[req.body.locale].required.password_confirmation)
else return true
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {}
data.first_name = req.body.first_name
data.last_name = req.body.last_name
data.type = req.body.type
data.company_name = req.body.company_name
data.email_personal = req.body.email_personal
data.email_company = req.body.email_company
data.fb_id_personal = req.body.fb_id_personal
data.fb_id_company = req.body.fb_id_company
data.ig_id_personal = req.body.ig_id_personal
data.ig_id_company = req.body.ig_id_company
data.skype_id_personal = req.body.skype_id_personal
data.skype_id_company = req.body.skype_id_company
data.phone_number = req.body.phone_number
data.scope = 'user'
data.created_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
// generate activation key
let confirmation_key
crypto.randomBytes(20, async (err, hash) => {
if (err) console.log(err)
confirmation_key = hash.toString('hex')
data.confirmation_key = confirmation_key
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
}
})
// send mail with defined transport object
let info = await transporter.sendMail({
from: '"Hima Co." <recovery@rubynaturalco.com>', // sender address
to: req.body.type === 'personal' ? req.body.email_personal : req.body.email_company, // list of receivers
subject: "Activation Link",
text: 'Active your account',
html: `
<h1>You just registered an account on <b style="color: #784fae;">Hima Website</b></h1>
<p>to activate your account click link below:</p>
<a href="https://www.rubynaturalco.com/en/account/activation/${confirmation_key}"
target="_blank"
style="display: inline-block;font-family: sans-serif;padding: 15px;background: #784fae;color: #fff;border-radius: 5px;margin-top: 20px;">Active Account</a>
`
})
// hash user password and done
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(req.body.password, salt, (err, hash) => {
if (err) console.log(err)
data.password = hash
const user = new User(data)
user.save(err => {
if (err) console.log(err)
return res.json({message: v_m[req.body.locale].response.success_save})
})
})
})
})
}
]
/////////////////////////////////////////////////////////////////////// active user
module.exports.activation = [
(req, res) => {
User.findOne({confirmation_key: req.params.key})
.then(user => {
if (user) {
user.confirmation_key = null
user.confirmed = true
user.save(err => {
if (err) console.log(err)
return res.json({message: v_m[req.body.locale].response.success_activation})
})
} else {
return res.status(404).json({message: v_m[req.body.locale].response.expired_activation_link})
}
})
.catch(err => {
return res.status(500).json(err)
})
}
]
/////////////////////////////////////////////////////////////////////// login
module.exports.login = [
[
body('email')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.email
})
.custom((value, {req}) => {
return User.findOne({$or: [{email_personal: value}, {email_company: value}]})
.then(user => {
if (!user) return Promise.reject(v_m[req.body.locale].not_found.user_id)
else return true
})
}),
body('password')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.password
}),
body('remember_me')
.exists()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.remember_me
})
.bail()
.isBoolean()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.boolean
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
User.findOne({$or: [{email_personal: req.body.email}, {email_company: req.body.email}]}, (err, user) => {
if (err) console.log(err)
if (!user.confirmed) return res.status(401).json({message: v_m[req.body.locale].response.email_not_confirmed})
bcrypt.compare(req.body.password, user.password, (err, isMatch) => {
if (err) console.log(err)
if (!isMatch) return res.status(422).json({validation: {password: {msg: v_m[req.body.locale].not_found.password}}})
let token
if (req.body.remember_me) token = jwt.sign({_id: user._id}, config.secretKey)
else token = jwt.sign({_id: user._id}, config.secretKey, {expiresIn: '1h'})
user.token = token
user.reset_pass_key = null
user.save(err => {
if (err) console.log(err)
})
return res.json({token: token})
})
})
}
]
/////////////////////////////////////////////////////////////////////// logout
module.exports.logout = [
(req, res) => {
const token = req.headers.authorization
if (token) {
User.findOneAndUpdate({token: token}, {token: null}, (err, oldData) => {
if (err) console.log(err)
if (oldData) return res.json({message: v_m['en'].response.logged_out})
return res.status(401).json({message: v_m['en'].response.not_logged_in})
})
} else {
return res.status(401).json({message: v_m['en'].response.not_logged_in})
}
}
]
/////////////////////////////////////////////////////////////////////// get user
module.exports.getUser = [
config.isUser,
(req, res) => {
const token = req.headers.authorization
if (token) {
jwt.verify(token, config.secretKey, (err, decoded) => {
if (err) return res.status(401).json({message: v_m['en'].response.unauthenticated})
User.findById(decoded._id).select('-password -reset_pass_key -token -confirmed -confirmation_key').exec((err, data) => {
if (err) console.log(err)
return res.json({user: data})
})
})
} else {
return res.status(401).json({message: v_m['en'].response.unauthenticated})
}
}
]
/////////////////////////////////////////////////////////////////////// reset password key generator
module.exports.resetPassKey = [
[
body('email')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.email
})
.bail()
.isEmail()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.email
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
User.findOne({$or: [{email_personal: req.body.email}, {email_company: req.body.email}]})
.then(user => {
if (user) {
let pass_token
crypto.randomBytes(20, async (err, hash) => {
if (err) console.log(err)
pass_token = hash.toString('hex')
user.reset_pass_key = pass_token
await user.save(err => {
if (err) console.log(err)
})
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
}
})
// send mail with defined transport object
let info = await transporter.sendMail({
from: '"Hima Co." <recovery@rubynaturalco.com>', // sender address
to: req.body.email, // list of receivers
subject: "Reset Password Link",
text: 'Reset your password',
html: `
<h1>You asked to reset your account password on <b style="color: #784fae;">Hima Website</b></h1>
<p>to reset your password click on link blow, then enter new password:</p>
<a href="https://www.rubynaturalco.com/en/account/new-password/${pass_token}"
target="_blank"
style="display: inline-block;font-family: sans-serif;padding: 15px;background: #784fae;color: #fff;border-radius: 5px;margin-top: 20px;">Reset Password</a>
`
})
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
return res.json({message: v_m[req.body.locale].response.recovery_link})
})
} else {
return res.status(404).json({message: v_m[req.body.locale].not_found.user_id})
}
})
.catch(err => {
return res.status(500).json(err)
})
}
]
/////////////////////////////////////////////////////////////////////// set new password
module.exports.setNewPass = [
[
body('password')
.isLength({min: 4})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min4
})
,
body('password_confirmation')
.isLength({min: 4})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min4
})
.bail()
.custom((value, {req}) => {
if (value !== req.body.password) return Promise.reject(v_m[req.body.locale].required.password_confirmation)
else return true
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
User.findOne({reset_pass_key: req.params.key})
.then(user => {
if (user) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(req.body.password, salt, (err, hash) => {
if (err) console.log(err)
user.password = hash
user.reset_pass_key = null
user.save(err => {
if (err) console.log(err)
})
return res.json({message: v_m[req.body.locale].response.success_save})
})
})
} else {
return res.status(404).json({message: v_m[req.body.locale].response.expired_reset_link})
}
})
.catch(err => {
return res.status(500).json(err)
})
}
]
/////////////////////////////////////////////////////////////////////// update user
module.exports.updateUser = [
[
body('first_name')
.isLength({min: 2})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min2
}),
body('last_name')
.isLength({min: 2})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min2
}),
body('email_personal')
.if((value, {req}) => req.body.type === 'personal')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.email_personal
}),
body('email_personal')
.if(body('email_personal').notEmpty())
.isEmail()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.email
}),
body('phone_number')
.isNumeric()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.phone_number
}),
body('email_company')
.if((value, {req}) => req.body.type === 'company')
.notEmpty()
.withMessage((value, {req}) => {
return v_m[req.body.locale].required.email_company
})
.bail()
.isEmail()
.withMessage((value, {req}) => {
return v_m[req.body.locale].format.email
}),
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const token = req.headers.authorization
const data = {}
data.first_name = req.body.first_name
data.last_name = req.body.last_name
data.email_personal = req.body.email_personal
data.fb_id_personal = req.body.fb_id_personal
data.ig_id_personal = req.body.ig_id_personal
data.skype_id_personal = req.body.skype_id_personal
data.phone_number = req.body.phone_number
data.updated_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
if (req.body.type === 'company') {
data.skype_id_company = req.body.skype_id_company
data.ig_id_company = req.body.ig_id_company
data.fb_id_company = req.body.fb_id_company
data.email_company = req.body.email_company
data.company_name = req.body.company_name
}
User.findOneAndUpdate({token: token}, data)
.then(user => {
return res.json({message: v_m[req.body.locale].response.success_save})
})
.catch(err => {
return res.status(401).json({message: v_m[req.body.locale].response.unauthenticated})
})
}
]
/////////////////////////////////////////////////////////////////////// update user password
module.exports.updateUserPassword = [
[
body('password')
.isLength({min: 4})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min4
}),
body('password_confirmation')
.isLength({min: 4})
.withMessage((value, {req}) => {
return v_m[req.body.locale].min_char.min4
})
.bail()
.custom((value, {req}) => {
if (value !== req.body.password) return Promise.reject(v_m[req.body.locale].required.password_confirmation)
else return true
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const token = req.headers.authorization
User.findOne({token: token})
.then(user => {
bcrypt.genSalt(10, (err, salt) => {
if (err) console.log(err)
bcrypt.hash(req.body.password, salt, (err, hash) => {
if (err) console.log(err)
user.password = hash
user.token = null
user.save(err => {
if (err) console.log(err)
return res.json({message: v_m[req.body.locale].response.success_save})
})
})
})
})
.catch(err => {
return res.status(404).json(err)
})
}
]
/////////////////////////////////////////////////////////////////////// addresses
module.exports.addAdress = [
[
body('user_id')
.custom((value, {req}) => {
return User.findById(value)
.then(user => {
return true
})
.catch(err => {
return Promise.reject(v_m[req.body.locale].not_found.user_id)
})
}),
body('country')
.if(body('country').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.country)
}),
body('province')
.if(body('province').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.province)
}),
body('city')
.if(body('city').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.city)
}),
body('address')
.if(body('address').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.address)
}),
body('postal_code')
.if(body('postal_code').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.postal_code)
}),
body('plaque')
.if(body('plaque').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.plaque)
}),
body('receiver_first_name')
.if(body('receiver_first_name').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.receiver_first_name)
}),
body('receiver_last_name')
.if(body('receiver_last_name').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.receiver_last_name)
}),
body('receiver_mobile')
.if(body('receiver_mobile').isEmpty())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].required.receiver_mobile)
}),
body('receiver_mobile')
.if(body('receiver_mobile').notEmpty())
.if(body('receiver_mobile').not().isNumeric())
.custom((value, {req}) => {
return Promise.reject(v_m[req.body.locale].format.phone_number)
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {
country: req.body.country,
province: req.body.province,
city: req.body.city,
address: req.body.address,
postal_code: req.body.postal_code,
plaque: req.body.plaque,
block_number: req.body.block_number,
receiver_first_name: req.body.receiver_first_name,
receiver_last_name: req.body.receiver_last_name,
receiver_mobile: req.body.receiver_mobile,
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
User.findById(req.body.user_id)
.then(user => {
user.addresses.push(data)
user.save()
return res.json(user.addresses)
})
.catch(err => {
console.log(err)
})
}
]
module.exports.getAddresses = [
(req, res) => {
User.findById(req.params.user_id)
.then(user => {
return res.json(user.addresses)
})
.catch(err => {
return res.status(404).json({message: v_m['en'].not_found.user_id})
})
}
]
module.exports.deleteAddress = [
(req, res) => {
User.findOne({'addresses._id': req.params.address_id})
.then(user => {
user.addresses.id(req.params.address_id).remove()
user.save()
return res.json({message: v_m['en'].response.success_remove})
})
.catch(err => {
console.log(err)
})
}
]
/////////////////////////////////////////////////////////////////////// get list of users by admin
module.exports.getAllUsers = [
(req, res) => {
User.find({confirmed: true}).select('-token -password -scope -reset_pass_key -confirmed -confirmation_key').exec((err, users) => {
if (err) console.log(err)
return res.json(users)
})
}
]
module.exports.getOneUser = [
(req, res) => {
User.findById(req.params.user_id).select('-token -password -scope -reset_pass_key -confirmed -confirmation_key').exec((err, user) => {
if (err) return res.status(404).json(err)
return res.json(user)
})
}
]