parent
72d310ccfa
commit
5130e0a248
461
src/controllers/AuthController.ts
Normal file
461
src/controllers/AuthController.ts
Normal file
@ -0,0 +1,461 @@
|
||||
import JwtService from "@services/jwt.service";
|
||||
|
||||
|
||||
import {Logger} from "tslog";
|
||||
import type {Request, Response} from "express";
|
||||
import UserService from "@services/user.service";
|
||||
|
||||
|
||||
const logger = new Logger({ name: "AuthController" });
|
||||
|
||||
//TODO 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.isAdmin) {
|
||||
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.isAdmin) {
|
||||
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);
|
||||
}
|
||||
|
||||
//TODO - Implement re-auth by current password in case of password change
|
||||
async function editUser(req: Request, res: Response) {
|
||||
const body = 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.isAdmin || sourceUser.id === payload.sub) {
|
||||
if (sourceUser.isAdmin) {
|
||||
logger.info(`EDIT :> Source user is an admin (${sourceUser.displayName})`)
|
||||
} else {
|
||||
logger.info(`EDIT :> Source user modify itself (${sourceUser.displayName})`)
|
||||
}
|
||||
|
||||
//TODO Interface
|
||||
const modifiedData= {}
|
||||
if (body.firstName) modifiedData.firstName = `${body.firstName}`;
|
||||
if (body.lastName) modifiedData.lastName = `${body.lastName}`;
|
||||
if (body.displayName) modifiedData.displayName = `${body.displayName}`;
|
||||
// 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.isAdmin || 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,
|
||||
displayName: dbUser.displayName,
|
||||
firstName: dbUser.firstName,
|
||||
lastName: dbUser.lastName,
|
||||
isAdmin: dbUser.isAdmin
|
||||
});
|
||||
}
|
||||
|
||||
const AuthController = {
|
||||
register: registerUser,
|
||||
login: loginUser,
|
||||
getAllUsers,
|
||||
getUser,
|
||||
editUser,
|
||||
deleteUser,
|
||||
deleteSelf,
|
||||
getSelf
|
||||
}
|
||||
|
||||
export default AuthController;
|
Loading…
x
Reference in New Issue
Block a user