/var/www/verywell.gr/server/delivery/api/controllers
Edit: /var/www/verywell.gr/server/delivery/api/controllers/auth.controller.js (13187B)
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const config = require('../../config/app.json')
const logger = require('../../logger')({ service: 'api' })
const { isSet, isEmail, isPhone, isEmpty, minLength, isNumber } = require('../utils/validator.util')
const RefreshTokenUtils = require('../utils/refreshToken.util')
const { Op } = require('sequelize')
const { BadRequest, Forbidden, NotFound } = require('../responseModels/errors')
module.exports = function ({ db }) {
// Логин
this.SignIn = async (req, res, next) => {
try {
logger.child({ path: req.path }).info()
const { login, password, app, platform, deviceId, googleId, googleName, googleToken } = req.body
const ipAddress = req.headers['x-forwarded-for'] || req.socket.remoteAddress
const userAgent = req.get('User-Agent')
let name = isSet(googleName) ? googleName : ''
if (!isSet(platform)) {
throw new BadRequest({
code: 1017,
lang: req.user?.languageCode
})
}
if (!isSet(app)) {
throw new BadRequest({
code: 1018,
lang: req.user?.languageCode
})
}
if (!isSet(deviceId)) {
throw new BadRequest({
code: 1019,
lang: req.user?.languageCode
})
}
let foundUser = null
if (isSet(googleId) && !isEmpty(googleId)) {
// google авторизация
// найти пользователя по googleId
foundUser = await db.user.findOne({ where: { googleId } })
if (!foundUser) {
// не нашли
// найти по email
const roleId = 7; // Client
foundUser = await db.user.findOne({ where: { email: login } })
if (!foundUser) {
// если не нашли создать
foundUser = await db.user.create({
name: name,
email: login,
roleId,
googleId
})
// !!! создается без логина
// !!! нужно дать пользователю возможность создать логин если его нет
} else {
// если нашли присвоить googleId
foundUser.googleId = googleId
await foundUser.save()
}
}
} else {
// авторизация по логину и паролю
if ((!isSet(login) || isEmpty(login)) && !isPhone(login) && !isEmail(login)) {
throw new BadRequest({
code: 1002,
lang: req.user?.languageCode
})
}
if (!isSet(password) || isEmpty(password)) {
throw new BadRequest({
code: 1005,
lang: req.user?.languageCode
})
}
let where = {}
let include = []
if (isPhone(login)) { // авторизация по номеру телефона
include = [
{
model: db.userPhone, where: { phone: login }
}
]
} else if (isEmail(login)) { // авторизация по email
where = { email: login }
} else { // авторизация по логину
where = { login }
}
foundUser = (
await db.user.findOne({ include, where })
)
if (!foundUser) {
throw new BadRequest({
code: 1007,
lang: req.user?.languageCode
})
}
if (foundUser) {
const passwordIsValid = await bcrypt.compare(password, foundUser.passwordHash)
if (!passwordIsValid) {
throw new BadRequest({
code: 1007,
lang: req.user?.languageCode
})
}
}
}
let accessToken = await RefreshTokenUtils.createAccessToken({
db,
app,
deviceId,
platform,
userId: foundUser.id
})
let refreshToken = await db.refreshToken.findOne({
where: { app, deviceId, userId: foundUser.id }
})
if (refreshToken !== null) {
await db.refreshToken.destroy({
where: { id: refreshToken.id }
})
}
refreshToken = await RefreshTokenUtils.createRefreshToken({
db,
app,
deviceId,
platform,
userId: foundUser.id
})
if (googleToken) {
const gToken = await db.userGoogleToken.findOne({ where: { token: googleToken } })
if (gToken) {
//обновить
gToken.token = googleToken
gToken.save()
} else {
// создать
db.userGoogleToken.create({
token: googleToken,
userId: foundUser.id,
deviceId: deviceId
})
}
}
db.userLoginHistory.create({
ipAddress,
userAgent,
app,
deviceId,
platform,
userId: foundUser.id
})
return res.status(200).json({ accessToken, refreshToken })
} catch (err) {
next(err)
}
}
//Выход
this.SignOut = async (req, res, next) => {
logger.child({ path: req.path, request: req.user }).info()
try {
const { uid } = req.user
const user = await db.user.findOne({ where: { uid } })
await db.refreshToken.destroy({ where: { userId: user.id } })
req.user = null
return res.status(200).json({ status: 'success' })
} catch (err) {
next(err)
}
}
// Регистрация
this.SignUp = async (req, res, next) => {
logger.child({ path: req.path }).info()
try {
const { login, name, email, phone, password, passwordConfirm, googleId, languageId } = req.body
// Role ID
const roleId = 7; // Client
// Not required
// if (!isSet(login) || isEmpty(login)) {
// throw new BadRequest({
// code: 1002,
// lang: req.user?.languageCode
// })
// }
if (!isSet(name) || isEmpty(name)) {
throw new BadRequest({
code: 1001,
lang: req.user?.languageCode
})
}
if (!minLength(name, 4)) {
throw new BadRequest({
code: 1009,
lang: req.user?.languageCode
})
}
if (!isSet(email) || !isEmail(email)) {
throw new BadRequest({
code: 1003,
lang: req.user?.languageCode
})
}
if (!isSet(languageId) || languageId == 0) {
throw new BadRequest({
code: 1024,
lang: req.user?.languageCode
})
}
let foundUser = null
let newUser = null
if (isSet(googleId) && !isEmpty(googleId)) {
// найти пользователя по googleId
foundUser = await db.user.findOne({ where: { googleId } })
if (foundUser) {
throw new BadRequest({
code: 1008,
lang: req.user?.languageCode
})
}
// найти пользователся по email
foundUser = await db.user.findOne({ where: { email } })
if (!foundUser) {
// если не нашли создать нового
newUser = await db.user.create({
login,
name,
email,
googleId,
roleId,
languageId
})
} else {
// если нашли присвоить googleId
foundUser.googleId = googleId
await foundUser.save()
}
} else {
// if (!isSet(phone) || !isPhone(phone)) {
// throw new BadRequest({
// code: 1004,
// lang: req.user?.languageCode
// })
// }
if (!isSet(password) || isEmpty(password)) {
throw new BadRequest({
code: 1005,
lang: req.user?.languageCode
})
}
if (password != passwordConfirm) {
throw new BadRequest({
code: 1006,
lang: req.user?.languageCode
})
}
// if (!minLength(login, 4)) {
// throw new BadRequest({
// code: 1010,
// lang: req.user?.languageCode
// })
// }
if (!minLength(password, 4)) {
throw new BadRequest({
code: 1011,
lang: req.user?.languageCode
})
}
let op_or = [
{ '$user.email$': email },
]
if (isSet(login) && !isEmpty(login)) {
op_or.push({ '$user.login$': login })
}
if (isSet(phone) && !isEmpty(phone)) {
op_or.push({ '$userPhone.phone$': phone })
}
foundUser = (
await db.userPhone.findOne({
include: ['user'],
where: {
[Op.or]: op_or
}
})
)?.user
if (foundUser) {
throw new BadRequest({
code: 1008,
lang: req.user?.languageCode
})
}
// сгенегрировать хэш пароля
const salt = await bcrypt.genSalt(10)
const passwordHash = await bcrypt.hash(password, salt)
// Params
let params = {
name,
email,
passwordHash,
roleId,
languageId,
}
if (isSet(login) && !isEmpty(login)) {
params.login = login
}
if (isSet(phone) && !isEmpty(phone)) {
params.userPhones = [
{
phone
}
]
}
let include = null;
if (isSet(phone) && !isEmpty(phone)) {
include = {
include: ['userPhones']
}
}
// создать запись в базе
newUser = await db.user.create(params, include)
}
// отправить PUSH userId == 1
let message = {
notification: {
title: config.app.name,
body: 'New user: '+ user.name
},
// data: {
// channel_id: threadId,
// },
android: {
ttl: 3600 * 1000,
notification: {
priority: 'high',
sound: 'default',
notificationCount: 1
// icon: 'stock_ticker_update',
// color: '#f45342',
}
},
apns: {
payload: {
aps: {
badge: 1,
sound: 'default'
}
}
},
fcmOptions: {
analyticsLabel: 'company_created'
}
}
await SERVICES.Firebase.SendToUser(1, message, {})
return res.status(200).json({
status: 'success',
uid: newUser.uid
})
} catch (err) {
next(err)
}
}
// Обновление токена
this.RefreshToken = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
const { refreshToken } = req.body
if (!isSet(refreshToken)) {
throw new Forbidden({ lang: req.user?.languageCode })
}
let token = await db.refreshToken.findOne({
where: { token: refreshToken }
})
if (!token) {
throw new Forbidden({ lang: req.user?.languageCode })
}
if (!RefreshTokenUtils.verify(token)) {
throw new Forbidden({ code: 1011, lang: req.user?.languageCode })
}
const { app, deviceId, platform, userId } = token
const accessToken = await RefreshTokenUtils.createAccessToken({
db,
app,
deviceId,
platform,
userId
})
return res.status(200).json({
accessToken: accessToken,
refreshToken: token.token
})
} catch (err) {
next(err)
}
}
this.ResetPassword = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
// разбор и валидация запроса
const { email } = req.body
if (!isSet(email) || isEmpty(email)) {
throw new BadRequest({
code: 1003,
lang: req.user?.languageCode
})
}
// найти пользователя
const user = await db.user.findOne({ where: { email: email } })
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
// сгенрировать токен
const resetPasswordToken = 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.ResetPasswordConfirm = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
// разбор и валидация запроса
const { token, newPassword, newPasswordConfirm } = req.body
if (!isSet(token) || isEmpty(token)) {
throw new BadRequest({
code: 1011,
lang: req.user?.languageCode
})
}
if (!isSet(newPassword) || isEmpty(newPassword)) {
throw new BadRequest({
code: 1005,
lang: req.user?.languageCode
})
}
if (newPassword != newPasswordConfirm) {
throw new BadRequest({
code: 1006,
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 }
})
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
// сгененировать соль и создать хэш пароля
const salt = await bcrypt.genSalt(10)
user.passwordHash = await bcrypt.hash(newPassword, salt)
await user.save()
return res.status(200).json({ status: 'success' })
} catch (err) {
next(err)
}
}
}