Compare commits

..

9 Commits

8 changed files with 542 additions and 295 deletions

View File

@ -17,22 +17,66 @@
- 1: Da para fazer - 1: Da para fazer
- 2: Tem que analisar - 2: Tem que analisar
- Users - Users
- [] CheckUser (1) - [ ] CheckUser (1)
- [] CreateUser (1) - [ ] CreateUser (1)
- [] DeleteUser (1) - [ ] DeleteUser (1)
- [] UpdateUser (1) - [ ] UpdateUser (1)
- [] ListAllUsers **OPCIONAL** - [ ] ResetPassword (1)
- [] LockUser (2) - [ ] LockUser (2)
- [] UnlockUser (2) - [ ] UnlockUser (2)
- [] ResetPassword (2) - [ ] ListAllUsers **OPCIONAL**
- Rights - Rights
- [] CheckUserRight (1) - [ ] CheckUserRight (1)
- [] CreateRight (1) - [ ] CreateRight (1)
- [] UpdateRight (1) - [ ] UpdateRight (1)
- [] DeleteRight (1) - [ ] DeleteRight (1)
- [] GetAllRights **OPCIONAL** - [ ] GetAllRights **OPCIONAL**
- Users X Rights - Users X Rights
- [] LinkUserAndUserRight (1) - [ ] LinkUserAndUserRight (1)
- [] UnlinkUserAndUserRight (1) - [ ] UnlinkUserAndUserRight (1)
- [] GetAllUserRights **OPCIONAL** - [ ] 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

View File

@ -24,133 +24,26 @@ import { splitDateTime } from "../helpers/SplitDateTime";
import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService"; import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService";
import { getSettingValue } from "../helpers/WhaticketSettings"; import { getSettingValue } from "../helpers/WhaticketSettings";
import { setBotInfo } from "../helpers/SetBotInfo"; 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";
type IndexQuery = { interface IAMResponse {
searchParam: string; return_code: string
pageNumber: string; return_msg: string
profile?: string; }
userId: string;
};
export const index = async (req: Request, res: Response): Promise<Response> => {
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<object> = [];
// 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<object> = [];
// 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<Response> => {
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<Response> => {
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);
}
//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({ const user = await CreateUserService({
email, email: user_tax_id,
password, password: "padrao",
name, name: user_first_name,
positionCompany,
profile,
queueIds
}); });
if (user) { if (user) {
@ -164,103 +57,150 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
user user
}); });
// await stopWhoIsOnlineMonitor()
await startWhoIsOnlineMonitor(); await startWhoIsOnlineMonitor();
return res.status(200).json(user); 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 show = async (req: Request, res: Response): Promise<Response> => { export const checkUser = async (req: Request, res: Response<IAMResponse & { user_exists: "1" | "0" }>): Promise<Response> => {
const { userId } = req.params; 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 user = await ShowUserService(userId); 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",
});
}
return res.status(200).json(user); return res.status(500).json({
return_code: "500",
return_msg: "Internal server error",
user_exists: "0",
});
}
}; };
export const logoutUser = async ( //TODO: REVIEW DELETE USER
req: Request, export const deleteUser = async (req: Request, res: Response<IAMResponse & { user_removed: "1" | "0" }>): Promise<Response> => {
res: Response try {
): Promise<Response> => { const { user_id } = req.body;
const { userId } = req.params;
await stopWhoIsOnlineMonitor(); await DeleteUserService(user_id);
let onlineTime = { del(`user:${user_id}`);
userId: userId,
status: "logout..."
};
const io = getIO(); const io = getIO();
io.emit("user", {
action: "delete",
user_id
});
//test del
await stopWhoIsOnlineMonitor();
io.emit("onlineStatus", { io.emit("onlineStatus", {
action: "logout", action: "delete",
userOnlineTime: onlineTime userOnlineTime: user_id
}); });
await startWhoIsOnlineMonitor(); await startWhoIsOnlineMonitor();
// return res.status(200).json({
return_code: "200",
return res.status(200).json({}); return_msg: `User ${user_id} deleted`,
}; user_removed: "1",
export const update = async (
req: Request,
res: Response
): Promise<Response> => {
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) } catch (error) {
// console.log() if (error instanceof AppError) {
// console.log('------> 1 userData.queueIds: ', userData.queueIds) logger.warn(error);
return res.status(error.statusCode).json({
let userQueuesAttendance = []; return_code: String(error.statusCode),
return_msg: error.message,
if ((openByUserOnQueue && openByUserOnQueue.length) > 0) { user_removed: "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 }); 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<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);
// 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); await setBotInfo(user);
if (user) { if (user) {
@ -274,41 +214,154 @@ export const update = async (
user user
}); });
user.userQueuesAttendance = userQueuesAttendance; // user.userQueuesAttendance = userQueuesAttendance;
return res.status(200).json({
return res.status(200).json(user); return_code: "200",
}; return_msg: `User ${user_id} updated`,
user_updated: "1"
export const remove = async ( });
req: Request, } catch (error) {
res: Response if (error instanceof AppError) {
): Promise<Response> => { logger.warn(error);
const { userId } = req.params; return res.status(error.statusCode).json({
return_code: String(error.statusCode),
if (req.user.profile !== "master") { return_msg: error.message,
throw new AppError("ERR_NO_PERMISSION", 403); user_updated: "0",
});
} }
await DeleteUserService(userId); return res.status(500).json({
return_code: "500",
del(`user:${userId}`); return_msg: "Internal server error",
user_updated: "0",
const io = getIO();
io.emit("user", {
action: "delete",
userId
}); });
}
//test del };
await stopWhoIsOnlineMonitor();
export const resetPassword = async (req: Request, res: Response<IAMResponse & { password_set: "1" | "0" }>): Promise<Response> => {
io.emit("onlineStatus", { try {
action: "delete", const { user_id, user_password } = req.body;
userOnlineTime: userId
}); await ResetPasswordService({
userPassword: user_password,
await startWhoIsOnlineMonitor(); userId: user_id
// })
return res.status(200).json({ message: "User deleted" }); 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",
});
}
};
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;
await LinkUserRightService({
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 unlinkUserRight = async (req: Request, res: Response<IAMResponse & { user_right_unlinked: "1" | "0" }>): Promise<Response> => {
try {
const { user_id, user_right_title } = req.body;
await UnlinkUserRightService({
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<IAMResponse & { user_right_exists: "1" | "0" }>): Promise<Response> => {
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",
});
}
}; };

View File

@ -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;

View File

@ -1,23 +1,19 @@
import { Router } from "express"; import { Router } from "express";
import isAuth from "../middleware/isAuth";
import * as IAMControllerEL from "../controllers/IAMControllerEL"; import * as IAMControllerEL from "../controllers/IAMControllerEL";
import verifyAPIKey from "../middleware/verifyAPIKey";
const iamRoutesEL = Router(); 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.patch("/IAM/users/reset-password", verifyAPIKey, IAMControllerEL.resetPassword);
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; export default iamRoutesEL;

View File

@ -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<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;

View File

@ -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<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;

View File

@ -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<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;

View File

@ -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<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;