scope: services, interfaces subject: Apply code formatting - Correct indentation and formatting to match code style standards in multiple 'interfaces' and 'services' files. - Also ensure lines at the end of the files. Signed-off-by: Mathis <yidhra@tuta.io>
445 lines
12 KiB
TypeScript
445 lines
12 KiB
TypeScript
import JwtService from "@services/jwt.service";
|
|
|
|
import type { IReqEditUserData } from "@interfaces/IReqEditUserData";
|
|
import UserService from "@services/user.service";
|
|
import type { Request, Response } from "express";
|
|
import { Logger } from "tslog";
|
|
|
|
const logger = new Logger({
|
|
name: "AuthController",
|
|
});
|
|
|
|
//FIX Better return object interface
|
|
/**
|
|
* Registers a user with the given request data.
|
|
*
|
|
* @param {Request} req - The request object containing user data.
|
|
* @param {Response} res - The response object to send the registration result.
|
|
*
|
|
* @return {Promise} A promise that resolves to the registration result.
|
|
* It can have the following properties:
|
|
* - error: "gdprNotApproved" if GDPR is not approved
|
|
* - error: "exist" if the user already exists
|
|
* - Otherwise, the registered user data
|
|
*/
|
|
async function registerUser(
|
|
req: Request,
|
|
res: Response,
|
|
): Promise<unknown> {
|
|
const body = req.body;
|
|
if (!body) {
|
|
logger.warn(`Invalid input data (${req.ip})`);
|
|
return res.type("application/json").status(400).json({
|
|
error: "Invalid input data",
|
|
});
|
|
}
|
|
if (
|
|
!body.password ||
|
|
!body.username ||
|
|
!body.firstName ||
|
|
!body.lastName ||
|
|
!body.displayName
|
|
) {
|
|
logger.warn(`Field(s) missing (${req.ip})`);
|
|
return res.type("application/json").status(400).json({
|
|
error: "Field(s) missing",
|
|
});
|
|
}
|
|
|
|
let gdpr = false;
|
|
if (body.gdpr === true) {
|
|
gdpr = true;
|
|
}
|
|
const sanitizeData = {
|
|
username: `${body.username}`,
|
|
displayName: `${body.displayName}`,
|
|
gdpr: gdpr,
|
|
password: `${body.password}`,
|
|
firstName: `${body.firstName}`,
|
|
lastName: `${body.lastName}`,
|
|
};
|
|
|
|
const RegisterServiceResult =
|
|
await UserService.register(sanitizeData);
|
|
|
|
if (RegisterServiceResult.error === "gdprNotApproved") {
|
|
logger.warn(`GDPR not approved (${req.ip})`);
|
|
return res.status(400).json({
|
|
error: RegisterServiceResult.error,
|
|
message: "GDPR not accepted.",
|
|
});
|
|
}
|
|
if (RegisterServiceResult.error === "exist") {
|
|
logger.warn(`The user already exists (${req.ip})`);
|
|
return res.type("application/json").status(400).json({
|
|
error: RegisterServiceResult.error,
|
|
message: "The user already exists.",
|
|
});
|
|
}
|
|
|
|
// SUCCESS
|
|
logger.info(`User registered successfully (${req.ip})`);
|
|
return res
|
|
.type("application/json")
|
|
.status(201)
|
|
.json(RegisterServiceResult);
|
|
}
|
|
|
|
/**
|
|
* Logs in a user with the provided credentials.
|
|
*
|
|
* @param {Request} req - The request object.
|
|
* @param {Response} res - The response object.
|
|
*
|
|
* @return {Promise<void>} A promise that resolves when the user is logged in or rejects with an error.
|
|
*/
|
|
async function loginUser(
|
|
req: Request,
|
|
res: Response,
|
|
): Promise<void> {
|
|
const body = req.body;
|
|
if (!body) {
|
|
res.type("application/json").status(400).json({
|
|
error: "Invalid input data",
|
|
});
|
|
}
|
|
if (!body.password || !body.username) {
|
|
logger.warn(`Field(s) missing (${req.ip})`);
|
|
res.type("application/json").status(400).json({
|
|
error: "Field(s) missing",
|
|
});
|
|
}
|
|
|
|
const loginData = {
|
|
username: `${body.username}`,
|
|
password: `${body.password}`,
|
|
};
|
|
console.log(body);
|
|
const LoginServiceResult = await UserService.login(loginData);
|
|
console.log(LoginServiceResult);
|
|
|
|
if (LoginServiceResult.error === "userNotFound") {
|
|
console.log("POOL");
|
|
res.type("application/json").status(404).json({
|
|
error: LoginServiceResult.error,
|
|
message: "User not found.",
|
|
});
|
|
}
|
|
if (LoginServiceResult.error === "invalidPassword") {
|
|
res.type("application/json").status(401).json({
|
|
error: LoginServiceResult.error,
|
|
message: "Invalid password.",
|
|
});
|
|
}
|
|
res
|
|
.type("application/json")
|
|
.status(200)
|
|
.json(LoginServiceResult);
|
|
}
|
|
|
|
async function getAllUsers(req: Request, res: Response) {
|
|
const authHeader = req.headers.authorization;
|
|
const bearerToken = authHeader?.split(" ")[1];
|
|
if (!bearerToken) {
|
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const payload = await JwtService.verify(bearerToken);
|
|
if (!payload) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const sourceUser = await UserService.getFromId(payload.sub);
|
|
if (!sourceUser) {
|
|
return res.type("application/json").status(404).json({
|
|
error: "You dont exist anymore",
|
|
});
|
|
}
|
|
if (!sourceUser.is_admin) {
|
|
return res.type("application/json").status(403).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const AllUserResponse = await UserService.getAll();
|
|
if (!AllUserResponse.users) {
|
|
return res.type("application/json").status(500).json({
|
|
error: "Internal server error",
|
|
});
|
|
}
|
|
return res
|
|
.type("application/json")
|
|
.status(200)
|
|
.json(AllUserResponse);
|
|
}
|
|
|
|
async function getUser(req: Request, res: Response) {
|
|
const authHeader = req.headers.authorization;
|
|
const bearerToken = authHeader?.split(" ")[1];
|
|
if (!bearerToken) {
|
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const payload = await JwtService.verify(bearerToken);
|
|
if (!payload) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const sourceUser = await UserService.getFromId(payload.sub);
|
|
if (!sourceUser) {
|
|
return res.type("application/json").status(404).json({
|
|
error: "You dont exist anymore",
|
|
});
|
|
}
|
|
if (!sourceUser.is_admin) {
|
|
return res.type("application/json").status(403).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const userId = req.params["id"];
|
|
const dbUser = await UserService.getFromId(userId);
|
|
if (!dbUser) {
|
|
logger.warn(`User not found (${req.ip})`);
|
|
return res.type("application/json").status(404).json({
|
|
error: "User not found",
|
|
});
|
|
}
|
|
// @ts-ignore
|
|
delete dbUser.passwordHash;
|
|
// @ts-ignore
|
|
delete dbUser._id;
|
|
return res.type("application/json").status(200).json(dbUser);
|
|
}
|
|
|
|
//FEAT - Implement re-auth by current password in case of password change
|
|
async function editUser(req: Request, res: Response) {
|
|
const body: IReqEditUserData | null = req.body;
|
|
if (!body) {
|
|
return res.type("application/json").status(400).json({
|
|
error: "Field(s) missing",
|
|
});
|
|
}
|
|
const authHeader = req.headers.authorization;
|
|
const bearerToken = authHeader?.split(" ")[1];
|
|
if (!bearerToken) {
|
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const payload = await JwtService.verify(bearerToken);
|
|
if (!payload) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const sourceUser = await UserService.getFromId(payload.sub);
|
|
|
|
//@ts-ignore
|
|
const targetUserId = req.params.id || payload.sub;
|
|
console.log(targetUserId);
|
|
|
|
if (!sourceUser) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(404).json({
|
|
error: "You dont exist anymore",
|
|
});
|
|
}
|
|
if (sourceUser.is_admin || sourceUser.id === payload.sub) {
|
|
if (sourceUser.is_admin) {
|
|
logger.info(
|
|
`EDIT :> Source user is an admin (${sourceUser.firstname} ${sourceUser.lastname})`,
|
|
);
|
|
} else {
|
|
logger.info(
|
|
`EDIT :> Source user modify itself (${sourceUser.firstname} ${sourceUser.lastname})`,
|
|
);
|
|
}
|
|
|
|
//TODO Interface
|
|
const modifiedData = {};
|
|
//@ts-ignore
|
|
if (body.firstName)
|
|
modifiedData.firstName = `${body.firstName}`;
|
|
//@ts-ignore
|
|
if (body.lastName)
|
|
modifiedData.lastName = `${body.lastName}`;
|
|
//@ts-ignore
|
|
if (body.displayName)
|
|
modifiedData.displayName = `${body.displayName}`;
|
|
//TODO Case handled with hashing by the service.
|
|
//if (body.password) modifiedData.password = `${body.password}`;
|
|
|
|
//Call service
|
|
const EditUserServiceResult = await UserService.edit(
|
|
`${targetUserId}`,
|
|
modifiedData,
|
|
);
|
|
if (EditUserServiceResult.error === "userNotFound") {
|
|
logger.warn(`User not found (${req.ip})`);
|
|
return res.type("application/json").status(404).json({
|
|
error: "User not found",
|
|
});
|
|
}
|
|
if (EditUserServiceResult.error !== "none") {
|
|
logger.error(
|
|
`Error occurred during user edit (${req.ip})`,
|
|
);
|
|
return res.type("application/json").status(500).json({
|
|
error: "Internal server error",
|
|
});
|
|
}
|
|
return res
|
|
.type("application/json")
|
|
.status(200)
|
|
.json(EditUserServiceResult);
|
|
}
|
|
//Not itself or
|
|
logger.warn(
|
|
`Unauthorized access attempt, not self or admin (${req.ip})`,
|
|
);
|
|
return res.type("application/json").status(403).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
|
|
async function deleteUser(
|
|
req: Request,
|
|
res: Response,
|
|
): Promise<Response> {
|
|
const authHeader = req.headers.authorization;
|
|
const bearerToken = authHeader?.split(" ")[1];
|
|
if (!bearerToken) {
|
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const payload = await JwtService.verify(bearerToken);
|
|
|
|
if (!payload) {
|
|
logger.warn(`Invalid token (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Invalid token",
|
|
});
|
|
}
|
|
const sourceUser = await UserService.getFromId(payload?.sub);
|
|
const targetUserId = req.params["id"];
|
|
if (!sourceUser) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(404).json({
|
|
error: "You dont exist anymore",
|
|
});
|
|
}
|
|
if (sourceUser.is_admin || sourceUser.id === payload.sub) {
|
|
const deleteUserServiceResult = await UserService.delete(
|
|
`${targetUserId}`,
|
|
);
|
|
if (!deleteUserServiceResult) {
|
|
logger.error(
|
|
`Error occurred during user delete (${req.ip})`,
|
|
);
|
|
return res.type("application/json").status(500).json({
|
|
error: "Internal server error",
|
|
});
|
|
}
|
|
|
|
return res.type("application/json").status(200).json({
|
|
message: "User deleted successfully",
|
|
});
|
|
}
|
|
return res.type("application/json").status(403).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
|
|
async function deleteSelf(req: Request, res: Response) {
|
|
const authHeader = req.headers.authorization;
|
|
const bearerToken = authHeader?.split(" ")[1];
|
|
if (!bearerToken) {
|
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const payload = await JwtService.verify(bearerToken);
|
|
if (!payload) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const sourceUser = await UserService.getFromId(payload.sub);
|
|
if (!sourceUser) {
|
|
return res.type("application/json").status(404).json({
|
|
error: "You dont exist anymore",
|
|
});
|
|
}
|
|
if (sourceUser.id !== req.params["id"]) {
|
|
return res.type("application/json").status(403).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const deleteResult = await UserService.delete(sourceUser.id);
|
|
if (!deleteResult) {
|
|
logger.error(`Failed to delete user (${req.ip})`);
|
|
return res.type("application/json").status(500).json({
|
|
error: "Failed to delete user",
|
|
});
|
|
}
|
|
return res.type("application/json").status(200).json({
|
|
message: "User deleted successfully",
|
|
});
|
|
}
|
|
|
|
async function getSelf(req: Request, res: Response) {
|
|
const authHeader = req.headers.authorization;
|
|
const bearerToken = authHeader?.split(" ")[1];
|
|
if (!bearerToken) {
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const payload = await JwtService.verify(bearerToken);
|
|
if (!payload) {
|
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
|
return res.type("application/json").status(401).json({
|
|
error: "Unauthorized",
|
|
});
|
|
}
|
|
const dbUser = await UserService.getFromId(payload.sub);
|
|
if (!dbUser) {
|
|
return res.type("application/json").status(404).json({
|
|
error: "User not found",
|
|
});
|
|
}
|
|
return res.type("application/json").status(200).json({
|
|
id: dbUser.id,
|
|
username: dbUser.username,
|
|
firstName: dbUser.firstname,
|
|
lastName: dbUser.firstname,
|
|
isAdmin: dbUser.firstname,
|
|
});
|
|
}
|
|
|
|
const AuthController = {
|
|
register: registerUser,
|
|
login: loginUser,
|
|
getAllUsers,
|
|
getUser,
|
|
editUser,
|
|
deleteUser,
|
|
deleteSelf,
|
|
getSelf,
|
|
};
|
|
|
|
export default AuthController;
|