From 4c7e49fb9ad7b22d47811b6aa9f8c2f19ba29a7f Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 12:46:12 -0300 Subject: [PATCH 01/11] feat: add base structure to EL-IAM integration --- ESPACO-LAZER-IAM.MD | 38 +++ backend/src/controllers/IAMControllerEL.ts | 314 +++++++++++++++++++++ backend/src/routes/iamRoutesEL.ts | 23 ++ backend/src/routes/index.ts | 2 + 4 files changed, 377 insertions(+) create mode 100644 ESPACO-LAZER-IAM.MD create mode 100644 backend/src/controllers/IAMControllerEL.ts create mode 100644 backend/src/routes/iamRoutesEL.ts diff --git a/ESPACO-LAZER-IAM.MD b/ESPACO-LAZER-IAM.MD new file mode 100644 index 0000000..d24ba28 --- /dev/null +++ b/ESPACO-LAZER-IAM.MD @@ -0,0 +1,38 @@ +# O que fazer? + +- Quando um usuário for criado na plataforma do E-trust Horacius, a aplicação do Omnihit deve criar o mesmo usuário no Banco de Dados do Omnihit. + - Criação + - Atualização + - Exclusão +- Quando um usuário for criado com um **profile(role)**, a aplicação do Omnihit deve alterar o profile + - Tipos de roles: `admin`, `user`, `supervisor` + - Atualização + - Exclusão + +# Como fazer? + +- Elaborar forma de autenticação +- Criar uma aplicação REST seguindo o protocolo especificado na documentação do Horacius + - Níveis + - 1: Da para fazer + - 2: Tem que analisar + - Users + - [] CheckUser (1) + - [] CreateUser (1) + - [] DeleteUser (1) + - [] UpdateUser (1) + - [] ListAllUsers **OPCIONAL** + - [] LockUser (2) + - [] UnlockUser (2) + - [] ResetPassword (2) + - Rights + - [] CheckUserRight (1) + - [] CreateRight (1) + - [] UpdateRight (1) + - [] DeleteRight (1) + - [] GetAllRights **OPCIONAL** + - Users X Rights + - [] LinkUserAndUserRight (1) + - [] UnlinkUserAndUserRight (1) + - [] GetAllUserRights **OPCIONAL** + diff --git a/backend/src/controllers/IAMControllerEL.ts b/backend/src/controllers/IAMControllerEL.ts new file mode 100644 index 0000000..afcdc76 --- /dev/null +++ b/backend/src/controllers/IAMControllerEL.ts @@ -0,0 +1,314 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import AppError from "../errors/AppError"; + +import CreateUserService from "../services/UserServices/CreateUserService"; +import ListUsersService from "../services/UserServices/ListUsersService"; +import UpdateUserService from "../services/UserServices/UpdateUserService"; +import ShowUserService from "../services/UserServices/ShowUserService"; +import DeleteUserService from "../services/UserServices/DeleteUserService"; + +import ListUser from "../services/UserServices/ListUserParamiterService"; +import { del, get, set } from "../helpers/RedisClient"; + +import { + startWhoIsOnlineMonitor, + stopWhoIsOnlineMonitor +} from "../helpers/WhoIsOnlineMonitor"; + +import { format, subMonths } from "date-fns"; +import { ptBR } from "date-fns/locale"; +import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue"; +import { splitDateTime } from "../helpers/SplitDateTime"; +import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService"; +import { getSettingValue } from "../helpers/WhaticketSettings"; +import { setBotInfo } from "../helpers/SetBotInfo"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + profile?: string; + userId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber, profile } = req.query as IndexQuery; + + const { users, count, hasMore } = await ListUsersService({ + searchParam, + pageNumber, + profile + }); + + if (req.user.profile !== "master") { + let auxUsers: Array = []; + + // for (var user of users) { + // if (user.profile !== 'master') { + // auxUsers.push(user) + // } + // } + + for (var user of users) { + if (user.profile !== "master") { + if (req.user.profile == "supervisor" && user.profile == "admin") + continue; + + auxUsers.push(user); + } + } + + return res.json({ users: auxUsers, count, hasMore }); + } + + return res.json({ users, count, hasMore }); + + // const { users, count, hasMore } = await ListUsersService({ + // searchParam, + // pageNumber + // }); + + // if(req.user.profile!=='master'){ + + // let auxUsers: Array = []; + + // for (var user of users) { + // if(user.profile!=='master'){ + // auxUsers.push(user) + // } + // } + + // return res.json({ users: auxUsers, count, hasMore }); + // } + + // return res.json({ users, count, hasMore }); +}; + +export const all = async (req: Request, res: Response): Promise => { + let { userId, profile }: any = req.query as IndexQuery; + + console.log( + "userId: ", + userId, + " | profile: ", + profile, + ' | getSettingValue("queueTransferByWhatsappScope")?.value: ', + getSettingValue("queueTransferByWhatsappScope")?.value + ); + + if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") { + if (!userId) return res.json({ users: [], queues: [] }); + + const obj = await ListUserByWhatsappQueuesService( + userId, + '"admin", "user", "supervisor"' + ); + + const usersByWhatsqueue = obj.users; + const queues = obj.queues; + + let userIds = usersByWhatsqueue.map((w: any) => w.userId); + + const users = await ListUser({ + userIds + }); + + return res.json({ users, queues }); + } else { + const users = await ListUser({ + profile + }); + return res.json({ users }); + } +}; + +export const store = async (req: Request, res: Response): Promise => { + const { email, password, name, profile, positionCompany, queueIds } = + req.body; + + console.log("===========> req.url: ", req.url); + + if ( + req.url === "/user" && + getSettingValue("userCreation")?.value == "disabled" && + req.user.profile == "admin" + ) { + throw new AppError("ERR_NO_PERMISSION", 403); + } else if ( + req.url === "/signup" && + getSettingValue("userCreation")?.value == "disabled" + ) { + throw new AppError("ERR_USER_CREATION_DISABLED", 403); + } else if (req.user.profile !== "master") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const user = await CreateUserService({ + email, + password, + name, + positionCompany, + profile, + queueIds + }); + + if (user) { + const { id, name } = user; + await set(`user:${id}`, { id, name }); + } + + const io = getIO(); + io.emit("user", { + action: "create", + user + }); + + // await stopWhoIsOnlineMonitor() + await startWhoIsOnlineMonitor(); + + return res.status(200).json(user); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { userId } = req.params; + + const user = await ShowUserService(userId); + + return res.status(200).json(user); +}; + +export const logoutUser = async ( + req: Request, + res: Response +): Promise => { + const { userId } = req.params; + + await stopWhoIsOnlineMonitor(); + + let onlineTime = { + userId: userId, + status: "logout..." + }; + + const io = getIO(); + io.emit("onlineStatus", { + action: "logout", + userOnlineTime: onlineTime + }); + + await startWhoIsOnlineMonitor(); + // + + return res.status(200).json({}); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + if ( + req.user.profile !== "admin" && + req.user.profile !== "master" && + req.user.profile !== "supervisor" + ) { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const { userId } = req.params; + const userData = req.body; + + const dateToday = splitDateTime( + new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) + ); + + const currentDate = new Date(); + const tenMonthsAgo = subMonths(currentDate, 10); + const formattedDate = format(tenMonthsAgo, "yyyy-MM-dd"); + console.log("dateToday.fullDate: ", dateToday.fullDate); + console.log("formattedDate 10 months ago: ", formattedDate); + + const openByUserOnQueue: any[] = await CountTicketsByUserQueue({ + startDate: formattedDate, + endDate: dateToday.fullDate, + status: "open", + clientChatStart: true, + userId: userId + }); + + // console.log('------> openByUserOnQueue: ', openByUserOnQueue) + // console.log() + // console.log('------> 1 userData.queueIds: ', userData.queueIds) + + let userQueuesAttendance = []; + + if ((openByUserOnQueue && openByUserOnQueue.length) > 0) { + userQueuesAttendance = openByUserOnQueue.filter( + (e: any) => !userData.queueIds.includes(e.queueId) + ); + + if (userQueuesAttendance && userQueuesAttendance.length > 0) { + const queueInAttendance = userQueuesAttendance.map(e => e.queueId); + + const mergedSet = new Set([...userData.queueIds, ...queueInAttendance]); + + // Convert the Set back to an array + userData.queueIds = Array.from(mergedSet); + + // console.log('------> 2 userData.queueIds: ', userData.queueIds) + } + } + + let user: any = await UpdateUserService({ userData, userId }); + + await setBotInfo(user); + + if (user) { + const { id, name } = user; + await set(`user:${id}`, { id, name }); + } + + const io = getIO(); + io.emit("user", { + action: "update", + user + }); + + user.userQueuesAttendance = userQueuesAttendance; + + return res.status(200).json(user); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { userId } = req.params; + + if (req.user.profile !== "master") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + await DeleteUserService(userId); + + del(`user:${userId}`); + + const io = getIO(); + io.emit("user", { + action: "delete", + userId + }); + + //test del + await stopWhoIsOnlineMonitor(); + + io.emit("onlineStatus", { + action: "delete", + userOnlineTime: userId + }); + + await startWhoIsOnlineMonitor(); + // + + return res.status(200).json({ message: "User deleted" }); +}; diff --git a/backend/src/routes/iamRoutesEL.ts b/backend/src/routes/iamRoutesEL.ts new file mode 100644 index 0000000..7c359d5 --- /dev/null +++ b/backend/src/routes/iamRoutesEL.ts @@ -0,0 +1,23 @@ +import { Router } from "express"; + +import isAuth from "../middleware/isAuth"; +import * as IAMControllerEL from "../controllers/IAMControllerEL"; + +const iamRoutesEL = Router(); + + +iamRoutesEL.get("/users/all", isAuth, IAMControllerEL.all); + +iamRoutesEL.get("/users", isAuth, IAMControllerEL.index); + +iamRoutesEL.post("/users", isAuth, IAMControllerEL.store); + +iamRoutesEL.put("/users/:userId", isAuth, IAMControllerEL.update); + +iamRoutesEL.get("/users/:userId", isAuth, IAMControllerEL.show); + +iamRoutesEL.get("/users/logout/:userId", isAuth, IAMControllerEL.logoutUser); + +iamRoutesEL.delete("/users/:userId", isAuth, IAMControllerEL.remove); + +export default iamRoutesEL; diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts index 297e954..1e769a5 100644 --- a/backend/src/routes/index.ts +++ b/backend/src/routes/index.ts @@ -14,10 +14,12 @@ import reportRoutes from "./reportRoutes"; import schedulingNotifiyRoutes from "./SchedulingNotifyRoutes"; import statusChatEndRoutes from "./statusChatEndRoutes"; import wbotMonitorRoutes from "./wbotMonitorRoutes"; +import iamRoutesEL from "./iamRoutesEL"; const routes = Router(); +routes.use(iamRoutesEL); routes.use(userRoutes); routes.use("/auth", authRoutes); routes.use(settingRoutes); From 3478b7c5b29941240b5be5f83323b11065faa449 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:06:39 -0300 Subject: [PATCH 02/11] feat: add iam controllers (createUser, checkUser, deleteUser, updateUser, resetPassword, linkUserAndUserRight, unlinkUserAndUserRight, checkUserRight) --- backend/src/controllers/IAMControllerEL.ts | 585 +++++++++++---------- 1 file changed, 319 insertions(+), 266 deletions(-) diff --git a/backend/src/controllers/IAMControllerEL.ts b/backend/src/controllers/IAMControllerEL.ts index afcdc76..19b4c51 100644 --- a/backend/src/controllers/IAMControllerEL.ts +++ b/backend/src/controllers/IAMControllerEL.ts @@ -24,291 +24,344 @@ import { splitDateTime } from "../helpers/SplitDateTime"; import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService"; import { getSettingValue } from "../helpers/WhaticketSettings"; import { setBotInfo } from "../helpers/SetBotInfo"; +import { logger } from "../utils/logger"; +import ResetPasswordService from "../services/UserServices/ResetPassword"; +import LinkUserAndUserRightService from "../services/UserServices/LinkUserAndUserRight"; +import UnlinkUserAndUserRightService from "../services/UserServices/UnlinkUserAndUserRight"; +import CheckUserRightService from "../services/UserServices/CheckUserRightService"; -type IndexQuery = { - searchParam: string; - pageNumber: string; - profile?: string; - userId: string; +interface IAMResponse { + return_code: string + return_msg: string +} + +//TODO: REVIEW CREATE USER +export const createUser = async (req: Request, res: Response): Promise => { + try { + const { user_id, user_first_name, user_tax_id } = req.body; + //user_id ou cria uma tabela nova ou um atributo novo + const user = await CreateUserService({ + email: user_tax_id, + password: "padrao", + name: user_first_name, + }); + + if (user) { + const { id, name } = user; + await set(`user:${id}`, { id, name }); + } + + const io = getIO(); + io.emit("user", { + action: "create", + user + }); + + await startWhoIsOnlineMonitor(); + + return res.status(204).json({ + return_code: "204", + return_msg: `User ${user_id} created`, + user_created: "1" + }); + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_created: "0", + }); + } + + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_created: "0", + }); + } }; -export const index = async (req: Request, res: Response): Promise => { - const { searchParam, pageNumber, profile } = req.query as IndexQuery; +export const checkUser = async (req: Request, res: Response): Promise => { + try { + const { user_id } = req.body; + await ShowUserService(user_id); + return res.status(200).json({ + return_code: "200", + return_msg: "", + user_exists: "1" + }); + } catch (error) { - const { users, count, hasMore } = await ListUsersService({ - searchParam, - pageNumber, - profile - }); + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_exists: "0", + }); + } - if (req.user.profile !== "master") { - let auxUsers: Array = []; + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_exists: "0", + }); + } +}; - // for (var user of users) { - // if (user.profile !== 'master') { - // auxUsers.push(user) +//TODO: REVIEW DELETE USER +export const deleteUser = async (req: Request, res: Response): Promise => { + try { + const { user_id } = req.body; + + await DeleteUserService(user_id); + + del(`user:${user_id}`); + + const io = getIO(); + io.emit("user", { + action: "delete", + user_id + }); + + //test del + await stopWhoIsOnlineMonitor(); + + io.emit("onlineStatus", { + action: "delete", + userOnlineTime: user_id + }); + + await startWhoIsOnlineMonitor(); + return res.status(200).json({ + return_code: "200", + return_msg: `User ${user_id} deleted`, + user_removed: "1", + }); + + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_removed: "0", + }); + } + + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_removed: "0", + }); + } +}; + +//TODO: REVIEW UPDATE USER +export const updateUser = async (req: Request, res: Response): Promise => { + try { + const { user_id, user_first_name, user_tax_id } = req.body; + // const dateToday = splitDateTime(new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))); + // const currentDate = new Date(); + // const tenMonthsAgo = subMonths(currentDate, 10); + // const formattedDate = format(tenMonthsAgo, "yyyy-MM-dd"); + // console.log("dateToday.fullDate: ", dateToday.fullDate); + // console.log("formattedDate 10 months ago: ", formattedDate); + + // const openByUserOnQueue: any[] = await CountTicketsByUserQueue({ + // startDate: formattedDate, + // endDate: dateToday.fullDate, + // status: "open", + // clientChatStart: true, + // userId: userId + // }); + // let userQueuesAttendance = []; + + // if ((openByUserOnQueue && openByUserOnQueue.length) > 0) { + // userQueuesAttendance = openByUserOnQueue.filter( + // (e: any) => !userData.queueIds.includes(e.queueId) + // ); + + // if (userQueuesAttendance && userQueuesAttendance.length > 0) { + // const queueInAttendance = userQueuesAttendance.map(e => e.queueId); + // const mergedSet = new Set([...userData.queueIds, ...queueInAttendance]); + + // userData.queueIds = Array.from(mergedSet); // } // } + const userData = { + email: user_tax_id, + name: user_first_name, + } + // email?: string; + // name?: string; + // password?: string; + // positionCompany?: string; + // profile?: string; + // queueIds?: number[]; + let user: any = await UpdateUserService({ userData, userId: user_id }); + await setBotInfo(user); - for (var user of users) { - if (user.profile !== "master") { - if (req.user.profile == "supervisor" && user.profile == "admin") - continue; - - auxUsers.push(user); - } + if (user) { + const { id, name } = user; + await set(`user:${id}`, { id, name }); } - return res.json({ users: auxUsers, count, hasMore }); - } - - return res.json({ users, count, hasMore }); - - // const { users, count, hasMore } = await ListUsersService({ - // searchParam, - // pageNumber - // }); - - // if(req.user.profile!=='master'){ - - // let auxUsers: Array = []; - - // for (var user of users) { - // if(user.profile!=='master'){ - // auxUsers.push(user) - // } - // } - - // return res.json({ users: auxUsers, count, hasMore }); - // } - - // return res.json({ users, count, hasMore }); -}; - -export const all = async (req: Request, res: Response): Promise => { - let { userId, profile }: any = req.query as IndexQuery; - - console.log( - "userId: ", - userId, - " | profile: ", - profile, - ' | getSettingValue("queueTransferByWhatsappScope")?.value: ', - getSettingValue("queueTransferByWhatsappScope")?.value - ); - - if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") { - if (!userId) return res.json({ users: [], queues: [] }); - - const obj = await ListUserByWhatsappQueuesService( - userId, - '"admin", "user", "supervisor"' - ); - - const usersByWhatsqueue = obj.users; - const queues = obj.queues; - - let userIds = usersByWhatsqueue.map((w: any) => w.userId); - - const users = await ListUser({ - userIds + const io = getIO(); + io.emit("user", { + action: "update", + user }); - return res.json({ users, queues }); - } else { - const users = await ListUser({ - profile + // user.userQueuesAttendance = userQueuesAttendance; + return res.status(200).json({ + return_code: "200", + return_msg: `User ${user_id} updated`, + user_updated: "1" }); - return res.json({ users }); - } -}; - -export const store = async (req: Request, res: Response): Promise => { - const { email, password, name, profile, positionCompany, queueIds } = - req.body; - - console.log("===========> req.url: ", req.url); - - if ( - req.url === "/user" && - getSettingValue("userCreation")?.value == "disabled" && - req.user.profile == "admin" - ) { - throw new AppError("ERR_NO_PERMISSION", 403); - } else if ( - req.url === "/signup" && - getSettingValue("userCreation")?.value == "disabled" - ) { - throw new AppError("ERR_USER_CREATION_DISABLED", 403); - } else if (req.user.profile !== "master") { - throw new AppError("ERR_NO_PERMISSION", 403); - } - - const user = await CreateUserService({ - email, - password, - name, - positionCompany, - profile, - queueIds - }); - - if (user) { - const { id, name } = user; - await set(`user:${id}`, { id, name }); - } - - const io = getIO(); - io.emit("user", { - action: "create", - user - }); - - // await stopWhoIsOnlineMonitor() - await startWhoIsOnlineMonitor(); - - return res.status(200).json(user); -}; - -export const show = async (req: Request, res: Response): Promise => { - const { userId } = req.params; - - const user = await ShowUserService(userId); - - return res.status(200).json(user); -}; - -export const logoutUser = async ( - req: Request, - res: Response -): Promise => { - const { userId } = req.params; - - await stopWhoIsOnlineMonitor(); - - let onlineTime = { - userId: userId, - status: "logout..." - }; - - const io = getIO(); - io.emit("onlineStatus", { - action: "logout", - userOnlineTime: onlineTime - }); - - await startWhoIsOnlineMonitor(); - // - - return res.status(200).json({}); -}; - -export const update = async ( - req: Request, - res: Response -): Promise => { - if ( - req.user.profile !== "admin" && - req.user.profile !== "master" && - req.user.profile !== "supervisor" - ) { - throw new AppError("ERR_NO_PERMISSION", 403); - } - - const { userId } = req.params; - const userData = req.body; - - const dateToday = splitDateTime( - new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) - ); - - const currentDate = new Date(); - const tenMonthsAgo = subMonths(currentDate, 10); - const formattedDate = format(tenMonthsAgo, "yyyy-MM-dd"); - console.log("dateToday.fullDate: ", dateToday.fullDate); - console.log("formattedDate 10 months ago: ", formattedDate); - - const openByUserOnQueue: any[] = await CountTicketsByUserQueue({ - startDate: formattedDate, - endDate: dateToday.fullDate, - status: "open", - clientChatStart: true, - userId: userId - }); - - // console.log('------> openByUserOnQueue: ', openByUserOnQueue) - // console.log() - // console.log('------> 1 userData.queueIds: ', userData.queueIds) - - let userQueuesAttendance = []; - - if ((openByUserOnQueue && openByUserOnQueue.length) > 0) { - userQueuesAttendance = openByUserOnQueue.filter( - (e: any) => !userData.queueIds.includes(e.queueId) - ); - - if (userQueuesAttendance && userQueuesAttendance.length > 0) { - const queueInAttendance = userQueuesAttendance.map(e => e.queueId); - - const mergedSet = new Set([...userData.queueIds, ...queueInAttendance]); - - // Convert the Set back to an array - userData.queueIds = Array.from(mergedSet); - - // console.log('------> 2 userData.queueIds: ', userData.queueIds) + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_updated: "0", + }); } + + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_updated: "0", + }); } - - let user: any = await UpdateUserService({ userData, userId }); - - await setBotInfo(user); - - if (user) { - const { id, name } = user; - await set(`user:${id}`, { id, name }); - } - - const io = getIO(); - io.emit("user", { - action: "update", - user - }); - - user.userQueuesAttendance = userQueuesAttendance; - - return res.status(200).json(user); }; -export const remove = async ( - req: Request, - res: Response -): Promise => { - const { userId } = req.params; +export const resetPassword = async (req: Request, res: Response): Promise => { + try { + const { user_id, user_password } = req.body; - if (req.user.profile !== "master") { - throw new AppError("ERR_NO_PERMISSION", 403); + await ResetPasswordService({ + userPassword: user_password, + userId: user_id + }) + + return res.status(200).json({ + return_code: "200", + return_msg: `User has the password changed`, + password_set: "1" + }); + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + password_set: "0", + }); + } + + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + password_set: "0", + }); } - await DeleteUserService(userId); - - del(`user:${userId}`); - - const io = getIO(); - io.emit("user", { - action: "delete", - userId - }); - - //test del - await stopWhoIsOnlineMonitor(); - - io.emit("onlineStatus", { - action: "delete", - userOnlineTime: userId - }); - - await startWhoIsOnlineMonitor(); - // - - return res.status(200).json({ message: "User deleted" }); }; + +export const linkUserAndUserRight = async (req: Request, res: Response): Promise => { + try { + const { user_id, user_right_title, } = req.body; + + await LinkUserAndUserRightService({ + userProfile: user_right_title, + userId: user_id + }) + + return res.status(200).json({ + return_code: "200", + return_msg: `User ${user_id} associated`, + user_right_linked: "1" + }); + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_right_linked: "0", + }); + } + + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_right_linked: "0", + }); + } +}; + +export const unlinkUserAndUserRight = async (req: Request, res: Response): Promise => { + try { + const { user_id, user_right_title } = req.body; + + await UnlinkUserAndUserRightService({ + userProfile: user_right_title, + userId: user_id + }) + + return res.status(200).json({ + return_code: "200", + return_msg: `User ${user_id} deassociated`, + user_right_unlinked: "1", + }); + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_right_unlinked: "0", + }); + } + + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_right_unlinked: "0", + }); + } +}; + +export const checkUserRight = async (req: Request, res: Response): Promise => { + try { + const { user_id, user_right_title } = req.body; + + const userHasRight = await CheckUserRightService({ + userProfileToCompare: user_right_title, + userId: user_id + }) + + return res.status(200).json({ + return_code: "200", + return_msg: "", + user_right_exists: userHasRight ? "1" : "0", + }); + } catch (error) { + if (error instanceof AppError) { + logger.warn(error); + return res.status(error.statusCode).json({ + return_code: String(error.statusCode), + return_msg: error.message, + user_right_exists: "0", + }); + } + return res.status(500).json({ + return_code: "500", + return_msg: "Internal server error", + user_right_exists: "0", + }); + } +}; \ No newline at end of file From 26e90c6ea9b405bfc5c8d5a6fa85b6501f5ca881 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:07:41 -0300 Subject: [PATCH 03/11] feat: add middleware to verify token (API KEY) send by horacius system --- backend/src/middleware/verifyAPIKey.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 backend/src/middleware/verifyAPIKey.ts diff --git a/backend/src/middleware/verifyAPIKey.ts b/backend/src/middleware/verifyAPIKey.ts new file mode 100644 index 0000000..5df8481 --- /dev/null +++ b/backend/src/middleware/verifyAPIKey.ts @@ -0,0 +1,23 @@ +import { Request, Response, NextFunction } from "express"; +import AppError from "../errors/AppError"; +const verifyAPIKey = (req: Request, res: Response, next: NextFunction): void => { + const authHeader = req.headers.authorization; + + if (!authHeader) { + throw new AppError("ERR_SESSION_EXPIRED", 401); + } + + const [, token] = authHeader.split(" "); + + const apiKeyIsValid = token === process.env.TOKEN_REMOTE_TICKET_CREATION + if (!apiKeyIsValid) { + throw new AppError( + "Invalid token", + 401 + ); + } + + return next(); +}; + +export default verifyAPIKey; From 097737a3b88277de126d8a241f5a0fb4c53a1605 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:11:26 -0300 Subject: [PATCH 04/11] feat: add check user right service --- .../UserServices/CheckUserRightService.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 backend/src/services/UserServices/CheckUserRightService.ts diff --git a/backend/src/services/UserServices/CheckUserRightService.ts b/backend/src/services/UserServices/CheckUserRightService.ts new file mode 100644 index 0000000..788d630 --- /dev/null +++ b/backend/src/services/UserServices/CheckUserRightService.ts @@ -0,0 +1,33 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import ShowUserService from "./ShowUserService"; + +interface CheckUserRightServiceRequest { + userProfileToCompare: string; + userId: string | number; +} + +type CheckUserRightServiceResponse = boolean; + +const CheckUserRightService = async ({userProfileToCompare, userId}: CheckUserRightServiceRequest): Promise => { + try { + const user = await ShowUserService(userId); + const schema = Yup.object().shape({ + userId: Yup.string().required(), + userProfile: Yup.string().oneOf(['admin', 'user', 'supervisor', 'master']).required() + }); + try { + await schema.validate({ userId, userProfile: userProfileToCompare }); + } catch (err: any) { + throw new AppError(err.message); + } + + return (user.profile == userProfileToCompare) ? true : false + + } catch (error: any) { + console.error('===> Error on CheckUserRightService.ts file: \n', error) + throw new AppError(error.message); + } +}; + +export default CheckUserRightService; From 2d22a4b9f06b70432399b454ec36eb3db5e54311 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:15:24 -0300 Subject: [PATCH 05/11] feat: add link user right to modify profile property of user --- .../services/UserServices/LinkUserRight.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 backend/src/services/UserServices/LinkUserRight.ts diff --git a/backend/src/services/UserServices/LinkUserRight.ts b/backend/src/services/UserServices/LinkUserRight.ts new file mode 100644 index 0000000..d34e393 --- /dev/null +++ b/backend/src/services/UserServices/LinkUserRight.ts @@ -0,0 +1,33 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import ShowUserService from "./ShowUserService"; + +interface LinkUserRightServiceRequest { + userProfile: string; + userId: string | number; +} +const LinkUserRightService = async ({userProfile, userId}: LinkUserRightServiceRequest): Promise => { + try { + const user = await ShowUserService(userId); + const schema = Yup.object().shape({ + userId: Yup.string().required(), + userProfile: Yup.string().oneOf(['admin', 'user', 'supervisor']).required() + }); + try { + await schema.validate({ userId, userProfile }); + } catch (err: any) { + throw new AppError(err.message); + } + + await user.update({ + profile: userProfile + }); + + await user.reload(); + } catch (error: any) { + console.error('===> Error on LinkUserRightService.ts file: \n', error) + throw new AppError(error.message); + } +}; + +export default LinkUserRightService; From fca4dd7036bb0e8b5e75c4ceb97058fd276f8018 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:16:07 -0300 Subject: [PATCH 06/11] feat: add unlink user right to change profile property of user to default --- .../services/UserServices/UnlinkUserRight.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 backend/src/services/UserServices/UnlinkUserRight.ts diff --git a/backend/src/services/UserServices/UnlinkUserRight.ts b/backend/src/services/UserServices/UnlinkUserRight.ts new file mode 100644 index 0000000..13850ac --- /dev/null +++ b/backend/src/services/UserServices/UnlinkUserRight.ts @@ -0,0 +1,33 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import ShowUserService from "./ShowUserService"; + +interface UnlinkUserRightServiceRequest { + userProfile: string; + userId: string | number; +} +const UnlinkUserRightService = async ({userProfile, userId}: UnlinkUserRightServiceRequest): Promise => { + try { + const user = await ShowUserService(userId); + const schema = Yup.object().shape({ + userId: Yup.string().required(), + userProfile: Yup.string().oneOf(['user']) + }); + try { + await schema.validate({ userId, userProfile }); + } catch (err: any) { + throw new AppError(err.message); + } + + await user.update({ + profile: userProfile || "user" + }); + + await user.reload(); + } catch (error: any) { + console.error('===> Error on UnlinkUserRightService.ts file: \n', error) + throw new AppError(error.message); + } +}; + +export default UnlinkUserRightService; From 2f56673962e4b124c28dd38e28a575fbdfb9bf64 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:16:46 -0300 Subject: [PATCH 07/11] refactor: update name of functions link and unlink user right --- backend/src/controllers/IAMControllerEL.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/controllers/IAMControllerEL.ts b/backend/src/controllers/IAMControllerEL.ts index 19b4c51..e759acd 100644 --- a/backend/src/controllers/IAMControllerEL.ts +++ b/backend/src/controllers/IAMControllerEL.ts @@ -26,9 +26,9 @@ import { getSettingValue } from "../helpers/WhaticketSettings"; import { setBotInfo } from "../helpers/SetBotInfo"; import { logger } from "../utils/logger"; import ResetPasswordService from "../services/UserServices/ResetPassword"; -import LinkUserAndUserRightService from "../services/UserServices/LinkUserAndUserRight"; -import UnlinkUserAndUserRightService from "../services/UserServices/UnlinkUserAndUserRight"; import CheckUserRightService from "../services/UserServices/CheckUserRightService"; +import UnlinkUserRightService from "../services/UserServices/UnlinkUserRight"; +import LinkUserRightService from "../services/UserServices/LinkUserRight"; interface IAMResponse { return_code: string @@ -271,11 +271,11 @@ export const resetPassword = async (req: Request, res: Response): Promise => { +export const linkUserRight = async (req: Request, res: Response): Promise => { try { const { user_id, user_right_title, } = req.body; - await LinkUserAndUserRightService({ + await LinkUserRightService({ userProfile: user_right_title, userId: user_id }) @@ -303,11 +303,11 @@ export const linkUserAndUserRight = async (req: Request, res: Response): Promise => { +export const unlinkUserRight = async (req: Request, res: Response): Promise => { try { const { user_id, user_right_title } = req.body; - await UnlinkUserAndUserRightService({ + await UnlinkUserRightService({ userProfile: user_right_title, userId: user_id }) From d608538c9e9ef8461de3647cec89fb91afa0a51e Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:18:22 -0300 Subject: [PATCH 08/11] feat: Add API routes for integrating Horacius users with Omnihit --- backend/src/routes/iamRoutesEL.ts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/backend/src/routes/iamRoutesEL.ts b/backend/src/routes/iamRoutesEL.ts index 7c359d5..597b854 100644 --- a/backend/src/routes/iamRoutesEL.ts +++ b/backend/src/routes/iamRoutesEL.ts @@ -1,23 +1,19 @@ import { Router } from "express"; -import isAuth from "../middleware/isAuth"; import * as IAMControllerEL from "../controllers/IAMControllerEL"; +import verifyAPIKey from "../middleware/verifyAPIKey"; const iamRoutesEL = Router(); +iamRoutesEL.post("/IAM/users", verifyAPIKey, IAMControllerEL.createUser); +iamRoutesEL.put("/IAM/users", verifyAPIKey, IAMControllerEL.updateUser); +iamRoutesEL.delete("/IAM/users", verifyAPIKey, IAMControllerEL.deleteUser); +iamRoutesEL.get("/IAM/users/check", verifyAPIKey, IAMControllerEL.checkUser); -iamRoutesEL.get("/users/all", isAuth, IAMControllerEL.all); +iamRoutesEL.patch("/IAM/users/rights/link", verifyAPIKey, IAMControllerEL.linkUserRight); +iamRoutesEL.patch("/IAM/users/rights/unlink", verifyAPIKey, IAMControllerEL.unlinkUserRight); +iamRoutesEL.post("/IAM/users/rights/check", verifyAPIKey, IAMControllerEL.checkUserRight); -iamRoutesEL.get("/users", isAuth, IAMControllerEL.index); - -iamRoutesEL.post("/users", isAuth, IAMControllerEL.store); - -iamRoutesEL.put("/users/:userId", isAuth, IAMControllerEL.update); - -iamRoutesEL.get("/users/:userId", isAuth, IAMControllerEL.show); - -iamRoutesEL.get("/users/logout/:userId", isAuth, IAMControllerEL.logoutUser); - -iamRoutesEL.delete("/users/:userId", isAuth, IAMControllerEL.remove); +iamRoutesEL.patch("/IAM/users/reset-password", verifyAPIKey, IAMControllerEL.resetPassword); export default iamRoutesEL; From 895ce83b5be8a0871f5eac6e146501a5bed0de48 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:18:41 -0300 Subject: [PATCH 09/11] feat: add reset password service --- .../services/UserServices/ResetPassword.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 backend/src/services/UserServices/ResetPassword.ts diff --git a/backend/src/services/UserServices/ResetPassword.ts b/backend/src/services/UserServices/ResetPassword.ts new file mode 100644 index 0000000..b396a26 --- /dev/null +++ b/backend/src/services/UserServices/ResetPassword.ts @@ -0,0 +1,32 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import ShowUserService from "./ShowUserService"; + +interface ResetPasswordServiceRequest { + userPassword: string; + userId: string | number; +} +const ResetPasswordService = async ({userPassword, userId}: ResetPasswordServiceRequest): Promise => { + try { + const user = await ShowUserService(userId); + const schema = Yup.object().shape({ + password: Yup.string(), + }); + try { + await schema.validate({ password: userPassword }); + } catch (err: any) { + throw new AppError(err.message); + } + + await user.update({ + userPassword, + }); + + await user.reload(); + } catch (error: any) { + console.error('===> Error on ResetPasswordService.ts file: \n', error) + throw new AppError(error.message); + } +}; + +export default ResetPasswordService; From 37c384a7124f0a66c7e939529d915743358ea0d5 Mon Sep 17 00:00:00 2001 From: Henrriky Date: Tue, 12 Mar 2024 17:19:16 -0300 Subject: [PATCH 10/11] chore: update md files --- ESPACO-LAZER-IAM.MD | 76 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/ESPACO-LAZER-IAM.MD b/ESPACO-LAZER-IAM.MD index d24ba28..7c058d9 100644 --- a/ESPACO-LAZER-IAM.MD +++ b/ESPACO-LAZER-IAM.MD @@ -17,22 +17,66 @@ - 1: Da para fazer - 2: Tem que analisar - Users - - [] CheckUser (1) - - [] CreateUser (1) - - [] DeleteUser (1) - - [] UpdateUser (1) - - [] ListAllUsers **OPCIONAL** - - [] LockUser (2) - - [] UnlockUser (2) - - [] ResetPassword (2) + - [ ] CheckUser (1) + - [ ] CreateUser (1) + - [ ] DeleteUser (1) + - [ ] UpdateUser (1) + - [ ] ResetPassword (1) + - [ ] LockUser (2) + - [ ] UnlockUser (2) + - [ ] ListAllUsers **OPCIONAL** - Rights - - [] CheckUserRight (1) - - [] CreateRight (1) - - [] UpdateRight (1) - - [] DeleteRight (1) - - [] GetAllRights **OPCIONAL** + - [ ] CheckUserRight (1) + - [ ] CreateRight (1) + - [ ] UpdateRight (1) + - [ ] DeleteRight (1) + - [ ] GetAllRights **OPCIONAL** - Users X Rights - - [] LinkUserAndUserRight (1) - - [] UnlinkUserAndUserRight (1) - - [] GetAllUserRights **OPCIONAL** + - [ ] LinkUserAndUserRight (1) + - [ ] UnlinkUserAndUserRight (1) + - [ ] GetAllUserRights **OPCIONAL** +# Atribuições + +- Henrriky + - [ ] Verify token middleware + - [X] CheckUser (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] CreateUser (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] DeleteUser (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] UpdateUser (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] ResetPassword (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] LinkUserAndUserRight (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] UnlinkUserAndUserRight (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling + - [X] CheckUserRight (1) + - [ ] Routes + - [X] Controller + - [X] Service + - [X] Error handling \ No newline at end of file From db4bf2bf847d3e2b5d9f9da965826373a93c72bd Mon Sep 17 00:00:00 2001 From: adriano Date: Mon, 18 Mar 2024 15:18:18 -0300 Subject: [PATCH 11/11] feat: Add routes and controllers to integrate with E-Trust Horacius for user and application management --- .gitignore | 3 +- ESPACO-LAZER-IAM.MD | 82 -- backend/src/controllers/IAMControllerEL.ts | 737 ++++++++++-------- ...20240315203708-add-secondaryId-to-users.ts | 14 + backend/src/middleware/verifyAPIKey.ts | 2 +- backend/src/models/User.ts | 11 +- backend/src/routes/iamRoutesEL.ts | 53 +- .../UserServices/CheckUserRightService.ts | 33 - .../UserServices/CreateUserService.ts | 43 +- .../UserServices/DeleteUserService.ts | 14 +- .../services/UserServices/LinkUserRight.ts | 33 - .../services/UserServices/ResetPassword.ts | 32 - .../services/UserServices/UnlinkUserRight.ts | 33 - .../UserServices/UpdateUserService.ts | 71 +- 14 files changed, 582 insertions(+), 579 deletions(-) delete mode 100644 ESPACO-LAZER-IAM.MD create mode 100644 backend/src/database/migrations/20240315203708-add-secondaryId-to-users.ts delete mode 100644 backend/src/services/UserServices/CheckUserRightService.ts delete mode 100644 backend/src/services/UserServices/LinkUserRight.ts delete mode 100644 backend/src/services/UserServices/ResetPassword.ts delete mode 100644 backend/src/services/UserServices/UnlinkUserRight.ts diff --git a/.gitignore b/.gitignore index c86c332..4dd37d9 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ WWebJS npm-debug.log* yarn-debug.log* -yarn-error.log* \ No newline at end of file +yarn-error.log* + diff --git a/ESPACO-LAZER-IAM.MD b/ESPACO-LAZER-IAM.MD deleted file mode 100644 index 7c058d9..0000000 --- a/ESPACO-LAZER-IAM.MD +++ /dev/null @@ -1,82 +0,0 @@ -# O que fazer? - -- Quando um usuário for criado na plataforma do E-trust Horacius, a aplicação do Omnihit deve criar o mesmo usuário no Banco de Dados do Omnihit. - - Criação - - Atualização - - Exclusão -- Quando um usuário for criado com um **profile(role)**, a aplicação do Omnihit deve alterar o profile - - Tipos de roles: `admin`, `user`, `supervisor` - - Atualização - - Exclusão - -# Como fazer? - -- Elaborar forma de autenticação -- Criar uma aplicação REST seguindo o protocolo especificado na documentação do Horacius - - Níveis - - 1: Da para fazer - - 2: Tem que analisar - - Users - - [ ] CheckUser (1) - - [ ] CreateUser (1) - - [ ] DeleteUser (1) - - [ ] UpdateUser (1) - - [ ] ResetPassword (1) - - [ ] LockUser (2) - - [ ] UnlockUser (2) - - [ ] ListAllUsers **OPCIONAL** - - Rights - - [ ] CheckUserRight (1) - - [ ] CreateRight (1) - - [ ] UpdateRight (1) - - [ ] DeleteRight (1) - - [ ] GetAllRights **OPCIONAL** - - Users X Rights - - [ ] LinkUserAndUserRight (1) - - [ ] UnlinkUserAndUserRight (1) - - [ ] GetAllUserRights **OPCIONAL** - -# Atribuições - -- Henrriky - - [ ] Verify token middleware - - [X] CheckUser (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] CreateUser (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] DeleteUser (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] UpdateUser (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] ResetPassword (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] LinkUserAndUserRight (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] UnlinkUserAndUserRight (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling - - [X] CheckUserRight (1) - - [ ] Routes - - [X] Controller - - [X] Service - - [X] Error handling \ No newline at end of file diff --git a/backend/src/controllers/IAMControllerEL.ts b/backend/src/controllers/IAMControllerEL.ts index e759acd..c3cd8b7 100644 --- a/backend/src/controllers/IAMControllerEL.ts +++ b/backend/src/controllers/IAMControllerEL.ts @@ -1,15 +1,9 @@ import { Request, Response } from "express"; import { getIO } from "../libs/socket"; - -import AppError from "../errors/AppError"; - +import { Op } from "sequelize"; import CreateUserService from "../services/UserServices/CreateUserService"; -import ListUsersService from "../services/UserServices/ListUsersService"; import UpdateUserService from "../services/UserServices/UpdateUserService"; -import ShowUserService from "../services/UserServices/ShowUserService"; import DeleteUserService from "../services/UserServices/DeleteUserService"; - -import ListUser from "../services/UserServices/ListUserParamiterService"; import { del, get, set } from "../helpers/RedisClient"; import { @@ -17,39 +11,56 @@ import { stopWhoIsOnlineMonitor } from "../helpers/WhoIsOnlineMonitor"; -import { format, subMonths } from "date-fns"; -import { ptBR } from "date-fns/locale"; -import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue"; -import { splitDateTime } from "../helpers/SplitDateTime"; -import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService"; -import { getSettingValue } from "../helpers/WhaticketSettings"; -import { setBotInfo } from "../helpers/SetBotInfo"; -import { logger } from "../utils/logger"; -import ResetPasswordService from "../services/UserServices/ResetPassword"; -import CheckUserRightService from "../services/UserServices/CheckUserRightService"; -import UnlinkUserRightService from "../services/UserServices/UnlinkUserRight"; -import LinkUserRightService from "../services/UserServices/LinkUserRight"; +import User from "../models/User"; -interface IAMResponse { - return_code: string - return_msg: string -} +export const createUser = async ( + req: Request, + res: Response +): Promise => { + const { user_id, user_first_name, user_tax_id, user_email, user_title }: any = + req.body; -//TODO: REVIEW CREATE USER -export const createUser = async (req: Request, res: Response): Promise => { - try { - const { user_id, user_first_name, user_tax_id } = req.body; - //user_id ou cria uma tabela nova ou um atributo novo - const user = await CreateUserService({ - email: user_tax_id, - password: "padrao", - name: user_first_name, - }); + const invalid = invalidProperties(req.body, [ + "user_id", + "user_tax_id", + "user_first_name" + ]); - if (user) { - const { id, name } = user; - await set(`user:${id}`, { id, name }); - } + if (invalid) { + return res.status(400).json(response("1", `${invalid}`, "0", "createUser")); + } + + const auxUser = await User.findOne({ where: { secondaryId: user_id } }); + + if (auxUser) { + return res + .status(400) + .json( + response("1", `The user ${user_id} already exist`, "0", "createUser") + ); + } + + const user = await CreateUserService({ + email: user_tax_id || user_email, + password: "12345", + name: user_first_name, + positionCompany: user_title, + profile: "user", + ignoreThrow: true + }); + + if (user?.error) { + return res + .status(user?.status) + .json(response("0", `${user?.msg}`, "0", "createUser")); + } + + if (!user?.error) { + const _user = await User.findByPk(user.id); + _user?.update({ secondaryId: user_id }); + + const { id, name } = user; + await set(`user:${id}`, { id, name }); const io = getIO(); io.emit("user", { @@ -58,310 +69,426 @@ export const createUser = async (req: Request, res: Response): Promise => { - try { - const { user_id } = req.body; - await ShowUserService(user_id); - return res.status(200).json({ - return_code: "200", - return_msg: "", - user_exists: "1" - }); - } catch (error) { +export const deleteUser = async ( + req: Request, + res: Response +): Promise => { + const { user_id }: any = req.body; - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - user_exists: "0", - }); + const invalid = invalidProperties(req.body, ["user_id"]); + + if (invalid) { + return res.status(400).json(response("1", `${invalid}`, "0", "deleteUser")); + } + + const _user = await User.findOne({ where: { secondaryId: user_id } }); + + if (_user) { + const user = await DeleteUserService(_user.id, true); + + if (user?.error) { + return res + .status(user?.status) + .json(response("0", `${user?.msg}`, "0", "deleteUser")); } - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - user_exists: "0", - }); + if (!user?.error) { + del(`user:${_user.id}`); + + const io = getIO(); + io.emit("user", { + action: "delete", + userId: _user.id + }); + + await stopWhoIsOnlineMonitor(); + + io.emit("onlineStatus", { + action: "delete", + userOnlineTime: _user.id + }); + + await startWhoIsOnlineMonitor(); + + return res + .status(200) + .json(response("1", `User ${user_id} deleted`, "1", "deleteUser")); + } } + + return res + .status(500) + .json(response("0", "Internal server error", "0", "deleteUser")); }; -//TODO: REVIEW DELETE USER -export const deleteUser = async (req: Request, res: Response): Promise => { - try { - const { user_id } = req.body; +export const listAllUsers = async ( + req: Request, + res: Response +): Promise => { + const _users: any = await User.findAll({ + where: { + secondaryId: { + [Op.ne]: "" + } + }, + attributes: ["secondaryId", "name"] + }); - await DeleteUserService(user_id); - - del(`user:${user_id}`); - - const io = getIO(); - io.emit("user", { - action: "delete", - user_id + if (_users) { + const user_list = _users.map((user: any) => { + const { secondaryId, name } = user; + return { user_id: secondaryId, full_name: name }; }); - //test del - await stopWhoIsOnlineMonitor(); - - io.emit("onlineStatus", { - action: "delete", - userOnlineTime: user_id - }); - - await startWhoIsOnlineMonitor(); - return res.status(200).json({ - return_code: "200", - return_msg: `User ${user_id} deleted`, - user_removed: "1", - }); - - } catch (error) { - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - user_removed: "0", - }); - } - - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - user_removed: "0", - }); + return res + .status(200) + .json(response("1", "Success", user_list, "listAllUsers")); } + + return res + .status(500) + .json(response("0", "Internal server error", [], "listAllUsers")); }; -//TODO: REVIEW UPDATE USER -export const updateUser = async (req: Request, res: Response): Promise => { - try { - const { user_id, user_first_name, user_tax_id } = req.body; - // const dateToday = splitDateTime(new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))); - // const currentDate = new Date(); - // const tenMonthsAgo = subMonths(currentDate, 10); - // const formattedDate = format(tenMonthsAgo, "yyyy-MM-dd"); - // console.log("dateToday.fullDate: ", dateToday.fullDate); - // console.log("formattedDate 10 months ago: ", formattedDate); +export const checkUser = async ( + req: Request, + res: Response +): Promise => { + const { user_id }: any = req.body; - // const openByUserOnQueue: any[] = await CountTicketsByUserQueue({ - // startDate: formattedDate, - // endDate: dateToday.fullDate, - // status: "open", - // clientChatStart: true, - // userId: userId - // }); - // let userQueuesAttendance = []; + const invalid = invalidProperties(req.body, ["user_id"]); - // if ((openByUserOnQueue && openByUserOnQueue.length) > 0) { - // userQueuesAttendance = openByUserOnQueue.filter( - // (e: any) => !userData.queueIds.includes(e.queueId) - // ); - - // if (userQueuesAttendance && userQueuesAttendance.length > 0) { - // const queueInAttendance = userQueuesAttendance.map(e => e.queueId); - // const mergedSet = new Set([...userData.queueIds, ...queueInAttendance]); - - // userData.queueIds = Array.from(mergedSet); - // } - // } - const userData = { - email: user_tax_id, - name: user_first_name, - } - // email?: string; - // name?: string; - // password?: string; - // positionCompany?: string; - // profile?: string; - // queueIds?: number[]; - let user: any = await UpdateUserService({ userData, userId: user_id }); - await setBotInfo(user); - - if (user) { - const { id, name } = user; - await set(`user:${id}`, { id, name }); - } - - const io = getIO(); - io.emit("user", { - action: "update", - user - }); - - // user.userQueuesAttendance = userQueuesAttendance; - return res.status(200).json({ - return_code: "200", - return_msg: `User ${user_id} updated`, - user_updated: "1" - }); - } catch (error) { - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - user_updated: "0", - }); - } - - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - user_updated: "0", - }); + if (invalid) { + return res.status(400).json(response("1", `${invalid}`, "0", "checkUser")); } + + const _user = await User.findOne({ where: { secondaryId: user_id } }); + + if (_user) { + return res + .status(200) + .json(response("1", `User ${user_id} exist`, "1", "checkUser")); + } + + return res + .status(404) + .json(response("1", `User ${user_id} not exist`, "0", "checkUser")); }; -export const resetPassword = async (req: Request, res: Response): Promise => { - try { - const { user_id, user_password } = req.body; +export const updateUser = async ( + req: Request, + res: Response +): Promise => { + const { user_id, user_first_name, user_tax_id, user_email, user_title }: any = + req.body; - await ResetPasswordService({ - userPassword: user_password, - userId: user_id - }) + const invalid = invalidProperties(req.body, ["user_id"]); - return res.status(200).json({ - return_code: "200", - return_msg: `User has the password changed`, - password_set: "1" - }); - } catch (error) { - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - password_set: "0", - }); - } - - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - password_set: "0", - }); + if (invalid) { + return res.status(400).json(response("1", `${invalid}`, "0", "checkUser")); } + const _user: any = await User.findOne({ where: { secondaryId: user_id } }); + + if (!_user) + return res + .status(404) + .json(response("1", `User ${user_id} not exist`, "0", "updateUser")); + + const userData = { + email: user_tax_id || user_email, + name: user_first_name, + positionCompany: user_title + }; + + let user: any = await UpdateUserService({ + userData, + userId: _user.id, + ignoreThrow: true + }); + + if (user?.error) { + return res + .status(user?.status) + .json(response("0", `${user?.msg}`, "0", "updateUser")); + } + + if (user) { + const { id, name } = user; + await set(`user:${id}`, { id, name }); + } + + const io = getIO(); + io.emit("user", { + action: "update", + user + }); + + return res + .status(200) + .json(response("1", `User ${user_id} updated`, "1", "updateUser")); }; -export const linkUserRight = async (req: Request, res: Response): Promise => { - try { - const { user_id, user_right_title, } = req.body; +export const resetPassword = async ( + req: Request, + res: Response +): Promise => { + const { user_id, user_password }: any = req.body; - await LinkUserRightService({ - userProfile: user_right_title, - userId: user_id - }) + const invalid = invalidProperties(req.body, ["user_id", "user_password"]); - return res.status(200).json({ - return_code: "200", - return_msg: `User ${user_id} associated`, - user_right_linked: "1" - }); - } catch (error) { - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - user_right_linked: "0", - }); - } - - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - user_right_linked: "0", - }); + if (invalid) { + return res + .status(400) + .json(response("1", `${invalid}`, "0", "resetPassword")); } + + const _user = await User.findOne({ where: { secondaryId: user_id } }); + + if (!_user) { + return res + .status(404) + .json(response("1", `User ${user_id} not exist`, "0", "resetPassword")); + } + + const userData = { + password: user_password, + email: _user.email + }; + + let user: any = await UpdateUserService({ + userData, + userId: _user.id, + ignoreThrow: true + }); + + if (user?.error) { + return res + .status(user?.status) + .json(response("0", `${user?.msg}`, "0", "resetPassword")); + } + + await logoutUser(_user.id); + + return res + .status(200) + .json( + response("1", `User ${user_id} password updated`, "1", "resetPassword") + ); }; -export const unlinkUserRight = async (req: Request, res: Response): Promise => { - try { - const { user_id, user_right_title } = req.body; +export const linkUserAndUserRight = async ( + req: Request, + res: Response +): Promise => { + const { user_id, user_right_id, user_right_title }: any = req.body; - await UnlinkUserRightService({ - userProfile: user_right_title, - userId: user_id - }) + const invalid = invalidProperties(req.body, ["user_id", "user_right_id"]); - return res.status(200).json({ - return_code: "200", - return_msg: `User ${user_id} deassociated`, - user_right_unlinked: "1", - }); - } catch (error) { - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - user_right_unlinked: "0", - }); - } - - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - user_right_unlinked: "0", - }); + if (invalid) { + return res + .status(400) + .json(response("1", `${invalid}`, "0", "linkUserAndUserRight")); } + + if ( + (user_right_id && + !["admin", "user", "supervisor"].includes( + user_right_id?.trim().toLocaleLowerCase() + )) || + (user_right_title && + !["admin", "user", "supervisor"].includes( + user_right_title?.trim().toLocaleLowerCase() + )) + ) { + return res + .status(400) + .json( + response( + "1", + `The user profile ${ + user_right_title || user_right_id + } provided by the property user_right_title or user_right_id does not match the following profiles: admin, user, supervisor`, + "0", + "linkUserAndUserRight" + ) + ); + } + + const _user: any = await User.findOne({ where: { secondaryId: user_id } }); + + if (!_user) + return res + .status(404) + .json( + response("1", `User ${user_id} not exist`, "0", "linkUserAndUserRight") + ); + + const userData = { + profile: user_right_title || user_right_id, + email: _user.email + }; + + let user: any = await UpdateUserService({ + userData, + userId: _user.id, + ignoreThrow: true + }); + + if (user?.error) { + return res + .status(user?.status) + .json(response("0", `${user?.msg}`, "0", "linkUserAndUserRight")); + } + + await logoutUser(_user.id); + + return res + .status(200) + .json( + response( + "1", + `User ${user_id} associated with ${ + user_right_title || user_right_id + } profile`, + "1", + "linkUserAndUserRight" + ) + ); }; -export const checkUserRight = async (req: Request, res: Response): Promise => { - try { - const { user_id, user_right_title } = req.body; +export const checkUserRight = async ( + req: Request, + res: Response +): Promise => { + const { user_id, user_right_id, user_right_title }: any = req.body; - const userHasRight = await CheckUserRightService({ - userProfileToCompare: user_right_title, - userId: user_id - }) + const invalid = invalidProperties(req.body, ["user_id", "user_right_id"]); - return res.status(200).json({ - return_code: "200", - return_msg: "", - user_right_exists: userHasRight ? "1" : "0", - }); - } catch (error) { - if (error instanceof AppError) { - logger.warn(error); - return res.status(error.statusCode).json({ - return_code: String(error.statusCode), - return_msg: error.message, - user_right_exists: "0", - }); - } - return res.status(500).json({ - return_code: "500", - return_msg: "Internal server error", - user_right_exists: "0", - }); + if (invalid) { + return res + .status(400) + .json(response("1", `${invalid}`, "0", "checkUserRight")); } -}; \ No newline at end of file + + if ( + (user_right_id && + !["admin", "user", "supervisor"].includes( + user_right_id?.trim().toLocaleLowerCase() + )) || + (user_right_title && + !["admin", "user", "supervisor"].includes( + user_right_title?.trim().toLocaleLowerCase() + )) + ) { + return res + .status(400) + .json( + response( + "1", + `The user profile ${ + user_right_title || user_right_id + } provided by the property user_right_title or user_right_id does not match the following profiles: admin, user, supervisor`, + "0", + "checkUserRight" + ) + ); + } + + const _user: any = await User.findOne({ + where: { + secondaryId: user_id + } + }); + + if (!_user) + return res + .status(404) + .json(response("1", `User ${user_id} not exist`, "0", "checkUserRight")); + + if ( + (user_right_id && _user.profile != user_right_id) || + (user_right_title && _user.profile != user_right_title) + ) { + return res + .status(403) + .json( + response( + "1", + `User ${user_id} does not have this profile`, + "0", + "checkUserRight" + ) + ); + } + + return res + .status(200) + .json( + response( + "1", + `User ${user_id} has ${user_right_title || user_right_id} profile`, + "1", + "checkUserRight" + ) + ); +}; + +async function logoutUser(userId: any) { + await stopWhoIsOnlineMonitor(); + + let onlineTime = { + userId: `${userId}`, + status: "logout..." + }; + + const io = getIO(); + io.emit("onlineStatus", { + action: "logout", + userOnlineTime: onlineTime + }); + + await startWhoIsOnlineMonitor(); +} + +function response(code: string, msg: string, obj: any, type: string) { + let payload = { return_code: code, return_msg: msg }; + + switch (type) { + case "createUser": + return { ...payload, user_created: obj }; + case "deleteUser": + return { ...payload, user_removed: obj }; + case "listAllUsers": + return { ...payload, user_list: obj }; + case "checkUser": + return { ...payload, user_exists: obj }; + case "updateUser": + return { ...payload, user_updated: obj }; + case "resetPassword": + return { ...payload, password_set: obj }; + case "linkUserAndUserRight": + return { ...payload, user_right_linked: obj }; + case "checkUserRight": + return { ...payload, user_right_exists: obj }; + default: + return payload; + } +} + +function invalidProperties(body: any, pros: any[]) { + for (const field of pros) { + console.log("body[field]: ", body[field], " field: ", field); + if (!body[field]) { + return `${field} is required`; + } + } + return false; +} diff --git a/backend/src/database/migrations/20240315203708-add-secondaryId-to-users.ts b/backend/src/database/migrations/20240315203708-add-secondaryId-to-users.ts new file mode 100644 index 0000000..a2c590e --- /dev/null +++ b/backend/src/database/migrations/20240315203708-add-secondaryId-to-users.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "secondaryId", { + type: DataTypes.STRING, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "secondaryId"); + } +}; diff --git a/backend/src/middleware/verifyAPIKey.ts b/backend/src/middleware/verifyAPIKey.ts index 5df8481..61cc6f7 100644 --- a/backend/src/middleware/verifyAPIKey.ts +++ b/backend/src/middleware/verifyAPIKey.ts @@ -9,7 +9,7 @@ const verifyAPIKey = (req: Request, res: Response, next: NextFunction): void => const [, token] = authHeader.split(" "); - const apiKeyIsValid = token === process.env.TOKEN_REMOTE_TICKET_CREATION + const apiKeyIsValid = token === process.env.TOKEN_IAM_HORACIUS_EL if (!apiKeyIsValid) { throw new AppError( "Invalid token", diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index fb2109e..af93cd5 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -41,10 +41,13 @@ class User extends Model { @Default(0) @Column tokenVersion: number; - + @Column positionCompany: string; - + + @Column + secondaryId: string; + @Default("admin") @Column profile: string; @@ -56,9 +59,9 @@ class User extends Model { updatedAt: Date; @HasMany(() => Ticket) tickets: Ticket[]; - + @HasMany(() => UserOnlineTime) - UserOnlineTime: UserOnlineTime[]; + UserOnlineTime: UserOnlineTime[]; @BelongsToMany(() => Queue, () => UserQueue) queues: Queue[]; diff --git a/backend/src/routes/iamRoutesEL.ts b/backend/src/routes/iamRoutesEL.ts index 597b854..2181547 100644 --- a/backend/src/routes/iamRoutesEL.ts +++ b/backend/src/routes/iamRoutesEL.ts @@ -5,15 +5,52 @@ import verifyAPIKey from "../middleware/verifyAPIKey"; const iamRoutesEL = Router(); -iamRoutesEL.post("/IAM/users", verifyAPIKey, IAMControllerEL.createUser); -iamRoutesEL.put("/IAM/users", verifyAPIKey, IAMControllerEL.updateUser); -iamRoutesEL.delete("/IAM/users", verifyAPIKey, IAMControllerEL.deleteUser); -iamRoutesEL.get("/IAM/users/check", verifyAPIKey, IAMControllerEL.checkUser); +iamRoutesEL.post( + "/iam/horacius/createUser", + verifyAPIKey, + IAMControllerEL.createUser +); -iamRoutesEL.patch("/IAM/users/rights/link", verifyAPIKey, IAMControllerEL.linkUserRight); -iamRoutesEL.patch("/IAM/users/rights/unlink", verifyAPIKey, IAMControllerEL.unlinkUserRight); -iamRoutesEL.post("/IAM/users/rights/check", verifyAPIKey, IAMControllerEL.checkUserRight); +iamRoutesEL.put( + "/iam/horacius/updateUser", + verifyAPIKey, + IAMControllerEL.updateUser +); -iamRoutesEL.patch("/IAM/users/reset-password", verifyAPIKey, IAMControllerEL.resetPassword); +iamRoutesEL.delete( + "/iam/horacius/deleteUser", + verifyAPIKey, + IAMControllerEL.deleteUser +); + +iamRoutesEL.get( + "/iam/horacius/listAllUsers", + verifyAPIKey, + IAMControllerEL.listAllUsers +); + +iamRoutesEL.get( + "/iam/horacius/checkUser", + verifyAPIKey, + IAMControllerEL.checkUser +); + +iamRoutesEL.patch( + "/iam/horacius/linkUserAndUserRight", + verifyAPIKey, + IAMControllerEL.linkUserAndUserRight +); + +iamRoutesEL.post( + "/iam/horacius/linkUserAndUserRight", + verifyAPIKey, + IAMControllerEL.checkUserRight +); + +iamRoutesEL.patch( + "/iam/horacius/resetPassword", + verifyAPIKey, + IAMControllerEL.resetPassword +); export default iamRoutesEL; diff --git a/backend/src/services/UserServices/CheckUserRightService.ts b/backend/src/services/UserServices/CheckUserRightService.ts deleted file mode 100644 index 788d630..0000000 --- a/backend/src/services/UserServices/CheckUserRightService.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as Yup from "yup"; -import AppError from "../../errors/AppError"; -import ShowUserService from "./ShowUserService"; - -interface CheckUserRightServiceRequest { - userProfileToCompare: string; - userId: string | number; -} - -type CheckUserRightServiceResponse = boolean; - -const CheckUserRightService = async ({userProfileToCompare, userId}: CheckUserRightServiceRequest): Promise => { - try { - const user = await ShowUserService(userId); - const schema = Yup.object().shape({ - userId: Yup.string().required(), - userProfile: Yup.string().oneOf(['admin', 'user', 'supervisor', 'master']).required() - }); - try { - await schema.validate({ userId, userProfile: userProfileToCompare }); - } catch (err: any) { - throw new AppError(err.message); - } - - return (user.profile == userProfileToCompare) ? true : false - - } catch (error: any) { - console.error('===> Error on CheckUserRightService.ts file: \n', error) - throw new AppError(error.message); - } -}; - -export default CheckUserRightService; diff --git a/backend/src/services/UserServices/CreateUserService.ts b/backend/src/services/UserServices/CreateUserService.ts index 5c6badb..9177289 100644 --- a/backend/src/services/UserServices/CreateUserService.ts +++ b/backend/src/services/UserServices/CreateUserService.ts @@ -11,6 +11,7 @@ interface Request { positionCompany?: string; queueIds?: number[]; profile?: string; + ignoreThrow?: boolean; } interface Response { @@ -27,25 +28,27 @@ const CreateUserService = async ({ name, positionCompany, queueIds = [], - profile = "master" -}: Request): Promise => { - + profile = "master", + ignoreThrow = false +}: Request): Promise => { try { - const schema = Yup.object().shape({ name: Yup.string().required().min(2), - email: Yup.string().required().trim().test( - "Check-email", - "An user with this email already exists.", - async value => { - if (!value) return false; - const emailExists = await User.findOne({ - where: { email: value } - }); - return !emailExists; - } - ), + email: Yup.string() + .required() + .trim() + .test( + "Check-email", + "An user with this email already exists.", + async value => { + if (!value) return false; + const emailExists = await User.findOne({ + where: { email: value } + }); + return !emailExists; + } + ), // email: Yup.string().email().required().test( // "Check-email", @@ -65,6 +68,8 @@ const CreateUserService = async ({ try { await schema.validate({ email, password, name }); } catch (err: any) { + if (ignoreThrow) return { error: true, msg: err.message, status: 400 }; + throw new AppError(err.message); } @@ -86,12 +91,14 @@ const CreateUserService = async ({ const serializedUser = SerializeUser(user); return serializedUser; - } catch (error: any) { - console.error('===> Error on CreateUserService.ts file: \n', error) + console.error("===> Error on CreateUserService.ts file: \n", error); + + if (ignoreThrow) + return { error: true, msg: "Create user error", status: 500 }; + throw new AppError(error.message); } - }; export default CreateUserService; diff --git a/backend/src/services/UserServices/DeleteUserService.ts b/backend/src/services/UserServices/DeleteUserService.ts index 7209cf2..e1e6a2c 100644 --- a/backend/src/services/UserServices/DeleteUserService.ts +++ b/backend/src/services/UserServices/DeleteUserService.ts @@ -2,14 +2,24 @@ import User from "../../models/User"; import AppError from "../../errors/AppError"; import Ticket from "../../models/Ticket"; import UpdateDeletedUserOpenTicketsStatus from "../../helpers/UpdateDeletedUserOpenTicketsStatus"; -import { set } from "../../helpers/RedisClient" +import { set } from "../../helpers/RedisClient"; -const DeleteUserService = async (id: string | number): Promise => { +const DeleteUserService = async ( + id: string | number, + ignoreThrow = false +): Promise => { const user = await User.findOne({ where: { id } }); if (!user) { + if (ignoreThrow) + return { + error: true, + msg: `No user found with this id ${id}`, + status: 404 + }; + throw new AppError("ERR_NO_USER_FOUND", 404); } diff --git a/backend/src/services/UserServices/LinkUserRight.ts b/backend/src/services/UserServices/LinkUserRight.ts deleted file mode 100644 index d34e393..0000000 --- a/backend/src/services/UserServices/LinkUserRight.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as Yup from "yup"; -import AppError from "../../errors/AppError"; -import ShowUserService from "./ShowUserService"; - -interface LinkUserRightServiceRequest { - userProfile: string; - userId: string | number; -} -const LinkUserRightService = async ({userProfile, userId}: LinkUserRightServiceRequest): Promise => { - try { - const user = await ShowUserService(userId); - const schema = Yup.object().shape({ - userId: Yup.string().required(), - userProfile: Yup.string().oneOf(['admin', 'user', 'supervisor']).required() - }); - try { - await schema.validate({ userId, userProfile }); - } catch (err: any) { - throw new AppError(err.message); - } - - await user.update({ - profile: userProfile - }); - - await user.reload(); - } catch (error: any) { - console.error('===> Error on LinkUserRightService.ts file: \n', error) - throw new AppError(error.message); - } -}; - -export default LinkUserRightService; diff --git a/backend/src/services/UserServices/ResetPassword.ts b/backend/src/services/UserServices/ResetPassword.ts deleted file mode 100644 index b396a26..0000000 --- a/backend/src/services/UserServices/ResetPassword.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as Yup from "yup"; -import AppError from "../../errors/AppError"; -import ShowUserService from "./ShowUserService"; - -interface ResetPasswordServiceRequest { - userPassword: string; - userId: string | number; -} -const ResetPasswordService = async ({userPassword, userId}: ResetPasswordServiceRequest): Promise => { - try { - const user = await ShowUserService(userId); - const schema = Yup.object().shape({ - password: Yup.string(), - }); - try { - await schema.validate({ password: userPassword }); - } catch (err: any) { - throw new AppError(err.message); - } - - await user.update({ - userPassword, - }); - - await user.reload(); - } catch (error: any) { - console.error('===> Error on ResetPasswordService.ts file: \n', error) - throw new AppError(error.message); - } -}; - -export default ResetPasswordService; diff --git a/backend/src/services/UserServices/UnlinkUserRight.ts b/backend/src/services/UserServices/UnlinkUserRight.ts deleted file mode 100644 index 13850ac..0000000 --- a/backend/src/services/UserServices/UnlinkUserRight.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as Yup from "yup"; -import AppError from "../../errors/AppError"; -import ShowUserService from "./ShowUserService"; - -interface UnlinkUserRightServiceRequest { - userProfile: string; - userId: string | number; -} -const UnlinkUserRightService = async ({userProfile, userId}: UnlinkUserRightServiceRequest): Promise => { - try { - const user = await ShowUserService(userId); - const schema = Yup.object().shape({ - userId: Yup.string().required(), - userProfile: Yup.string().oneOf(['user']) - }); - try { - await schema.validate({ userId, userProfile }); - } catch (err: any) { - throw new AppError(err.message); - } - - await user.update({ - profile: userProfile || "user" - }); - - await user.reload(); - } catch (error: any) { - console.error('===> Error on UnlinkUserRightService.ts file: \n', error) - throw new AppError(error.message); - } -}; - -export default UnlinkUserRightService; diff --git a/backend/src/services/UserServices/UpdateUserService.ts b/backend/src/services/UserServices/UpdateUserService.ts index 8a0a4ba..329186c 100644 --- a/backend/src/services/UserServices/UpdateUserService.ts +++ b/backend/src/services/UserServices/UpdateUserService.ts @@ -16,6 +16,7 @@ interface UserData { interface Request { userData: UserData; userId: string | number; + ignoreThrow?: boolean; } interface Response { @@ -27,41 +28,53 @@ interface Response { const UpdateUserService = async ({ userData, - userId -}: Request): Promise => { - + userId, + ignoreThrow = false +}: Request): Promise => { try { - const user = await ShowUserService(userId); const schema = Yup.object().shape({ name: Yup.string().min(2), - // email: Yup.string().min(2), + // email: Yup.string().min(2), profile: Yup.string(), password: Yup.string(), - email: Yup.string().trim().required().test( - "Check-email", - "An user with this email already exists.", - async value => { + email: Yup.string() + .trim() + .required() + .test( + "Check-email", + "An user with this email already exists.", + async value => { + if (!value) return false; - if (!value) return false; + const emailExists = await User.findOne({ + where: { email: value }, + raw: true, + attributes: ["email", "id"] + }); - const emailExists = await User.findOne({ where: { email: value }, raw: true, attributes: ['email', 'id'] }); + if (emailExists && user.id != emailExists?.id) { + console.error( + "The email already exists in another user profile!" + ); + return !emailExists; + } - if (emailExists && user.id != emailExists?.id) { - - console.error('The email already exists in another user profile!') - return !emailExists; + return true; } - - return true - } - ), - + ) }); - const { email, password, profile, name, positionCompany, queueIds = [] } = userData; + const { + email, + password, + profile, + name, + positionCompany, + queueIds = [] + } = userData; try { await schema.validate({ email, password, profile, name }); @@ -69,7 +82,6 @@ const UpdateUserService = async ({ throw new AppError(err.message); } - await user.update({ email, password, @@ -91,13 +103,18 @@ const UpdateUserService = async ({ }; return serializedUser; + } catch (err: any) { + console.error("===> Error on UpdateUserService.ts file: \n", err); - } catch (error: any) { - console.error('===> Error on UpdateUserService.ts file: \n', error) - throw new AppError(error.message); + if (ignoreThrow) + return { + error: true, + msg: err.message, + status: 500 + }; + + throw new AppError(err.message); } - - }; export default UpdateUserService;