backend: implement user role update functionality
This commit is contained in:
parent
7d7f66edf3
commit
de0674d82c
@ -1,4 +1,4 @@
|
||||
import { MeetUserFilters, MeetUserOptions } from '@openvidu-meet/typings';
|
||||
import { MeetUserFilters, MeetUserOptions, MeetUserRole } from '@openvidu-meet/typings';
|
||||
import { Request, Response } from 'express';
|
||||
import { container } from '../config/dependency-injector.config.js';
|
||||
import { INTERNAL_CONFIG } from '../config/internal-config.js';
|
||||
@ -150,6 +150,26 @@ export const resetUserPassword = async (req: Request, res: Response) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const updateUserRole = async (req: Request, res: Response) => {
|
||||
const { userId } = req.params;
|
||||
const { role } = req.body as { role: MeetUserRole };
|
||||
|
||||
const logger = container.get(LoggerService);
|
||||
logger.verbose(`Admin updating role for user '${userId}' to '${role}'`);
|
||||
|
||||
try {
|
||||
const userService = container.get(UserService);
|
||||
const user = await userService.changeUserRole(userId, role);
|
||||
|
||||
return res.status(200).json({
|
||||
message: `Role for user '${userId}' updated successfully to '${role}'`,
|
||||
user: userService.convertToDTO(user)
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(res, error, 'updating user role');
|
||||
}
|
||||
};
|
||||
|
||||
export const changePassword = async (req: Request, res: Response) => {
|
||||
const requestSessionService = container.get(RequestSessionService);
|
||||
const user = requestSessionService.getAuthenticatedUser();
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
BulkDeleteUsersReqSchema,
|
||||
ChangePasswordReqSchema,
|
||||
ResetUserPasswordReqSchema,
|
||||
UpdateUserRoleReqSchema,
|
||||
UserFiltersSchema,
|
||||
UserOptionsSchema
|
||||
} from '../../models/zod-schemas/user.schema.js';
|
||||
@ -65,3 +66,14 @@ export const validateResetUserPasswordReq = (req: Request, res: Response, next:
|
||||
req.body = data;
|
||||
next();
|
||||
};
|
||||
|
||||
export const validateUpdateUserRoleReq = (req: Request, res: Response, next: NextFunction) => {
|
||||
const { success, error, data } = UpdateUserRoleReqSchema.safeParse(req.body);
|
||||
|
||||
if (!success) {
|
||||
return rejectUnprocessableRequest(res, error);
|
||||
}
|
||||
|
||||
req.body = data;
|
||||
next();
|
||||
};
|
||||
|
||||
@ -249,6 +249,22 @@ export const errorCannotDeleteOwnAccount = (): OpenViduMeetError => {
|
||||
);
|
||||
};
|
||||
|
||||
export const errorCannotChangeRootAdminRole = (): OpenViduMeetError => {
|
||||
return new OpenViduMeetError(
|
||||
'User Error',
|
||||
'Cannot change the role of the root admin user. This account must retain administrative privileges.',
|
||||
403
|
||||
);
|
||||
};
|
||||
|
||||
export const errorCannotChangeOwnRole = (): OpenViduMeetError => {
|
||||
return new OpenViduMeetError(
|
||||
'User Error',
|
||||
'Cannot change your own role. Please have another administrator change your role if needed.',
|
||||
403
|
||||
);
|
||||
};
|
||||
|
||||
// Room errors
|
||||
|
||||
export const errorRoomNotFound = (roomId: string): OpenViduMeetError => {
|
||||
|
||||
@ -58,3 +58,7 @@ export const ChangePasswordReqSchema = z.object({
|
||||
export const ResetUserPasswordReqSchema = z.object({
|
||||
newPassword: z.string().min(5, 'New password must be at least 5 characters long')
|
||||
});
|
||||
|
||||
export const UpdateUserRoleReqSchema = z.object({
|
||||
role: z.nativeEnum(MeetUserRole)
|
||||
});
|
||||
|
||||
@ -8,7 +8,8 @@ import {
|
||||
validateChangePasswordReq,
|
||||
validateCreateUserReq,
|
||||
validateGetUsersReq,
|
||||
validateResetUserPasswordReq
|
||||
validateResetUserPasswordReq,
|
||||
validateUpdateUserRoleReq
|
||||
} from '../middlewares/request-validators/user-validator.middleware.js';
|
||||
|
||||
export const userRouter: Router = Router();
|
||||
@ -49,4 +50,10 @@ userRouter.put(
|
||||
validateResetUserPasswordReq,
|
||||
userCtrl.resetUserPassword
|
||||
);
|
||||
userRouter.put(
|
||||
'/:userId/role',
|
||||
withAuth(tokenAndRoleValidator(MeetUserRole.ADMIN)),
|
||||
validateUpdateUserRoleReq,
|
||||
userCtrl.updateUserRole
|
||||
);
|
||||
userRouter.delete('/:userId', withAuth(tokenAndRoleValidator(MeetUserRole.ADMIN)), userCtrl.deleteUser);
|
||||
|
||||
@ -3,6 +3,8 @@ import { inject, injectable } from 'inversify';
|
||||
import { MEET_ENV } from '../environment.js';
|
||||
import { PasswordHelper } from '../helpers/password.helper.js';
|
||||
import {
|
||||
errorCannotChangeOwnRole,
|
||||
errorCannotChangeRootAdminRole,
|
||||
errorCannotDeleteOwnAccount,
|
||||
errorCannotDeleteRootAdmin,
|
||||
errorCannotResetOwnPassword,
|
||||
@ -151,6 +153,38 @@ export class UserService {
|
||||
this.logger.info(`Password reset for user '${userId}' by admin. User must change password on next login.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user role by admin.
|
||||
*
|
||||
* @param userId - The ID of the user whose role will be changed
|
||||
* @param newRole - The new role to assign to the user
|
||||
*/
|
||||
async changeUserRole(userId: string, newRole: MeetUserRole): Promise<MeetUser> {
|
||||
// Prevent changing role of the root admin user
|
||||
if (userId === MEET_ENV.INITIAL_ADMIN_USER) {
|
||||
throw errorCannotChangeRootAdminRole();
|
||||
}
|
||||
|
||||
// Prevent changing own role
|
||||
const authenticatedUser = this.requestSessionService.getAuthenticatedUser();
|
||||
|
||||
if (authenticatedUser && authenticatedUser.userId === userId) {
|
||||
throw errorCannotChangeOwnRole();
|
||||
}
|
||||
|
||||
const user = await this.userRepository.findByUserId(userId);
|
||||
|
||||
if (!user) {
|
||||
throw errorUserNotFound(userId);
|
||||
}
|
||||
|
||||
user.role = newRole;
|
||||
await this.userRepository.update(user);
|
||||
|
||||
this.logger.info(`Role for user '${userId}' changed to '${newRole}' by admin`);
|
||||
return user;
|
||||
}
|
||||
|
||||
async deleteUser(userId: string): Promise<void> {
|
||||
// Prevent deleting the root admin user
|
||||
if (userId === MEET_ENV.INITIAL_ADMIN_USER) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user