backend: add password reset functionality for admin users
This commit is contained in:
parent
1498332d28
commit
23154bd380
@ -131,6 +131,25 @@ export const getMe = (_req: Request, res: Response) => {
|
||||
return res.status(200).json(userDTO);
|
||||
};
|
||||
|
||||
export const resetUserPassword = async (req: Request, res: Response) => {
|
||||
const { userId } = req.params;
|
||||
const { newPassword } = req.body as { newPassword: string };
|
||||
|
||||
const logger = container.get(LoggerService);
|
||||
logger.verbose(`Admin resetting password for user '${userId}'`);
|
||||
|
||||
try {
|
||||
const userService = container.get(UserService);
|
||||
await userService.resetUserPassword(userId, newPassword);
|
||||
|
||||
return res.status(200).json({
|
||||
message: `Password for user '${userId}' has been reset successfully. User must change password on next login.`
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(res, error, 'resetting user password');
|
||||
}
|
||||
};
|
||||
|
||||
export const changePassword = async (req: Request, res: Response) => {
|
||||
const requestSessionService = container.get(RequestSessionService);
|
||||
const user = requestSessionService.getAuthenticatedUser();
|
||||
|
||||
@ -3,6 +3,7 @@ import { rejectUnprocessableRequest } from '../../models/error.model.js';
|
||||
import {
|
||||
BulkDeleteUsersReqSchema,
|
||||
ChangePasswordReqSchema,
|
||||
ResetUserPasswordReqSchema,
|
||||
UserFiltersSchema,
|
||||
UserOptionsSchema
|
||||
} from '../../models/zod-schemas/user.schema.js';
|
||||
@ -53,3 +54,14 @@ export const validateChangePasswordReq = (req: Request, res: Response, next: Nex
|
||||
req.body = data;
|
||||
next();
|
||||
};
|
||||
|
||||
export const validateResetUserPasswordReq = (req: Request, res: Response, next: NextFunction) => {
|
||||
const { success, error, data } = ResetUserPasswordReqSchema.safeParse(req.body);
|
||||
|
||||
if (!success) {
|
||||
return rejectUnprocessableRequest(res, error);
|
||||
}
|
||||
|
||||
req.body = data;
|
||||
next();
|
||||
};
|
||||
|
||||
@ -54,3 +54,7 @@ export const ChangePasswordReqSchema = z.object({
|
||||
currentPassword: z.string(),
|
||||
newPassword: z.string().min(5, 'New password must be at least 5 characters long')
|
||||
});
|
||||
|
||||
export const ResetUserPasswordReqSchema = z.object({
|
||||
newPassword: z.string().min(5, 'New password must be at least 5 characters long')
|
||||
});
|
||||
|
||||
@ -7,7 +7,8 @@ import {
|
||||
validateBulkDeleteUsersReq,
|
||||
validateChangePasswordReq,
|
||||
validateCreateUserReq,
|
||||
validateGetUsersReq
|
||||
validateGetUsersReq,
|
||||
validateResetUserPasswordReq
|
||||
} from '../middlewares/request-validators/user-validator.middleware.js';
|
||||
|
||||
export const userRouter: Router = Router();
|
||||
@ -42,4 +43,10 @@ userRouter.post(
|
||||
);
|
||||
|
||||
userRouter.get('/:userId', withAuth(tokenAndRoleValidator(MeetUserRole.ADMIN, MeetUserRole.USER)), userCtrl.getUser);
|
||||
userRouter.put(
|
||||
'/:userId/password',
|
||||
withAuth(tokenAndRoleValidator(MeetUserRole.ADMIN)),
|
||||
validateResetUserPasswordReq,
|
||||
userCtrl.resetUserPassword
|
||||
);
|
||||
userRouter.delete('/:userId', withAuth(tokenAndRoleValidator(MeetUserRole.ADMIN)), userCtrl.deleteUser);
|
||||
|
||||
@ -108,6 +108,27 @@ export class UserService {
|
||||
await this.userRepository.update(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset user password by admin. This is used when a user forgets their password.
|
||||
* The mustChangePassword flag is set to true to force the user to change the password on next login.
|
||||
*
|
||||
* @param userId - The ID of the user whose password will be reset
|
||||
* @param newPassword - The new temporary password set by admin
|
||||
*/
|
||||
async resetUserPassword(userId: string, newPassword: string): Promise<void> {
|
||||
const user = await this.userRepository.findByUserId(userId);
|
||||
|
||||
if (!user) {
|
||||
throw errorUserNotFound(userId);
|
||||
}
|
||||
|
||||
user.passwordHash = await PasswordHelper.hashPassword(newPassword);
|
||||
user.mustChangePassword = true; // Force password change on next login
|
||||
|
||||
await this.userRepository.update(user);
|
||||
this.logger.info(`Password reset for user '${userId}' by admin. User must change password on next login.`);
|
||||
}
|
||||
|
||||
async deleteUser(userId: string): Promise<void> {
|
||||
const user = await this.userRepository.findByUserId(userId);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user