Files
asan-service/server/controllers/GPS.User.js
T
2024-12-31 16:14:08 +03:30

603 lines
20 KiB
JavaScript

/* eslint-disable no-unused-vars */
const bcrypt = require('bcryptjs')
const { body, validationResult, param } = require('express-validator')
const uid = require('uuid')
const User = require('../models/GPS.User')
const { _sr } = require('../plugins/serverResponses')
const { SMS } = require('../plugins/SMS_Module')
const {
res500,
checkValidations,
removeWhiteSpaces,
checkMobileNumber,
normalizeMobileNumber,
nameOptimizer,
checkNationalCode,
isPersian,
generateRandomDigits
} = require('../plugins/controllersHelperFunctions')
const _faSr = _sr.fa
const { notifyAdmin } = require('../WebSocket/controllers/admin_EventsController')
function sendConfirmationSMS(userId) {
return new Promise(async (resolve, reject) => {
try {
const user = await User.findById(userId)
if (!user) throw new Error('invalid id')
const mobileKey = generateRandomDigits(6)
user.otp = mobileKey
await user.save()
const smsMsg = ['این شماره در وبسایت آسان سرویس ثبت گردیده.', ' کد تایید شماره همراه: ', mobileKey]
await SMS([user.mobile_number], smsMsg.join(''))
resolve()
} catch (err) {
reject(err)
}
})
}
module.exports.register_user = [
[
body('first_name')
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('last_name')
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('national_code')
.notEmpty()
.withMessage(_faSr.required.national_code)
.bail()
.custom((value, { req }) => {
if (checkNationalCode(value)) return true
else return Promise.reject(_faSr.format.national_code)
})
.bail()
.custom((value, { req }) => {
const nationalCode = value.trim()
return User.findOne({ national_code: nationalCode }).then(user => {
if (user && user.national_code === nationalCode)
return Promise.reject(new Error('کاربر با این کد ملی از قبل وجود دارد'))
else return true
})
}),
body('province_name').notEmpty().withMessage(_faSr.required.province),
body('city_name').notEmpty().withMessage(_faSr.required.city),
body('shopName').notEmpty().withMessage(_faSr.required.address),
body('mobile_number')
.notEmpty()
.withMessage(_faSr.required.phone_number)
.bail()
.custom((value, { req }) => {
const mobileNStatus = checkMobileNumber(value)
if (!mobileNStatus) return Promise.reject(_faSr.format.phone_number)
else return Promise.resolve()
})
.bail()
.custom((value, { req }) => {
const mobileNumber = value.trim()
return User.findOne({ mobile_number: mobileNumber }).then(user => {
if (user && user.mobile_number === mobileNumber)
return Promise.reject(new Error('کاربر با این شماره موبایل از قبل وجود دارد'))
else return true
})
}),
body('password')
.isLength({ min: 4 })
.withMessage(_faSr.min_char.min4)
.custom((value, { req }) => {
if (value === req.body.password_confirmation) return true
else return Promise.reject(_faSr.response.passwords_not_match)
})
],
checkValidations(validationResult),
async (req, res) => {
try {
const provinceId = uid.v4()
const cityId = uid.v4()
const { first_name, last_name, national_code, province_name, city_name, mobile_number, password, shopName } =
req.body
const data = {
last_name,
province_name: { id: provinceId, provinceName: province_name },
city_name: { id: cityId, cityName: city_name },
shopName
}
data.first_name = nameOptimizer(first_name)
data.national_code = national_code.trim()
data.mobile_number = normalizeMobileNumber(mobile_number)
// hash user password and done
const salt = await bcrypt.genSalt(10)
const hash = await bcrypt.hash(password, salt)
data.password = hash
const user = new User(data)
await user.save()
notifyAdmin('pendingUsers')
return res.json({ message: _faSr.response.success_save })
} catch (err) {
const registerFailurMsg = 'مشکلی در ثبت نام پیش آمده، لطفا مجددا تلاش کنید'
res500(res, registerFailurMsg)
}
}
]
module.exports.update_user = [
[
body('first_name')
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('last_name')
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('province_name').notEmpty().withMessage(_faSr.required.province),
body('city_name').notEmpty().withMessage(_faSr.required.city),
body('shopName').notEmpty().withMessage(_faSr.required.field),
body('address').notEmpty().withMessage(_faSr.required.address),
body('cell_number').notEmpty().withMessage(_faSr.required.address),
body('birthDate').notEmpty().withMessage(_faSr.required.address)
],
checkValidations(validationResult),
async (req, res) => {
try {
const { first_name, last_name, province_name, city_name, shopName, birthDate, address, cell_number } = req.body
const data = {
last_name,
province_name,
city_name,
shopName,
birthDate,
address,
cell_number
}
if (req.files?.image) {
const image = req.files?.image
const fileName = 'profile' + Date.now() + '.' + image.name
await image.mv(`./static/uploads/images/${fileName}`)
data.profilePic = `/uploads/images/${fileName}`
}
data.first_name = nameOptimizer(first_name)
await User.findByIdAndUpdate(req.params.id, data)
const user = await User.findById(req.params.id)
return res.json({ message: _faSr.response.success_save, user })
} catch (err) {
const registerFailurMsg = 'مشکلی در به روز رسانی پیش آمده، لطفا مجددا تلاش کنید'
throw new Error(registerFailurMsg)
}
}
]
module.exports.update_user_password = [
[
body('newPassword')
.isLength({ min: 4 })
.withMessage(_faSr.min_char.min4)
.custom((value, { req }) => {
if (value === req.body.password_confirmation) return true
else return Promise.reject(_faSr.response.passwords_not_match)
}),
body('password').isLength({ min: 4 }).withMessage(_faSr.min_char.min4)
],
checkValidations(validationResult),
async (req, res) => {
try {
const { password, newPassword } = req.body
const { user_id } = req
const salt = await bcrypt.genSalt(10)
const hash = await bcrypt.hash(newPassword, salt)
const user = await User.findById(user_id)
if (!user) {
res.status(404)
throw new Error(_faSr.not_found.user_id)
}
const passwordMatch = await bcrypt.compare(password, user.password)
if (!passwordMatch) {
res.status(401)
throw new Error('err')
}
user.password = hash
await user.save()
return res.json({ message: _faSr.response.success_save })
} catch (err) {
throw new Error(err.message)
}
}
]
module.exports.send_otp = [
[body('mobile_number').notEmpty().withMessage(_faSr.required.phone_number)],
checkValidations(validationResult),
async (req, res) => {
try {
const { mobile_number } = req.body
const user = await User.findOne({ mobile_number })
if (!user) {
res.status(404)
throw new Error(_sr.fa.not_found.user_id)
}
await sendConfirmationSMS(user.id)
res.status(200).json({ msg: 'ok' })
} catch (err) {
throw new Error(err.message)
}
}
]
module.exports.check_otp = [
[
body('mobile_number').notEmpty().withMessage(_faSr.required.phone_number),
body('otp').notEmpty().withMessage(_faSr.required.phone_number)
],
checkValidations(validationResult),
async (req, res) => {
try {
const { mobile_number, otp } = req.body
const user = await User.findOne({ mobile_number })
if (!user) throw new Error(_sr.fa.not_found.user_id)
if (user.otp !== otp) throw new Error('کد اشتباه است')
if (user.otp === otp) res.status(200).json({ msg: 'ok' })
} catch (err) {
throw new Error(err.message)
}
}
]
module.exports.resetpass_otp = [
[
body('mobile_number').notEmpty().withMessage(_faSr.required.phone_number),
body('otp').notEmpty().withMessage(_faSr.required.phone_number),
body('password')
.isLength({ min: 4 })
.withMessage(_faSr.min_char.min4)
.custom((value, { req }) => {
if (value === req.body?.password_confirmation) return true
else return Promise.reject(_faSr.response.passwords_not_match)
})
],
checkValidations(validationResult),
async (req, res) => {
try {
const { mobile_number, otp, password } = req.body
const salt = await bcrypt.genSalt(10)
const hash = await bcrypt.hash(password, salt)
const user = await User.findOne({ mobile_number })
if (!user) throw new Error(_sr.fa.not_found.user_id)
if (user.otp !== otp) throw new Error('کد اشتباه است')
if (user.otp === otp) {
user.password = hash
user.otp = generateRandomDigits(6)
user.save()
res.status(200).json({ msg: _sr.fa.response.success_save })
}
} catch (err) {
throw new Error(err.message)
}
}
]
module.exports.getCurrent = async (req, res) => {
const user = await User.findById(req.user_id).select('-password -token -otp -seenByAdmin')
if (!user || !user.active) return res.ststus(404).json({ msg: _sr.fa.not_found.user_id })
else return res.status(200).json({ user })
}
module.exports.getUsersForAdmin = async (req, res) => {
const user = await User.find({})
.sort({ active: 1, created_at: -1 })
.select('-password -token -otp -seenByAdmin -cardBank')
res.status(200).json(user)
}
module.exports.getPendingUsersForAdmin = async (req, res) => {
const user = await User.find({ active: false })
.sort({ active: 1, created_at: -1 })
.select('-password -token -otp -seenByAdmin -cardBank')
res.status(200).json(user)
}
module.exports.getUserForAdmin = async (req, res) => {
const user = await User.findById(req.params.id).select('-password -token -otp -seenByAdmin')
if (!user) {
return res.status(404).json({ msg: _sr.fa.not_found.user_id })
} else {
user.seenByAdmin = true
user.save()
res.status(200).json(user)
}
}
module.exports.updateUserByAdmin = [
[
body('first_name')
.optional()
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('last_name')
.optional()
.notEmpty()
.withMessage(_faSr.required.last_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('national_code')
.optional()
.notEmpty()
.withMessage(_faSr.required.national_code)
.bail()
.custom((value, { req }) => {
if (checkNationalCode(value)) return true
else return Promise.reject(_faSr.format.national_code)
})
.bail()
.custom((value, { req }) => {
const nationalCode = value.trim()
return User.findOne({ national_code: nationalCode, _id: { $ne: req.params.id } }).then(user => {
if (user && user.national_code === nationalCode)
return Promise.reject(new Error('کاربر با این کد ملی از قبل وجود دارد'))
else return true
})
}),
body('shopName').optional().notEmpty().withMessage(_faSr.required.address),
body('mobile_number')
.optional()
.notEmpty()
.withMessage(_faSr.required.phone_number)
.bail()
.custom((value, { req }) => {
const mobileNStatus = checkMobileNumber(value)
if (!mobileNStatus) return Promise.reject(_faSr.format.phone_number)
else return Promise.resolve()
})
.bail()
.custom((value, { req }) => {
const mobileNumber = value.trim()
return User.findOne({ mobile_number: mobileNumber, _id: { $ne: req.params.id } }).then(user => {
if (user && user.mobile_number === mobileNumber)
return Promise.reject(new Error('کاربر با این شماره موبایل از قبل وجود دارد'))
else return true
})
}),
body('cell_number').optional().notEmpty().withMessage(_faSr.required.phone_number).bail(),
body('birthDate').optional().notEmpty().withMessage(_faSr.required.birthdate).bail(),
body('address').optional().notEmpty().withMessage(_faSr.required.address).bail()
],
checkValidations(validationResult),
async (req, res) => {
try {
const { first_name, last_name, national_code, mobile_number, shopName, birthDate, address, cell_number } =
req.body
const data = {
first_name: nameOptimizer(first_name),
last_name,
national_code: national_code.trim(),
mobile_number: normalizeMobileNumber(mobile_number),
shopName,
birthDate,
address,
cell_number
}
// const existMobile = await User.findOne({ mobile_number, _id: { $ne: req.params.id } })
// if (existMobile) return res.status(400).json({ msg: 'این شماره موبایل قبلا ثبت شده است' })
const updateUser = await User.findByIdAndUpdate(req.params.id, data, { new: true })
if (!updateUser) return res.status(404).json({ msg: _sr.fa.not_found.user_id })
return res.status(200).json({ message: _faSr.response.success_update, user: updateUser })
} catch (error) {
const registerFailurMsg = 'مشکلی پیش آمده، لطفا مجددا تلاش کنید'
res500(res, registerFailurMsg)
}
}
]
module.exports.activeUser = [
[
param('status').notEmpty().isBoolean().withMessage('این استاتوس اشتباه است'),
param('id').notEmpty().isMongoId().withMessage('این ایدی اشتباه است')
],
checkValidations(validationResult),
async (req, res) => {
const data = await User.findByIdAndUpdate(
req.params.id,
{
active: req.params.status
},
{ new: true }
).select('-password -token -otp -seenByAdmin')
if (!data) return res.status(404).json({ msg: _sr.fa.not_found.user_id })
notifyAdmin('pendingUsers')
res.status(200).json(data)
}
]
module.exports.addUserByAdmin = [
[
body('first_name')
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('last_name')
.notEmpty()
.withMessage(_faSr.required.first_name)
.bail()
.isLength({ min: 2 })
.withMessage(_faSr.min_char.min2)
.bail()
.custom((value, { req }) => {
if (removeWhiteSpaces(value).length < 2) return Promise.reject(_faSr.min_char.min2)
if (!isPersian(value)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید'))
else return true
}),
body('national_code')
.notEmpty()
.withMessage(_faSr.required.national_code)
.bail()
.custom((value, { req }) => {
if (checkNationalCode(value)) return true
else return Promise.reject(_faSr.format.national_code)
})
.bail()
.custom((value, { req }) => {
const nationalCode = value.trim()
return User.findOne({ national_code: nationalCode }).then(user => {
if (user && user.national_code === nationalCode)
return Promise.reject(new Error('کاربر با این کد ملی از قبل وجود دارد'))
else return true
})
}),
body('province_name').notEmpty().withMessage(_faSr.required.province),
body('city_name').notEmpty().withMessage(_faSr.required.city),
body('shopName').notEmpty().withMessage(_faSr.required.address),
body('mobile_number')
.notEmpty()
.withMessage(_faSr.required.phone_number)
.bail()
.custom((value, { req }) => {
const mobileNStatus = checkMobileNumber(value)
if (!mobileNStatus) return Promise.reject(_faSr.format.phone_number)
else return Promise.resolve()
})
.bail()
.custom((value, { req }) => {
const mobileNumber = value.trim()
return User.findOne({ mobile_number: mobileNumber }).then(user => {
if (user && user.mobile_number === mobileNumber)
return Promise.reject(new Error('کاربر با این شماره موبایل از قبل وجود دارد'))
else return true
})
}),
body('password')
.isLength({ min: 4 })
.withMessage(_faSr.min_char.min4)
.custom((value, { req }) => {
if (value === req.body.password_confirmation) return true
else return Promise.reject(_faSr.response.passwords_not_match)
})
],
checkValidations(validationResult),
async (req, res) => {
try {
const provinceId = uid.v4()
const cityId = uid.v4()
const { first_name, last_name, national_code, province_name, city_name, mobile_number, password, shopName } =
req.body
const data = {
last_name,
province_name: { id: provinceId, provinceName: province_name },
city_name: { id: cityId, cityName: city_name },
shopName,
active: true
}
data.first_name = nameOptimizer(first_name)
data.national_code = national_code.trim()
data.mobile_number = normalizeMobileNumber(mobile_number)
// hash user password and done
const salt = await bcrypt.genSalt(10)
const hash = await bcrypt.hash(password, salt)
data.password = hash
const user = new User(data)
await user.save()
return res.status(200).json({ message: _faSr.response.success_save })
} catch (err) {
const registerFailurMsg = 'مشکلی در ثبت نام پیش آمده، لطفا مجددا تلاش کنید'
res500(res, registerFailurMsg)
}
}
]