refactor: Cập nhật cấu hình các tuyến đường (routes) của dịch vụ IAM và API xác thực phía client, đồng thời loại bỏ tệp sao lưu RBAC cũ.
This commit is contained in:
@@ -69,7 +69,7 @@ export const authApi = {
|
||||
* VI: Lấy hồ sơ người dùng đã xác thực hiện tại
|
||||
*/
|
||||
getMe: async (): Promise<ApiResponse<UserResponse>> => {
|
||||
return apiClient.get('/users/me');
|
||||
return apiClient.get('/identity/profile');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -104,17 +104,17 @@ export const authApi = {
|
||||
// EN: Set the token in the client
|
||||
// VI: Đặt token trong client
|
||||
apiClient.setAuthToken(accessToken);
|
||||
|
||||
|
||||
// EN: Fetch user profile to complete authentication
|
||||
// VI: Lấy thông tin user để hoàn tất xác thực
|
||||
const userResponse = await apiClient.get('/users/me');
|
||||
|
||||
const userResponse = await apiClient.get('/identity/profile');
|
||||
|
||||
if (userResponse.success && userResponse.data) {
|
||||
// EN: Store refresh token if available (OAuth might not provide refresh token)
|
||||
// VI: Lưu refresh token nếu có (OAuth có thể không cung cấp refresh token)
|
||||
// Note: For OAuth, we only have access token, refresh token handling depends on backend
|
||||
// Ghi chú: Đối với OAuth, chúng ta chỉ có access token, xử lý refresh token phụ thuộc vào backend
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
@@ -125,7 +125,7 @@ export const authApi = {
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
throw new Error('Failed to fetch user profile / Không thể lấy thông tin người dùng');
|
||||
},
|
||||
|
||||
|
||||
@@ -33,14 +33,26 @@ app.use(
|
||||
cors({
|
||||
origin: appConfig.corsOrigin,
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-correlation-id', 'x-request-id'],
|
||||
exposedHeaders: ['x-correlation-id'],
|
||||
})
|
||||
);
|
||||
|
||||
// EN: Rate limiting
|
||||
// VI: Giới hạn số lượng request
|
||||
// EN: Rate limiting (more permissive for development)
|
||||
// VI: Giới hạn số lượng request (cho phép nhiều hơn trong development)
|
||||
const limiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000,
|
||||
max: 100,
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: appConfig.nodeEnv === 'production' ? 100 : 1000, // 1000 for dev, 100 for prod
|
||||
message: {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'RATE_LIMIT_EXCEEDED',
|
||||
message: 'Too many requests, please try again later',
|
||||
},
|
||||
},
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
});
|
||||
app.use('/api', limiter);
|
||||
|
||||
|
||||
@@ -615,5 +615,43 @@ export const createGovernanceRouter = (): Router => {
|
||||
*/
|
||||
router.get('/reports/risk-overview', authenticate(), requirePermission('governance', 'read'), reportingController.riskOverview.bind(reportingController));
|
||||
|
||||
// =============================================================================
|
||||
// EN: Alias Routes (for backward compatibility)
|
||||
// VI: Routes Alias (để tương thích ngược)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/governance/audit-logs:
|
||||
* get:
|
||||
* summary: Get audit logs (stub)
|
||||
* description: Get audit logs - not yet implemented
|
||||
* tags: [Governance]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
*/
|
||||
router.get('/audit-logs', authenticate(), requirePermission('governance', 'read'), (req, res) => {
|
||||
res.status(501).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'NOT_IMPLEMENTED',
|
||||
message: 'Audit logs endpoint is not yet implemented / Endpoint audit logs chưa được triển khai'
|
||||
},
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/governance/compliance:
|
||||
* get:
|
||||
* summary: Get compliance status (alias)
|
||||
* description: Alias for /reports/compliance-status
|
||||
* tags: [Governance]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
*/
|
||||
router.get('/compliance', authenticate(), requirePermission('governance', 'read'), reportingController.complianceStatus.bind(reportingController));
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
@@ -1248,5 +1248,53 @@ export const createIdentityRouter = (): Router => {
|
||||
*/
|
||||
router.delete('/groups/:id/members/:userId', authenticate(), requirePermission('identity', 'update'), groupController.removeMember.bind(groupController));
|
||||
|
||||
// =============================================================================
|
||||
// EN: Alias Routes (for backward compatibility)
|
||||
// VI: Routes Alias (để tương thích ngược)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/identity/users:
|
||||
* post:
|
||||
* summary: Create user (stub)
|
||||
* description: Create a new user - not yet implemented
|
||||
* tags: [Identity - Users]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
*/
|
||||
router.post('/users', authenticate(), requirePermission('identity', 'create'), (req, res) => {
|
||||
res.status(501).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'NOT_IMPLEMENTED',
|
||||
message: 'Create user endpoint is not yet implemented / Endpoint tạo người dùng chưa được triển khai'
|
||||
},
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/identity/profile:
|
||||
* get:
|
||||
* summary: Get current user profile
|
||||
* description: Get profile of currently authenticated user
|
||||
* tags: [Identity - Profile]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
*/
|
||||
router.get('/profile', authenticate(), (req, res) => {
|
||||
const userId = (req as any).user?.id || (req as any).user?.sub;
|
||||
if (!userId) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: { code: 'UNAUTHORIZED', message: 'Authentication required' }
|
||||
});
|
||||
}
|
||||
// Redirect to /users/:id/profile
|
||||
return res.redirect(`/api/v1/identity/users/${userId}/profile`);
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
@@ -216,5 +216,34 @@ export const createMfaRouter = (): Router => {
|
||||
*/
|
||||
router.get('/devices', authenticate(), mfaController.getMFADevices.bind(mfaController));
|
||||
|
||||
// =============================================================================
|
||||
// EN: Alias Routes (for backward compatibility)
|
||||
// VI: Routes Alias (để tương thích ngược)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/mfa/setup:
|
||||
* post:
|
||||
* summary: Setup MFA (alias for /totp/enable)
|
||||
* description: Alias endpoint for setting up MFA
|
||||
* tags: [MFA]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
*/
|
||||
router.post('/setup', authenticate(), mfaController.enableTOTP.bind(mfaController));
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/mfa/verify:
|
||||
* post:
|
||||
* summary: Verify MFA (alias for /totp/verify)
|
||||
* description: Alias endpoint for verifying MFA code
|
||||
* tags: [MFA]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
*/
|
||||
router.post('/verify', authenticate(), mfaController.verifyAndEnableTOTP.bind(mfaController));
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import { authenticate } from '../../middlewares/auth.middleware';
|
||||
import { requirePermission } from '../../middlewares/rbac.middleware';
|
||||
import { rbacController } from './rbac.controller';
|
||||
|
||||
/**
|
||||
* EN: Create and configure RBAC routes
|
||||
* VI: Tạo và cấu hình routes cho RBAC
|
||||
*/
|
||||
export const createRbacRouter = (): Router => {
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/rbac/permissions:
|
||||
* get:
|
||||
* summary: Get user permissions
|
||||
* description: Get list of permissions assigned to the current user
|
||||
* tags: [RBAC]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: version
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* default: v1
|
||||
* description: API version
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Permissions retrieved successfully
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* allOf:
|
||||
* - $ref: '#/components/schemas/ApiResponse'
|
||||
* - type: object
|
||||
* properties:
|
||||
* data:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get('/permissions', authenticate(), rbacController.getUserPermissions.bind(rbacController));
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/rbac/roles/assign:
|
||||
* post:
|
||||
* summary: Assign role to user
|
||||
* description: Assign a specific role to a user. Requires 'rbac:assign' permission.
|
||||
* tags: [RBAC]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: version
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* default: v1
|
||||
* description: API version
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [userId, roleId]
|
||||
* properties:
|
||||
* userId:
|
||||
* type: string
|
||||
* roleId:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Role assigned successfully
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/ApiResponse'
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
* 403:
|
||||
* description: Forbidden - Insufficient permissions
|
||||
* 404:
|
||||
* description: User or Role not found
|
||||
*/
|
||||
router.post('/roles/assign', authenticate(), requirePermission('rbac', 'assign'), rbacController.assignRole.bind(rbacController));
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/rbac/roles/revoke:
|
||||
* post:
|
||||
* summary: Revoke role from user
|
||||
* description: Revoke a specific role from a user. Requires 'rbac:revoke' permission.
|
||||
* tags: [RBAC]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: version
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* default: v1
|
||||
* description: API version
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [userId, roleId]
|
||||
* properties:
|
||||
* userId:
|
||||
* type: string
|
||||
* roleId:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Role revoked successfully
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/ApiResponse'
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
* 403:
|
||||
* description: Forbidden - Insufficient permissions
|
||||
* 404:
|
||||
* description: User or Role not found
|
||||
*/
|
||||
router.post('/roles/revoke', authenticate(), requirePermission('rbac', 'revoke'), rbacController.revokeRole.bind(rbacController));
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/rbac/permissions/grant:
|
||||
* post:
|
||||
* summary: Grant permission to role
|
||||
* description: Grant a specific permission to a role. Requires 'rbac:grant' permission.
|
||||
* tags: [RBAC]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: version
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* default: v1
|
||||
* description: API version
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [roleId, permissionId]
|
||||
* properties:
|
||||
* roleId:
|
||||
* type: string
|
||||
* permissionId:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Permission granted successfully
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/ApiResponse'
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
* 403:
|
||||
* description: Forbidden - Insufficient permissions
|
||||
* 404:
|
||||
* description: Role or Permission not found
|
||||
*/
|
||||
router.post('/permissions/grant', authenticate(), requirePermission('rbac', 'grant'), rbacController.grantPermission.bind(rbacController));
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/{version}/rbac/permissions/check:
|
||||
* get:
|
||||
* summary: Check permission
|
||||
* description: Check if the current user has a specific permission
|
||||
* tags: [RBAC]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: version
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* default: v1
|
||||
* description: API version
|
||||
* - in: query
|
||||
* name: resource
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* - in: query
|
||||
* name: action
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Permission check result
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* allOf:
|
||||
* - $ref: '#/components/schemas/ApiResponse'
|
||||
* - type: object
|
||||
* properties:
|
||||
* data:
|
||||
* type: object
|
||||
* properties:
|
||||
* allowed:
|
||||
* type: boolean
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
* 403:
|
||||
* description: Forbidden
|
||||
*/
|
||||
router.get('/permissions/check', authenticate(), rbacController.checkPermission.bind(rbacController));
|
||||
|
||||
return router;
|
||||
};
|
||||
Reference in New Issue
Block a user