Files
pos-system/services/iam-service/src/modules/rbac/rbac.controller.ts

250 lines
6.2 KiB
TypeScript

import { Request, Response } from 'express';
import { z } from 'zod';
import { getErrorMessage } from '../../utils/error-utils';
import { rbacService } from './rbac.service';
const AssignRoleDto = z.object({
userId: z.string(),
roleId: z.string(),
expiresAt: z.string().optional(),
});
const GrantPermissionDto = z.object({
userId: z.string(),
permissionId: z.string(),
expiresAt: z.string().optional(),
});
/**
* EN: RBAC Controller
* VI: Controller RBAC
*/
export class RBACController {
/**
* EN: Get user permissions
* VI: Lấy quyền của người dùng
*/
async getUserPermissions(req: Request, res: Response): Promise<void> {
try {
const userId = (req as any).user?.id || (req as any).user?.sub || req.params.userId;
if (!userId) {
res.status(400).json({
success: false,
error: { code: 'USER_ID_REQUIRED', message: 'User ID required' },
});
return;
}
const permissions = await rbacService.getUserPermissions(userId);
const roles = await rbacService.getUserRoles(userId);
res.json({
success: true,
data: {
permissions,
roles,
},
});
} catch (error: unknown) {
res.status(500).json({
success: false,
error: {
code: 'GET_PERMISSIONS_FAILED',
message: getErrorMessage(error) || 'Failed to get permissions',
},
});
}
}
/**
* EN: Assign role to user
* VI: Gán role cho người dùng
*/
async assignRole(req: Request, res: Response): Promise<void> {
try {
const data = AssignRoleDto.parse(req.body);
const grantedBy = (req as any).user?.id || (req as any).user?.sub;
await rbacService.assignRole(data.userId, data.roleId, {
grantedBy,
expiresAt: data.expiresAt ? new Date(data.expiresAt) : undefined,
});
res.json({
success: true,
data: { message: 'Role assigned successfully' },
});
} catch (error: unknown) {
if (error instanceof z.ZodError) {
res.status(400).json({
success: false,
error: {
code: 'VALIDATION_ERROR',
message: 'Invalid input',
details: error.issues,
},
});
return;
}
res.status(500).json({
success: false,
error: {
code: 'ASSIGN_ROLE_FAILED',
message: getErrorMessage(error) || 'Failed to assign role',
},
});
}
}
/**
* EN: Revoke role from user
* VI: Thu hồi role từ người dùng
*/
async revokeRole(req: Request, res: Response): Promise<void> {
try {
const { userId, roleId } = req.body;
if (!userId || !roleId) {
res.status(400).json({
success: false,
error: { code: 'INVALID_INPUT', message: 'userId and roleId required' },
});
return;
}
await rbacService.revokeRole(userId, roleId);
res.json({
success: true,
data: { message: 'Role revoked successfully' },
});
} catch (error: unknown) {
res.status(500).json({
success: false,
error: {
code: 'REVOKE_ROLE_FAILED',
message: getErrorMessage(error) || 'Failed to revoke role',
},
});
}
}
/**
* EN: Grant permission to user
* VI: Cấp quyền cho người dùng
*/
async grantPermission(req: Request, res: Response): Promise<void> {
try {
const data = GrantPermissionDto.parse(req.body);
const grantedBy = (req as any).user?.id || (req as any).user?.sub;
await rbacService.grantPermission(data.userId, data.permissionId, {
grantedBy,
expiresAt: data.expiresAt ? new Date(data.expiresAt) : undefined,
});
res.json({
success: true,
data: { message: 'Permission granted successfully' },
});
} catch (error: unknown) {
if (error instanceof z.ZodError) {
res.status(400).json({
success: false,
error: {
code: 'VALIDATION_ERROR',
message: 'Invalid input',
details: error.issues,
},
});
return;
}
res.status(500).json({
success: false,
error: {
code: 'GRANT_PERMISSION_FAILED',
message: getErrorMessage(error) || 'Failed to grant permission',
},
});
}
}
/**
* EN: Check permission
* VI: Kiểm tra quyền
*/
async checkPermission(req: Request, res: Response): Promise<void> {
try {
const userId = (req as any).user?.id || (req as any).user?.sub;
const { resource, action, scope } = req.query;
if (!userId || !resource || !action) {
res.status(400).json({
success: false,
error: {
code: 'INVALID_INPUT',
message: 'userId, resource, and action are required',
},
});
return;
}
const hasPermission = await rbacService.hasPermission(
userId,
resource as string,
action as string,
scope as string | undefined
);
res.json({
success: true,
data: { hasPermission },
});
} catch (error: unknown) {
res.status(500).json({
success: false,
error: {
code: 'CHECK_PERMISSION_FAILED',
message: getErrorMessage(error) || 'Failed to check permission',
},
});
}
}
/**
* EN: Get all roles
* VI: Lấy tất cả roles
*/
async getRoles(req: Request, res: Response): Promise<void> {
res.status(501).json({
success: false,
error: {
code: 'NOT_IMPLEMENTED',
message: 'Get roles is not yet implemented / Lấy roles chưa được triển khai'
},
timestamp: new Date().toISOString()
});
}
/**
* EN: Create new role
* VI: Tạo role mới
*/
async createRole(req: Request, res: Response): Promise<void> {
res.status(501).json({
success: false,
error: {
code: 'NOT_IMPLEMENTED',
message: 'Create role is not yet implemented / Tạo role chưa được triển khai'
},
timestamp: new Date().toISOString()
});
}
}
export const rbacController = new RBACController();