226 lines
4.9 KiB
TypeScript
226 lines
4.9 KiB
TypeScript
import { Response } from 'express';
|
|
import { AuthenticatedRequest } from '../types';
|
|
import * as roleService from '../services/role.service';
|
|
import { CreateRoleInput, UpdateRoleInput } from '../validators/role.validator';
|
|
|
|
/**
|
|
* GET /roles
|
|
* List all roles (all authenticated users)
|
|
*/
|
|
export async function getAllRoles(
|
|
_req: AuthenticatedRequest,
|
|
res: Response
|
|
): Promise<void> {
|
|
try {
|
|
const roles = await roleService.getAll();
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Roles retrieved successfully',
|
|
data: roles,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : 'Failed to retrieve roles';
|
|
res.status(500).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GET /roles/:id
|
|
* Get a single role by ID with user count (all authenticated users)
|
|
*/
|
|
export async function getRoleById(
|
|
req: AuthenticatedRequest,
|
|
res: Response
|
|
): Promise<void> {
|
|
try {
|
|
const roleId = req.params.id;
|
|
|
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
if (!uuidRegex.test(roleId)) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: 'Invalid role ID',
|
|
});
|
|
return;
|
|
}
|
|
|
|
const role = await roleService.getById(roleId);
|
|
|
|
if (!role) {
|
|
res.status(404).json({
|
|
success: false,
|
|
error: 'Role not found',
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Role retrieved successfully',
|
|
data: role,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : 'Failed to retrieve role';
|
|
res.status(500).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /roles
|
|
* Create a new role (admin only)
|
|
*/
|
|
export async function createRole(
|
|
req: AuthenticatedRequest,
|
|
res: Response
|
|
): Promise<void> {
|
|
try {
|
|
const data = req.body as CreateRoleInput;
|
|
|
|
const role = await roleService.create({
|
|
name: data.name,
|
|
description: data.description,
|
|
permissions: data.permissions as Record<string, unknown> | undefined,
|
|
});
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: 'Role created successfully',
|
|
data: role,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : 'Failed to create role';
|
|
|
|
if (message === 'Role name already exists') {
|
|
res.status(409).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PUT /roles/:id
|
|
* Update a role (admin only)
|
|
*/
|
|
export async function updateRole(
|
|
req: AuthenticatedRequest,
|
|
res: Response
|
|
): Promise<void> {
|
|
try {
|
|
const roleId = req.params.id;
|
|
|
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
if (!uuidRegex.test(roleId)) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: 'Invalid role ID',
|
|
});
|
|
return;
|
|
}
|
|
|
|
const data = req.body as UpdateRoleInput;
|
|
|
|
const role = await roleService.update(roleId, {
|
|
name: data.name,
|
|
description: data.description,
|
|
permissions: data.permissions as Record<string, unknown> | undefined,
|
|
});
|
|
|
|
if (!role) {
|
|
res.status(404).json({
|
|
success: false,
|
|
error: 'Role not found',
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Role updated successfully',
|
|
data: role,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : 'Failed to update role';
|
|
|
|
if (message === 'Role name already exists') {
|
|
res.status(409).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DELETE /roles/:id
|
|
* Delete a role (admin only, only if no users assigned)
|
|
*/
|
|
export async function deleteRole(
|
|
req: AuthenticatedRequest,
|
|
res: Response
|
|
): Promise<void> {
|
|
try {
|
|
const roleId = req.params.id;
|
|
|
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
if (!uuidRegex.test(roleId)) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: 'Invalid role ID',
|
|
});
|
|
return;
|
|
}
|
|
|
|
const deleted = await roleService.deleteRole(roleId);
|
|
|
|
if (!deleted) {
|
|
res.status(404).json({
|
|
success: false,
|
|
error: 'Role not found',
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Role deleted successfully',
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : 'Failed to delete role';
|
|
|
|
// Handle case where users are assigned to the role
|
|
if (message.includes('Cannot delete role')) {
|
|
res.status(409).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: message,
|
|
});
|
|
}
|
|
}
|