Implement change password request. Adapt authorizationMiddleware to allow for adminOrOwner access to resources

This commit is contained in:
araemer 2025-11-19 20:55:13 +01:00
parent 555dacfaf5
commit 2a6153002c
4 changed files with 180 additions and 59 deletions

View file

@ -4,39 +4,47 @@ import { CreateUserRequest } from "../dtos/CreateUserRequest.js";
import { UserRepository } from "../repositories/UserRepository.js";
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
import { asyncHandler } from "../utils/asyncHandler.js";
import {CreateUserResponse} from "../dtos/CreateUserResponse.js";
import {UserDto} from "../dtos/UserDto.js";
import {requireAdmin} from "../middleware/authorizationMiddleware.js";
import {UserListResponse} from "../dtos/UserListResponse.js";
import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js";
import { CreateUserResponse } from "../dtos/CreateUserResponse.js";
import { UserDto } from "../dtos/UserDto.js";
import {
requireAdmin,
requireAdminOrOwner,
requireAdminOrSelf
} from "../middleware/authorizationMiddleware.js";
import { UserListResponse } from "../dtos/UserListResponse.js";
import { HttpStatusCode } from "../apiHelpers/HttpStatusCodes.js";
import { InternalServerError, NotFoundError } from "../errors/httpErrors.js";
import { ChangeUserPasswordRequest } from "../dtos/ChangeUserPasswordRequest.js";
export const userBasicRoute = "/user";
/**
* Handles all user related routes
*/
const router = Router();
router.use((req, res, next) => {
console.log(`Incoming request: ${req.method} ${req.path}`);
next();
});
// Inject repo + mapper here
const handler
= new UserHandler(new UserRepository(), new UserDtoEntityMapper());
const handler = new UserHandler(new UserRepository(), new UserDtoEntityMapper());
/**
* Create a new user
* Create a new user (admin only)
* Consumes CreateUserRequest
* Responds with UserDto
*/
router.post(
"/create",
asyncHandler(async (req, res) => {
const request: CreateUserRequest = req.body;
const user : UserDto = await handler.createUser(request);
const response : CreateUserResponse = { userData: user };
res.status(201).json(response);
})
"/create",
requireAdmin,
asyncHandler(async (req, res) => {
const request: CreateUserRequest = req.body;
const user: UserDto = await handler.createUser(request);
const response: CreateUserResponse = { userData: user };
res.status(HttpStatusCode.CREATED).json(response);
})
);
/**
@ -44,25 +52,36 @@ router.post(
* Consumes UserDto
* Responds with UserDto
* Does not allow for password change. Use change-password instead
*
* Users can update their own data, admins can update any user
*/
router.post(
"/update",
requireAdminOrSelf, // Checks req.body.id or req.body.userId
asyncHandler(async (req, res) => {
const dto : UserDto = req.body;
const dto: UserDto = req.body;
const response = await handler.updateUserData(dto);
res.status(HttpStatusCode.CREATED).json(response);
res.status(HttpStatusCode.OK).json(response);
})
);
/**
* Update password of existing user
* Consumes ChangeUserPasswordRequest
* Responds with code 201 indicating success
* Responds with code 200 indicating success
*
* Users can change their own password, admins can change any password
*/
router.post(
"/change-password",
requireAdminOrOwner(req => req.body.userId),
asyncHandler(async (req, res) => {
throw Error("not implemented!");
const requestData: ChangeUserPasswordRequest = req.body;
const success = await handler.changePassword(requestData);
if (!success) {
throw new InternalServerError("Failed to change password");
}
res.status(HttpStatusCode.OK).json({ message: "Password changed successfully" });
})
);
@ -72,11 +91,10 @@ router.post(
*/
router.get(
"/all",
//requireAdmin,
requireAdmin,
asyncHandler(async (req, res) => {
const id = req.currentUser?.id;
const users = await handler.getAllUsers();
const response : UserListResponse = {valueList: users}
const response: UserListResponse = { valueList: users };
res.status(HttpStatusCode.OK).json(response);
})
);
@ -85,15 +103,33 @@ router.get(
* Get user data for current user
* Responds with UserDto
*/
router.get("/me",
asyncHandler(async (req, res) => {
const id = req.currentUser?.id;
if(id){
const responseDto = await handler.getUserById(id);
res.status(HttpStatusCode.OK).json(responseDto);
}
})
router.get(
"/me",
asyncHandler(async (req, res) => {
const id = req.currentUser?.id;
if (id) {
const responseDto = await handler.getUserById(id);
res.status(HttpStatusCode.OK).json(responseDto);
} else {
throw new NotFoundError("There is no user id for current session!");
}
})
);
export default router;
/**
* Get specific user by ID
* Responds with UserDto
*
* Users can get their own data, admins can get any user's data
*/
router.get(
"/:userId",
requireAdminOrOwner(req => req.params.userId),
asyncHandler(async (req, res) => {
const userId = req.params.userId;
const responseDto = await handler.getUserById(userId);
res.status(HttpStatusCode.OK).json(responseDto);
})
);
export default router;