/var/www/verywell.gr/server/delivery/api/controllers
Edit: /var/www/verywell.gr/server/delivery/api/controllers/user.controller.js (22213B)
const logger = require('../../logger')({ service: 'api' })
const { Op } = require('sequelize')
const PointInPolygon = require('point-in-polygon')
const { UserModel, UsersListModel } = require('../responseModels')
const { NotFound, BadRequest } = require('../responseModels/errors')
const { isSet, isEmpty, isArray, minLength, isPhone, isEmail } = require('../utils/validator.util')
const checkPermission = require('../utils/checkPermission.util')
module.exports = function ({ db }) {
this.Profile = async (req, res, next) => {
logger.child({ path: req.path, user: req.user.uid }).info()
try {
let user = await db.user.findOne({
include: [{ model: db.language }],
where: { uid: req.user.uid }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
const userData = await Promise.all([
/*0*/ db.role.findOne({
include: {
model: db.permission,
through: { attributes: [] }
},
where: { id: user.roleId }
}),
/*1*/ db.userLoginHistory.findAll({ where: { userId: user.id }, limit: 10, order: [['createdAt', 'DESC']] }),
/*2*/ db.userPhone.findAll({ where: { userId: user.id }, limit: 10 }),
/*3*/ db.userToken.findAll({ where: { userId: user.id }, limit: 10 }),
/*4*/ db.address.findAll({ where: { userId: user.id }, limit: 10 }),
/*5*/ db.companyClients.findAll({
include: { model: db.company, where: { deletedAt: null } },
where: { userId: user.id }
}),
/*6*/ db.companyUsers.findAll({
include: [
{ model: db.company, paranoid: false, where: { deletedAt: null } },
{ model: db.role }
],
where: { userId: user.id }
}),
/*7*/ db.branchUsers.findAll({
include: [
{
model: db.branch,
include: [
{
model: db.company,
as: 'company',
paranoid: false,
where: { deletedAt: null }
}
],
paranoid: false,
where: { deletedAt: null }
},
{ model: db.role }
],
where: { userId: user.id, '$branch.company.deletedAt$': null }
}),
/*8*/ db.userGoogleToken.findAll({ where: { userId: user.id } })
])
if (isArray(userData)) {
user.role = userData[0]
user.userLoginHistories = userData[1]
user.userPhones = userData[2]
user.userTokens = userData[3]
user.addresses = userData[4]
user.companyClient = userData[5]
user.userCompanies = userData[6]
user.userBranches = userData[7]
user.userGoogleTokens = userData[8]
}
return res.status(200).json(new UserModel(user))
} catch (err) {
next(err)
}
}
this.List = async (req, res, next) => {
logger.child({ path: req.path, request: req.query }).info()
try {
const t1 = performance.now()
checkPermission(req, 'user_list')
const { branchId, companyId, languageId, roleId, phone, email, name, limit, page } =
req.query
let required = {
phones: false,
companies: false,
branches: false
}
let where = {}
if (isSet(name)) {
where['name'] = { [Op.like]: `%${name}%` }
}
if (isSet(email)) {
where['email'] = { [Op.like]: `%${email}%` }
}
if (isSet(roleId)) {
where['roleId'] = parseInt(roleId)
}
if (isSet(languageId)) {
where['languageId'] = parseInt(languageId)
}
let whereBranch = {}
if (isSet(branchId)) {
whereBranch['id'] = parseInt(branchId)
required.branches = true
}
let whereCompany = {}
if (isSet(companyId)) {
whereCompany['id'] = parseInt(companyId)
required.companies = true
}
let wherePhone = {}
if (isSet(phone)) {
wherePhone['phone'] = {
[Op.like]: `%${phone}%`
}
required.phones = true
}
let offset = page ? (page - 1) * (limit || 10) : 0
const rows = await db.user.findAll({
include: [
{
model: db.userPhone,
required: required.phones,
as: 'userPhones',
where: wherePhone
},
{
model: db.role,
// Очень долго выбирает, непонятно зачем разрешения в списке
// include: {
// model: db.permission,
// through: { attributes: [] }
// }
},
{
model: db.branch,
required: required.branches,
through: 'branch_users',
as: 'userBranches',
where: whereBranch
},
{
model: db.company,
required: required.companies,
through: 'copmany_users',
as: 'userCompanies',
where: whereCompany
},
{ model: db.language }
],
where,
offset,
limit: parseInt(limit) || 10
})
if (!rows || rows.length == 0) {
throw new NotFound({ lang: req.user?.languageCode })
}
const time = performance.now() - t1
return res.status(200).json(new UsersListModel({ users: rows, page, time }))
} catch (err) {
next(err)
}
}
this.Details = async (req, res, next) => {
logger.child({ path: req.path, request: req.params }).info()
try {
const t1 = performance.now()
checkPermission(req, 'user_list')
const { uid } = req.params
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
const user = await db.user.findOne({
include: [
{ model: db.address, as: 'addresses', limit: 10 },
{ model: db.userPhone, as: 'userPhones', limit: 10 },
{ model: db.userToken, as: 'userTokens', limit: 10 },
{ model: db.userLoginHistory, as: 'userLoginHistories', order: [['createdAt', 'DESC']], limit: 10 },
{ model: db.userGoogleToken },
{
model: db.role,
include: {
model: db.permission,
through: { attributes: [] }
}
}
],
where: { uid }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
const time = performance.now() - t1
return res.status(200).json(new UserModel(user))
} catch (err) {
next(err)
}
}
this.Create = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let t1 = performance.now()
try {
checkPermission(req, 'user_edit')
const { name, image, login, email } = req.body
if (!isSet(name) || isEmpty(name) || !minLength(name, 4)) {
throw new BadRequest({
code: 1001,
lang: req.user?.languageCode
})
}
if (!isSet(login) || isEmpty(login) || !minLength(login, 4)) {
throw new BadRequest({
code: 1002,
lang: req.user?.languageCode
})
}
if (!isset(email) || !isEmail(email)) {
throw new BadRequest({
code: 1003,
lang: req.user?.languageCode
})
}
const user = await db.user.create({
name,
image,
login,
email,
userAccount: {
type: ACCOUNT_TYPE.CLIENT,
default: true
}
})
const time = performance.now() - t1
return res.status(200).json({ status: 'success', uid: user.uid, time })
} catch (err) {
next(err)
}
}
this.Edit = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { uid, name, image, login, email } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
if (!isSet(name) || isEmpty(name) || !minLength(name, 4)) {
throw new BadRequest({
code: 1001,
lang: req.user?.languageCode
})
}
if (!isSet(login) || isEmpty(login) || !minLength(login, 4)) {
throw new BadRequest({
code: 1002,
lang: req.user?.languageCode
})
}
if (!isSet(email) || !isEmail(email)) {
throw new BadRequest({
code: 1003,
lang: req.user?.languageCode
})
}
const user = await db.user.findOne({
include: [{ model: db.language }, { model: db.role }],
where: { uid: uid }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
user.name = name
user.image = image
user.login = login
if (user.email != email) {
user.emailConfirmed = false
}
user.email = email
await user.save()
return res.status(200).json(new UserModel(user))
} catch (err) {
next(err)
}
}
this.Delete = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
checkPermission(req, 'user_edit')
const { uid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
const user = await db.user.findOne({
where: { uid: uid }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
await db.user.destroy({ where: { uid: uid } })
return res.status(200).json({ status: 'success', uid: user.uid })
} catch (err) {
next(err)
}
}
this.AddPhone = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { phone, uid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
if (!isSet(phone) || isEmpty(phone) || !isPhone(phone)) {
throw new BadRequest({ code: 1004, lang: req.user?.languageCode })
}
const foundPhone = await db.userPhone.findOne({
where: { phone: phone }
})
if (foundPhone) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({
where: { uid: uid },
include: ['userPhones']
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
const new_phone = await db.userPhone.create({
phone,
userId: user.id
})
return res.status(200).json({ status: 'success', uid: new_phone.uid })
} catch (err) {
next(err)
}
}
this.RemovePhone = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { uid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
const userPhone = await db.userPhone.findOne({
where: { uid: uid }
})
if (!userPhone) {
throw new NotFound({ lang: req.user?.languageCode })
}
await userPhone.destroy()
return res.status(200).json({ status: 'success', uid: uid })
} catch (err) {
next(err)
}
}
this.AddAddress = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const {
address,
latitude,
longtitude,
uid,
street,
street_number,
number,
zip,
comment,
doorbell,
floor
} = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
if (!isSet(address) || isEmpty(address)) {
throw new BadRequest({ code: 1004, lang: req.user?.languageCode })
}
const foundAddress = await db.address.findOne({
where: { adres: address }
})
if (foundAddress) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({
where: { uid: uid },
include: ['addresses']
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
const new_address = await db.address.create({
adres: address,
latitude: latitude,
longtitude: longtitude,
street: street,
street_number: street_number,
number: number,
zip: zip,
comment: comment,
doorbell: doorbell,
floor: floor,
userId: user.id
})
return res.status(200).json({ status: 'success', uid: new_address.uid })
} catch (err) {
next(err)
}
}
this.EditAddress = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const {
address,
latitude,
longtitude,
uid,
addressUid,
street,
street_number,
number,
zip,
comment,
doorbell,
floor
} = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
if (!isSet(addressUid) || isEmpty(addressUid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
if (!isSet(address) || isEmpty(address)) {
throw new BadRequest({ code: 1004, lang: req.user?.languageCode })
}
const foundAddress = await db.address.findOne({
where: { uid: addressUid }
})
if (!foundAddress) {
throw new NotFound({ lang: req.user?.languageCode })
}
foundAddress.adres = address
foundAddress.latitude = latitude
foundAddress.longtitude = longtitude
;(foundAddress.street = street),
(foundAddress.street_number = street_number),
(foundAddress.number = number),
(foundAddress.zip = zip),
(foundAddress.comment = comment),
(foundAddress.doorbell = doorbell),
(foundAddress.floor = floor),
foundAddress.save()
return res.status(200).json({ status: 'success', address: foundAddress })
} catch (err) {
next(err)
}
}
this.RemoveAddress = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { uid, addressUid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
if (!isSet(addressUid) || isEmpty(addressUid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
const userAddress = await db.address.findOne({
where: { uid: addressUid }
})
if (!userAddress) {
throw new NotFound({ lang: req.user?.languageCode })
}
await userAddress.destroy()
return res.status(200).json({ status: 'success', uid: addressUid })
} catch (err) {
next(err)
}
}
this.SetDefaultAddress = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { uid, addressUid, branches } = req.body
let branchesResult = []
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
if (!isSet(addressUid) || isEmpty(addressUid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
const userAddress = await db.address.findOne({
where: { uid: addressUid }
})
if (!userAddress) {
throw new NotFound({ lang: req.user?.languageCode })
}
const userId = userAddress['userId']
const user = await db.user.findOne({
where: { id: userId }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
user.defaultAddressId = userAddress.id
await user.save()
if (isArray(branches) && branches.length > 0) {
const branchesArray = await db.branch.findAll({
where: {
uid: { [Op.in]: branches }
}
})
if (branchesArray.length > 0) {
for (const branch in branchesArray) {
branchesResult.push({
uid: branch.uid,
result: PointInPolygon(
[userAddress.latitude, userAddress.longtitude], // или [userAddress.longtitude, userAddress.latitude] ?
JSON.parse(branch.area) // area в базе "[[1, 1], [1, -1], [-1, -1], [-1, 1]]"
)
})
}
}
}
return res.status(200).json({ status: 'success', uid: uid, branches: branchesResult })
} catch (err) {
next(err)
}
}
this.AddToken = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { token, platform, deviceId, app, uid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
if (!isSet(token) || isEmpty(token)) {
throw new BadRequest({ code: 1016, lang: req.user?.languageCode })
}
if (!isSet(app) || isEmpty(app)) {
throw new BadRequest({ code: 1018, lang: req.user?.languageCode })
}
if (!isSet(deviceId) || isEmpty(deviceId)) {
throw new BadRequest({ code: 1019, lang: req.user?.languageCode })
}
if (!isSet(platform) || isEmpty(platform)) {
throw new BadRequest({ code: 1017, lang: req.user?.languageCode })
}
const foundToken = await db.userToken.findOne({
where: { token: token }
})
if (foundToken) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({
where: { uid: uid },
include: ['userTokens']
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
const new_token = await db.userToken.create({
token,
platform,
deviceId,
app,
userId: user.id
})
return res.status(200).json({ status: 'success', uid: new_token.uid })
} catch (err) {
next(err)
}
}
this.RemoveToken = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
if (req.body.uid != req.user.uid) {
checkPermission(req, 'user_edit')
}
const { uid, tokenUid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({ code: 400, lang: req.user?.languageCode })
}
const userToken = await db.userToken.findOne({
where: { uid: tokenUid }
})
if (!userToken) {
throw new NotFound({ lang: req.user?.languageCode })
}
await userToken.destroy()
return res.status(200).json({ status: 'success', uid: tokenUid })
} catch (err) {
next(err)
}
}
this.ConfirmEmailRequest = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
const { uid } = req.body
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
// найти пользователя
const user = await db.user.findOne({ where: { uid } })
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
// сгенрировать токен
const mailConfirmToken = jwt.sign(
{
uid: user.uid
},
config.jwt.secret,
{
expiresIn: config.jwt.confirmTokenExpires
}
)
const nodemailer = require('nodemailer')
const smtpProtocol = nodemailer.createTransport({
host: config.mail.smtpServer,
port: config.mail.smtpPort,
secure: true,
auth: {
user: config.mail.userName,
pass: config.mail.password
}
})
const message = {
from: config.mail.userName, // адрес отправителя
to: email, // список получателей "mailto1, mailto2"
subject: 'Подтверждение адреса электронной почты', // заголовок
//text: 'text',
html: `Для подтверждения адреса электронной почты перейдите по
ссылке.`
}
// отправка сообщения
const result = await smtpProtocol.sendMail(message)
return res.status(200).json(result)
} catch (err) {
next(err)
}
}
this.ConfirmEmail = async (req, res, next) => {
try {
logger.child({ path: req.path, request: req.body }).info()
// разбор и валидация запроса
const { token } = req.body
if (!isSet(token) || isEmpty(token)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
// декодировать токен
const decodedToken = jwt.verify(token, config.jwt.secret)
if (!decodedToken || !decodedToken.uid) {
throw new NotFound({ lang: req.user?.languageCode })
}
// найти пользователя
let user = await db.user.findOne({
where: { uid: decodedToken.uid }
})
user.emailConfirmed = true
await user.save()
return res.status(200).json({ status: 'success' })
} catch (err) {
next(err)
}
}
this.UserLoginHistory = async (req, res, next) => {
logger.child({ path: req.path, request: req.query }).info()
try {
const t1 = performance.now()
checkPermission(req, 'user_login_history')
const { userId, roleId, phone, ipAddress, limit, page } = req.query
let where = {}
if (userId) {
where['userId'] = parseInt(userId)
}
if (ipAddress) {
where['ipAddress'] = ipAddress
}
// let whereRole = {}
// if (roleId) {
// whereRole['id'] = parseInt(roleId)
// }
// let wherePhone = {}
// if (phone) {
// wherePhone['phone'] = phone
// }
let offset = page ? (page - 1) * (limit || 10) : 0
const userLoginHistories = await db.userLoginHistory.findAll({
include: [
{
model: db.user,
// include: [
// { model: db.userPhone, as: 'userPhones', where: wherePhone },
// {
// model: db.role,
// where: whereRole
// }
// ]
}
],
where,
offset,
order: [
['id', 'DESC'],
],
limit: parseInt(limit) || 10
})
if (!userLoginHistories || userLoginHistories.length == 0) {
throw new NotFound({ lang: req.user?.languageCode })
}
const time = performance.now() - t1
return res.status(200).json({ list: userLoginHistories, page, time })
} catch (err) {
next(err)
}
}
this.PushMessage = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
let { message, uid } = req.body
if (!isSet(message) || isEmpty(message)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
if (!isSet(uid) || isEmpty(uid)) {
throw new BadRequest({
lang: req.user?.languageCode
})
}
const user = await this.db.user.findOne({
where: { uid }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
let options = {}
const result = await SERVICES.Firebase.sendToUser(user.id, message, options)
res.status(200).json(result)
} catch (err) {
next(err)
}
}
}