feat: Add routes and controllers to integrate with E-Trust Horacius for user and application management
parent
37c384a712
commit
db4bf2bf84
|
@ -43,4 +43,5 @@ WWebJS
|
|||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
yarn-error.log*
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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<Response> => {
|
||||
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<IAMResponse & { user_created: "1" | "0" }>): Promise<Response> => {
|
||||
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<IAMResponse & { use
|
|||
});
|
||||
|
||||
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",
|
||||
});
|
||||
}
|
||||
|
||||
return res
|
||||
.status(200)
|
||||
.json(response("1", `User ${user_id} created`, "1", "createUser"));
|
||||
};
|
||||
|
||||
export const checkUser = async (req: Request, res: Response<IAMResponse & { user_exists: "1" | "0" }>): Promise<Response> => {
|
||||
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<Response> => {
|
||||
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<IAMResponse & { user_removed: "1" | "0" }>): Promise<Response> => {
|
||||
try {
|
||||
const { user_id } = req.body;
|
||||
export const listAllUsers = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
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<IAMResponse & { user_updated: "1" | "0" }>): Promise<Response> => {
|
||||
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<Response> => {
|
||||
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<IAMResponse & { password_set: "1" | "0" }>): Promise<Response> => {
|
||||
try {
|
||||
const { user_id, user_password } = req.body;
|
||||
export const updateUser = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
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<IAMResponse & { user_right_linked: "1" | "0" }>): Promise<Response> => {
|
||||
try {
|
||||
const { user_id, user_right_title, } = req.body;
|
||||
export const resetPassword = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
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<IAMResponse & { user_right_unlinked: "1" | "0" }>): Promise<Response> => {
|
||||
try {
|
||||
const { user_id, user_right_title } = req.body;
|
||||
export const linkUserAndUserRight = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
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<IAMResponse & { user_right_exists: "1" | "0" }>): Promise<Response> => {
|
||||
try {
|
||||
const { user_id, user_right_title } = req.body;
|
||||
export const checkUserRight = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
};
|
|
@ -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",
|
||||
|
|
|
@ -41,10 +41,13 @@ class User extends Model<User> {
|
|||
@Default(0)
|
||||
@Column
|
||||
tokenVersion: number;
|
||||
|
||||
|
||||
@Column
|
||||
positionCompany: string;
|
||||
|
||||
|
||||
@Column
|
||||
secondaryId: string;
|
||||
|
||||
@Default("admin")
|
||||
@Column
|
||||
profile: string;
|
||||
|
@ -56,9 +59,9 @@ class User extends Model<User> {
|
|||
updatedAt: Date;
|
||||
@HasMany(() => Ticket)
|
||||
tickets: Ticket[];
|
||||
|
||||
|
||||
@HasMany(() => UserOnlineTime)
|
||||
UserOnlineTime: UserOnlineTime[];
|
||||
UserOnlineTime: UserOnlineTime[];
|
||||
|
||||
@BelongsToMany(() => Queue, () => UserQueue)
|
||||
queues: Queue[];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<CheckUserRightServiceResponse> => {
|
||||
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;
|
|
@ -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<Response> => {
|
||||
|
||||
profile = "master",
|
||||
ignoreThrow = false
|
||||
}: Request): Promise<Response | any> => {
|
||||
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;
|
||||
|
|
|
@ -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<void> => {
|
||||
const DeleteUserService = async (
|
||||
id: string | number,
|
||||
ignoreThrow = false
|
||||
): Promise<void | any> => {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<void> => {
|
||||
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;
|
|
@ -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<void> => {
|
||||
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;
|
|
@ -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<void> => {
|
||||
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;
|
|
@ -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<Response | undefined> => {
|
||||
|
||||
userId,
|
||||
ignoreThrow = false
|
||||
}: Request): Promise<Response | undefined | any> => {
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue