Compare commits

...

9 Commits

8 changed files with 542 additions and 295 deletions

View File

@ -21,10 +21,10 @@
- [ ] CreateUser (1)
- [ ] DeleteUser (1)
- [ ] UpdateUser (1)
- [] ListAllUsers **OPCIONAL**
- [ ] ResetPassword (1)
- [ ] LockUser (2)
- [ ] UnlockUser (2)
- [] ResetPassword (2)
- [ ] ListAllUsers **OPCIONAL**
- Rights
- [ ] CheckUserRight (1)
- [ ] CreateRight (1)
@ -36,3 +36,47 @@
- [ ] 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

View File

@ -24,133 +24,26 @@ 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";
type IndexQuery = {
searchParam: string;
pageNumber: 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);
interface IAMResponse {
return_code: string
return_msg: string
}
//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,
password,
name,
positionCompany,
profile,
queueIds
email: user_tax_id,
password: "padrao",
name: user_first_name,
});
if (user) {
@ -164,103 +57,150 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
user
});
// await stopWhoIsOnlineMonitor()
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> => {
const { userId } = req.params;
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) {
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 (
req: Request,
res: Response
): Promise<Response> => {
const { userId } = req.params;
//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;
await stopWhoIsOnlineMonitor();
await DeleteUserService(user_id);
let onlineTime = {
userId: userId,
status: "logout..."
};
del(`user:${user_id}`);
const io = getIO();
io.emit("user", {
action: "delete",
user_id
});
//test del
await stopWhoIsOnlineMonitor();
io.emit("onlineStatus", {
action: "logout",
userOnlineTime: onlineTime
action: "delete",
userOnlineTime: user_id
});
await startWhoIsOnlineMonitor();
//
return res.status(200).json({});
};
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
return res.status(200).json({
return_code: "200",
return_msg: `User ${user_id} deleted`,
user_removed: "1",
});
// 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_removed: "0",
});
}
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);
if (user) {
@ -274,41 +214,154 @@ export const update = async (
user
});
user.userQueuesAttendance = userQueuesAttendance;
return res.status(200).json(user);
};
export const remove = async (
req: Request,
res: Response
): Promise<Response> => {
const { userId } = req.params;
if (req.user.profile !== "master") {
throw new AppError("ERR_NO_PERMISSION", 403);
// 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",
});
}
await DeleteUserService(userId);
del(`user:${userId}`);
const io = getIO();
io.emit("user", {
action: "delete",
userId
return res.status(500).json({
return_code: "500",
return_msg: "Internal server error",
user_updated: "0",
});
//test del
await stopWhoIsOnlineMonitor();
io.emit("onlineStatus", {
action: "delete",
userOnlineTime: userId
});
await startWhoIsOnlineMonitor();
//
return res.status(200).json({ message: "User deleted" });
}
};
export const resetPassword = async (req: Request, res: Response<IAMResponse & { password_set: "1" | "0" }>): Promise<Response> => {
try {
const { user_id, user_password } = req.body;
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",
});
}
};
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 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;

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;