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." ', // 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: `

You just registered an account on Hima Website

to activate your account click link below:

Active Account ` }) // 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." ', // sender address to: req.body.email, // list of receivers subject: "Reset Password Link", text: 'Reset your password', html: `

You asked to reset your account password on Hima Website

to reset your password click on link blow, then enter new password:

Reset Password ` }) // Message sent: 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) }) } ]