refactor: chuẩn hóa xử lý lỗi bằng cách giới thiệu tiện ích getErrorMessage và cập nhật kiểu catch thành unknown.
This commit is contained in:
67
scripts/add-error-imports.py
Normal file
67
scripts/add-error-imports.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# Base directory
|
||||
base_dir = Path("/Users/velikho/Desktop/WORKING/Base/services/iam-service/src")
|
||||
|
||||
# Find all files that use getErrorMessage
|
||||
for root, dirs, files in os.walk(base_dir):
|
||||
# Skip test directories
|
||||
if '__tests__' in root or 'node_modules' in root:
|
||||
continue
|
||||
|
||||
for file in files:
|
||||
if not (file.endswith('.controller.ts') or file.endswith('.middleware.ts') or file.endswith('.service.ts')):
|
||||
continue
|
||||
if file.endswith('.test.ts') or file.endswith('.e2e.ts'):
|
||||
continue
|
||||
|
||||
filepath = Path(root) / file
|
||||
|
||||
# Read file content
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check if file uses getErrorMessage
|
||||
if 'getErrorMessage(' not in content:
|
||||
continue
|
||||
|
||||
# Check if import already exists
|
||||
if re.search(r'import.*getErrorMessage.*from.*error-utils', content):
|
||||
continue
|
||||
|
||||
# Calculate relative path
|
||||
rel_path = filepath.relative_to(base_dir)
|
||||
depth = len(rel_path.parts) - 1 # -1 for the file itself
|
||||
|
||||
# Build relative import path
|
||||
if depth == 1: # src/middlewares/
|
||||
import_path = '../utils/error-utils'
|
||||
elif depth == 2: # src/modules/xxx/
|
||||
import_path = '../../utils/error-utils'
|
||||
elif depth == 3: # src/modules/xxx/yyy/
|
||||
import_path = '../../../utils/error-utils'
|
||||
else:
|
||||
import_path = '../../utils/error-utils' # default
|
||||
|
||||
# Find the last import line
|
||||
lines = content.split('\n')
|
||||
last_import_idx = -1
|
||||
for i, line in enumerate(lines):
|
||||
if line.strip().startswith('import '):
|
||||
last_import_idx = i
|
||||
|
||||
if last_import_idx >= 0:
|
||||
# Insert new import after last import
|
||||
import_statement = f"import {{ getErrorMessage }} from '{import_path}';"
|
||||
lines.insert(last_import_idx + 1, import_statement)
|
||||
|
||||
# Write back
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
f.write('\n'.join(lines))
|
||||
|
||||
print(f"Added import to {filepath}")
|
||||
|
||||
print("Done!")
|
||||
42
scripts/add-error-imports.sh
Executable file
42
scripts/add-error-imports.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
# Script to add getErrorMessage import to files that use it
|
||||
|
||||
cd /Users/velikho/Desktop/WORKING/Base/services/iam-service/src
|
||||
|
||||
# Find all files that use getErrorMessage but don't have the import
|
||||
for file in $(find . \( -name "*.controller.ts" -o -name "*.middleware.ts" -o -name "*.service.ts" \) -not -path "*/__tests__/*" -not -name "*.test.ts" -exec grep -l "getErrorMessage" {} \;); do
|
||||
# Check if import already exists
|
||||
if ! grep -q "getErrorMessage.*from.*error-utils" "$file"; then
|
||||
# Calculate relative path to error-utils
|
||||
depth=$(echo "$file" | grep -o "/" | wc -l)
|
||||
if [ $depth -eq 2 ]; then
|
||||
# File is in src/modules/xxx/
|
||||
relative_path="../utils/error-utils"
|
||||
elif [ $depth -eq 3 ]; then
|
||||
# File is in src/modules/xxx/yyy/
|
||||
relative_path="../../utils/error-utils"
|
||||
elif [ $depth -eq 4 ]; then
|
||||
# File is in src/modules/xxx/yyy/zzz/
|
||||
relative_path="../../../utils/error-utils"
|
||||
else
|
||||
# Default to ../../utils/error-utils
|
||||
relative_path="../../utils/error-utils"
|
||||
fi
|
||||
|
||||
# Add import after the last import statement
|
||||
awk -v path="$relative_path" '
|
||||
/^import/ { last_import=NR }
|
||||
{ lines[NR]=$0 }
|
||||
END {
|
||||
for(i=1; i<=NR; i++) {
|
||||
print lines[i]
|
||||
if(i==last_import) {
|
||||
print "import { getErrorMessage } from \"" path "\";"
|
||||
}
|
||||
}
|
||||
}
|
||||
' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
|
||||
|
||||
echo "Added import to $file"
|
||||
fi
|
||||
done
|
||||
@@ -3,6 +3,7 @@ import { ApiResponse } from '@goodgo/types';
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
import { jwtService } from '../modules/token/jwt.service';
|
||||
import { getErrorMessage } from '../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Extended Request interface with user information
|
||||
@@ -97,9 +98,9 @@ export const authenticate = (_options: {
|
||||
});
|
||||
|
||||
next();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.warn('Authentication failed / Xác thực thất bại', {
|
||||
error: error.message,
|
||||
error: getErrorMessage(error),
|
||||
path: req.path,
|
||||
method: req.method,
|
||||
});
|
||||
@@ -239,11 +240,11 @@ export const optionalAuth = (_options: {
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
// EN: For optional auth, just continue without user info
|
||||
// VI: Với optional auth, chỉ tiếp tục mà không có thông tin user
|
||||
logger.debug('Optional authentication skipped / Xác thực tùy chọn bị bỏ qua', {
|
||||
reason: error.message,
|
||||
reason: getErrorMessage(error),
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { z } from 'zod';
|
||||
import { DateRangeDto, RiskFiltersDto } from '../access.dto';
|
||||
|
||||
import { accessAnalyticsService } from './analytics.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Access Analytics Controller
|
||||
@@ -27,7 +28,7 @@ export class AccessAnalyticsController {
|
||||
success: true,
|
||||
data: stats,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -44,7 +45,7 @@ export class AccessAnalyticsController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_USAGE_STATS_FAILED',
|
||||
message: error.message || 'Failed to get usage statistics',
|
||||
message: getErrorMessage(error) || 'Failed to get usage statistics',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -62,12 +63,12 @@ export class AccessAnalyticsController {
|
||||
success: true,
|
||||
data: distribution,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_PERMISSION_DISTRIBUTION_FAILED',
|
||||
message: error.message || 'Failed to get permission distribution',
|
||||
message: getErrorMessage(error) || 'Failed to get permission distribution',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -86,12 +87,12 @@ export class AccessAnalyticsController {
|
||||
success: true,
|
||||
data: summary,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_USER_SUMMARY_FAILED',
|
||||
message: error.message || 'Failed to get user access summary',
|
||||
message: getErrorMessage(error) || 'Failed to get user access summary',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -114,7 +115,7 @@ export class AccessAnalyticsController {
|
||||
success: true,
|
||||
data: trends,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -131,7 +132,7 @@ export class AccessAnalyticsController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_TRENDS_FAILED',
|
||||
message: error.message || 'Failed to get access trends',
|
||||
message: getErrorMessage(error) || 'Failed to get access trends',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -156,7 +157,7 @@ export class AccessAnalyticsController {
|
||||
success: true,
|
||||
data: analysis,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -173,7 +174,7 @@ export class AccessAnalyticsController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_RISK_ANALYSIS_FAILED',
|
||||
message: error.message || 'Failed to get risk analysis',
|
||||
message: getErrorMessage(error) || 'Failed to get risk analysis',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError, BadRequestError } from '../../../errors/http-error';
|
||||
import { CreateAccessRequestDto, ApproveAccessRequestDto, RejectAccessRequestDto } from '../access.dto';
|
||||
|
||||
import { accessRequestService } from './request.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Access Request Controller
|
||||
@@ -36,12 +37,12 @@ export class AccessRequestController {
|
||||
success: true,
|
||||
data: requests,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_REQUESTS_FAILED',
|
||||
message: error.message || 'Failed to list access requests',
|
||||
message: getErrorMessage(error) || 'Failed to list access requests',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -73,7 +74,7 @@ export class AccessRequestController {
|
||||
data: request,
|
||||
message: 'Access request created successfully / Yêu cầu truy cập đã được tạo thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -90,7 +91,7 @@ export class AccessRequestController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CREATE_REQUEST_FAILED',
|
||||
message: error.message || 'Failed to create access request',
|
||||
message: getErrorMessage(error) || 'Failed to create access request',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -109,7 +110,7 @@ export class AccessRequestController {
|
||||
success: true,
|
||||
data: request,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -119,7 +120,7 @@ export class AccessRequestController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_REQUEST_FAILED',
|
||||
message: error.message || 'Failed to get access request',
|
||||
message: getErrorMessage(error) || 'Failed to get access request',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -152,7 +153,7 @@ export class AccessRequestController {
|
||||
data: request,
|
||||
message: 'Access request approved successfully / Yêu cầu truy cập đã được phê duyệt thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -174,7 +175,7 @@ export class AccessRequestController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'APPROVE_REQUEST_FAILED',
|
||||
message: error.message || 'Failed to approve access request',
|
||||
message: getErrorMessage(error) || 'Failed to approve access request',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -207,7 +208,7 @@ export class AccessRequestController {
|
||||
data: request,
|
||||
message: 'Access request rejected / Yêu cầu truy cập đã bị từ chối',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -229,7 +230,7 @@ export class AccessRequestController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REJECT_REQUEST_FAILED',
|
||||
message: error.message || 'Failed to reject access request',
|
||||
message: getErrorMessage(error) || 'Failed to reject access request',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -260,7 +261,7 @@ export class AccessRequestController {
|
||||
success: true,
|
||||
message: 'Access request cancelled successfully / Yêu cầu truy cập đã được hủy thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof BadRequestError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -270,7 +271,7 @@ export class AccessRequestController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CANCEL_REQUEST_FAILED',
|
||||
message: error.message || 'Failed to cancel access request',
|
||||
message: getErrorMessage(error) || 'Failed to cancel access request',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -300,12 +301,12 @@ export class AccessRequestController {
|
||||
success: true,
|
||||
data: requests,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_PENDING_APPROVALS_FAILED',
|
||||
message: error.message || 'Failed to get pending approvals',
|
||||
message: getErrorMessage(error) || 'Failed to get pending approvals',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError, BadRequestError } from '../../../errors/http-error';
|
||||
import { CreateAccessReviewDto, ReviewAccessItemDto } from '../access.dto';
|
||||
|
||||
import { accessReviewService } from './review.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Access Review Controller
|
||||
@@ -24,12 +25,12 @@ export class AccessReviewController {
|
||||
success: true,
|
||||
data: reviews,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_REVIEWS_FAILED',
|
||||
message: error.message || 'Failed to list reviews',
|
||||
message: getErrorMessage(error) || 'Failed to list reviews',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -61,7 +62,7 @@ export class AccessReviewController {
|
||||
data: review,
|
||||
message: 'Access review created successfully / Đánh giá truy cập đã được tạo thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -83,7 +84,7 @@ export class AccessReviewController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CREATE_REVIEW_FAILED',
|
||||
message: error.message || 'Failed to create review',
|
||||
message: getErrorMessage(error) || 'Failed to create review',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -102,7 +103,7 @@ export class AccessReviewController {
|
||||
success: true,
|
||||
data: review,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -112,7 +113,7 @@ export class AccessReviewController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_REVIEW_FAILED',
|
||||
message: error.message || 'Failed to get review',
|
||||
message: getErrorMessage(error) || 'Failed to get review',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -132,7 +133,7 @@ export class AccessReviewController {
|
||||
data: review,
|
||||
message: 'Access review started successfully / Đánh giá truy cập đã được bắt đầu thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof BadRequestError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -142,7 +143,7 @@ export class AccessReviewController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'START_REVIEW_FAILED',
|
||||
message: error.message || 'Failed to start review',
|
||||
message: getErrorMessage(error) || 'Failed to start review',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -162,7 +163,7 @@ export class AccessReviewController {
|
||||
data: review,
|
||||
message: 'Access review completed successfully / Đánh giá truy cập đã được hoàn thành thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof BadRequestError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -172,7 +173,7 @@ export class AccessReviewController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'COMPLETE_REVIEW_FAILED',
|
||||
message: error.message || 'Failed to complete review',
|
||||
message: getErrorMessage(error) || 'Failed to complete review',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -191,12 +192,12 @@ export class AccessReviewController {
|
||||
success: true,
|
||||
data: items,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_REVIEW_ITEMS_FAILED',
|
||||
message: error.message || 'Failed to get review items',
|
||||
message: getErrorMessage(error) || 'Failed to get review items',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -229,7 +230,7 @@ export class AccessReviewController {
|
||||
data: item,
|
||||
message: 'Review item updated successfully / Item đánh giá đã được cập nhật thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -251,7 +252,7 @@ export class AccessReviewController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REVIEW_ITEM_FAILED',
|
||||
message: error.message || 'Failed to review item',
|
||||
message: getErrorMessage(error) || 'Failed to review item',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { z } from 'zod';
|
||||
|
||||
import { RegisterDto, LoginDto } from './auth.dto';
|
||||
import { authService } from './auth.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,7 +36,7 @@ export class AuthController {
|
||||
tokens: result.tokens,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -52,7 +53,7 @@ export class AuthController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REGISTRATION_FAILED',
|
||||
message: error.message || 'Registration failed',
|
||||
message: getErrorMessage(error) || 'Registration failed',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -92,7 +93,7 @@ export class AuthController {
|
||||
tokens: result.tokens,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -109,7 +110,7 @@ export class AuthController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LOGIN_FAILED',
|
||||
message: error.message || 'Login failed',
|
||||
message: getErrorMessage(error) || 'Login failed',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -137,12 +138,12 @@ export class AuthController {
|
||||
success: true,
|
||||
data: { message: 'Logged out successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LOGOUT_FAILED',
|
||||
message: error.message || 'Logout failed',
|
||||
message: getErrorMessage(error) || 'Logout failed',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -178,12 +179,12 @@ export class AuthController {
|
||||
success: true,
|
||||
data: result,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(401).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REFRESH_FAILED',
|
||||
message: error.message || 'Token refresh failed',
|
||||
message: getErrorMessage(error) || 'Token refresh failed',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
||||
|
||||
import { ChangePasswordDto } from './auth.dto';
|
||||
import { changePasswordService } from './change-password.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Change Password Controller
|
||||
@@ -38,7 +39,7 @@ export class ChangePasswordController {
|
||||
success: true,
|
||||
data: { message: 'Password changed successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -55,7 +56,7 @@ export class ChangePasswordController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CHANGE_PASSWORD_FAILED',
|
||||
message: error.message || 'Failed to change password',
|
||||
message: getErrorMessage(error) || 'Failed to change password',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { logger } from '@goodgo/logger';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
import { DatabaseError } from '../../errors/http-error';
|
||||
import { formatErrorForLogging, hasCode } from '../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Base repository class providing common database operations
|
||||
@@ -30,8 +31,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`${this.modelName} ${entity ? 'found' : 'not found'} / ${this.modelName} ${entity ? 'đã tìm thấy' : 'không tìm thấy'}`, { id });
|
||||
return entity;
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to find ${this.modelName} by ID / Không thể tìm ${this.modelName} theo ID`, { error, id });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`Failed to find ${this.modelName} by ID / Không thể tìm ${this.modelName} theo ID`, { ...formatErrorForLogging(error), id });
|
||||
throw new DatabaseError(`Failed to find ${this.modelName}`, { id, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -40,7 +41,7 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
* EN: Find entity by unique field
|
||||
* VI: Tìm entity theo field duy nhất
|
||||
*/
|
||||
async findByUnique(field: string, value: any): Promise<T | null> {
|
||||
async findByUnique(field: string, value: unknown): Promise<T | null> {
|
||||
try {
|
||||
logger.debug(`Finding ${this.modelName} by ${field} / Tìm ${this.modelName} theo ${field}`, { field, value });
|
||||
|
||||
@@ -50,8 +51,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`${this.modelName} ${entity ? 'found' : 'not found'} / ${this.modelName} ${entity ? 'đã tìm thấy' : 'không tìm thấy'}`, { field, value });
|
||||
return entity;
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to find ${this.modelName} by ${field} / Không thể tìm ${this.modelName} theo ${field}`, { error, field, value });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`Failed to find ${this.modelName} by ${field} / Không thể tìm ${this.modelName} theo ${field}`, { ...formatErrorForLogging(error), field, value });
|
||||
throw new DatabaseError(`Failed to find ${this.modelName}`, { field, value, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -74,8 +75,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`Found ${entities.length} ${this.modelName} entities / Đã tìm thấy ${entities.length} ${this.modelName} entities`);
|
||||
return entities;
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to find all ${this.modelName} / Không thể tìm tất cả ${this.modelName}`, { error, options });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`Failed to find all ${this.modelName} / Không thể tìm tất cả ${this.modelName}`, { ...formatErrorForLogging(error), options });
|
||||
throw new DatabaseError(`Failed to find ${this.modelName} entities`, { options, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -94,8 +95,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`${this.modelName} created successfully / ${this.modelName} đã được tạo thành công`, { id: (entity as any).id });
|
||||
return entity;
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to create ${this.modelName} / Không thể tạo ${this.modelName}`, { error, data });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`Failed to create ${this.modelName} / Không thể tạo ${this.modelName}`, { ...formatErrorForLogging(error), data });
|
||||
throw new DatabaseError(`Failed to create ${this.modelName}`, { data, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -115,12 +116,12 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`${this.modelName} updated successfully / ${this.modelName} đã được cập nhật thành công`, { id });
|
||||
return entity;
|
||||
} catch (error: any) {
|
||||
if (error.code === 'P2025') {
|
||||
} catch (error: unknown) {
|
||||
if (hasCode(error) && error.code === 'P2025') {
|
||||
logger.warn(`${this.modelName} not found for update / ${this.modelName} không tìm thấy để cập nhật`, { id });
|
||||
throw new DatabaseError(`${this.modelName} not found`, { id });
|
||||
}
|
||||
logger.error(`Failed to update ${this.modelName} / Không thể cập nhật ${this.modelName}`, { error, id, data });
|
||||
logger.error(`Failed to update ${this.modelName} / Không thể cập nhật ${this.modelName}`, { ...formatErrorForLogging(error), id, data });
|
||||
throw new DatabaseError(`Failed to update ${this.modelName}`, { id, data, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -139,12 +140,12 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`${this.modelName} deleted successfully / ${this.modelName} đã được xóa thành công`, { id });
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
if (error.code === 'P2025') {
|
||||
} catch (error: unknown) {
|
||||
if (hasCode(error) && error.code === 'P2025') {
|
||||
logger.warn(`${this.modelName} not found for deletion / ${this.modelName} không tìm thấy để xóa`, { id });
|
||||
throw new DatabaseError(`${this.modelName} not found`, { id });
|
||||
}
|
||||
logger.error(`Failed to delete ${this.modelName} / Không thể xóa ${this.modelName}`, { error, id });
|
||||
logger.error(`Failed to delete ${this.modelName} / Không thể xóa ${this.modelName}`, { ...formatErrorForLogging(error), id });
|
||||
throw new DatabaseError(`Failed to delete ${this.modelName}`, { id, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -163,8 +164,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`Counted ${count} ${this.modelName} entities / Đã đếm ${count} ${this.modelName} entities`);
|
||||
return count;
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to count ${this.modelName} / Không thể đếm ${this.modelName}`, { error, where });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`Failed to count ${this.modelName} / Không thể đếm ${this.modelName}`, { ...formatErrorForLogging(error), where });
|
||||
throw new DatabaseError(`Failed to count ${this.modelName}`, { where, originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -177,8 +178,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
try {
|
||||
const count = await this.count({ id });
|
||||
return count > 0;
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to check if ${this.modelName} exists / Không thể kiểm tra ${this.modelName} có tồn tại`, { error, id });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`Failed to check if ${this.modelName} exists / Không thể kiểm tra ${this.modelName} có tồn tại`, { ...formatErrorForLogging(error), id });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -197,8 +198,8 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
|
||||
logger.debug(`${this.modelName} transaction completed successfully / Transaction ${this.modelName} đã hoàn thành thành công`);
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
logger.error(`${this.modelName} transaction failed / Transaction ${this.modelName} thất bại`, { error });
|
||||
} catch (error: unknown) {
|
||||
logger.error(`${this.modelName} transaction failed / Transaction ${this.modelName} thất bại`, formatErrorForLogging(error));
|
||||
throw new DatabaseError(`${this.modelName} transaction failed`, { originalError: error });
|
||||
}
|
||||
}
|
||||
@@ -210,7 +211,7 @@ export abstract class BaseRepository<T, CreateInput, UpdateInput> {
|
||||
*/
|
||||
export interface IRepository<T, CreateInput, UpdateInput> {
|
||||
findById(id: string): Promise<T | null>;
|
||||
findByUnique(field: string, value: any): Promise<T | null>;
|
||||
findByUnique(field: string, value: unknown): Promise<T | null>;
|
||||
findAll(options?: any): Promise<T[]>;
|
||||
create(data: CreateInput): Promise<T>;
|
||||
update(id: string, data: UpdateInput): Promise<T>;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Request, Response } from 'express';
|
||||
import { asyncHandler } from '../../middlewares/error.middleware';
|
||||
|
||||
import { FeatureService } from './feature.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
|
||||
/**
|
||||
@@ -83,12 +84,12 @@ export class FeatureController {
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
res.json(response);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'FEATURE_004',
|
||||
message: error.message || 'Failed to retrieve feature / Không thể lấy feature',
|
||||
message: getErrorMessage(error) || 'Failed to retrieve feature / Không thể lấy feature',
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
@@ -112,12 +113,12 @@ export class FeatureController {
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
res.json(response);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'FEATURE_005',
|
||||
message: error.message || 'Failed to update feature / Không thể cập nhật feature',
|
||||
message: getErrorMessage(error) || 'Failed to update feature / Không thể cập nhật feature',
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
@@ -139,12 +140,12 @@ export class FeatureController {
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
res.json(response);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'FEATURE_006',
|
||||
message: error.message || 'Failed to delete feature / Không thể xóa feature',
|
||||
message: getErrorMessage(error) || 'Failed to delete feature / Không thể xóa feature',
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
@@ -167,12 +168,12 @@ export class FeatureController {
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
res.json(response);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'FEATURE_007',
|
||||
message: error.message || 'Failed to toggle feature / Không thể chuyển đổi feature',
|
||||
message: getErrorMessage(error) || 'Failed to toggle feature / Không thể chuyển đổi feature',
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { logger } from '@goodgo/logger';
|
||||
import { prisma } from '../../config/database.config';
|
||||
import { ConflictError } from '../../errors/http-error';
|
||||
import { BaseRepository, IRepository } from '../common/repository';
|
||||
import { hasCode } from '../../utils/error-utils';
|
||||
|
||||
// EN: Feature entity type from Prisma
|
||||
// VI: Feature entity type từ Prisma
|
||||
@@ -11,7 +12,7 @@ type Feature = {
|
||||
name: string;
|
||||
title: string | null;
|
||||
description: string | null;
|
||||
config: any;
|
||||
config: Record<string, unknown>;
|
||||
enabled: boolean;
|
||||
version: string | null;
|
||||
tags: string[];
|
||||
@@ -25,14 +26,14 @@ type CreateFeatureInput = {
|
||||
name: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
config?: any;
|
||||
config?: Record<string, unknown>;
|
||||
tags?: string[];
|
||||
};
|
||||
|
||||
type UpdateFeatureInput = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
config?: any;
|
||||
config?: Record<string, unknown>;
|
||||
enabled?: boolean;
|
||||
tags?: string[];
|
||||
};
|
||||
@@ -229,8 +230,8 @@ export class FeatureRepository extends BaseRepository<Feature, CreateFeatureInpu
|
||||
* EN: Handle database-specific errors
|
||||
* VI: Xử lý lỗi database-specific
|
||||
*/
|
||||
private handleDatabaseError(error: any, context?: any) {
|
||||
if (error.code === 'P2002') {
|
||||
private handleDatabaseError(error: unknown, context?: unknown) {
|
||||
if (hasCode(error) && error.code === 'P2002') {
|
||||
return new ConflictError('Feature with this name already exists / Feature với tên này đã tồn tại', context);
|
||||
}
|
||||
return error;
|
||||
|
||||
@@ -13,7 +13,7 @@ export class FeatureService {
|
||||
* EN: Create a new feature
|
||||
* VI: Tạo một feature mới
|
||||
*/
|
||||
async create(data: { name: string; title?: string; description?: string; config?: any; tags?: string[] }) {
|
||||
async create(data: { name: string; title?: string; description?: string; config?: Record<string, unknown>; tags?: string[] }) {
|
||||
logger.info('Creating feature / Tạo feature', { data });
|
||||
|
||||
const feature = await featureRepository.create(data);
|
||||
@@ -77,7 +77,7 @@ export class FeatureService {
|
||||
* EN: Update feature
|
||||
* VI: Cập nhật feature
|
||||
*/
|
||||
async update(id: string, data: Partial<{ title?: string; description?: string; config?: any; enabled?: boolean; tags?: string[] }>) {
|
||||
async update(id: string, data: Partial<{ title?: string; description?: string; config?: Record<string, unknown>; enabled?: boolean; tags?: string[] }>) {
|
||||
logger.info('Updating feature / Cập nhật feature', { id, data });
|
||||
|
||||
const feature = await featureRepository.update(id, data);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError, BadRequestError } from '../../../errors/http-error';
|
||||
import { GenerateComplianceReportDto, ReportFiltersDto } from '../governance.dto';
|
||||
|
||||
import { complianceService } from './compliance.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Compliance Controller
|
||||
@@ -39,7 +40,7 @@ export class ComplianceController {
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -56,7 +57,7 @@ export class ComplianceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_REPORTS_FAILED',
|
||||
message: error.message || 'Failed to list reports',
|
||||
message: getErrorMessage(error) || 'Failed to list reports',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -97,7 +98,7 @@ export class ComplianceController {
|
||||
data: report,
|
||||
message: 'Compliance report generated successfully / Báo cáo tuân thủ đã được tạo thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -119,7 +120,7 @@ export class ComplianceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GENERATE_REPORT_FAILED',
|
||||
message: error.message || 'Failed to generate report',
|
||||
message: getErrorMessage(error) || 'Failed to generate report',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -138,7 +139,7 @@ export class ComplianceController {
|
||||
success: true,
|
||||
data: report,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -148,7 +149,7 @@ export class ComplianceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_REPORT_FAILED',
|
||||
message: error.message || 'Failed to get report',
|
||||
message: getErrorMessage(error) || 'Failed to get report',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -182,7 +183,7 @@ export class ComplianceController {
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -192,7 +193,7 @@ export class ComplianceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'EXPORT_REPORT_FAILED',
|
||||
message: error.message || 'Failed to export report',
|
||||
message: getErrorMessage(error) || 'Failed to export report',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -212,7 +213,7 @@ export class ComplianceController {
|
||||
data: report,
|
||||
message: 'Report published successfully / Báo cáo đã được xuất bản thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -222,7 +223,7 @@ export class ComplianceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'PUBLISH_REPORT_FAILED',
|
||||
message: error.message || 'Failed to publish report',
|
||||
message: getErrorMessage(error) || 'Failed to publish report',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError } from '../../../errors/http-error';
|
||||
import { CreatePolicyTemplateDto, TestPolicyDto } from '../governance.dto';
|
||||
|
||||
import { policyGovernanceService } from './policy-governance.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Policy Governance Controller
|
||||
@@ -24,12 +25,12 @@ export class PolicyGovernanceController {
|
||||
success: true,
|
||||
data: templates,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_TEMPLATES_FAILED',
|
||||
message: error.message || 'Failed to get templates',
|
||||
message: getErrorMessage(error) || 'Failed to get templates',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -49,7 +50,7 @@ export class PolicyGovernanceController {
|
||||
data: template,
|
||||
message: 'Policy template created successfully / Template policy đã được tạo thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -66,7 +67,7 @@ export class PolicyGovernanceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CREATE_TEMPLATE_FAILED',
|
||||
message: error.message || 'Failed to create template',
|
||||
message: getErrorMessage(error) || 'Failed to create template',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -85,7 +86,7 @@ export class PolicyGovernanceController {
|
||||
success: true,
|
||||
data: versions,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -95,7 +96,7 @@ export class PolicyGovernanceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_VERSIONS_FAILED',
|
||||
message: error.message || 'Failed to get policy versions',
|
||||
message: getErrorMessage(error) || 'Failed to get policy versions',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -115,7 +116,7 @@ export class PolicyGovernanceController {
|
||||
success: true,
|
||||
data: result,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -137,7 +138,7 @@ export class PolicyGovernanceController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'TEST_POLICY_FAILED',
|
||||
message: error.message || 'Failed to test policy',
|
||||
message: getErrorMessage(error) || 'Failed to test policy',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { z } from 'zod';
|
||||
import { AccessSummaryFiltersDto, UserActivityFiltersDto, SecurityEventsFiltersDto } from '../governance.dto';
|
||||
|
||||
import { reportingService } from './reporting.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Reporting Controller
|
||||
@@ -28,7 +29,7 @@ export class ReportingController {
|
||||
success: true,
|
||||
data: summary,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -45,7 +46,7 @@ export class ReportingController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_ACCESS_SUMMARY_FAILED',
|
||||
message: error.message || 'Failed to get access summary',
|
||||
message: getErrorMessage(error) || 'Failed to get access summary',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -70,7 +71,7 @@ export class ReportingController {
|
||||
success: true,
|
||||
data: activity,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -87,7 +88,7 @@ export class ReportingController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_USER_ACTIVITY_FAILED',
|
||||
message: error.message || 'Failed to get user activity',
|
||||
message: getErrorMessage(error) || 'Failed to get user activity',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -121,7 +122,7 @@ export class ReportingController {
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -138,7 +139,7 @@ export class ReportingController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_SECURITY_EVENTS_FAILED',
|
||||
message: error.message || 'Failed to get security events',
|
||||
message: getErrorMessage(error) || 'Failed to get security events',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -156,12 +157,12 @@ export class ReportingController {
|
||||
success: true,
|
||||
data: status,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_COMPLIANCE_STATUS_FAILED',
|
||||
message: error.message || 'Failed to get compliance status',
|
||||
message: getErrorMessage(error) || 'Failed to get compliance status',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -179,12 +180,12 @@ export class ReportingController {
|
||||
success: true,
|
||||
data: overview,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_RISK_OVERVIEW_FAILED',
|
||||
message: error.message || 'Failed to get risk overview',
|
||||
message: getErrorMessage(error) || 'Failed to get risk overview',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { NotFoundError } from '../../../errors/http-error';
|
||||
import { CalculateRiskScoreDto, RiskFiltersDto } from '../governance.dto';
|
||||
|
||||
import { riskService } from './risk.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Risk Management Controller
|
||||
@@ -41,7 +42,7 @@ export class RiskController {
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -58,7 +59,7 @@ export class RiskController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_RISK_SCORES_FAILED',
|
||||
message: error.message || 'Failed to list risk scores',
|
||||
message: getErrorMessage(error) || 'Failed to list risk scores',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -77,7 +78,7 @@ export class RiskController {
|
||||
success: true,
|
||||
data: score,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -87,7 +88,7 @@ export class RiskController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_RISK_SCORE_FAILED',
|
||||
message: error.message || 'Failed to get risk score',
|
||||
message: getErrorMessage(error) || 'Failed to get risk score',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -107,7 +108,7 @@ export class RiskController {
|
||||
data: score,
|
||||
message: 'Risk score calculated successfully / Điểm rủi ro đã được tính thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -129,7 +130,7 @@ export class RiskController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CALCULATE_RISK_SCORE_FAILED',
|
||||
message: error.message || 'Failed to calculate risk score',
|
||||
message: getErrorMessage(error) || 'Failed to calculate risk score',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -170,12 +171,12 @@ export class RiskController {
|
||||
totalUsers: allScores.length,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_DASHBOARD_FAILED',
|
||||
message: error.message || 'Failed to get risk dashboard',
|
||||
message: getErrorMessage(error) || 'Failed to get risk dashboard',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError, ConflictError } from '../../../errors/http-error';
|
||||
import { CreateGroupDto, UpdateGroupDto, AddGroupMemberDto } from '../identity.dto';
|
||||
|
||||
import { groupService } from './group.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Group Controller
|
||||
@@ -24,12 +25,12 @@ export class GroupController {
|
||||
success: true,
|
||||
data: groups,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_GROUPS_FAILED',
|
||||
message: error.message || 'Failed to list groups',
|
||||
message: getErrorMessage(error) || 'Failed to list groups',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -50,7 +51,7 @@ export class GroupController {
|
||||
data: group,
|
||||
message: 'Group created successfully / Nhóm đã được tạo thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -72,7 +73,7 @@ export class GroupController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CREATE_GROUP_FAILED',
|
||||
message: error.message || 'Failed to create group',
|
||||
message: getErrorMessage(error) || 'Failed to create group',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -91,7 +92,7 @@ export class GroupController {
|
||||
success: true,
|
||||
data: group,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -101,7 +102,7 @@ export class GroupController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_GROUP_FAILED',
|
||||
message: error.message || 'Failed to get group',
|
||||
message: getErrorMessage(error) || 'Failed to get group',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -122,7 +123,7 @@ export class GroupController {
|
||||
data: group,
|
||||
message: 'Group updated successfully / Nhóm đã được cập nhật thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -144,7 +145,7 @@ export class GroupController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'UPDATE_GROUP_FAILED',
|
||||
message: error.message || 'Failed to update group',
|
||||
message: getErrorMessage(error) || 'Failed to update group',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -163,7 +164,7 @@ export class GroupController {
|
||||
success: true,
|
||||
message: 'Group deleted successfully / Nhóm đã được xóa thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof ConflictError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -173,7 +174,7 @@ export class GroupController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DELETE_GROUP_FAILED',
|
||||
message: error.message || 'Failed to delete group',
|
||||
message: getErrorMessage(error) || 'Failed to delete group',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -192,12 +193,12 @@ export class GroupController {
|
||||
success: true,
|
||||
data: members,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_GROUP_MEMBERS_FAILED',
|
||||
message: error.message || 'Failed to get group members',
|
||||
message: getErrorMessage(error) || 'Failed to get group members',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -219,7 +220,7 @@ export class GroupController {
|
||||
success: true,
|
||||
message: 'Member added successfully / Thành viên đã được thêm thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -241,7 +242,7 @@ export class GroupController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'ADD_MEMBER_FAILED',
|
||||
message: error.message || 'Failed to add member',
|
||||
message: getErrorMessage(error) || 'Failed to add member',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -260,7 +261,7 @@ export class GroupController {
|
||||
success: true,
|
||||
message: 'Member removed successfully / Thành viên đã được xóa thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -270,7 +271,7 @@ export class GroupController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REMOVE_MEMBER_FAILED',
|
||||
message: error.message || 'Failed to remove member',
|
||||
message: getErrorMessage(error) || 'Failed to remove member',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError, ConflictError } from '../../../errors/http-error';
|
||||
import { CreateOrganizationDto, UpdateOrganizationDto } from '../identity.dto';
|
||||
|
||||
import { organizationService } from './organization.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Organization Controller
|
||||
@@ -33,12 +34,12 @@ export class OrganizationController {
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_ORGANIZATIONS_FAILED',
|
||||
message: error.message || 'Failed to list organizations',
|
||||
message: getErrorMessage(error) || 'Failed to list organizations',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -58,7 +59,7 @@ export class OrganizationController {
|
||||
data: organization,
|
||||
message: 'Organization created successfully / Tổ chức đã được tạo thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -80,7 +81,7 @@ export class OrganizationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CREATE_ORGANIZATION_FAILED',
|
||||
message: error.message || 'Failed to create organization',
|
||||
message: getErrorMessage(error) || 'Failed to create organization',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -99,7 +100,7 @@ export class OrganizationController {
|
||||
success: true,
|
||||
data: organization,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -109,7 +110,7 @@ export class OrganizationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_ORGANIZATION_FAILED',
|
||||
message: error.message || 'Failed to get organization',
|
||||
message: getErrorMessage(error) || 'Failed to get organization',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -130,7 +131,7 @@ export class OrganizationController {
|
||||
data: organization,
|
||||
message: 'Organization updated successfully / Tổ chức đã được cập nhật thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -152,7 +153,7 @@ export class OrganizationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'UPDATE_ORGANIZATION_FAILED',
|
||||
message: error.message || 'Failed to update organization',
|
||||
message: getErrorMessage(error) || 'Failed to update organization',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -171,7 +172,7 @@ export class OrganizationController {
|
||||
success: true,
|
||||
message: 'Organization deleted successfully / Tổ chức đã được xóa thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof ConflictError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -181,7 +182,7 @@ export class OrganizationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DELETE_ORGANIZATION_FAILED',
|
||||
message: error.message || 'Failed to delete organization',
|
||||
message: getErrorMessage(error) || 'Failed to delete organization',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -210,7 +211,7 @@ export class OrganizationController {
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -220,7 +221,7 @@ export class OrganizationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_ORGANIZATION_USERS_FAILED',
|
||||
message: error.message || 'Failed to get organization users',
|
||||
message: getErrorMessage(error) || 'Failed to get organization users',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError } from '../../../errors/http-error';
|
||||
import { UpdateUserProfileDto } from '../identity.dto';
|
||||
|
||||
import { profileService } from './profile.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Profile Management Controller
|
||||
@@ -35,12 +36,12 @@ export class ProfileController {
|
||||
success: true,
|
||||
data: profile,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_PROFILE_FAILED',
|
||||
message: error.message || 'Failed to get profile',
|
||||
message: getErrorMessage(error) || 'Failed to get profile',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -61,7 +62,7 @@ export class ProfileController {
|
||||
data: profile,
|
||||
message: 'Profile updated successfully / Profile đã được cập nhật thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -83,7 +84,7 @@ export class ProfileController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'UPDATE_PROFILE_FAILED',
|
||||
message: error.message || 'Failed to update profile',
|
||||
message: getErrorMessage(error) || 'Failed to update profile',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -116,7 +117,7 @@ export class ProfileController {
|
||||
data: profile,
|
||||
message: 'Avatar uploaded successfully / Avatar đã được upload thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -126,7 +127,7 @@ export class ProfileController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'UPLOAD_AVATAR_FAILED',
|
||||
message: error.message || 'Failed to upload avatar',
|
||||
message: getErrorMessage(error) || 'Failed to upload avatar',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -146,7 +147,7 @@ export class ProfileController {
|
||||
data: profile,
|
||||
message: 'Avatar deleted successfully / Avatar đã được xóa thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -156,7 +157,7 @@ export class ProfileController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DELETE_AVATAR_FAILED',
|
||||
message: error.message || 'Failed to delete avatar',
|
||||
message: getErrorMessage(error) || 'Failed to delete avatar',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NotFoundError } from '../../../errors/http-error';
|
||||
import { UpdateUserDto, UserFiltersDto, BulkImportUsersDto } from '../identity.dto';
|
||||
|
||||
import { userManagementService } from './user.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: User Management Controller
|
||||
@@ -39,7 +40,7 @@ export class UserManagementController {
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -56,7 +57,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'LIST_USERS_FAILED',
|
||||
message: error.message || 'Failed to list users',
|
||||
message: getErrorMessage(error) || 'Failed to list users',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -75,7 +76,7 @@ export class UserManagementController {
|
||||
success: true,
|
||||
data: user,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -85,7 +86,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_USER_FAILED',
|
||||
message: error.message || 'Failed to get user',
|
||||
message: getErrorMessage(error) || 'Failed to get user',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -106,7 +107,7 @@ export class UserManagementController {
|
||||
data: user,
|
||||
message: 'User updated successfully / User đã được cập nhật thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -128,7 +129,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'UPDATE_USER_FAILED',
|
||||
message: error.message || 'Failed to update user',
|
||||
message: getErrorMessage(error) || 'Failed to update user',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -147,7 +148,7 @@ export class UserManagementController {
|
||||
success: true,
|
||||
message: 'User deleted successfully / User đã được xóa thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -157,7 +158,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DELETE_USER_FAILED',
|
||||
message: error.message || 'Failed to delete user',
|
||||
message: getErrorMessage(error) || 'Failed to delete user',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -177,7 +178,7 @@ export class UserManagementController {
|
||||
data: user,
|
||||
message: 'User deactivated successfully / User đã được vô hiệu hóa thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -187,7 +188,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DEACTIVATE_USER_FAILED',
|
||||
message: error.message || 'Failed to deactivate user',
|
||||
message: getErrorMessage(error) || 'Failed to deactivate user',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -207,7 +208,7 @@ export class UserManagementController {
|
||||
data: user,
|
||||
message: 'User reactivated successfully / User đã được kích hoạt lại thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError) {
|
||||
res.status(404).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -217,7 +218,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REACTIVATE_USER_FAILED',
|
||||
message: error.message || 'Failed to reactivate user',
|
||||
message: getErrorMessage(error) || 'Failed to reactivate user',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -237,7 +238,7 @@ export class UserManagementController {
|
||||
data: result,
|
||||
message: `Imported ${result.created} users successfully / Đã import ${result.created} users thành công`,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -254,7 +255,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'BULK_IMPORT_FAILED',
|
||||
message: error.message || 'Failed to import users',
|
||||
message: getErrorMessage(error) || 'Failed to import users',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -284,7 +285,7 @@ export class UserManagementController {
|
||||
exportedAt: new Date().toISOString(),
|
||||
total: users.length,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -301,7 +302,7 @@ export class UserManagementController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'BULK_EXPORT_FAILED',
|
||||
message: error.message || 'Failed to export users',
|
||||
message: getErrorMessage(error) || 'Failed to export users',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { NotFoundError, ConflictError } from '../../../errors/http-error';
|
||||
import { UserProfileRepository } from '../../../repositories/user-profile.repository';
|
||||
import { UserRepository } from '../../../repositories/user.repository';
|
||||
import { UpdateUserDto, UserFiltersDto, BulkImportUsersDto } from '../identity.dto';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: User Management Service for user lifecycle operations
|
||||
@@ -246,8 +247,8 @@ export class UserManagementService {
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
errors.push({ email: userData.email, error: error.message });
|
||||
} catch (error: unknown) {
|
||||
errors.push({ email: userData.email, error: getErrorMessage(error) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { BadRequestError, NotFoundError } from '../../../errors/http-error';
|
||||
import { VerifyEmailDto, VerifyPhoneDto } from '../identity.dto';
|
||||
|
||||
import { verificationService } from './verification.service';
|
||||
import { getErrorMessage } from '../../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Identity Verification Controller
|
||||
@@ -36,7 +37,7 @@ export class VerificationController {
|
||||
data: result,
|
||||
message: 'Verification email sent / Email xác thực đã được gửi',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof BadRequestError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -46,7 +47,7 @@ export class VerificationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REQUEST_VERIFICATION_FAILED',
|
||||
message: error.message || 'Failed to request verification',
|
||||
message: getErrorMessage(error) || 'Failed to request verification',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -66,7 +67,7 @@ export class VerificationController {
|
||||
data: result,
|
||||
message: 'Email verified successfully / Email đã được xác thực thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -88,7 +89,7 @@ export class VerificationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'VERIFY_EMAIL_FAILED',
|
||||
message: error.message || 'Failed to verify email',
|
||||
message: getErrorMessage(error) || 'Failed to verify email',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -132,7 +133,7 @@ export class VerificationController {
|
||||
data: result,
|
||||
message: 'Verification code sent / Mã xác thực đã được gửi',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NotFoundError || error instanceof BadRequestError) {
|
||||
res.status(error.statusCode).json(error.toApiResponse());
|
||||
return;
|
||||
@@ -142,7 +143,7 @@ export class VerificationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REQUEST_PHONE_VERIFICATION_FAILED',
|
||||
message: error.message || 'Failed to request phone verification',
|
||||
message: getErrorMessage(error) || 'Failed to request phone verification',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -162,7 +163,7 @@ export class VerificationController {
|
||||
data: result,
|
||||
message: 'Phone verified successfully / Điện thoại đã được xác thực thành công',
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -184,7 +185,7 @@ export class VerificationController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'VERIFY_PHONE_FAILED',
|
||||
message: error.message || 'Failed to verify phone',
|
||||
message: getErrorMessage(error) || 'Failed to verify phone',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -216,12 +217,12 @@ export class VerificationController {
|
||||
success: true,
|
||||
data: status,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_VERIFICATION_STATUS_FAILED',
|
||||
message: error.message || 'Failed to get verification status',
|
||||
message: getErrorMessage(error) || 'Failed to get verification status',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response } from 'express';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { mfaService } from './mfa.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
const VerifyTOTPDto = z.object({
|
||||
token: z.string().length(6),
|
||||
@@ -38,12 +39,12 @@ export class MFAController {
|
||||
message: 'Scan QR code with authenticator app and verify with token',
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'ENABLE_TOTP_FAILED',
|
||||
message: error.message || 'Failed to enable TOTP',
|
||||
message: getErrorMessage(error) || 'Failed to enable TOTP',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -80,7 +81,7 @@ export class MFAController {
|
||||
error: { code: 'INVALID_TOKEN', message: 'Invalid TOTP token' },
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -97,7 +98,7 @@ export class MFAController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'VERIFY_TOTP_FAILED',
|
||||
message: error.message || 'Failed to verify TOTP',
|
||||
message: getErrorMessage(error) || 'Failed to verify TOTP',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -133,7 +134,7 @@ export class MFAController {
|
||||
error: { code: 'INVALID_TOKEN', message: 'Invalid TOTP token' },
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -150,7 +151,7 @@ export class MFAController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'VERIFY_TOTP_FAILED',
|
||||
message: error.message || 'Failed to verify TOTP',
|
||||
message: getErrorMessage(error) || 'Failed to verify TOTP',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -178,12 +179,12 @@ export class MFAController {
|
||||
success: true,
|
||||
data: { message: 'MFA disabled successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DISABLE_MFA_FAILED',
|
||||
message: error.message || 'Failed to disable MFA',
|
||||
message: getErrorMessage(error) || 'Failed to disable MFA',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -217,12 +218,12 @@ export class MFAController {
|
||||
createdAt: d.createdAt,
|
||||
})),
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_MFA_DEVICES_FAILED',
|
||||
message: error.message || 'Failed to get MFA devices',
|
||||
message: getErrorMessage(error) || 'Failed to get MFA devices',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { logger } from '@goodgo/logger';
|
||||
import { Request, Response } from 'express';
|
||||
|
||||
import { oidcProviderService } from './oidc-provider.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: OIDC Controller
|
||||
@@ -16,7 +17,7 @@ export class OIDCController {
|
||||
try {
|
||||
const discovery = oidcProviderService.getDiscoveryDocument();
|
||||
res.json(discovery);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('OIDC discovery failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
@@ -70,7 +71,7 @@ export class OIDCController {
|
||||
}
|
||||
|
||||
res.redirect(redirectUrl.toString());
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('OIDC authorization failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
@@ -115,13 +116,13 @@ export class OIDCController {
|
||||
token_type: 'Bearer',
|
||||
expires_in: 900, // 15 minutes
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('OIDC token exchange failed', { error });
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'TOKEN_EXCHANGE_FAILED',
|
||||
message: error.message || 'Token exchange failed',
|
||||
message: getErrorMessage(error) || 'Token exchange failed',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -170,7 +171,7 @@ export class OIDCController {
|
||||
name: user.username,
|
||||
updated_at: Math.floor(user.updatedAt.getTime() / 1000),
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('OIDC userinfo failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
@@ -190,7 +191,7 @@ export class OIDCController {
|
||||
try {
|
||||
const jwks = oidcProviderService.getJWKS();
|
||||
res.json(jwks);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('OIDC JWKS failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response } from 'express';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { rbacService } from './rbac.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
const AssignRoleDto = z.object({
|
||||
userId: z.string(),
|
||||
@@ -46,12 +47,12 @@ export class RBACController {
|
||||
roles,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_PERMISSIONS_FAILED',
|
||||
message: error.message || 'Failed to get permissions',
|
||||
message: getErrorMessage(error) || 'Failed to get permissions',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -75,7 +76,7 @@ export class RBACController {
|
||||
success: true,
|
||||
data: { message: 'Role assigned successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -92,7 +93,7 @@ export class RBACController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'ASSIGN_ROLE_FAILED',
|
||||
message: error.message || 'Failed to assign role',
|
||||
message: getErrorMessage(error) || 'Failed to assign role',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -120,12 +121,12 @@ export class RBACController {
|
||||
success: true,
|
||||
data: { message: 'Role revoked successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REVOKE_ROLE_FAILED',
|
||||
message: error.message || 'Failed to revoke role',
|
||||
message: getErrorMessage(error) || 'Failed to revoke role',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -149,7 +150,7 @@ export class RBACController {
|
||||
success: true,
|
||||
data: { message: 'Permission granted successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
@@ -166,7 +167,7 @@ export class RBACController {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GRANT_PERMISSION_FAILED',
|
||||
message: error.message || 'Failed to grant permission',
|
||||
message: getErrorMessage(error) || 'Failed to grant permission',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -203,12 +204,12 @@ export class RBACController {
|
||||
success: true,
|
||||
data: { hasPermission },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'CHECK_PERMISSION_FAILED',
|
||||
message: error.message || 'Failed to check permission',
|
||||
message: getErrorMessage(error) || 'Failed to check permission',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Request, Response } from 'express';
|
||||
|
||||
import { sessionService } from './session.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Sessions Controller
|
||||
@@ -36,12 +37,12 @@ export class SessionsController {
|
||||
expiresAt: s.expiresAt,
|
||||
})),
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'GET_SESSIONS_FAILED',
|
||||
message: error.message || 'Failed to get sessions',
|
||||
message: getErrorMessage(error) || 'Failed to get sessions',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -70,12 +71,12 @@ export class SessionsController {
|
||||
success: true,
|
||||
data: { message: 'Session revoked successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REVOKE_SESSION_FAILED',
|
||||
message: error.message || 'Failed to revoke session',
|
||||
message: getErrorMessage(error) || 'Failed to revoke session',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -103,12 +104,12 @@ export class SessionsController {
|
||||
success: true,
|
||||
data: { message: 'All sessions revoked successfully' },
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'REVOKE_ALL_SESSIONS_FAILED',
|
||||
message: error.message || 'Failed to revoke all sessions',
|
||||
message: getErrorMessage(error) || 'Failed to revoke all sessions',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { cookieService } from '../token/cookie.service';
|
||||
import { jwtService } from '../token/jwt.service';
|
||||
|
||||
import { socialAuthService } from './social.service';
|
||||
import { getErrorMessage } from '../../utils/error-utils';
|
||||
|
||||
/**
|
||||
* EN: Social Auth Controller
|
||||
@@ -24,7 +25,7 @@ export class SocialAuthController {
|
||||
const provider = new GoogleProvider();
|
||||
const url = provider.getAuthorizationUrl();
|
||||
res.redirect(url);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('Google auth initiation failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
@@ -84,9 +85,9 @@ export class SocialAuthController {
|
||||
|
||||
// Redirect to frontend
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/callback?token=${tokens.accessToken}`);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('Google callback failed', { error });
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/error?message=${encodeURIComponent(error.message)}`);
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/error?message=${encodeURIComponent(getErrorMessage(error))}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +101,7 @@ export class SocialAuthController {
|
||||
const provider = new FacebookProvider();
|
||||
const url = provider.getAuthorizationUrl();
|
||||
res.redirect(url);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('Facebook auth initiation failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
@@ -154,9 +155,9 @@ export class SocialAuthController {
|
||||
});
|
||||
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/callback?token=${tokens.accessToken}`);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('Facebook callback failed', { error });
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/error?message=${encodeURIComponent(error.message)}`);
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/error?message=${encodeURIComponent(getErrorMessage(error))}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +171,7 @@ export class SocialAuthController {
|
||||
const provider = new GitHubProvider();
|
||||
const url = provider.getAuthorizationUrl();
|
||||
res.redirect(url);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('GitHub auth initiation failed', { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
@@ -224,9 +225,9 @@ export class SocialAuthController {
|
||||
});
|
||||
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/callback?token=${tokens.accessToken}`);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
logger.error('GitHub callback failed', { error });
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/error?message=${encodeURIComponent(error.message)}`);
|
||||
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/auth/error?message=${encodeURIComponent(getErrorMessage(error))}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export class JWTService {
|
||||
* EN: Verify ID token (OIDC)
|
||||
* VI: Xác thực ID token (OIDC)
|
||||
*/
|
||||
verifyIdToken(token: string, expectedAudience: string): any {
|
||||
verifyIdToken(token: string, expectedAudience: string): unknown {
|
||||
try {
|
||||
const decoded = verify(token, jwtConfig.idSecret, {
|
||||
issuer: jwtConfig.issuer,
|
||||
@@ -226,7 +226,7 @@ export class JWTService {
|
||||
* EN: Decode token without verification (for debugging)
|
||||
* VI: Giải mã token không xác thực (để debug)
|
||||
*/
|
||||
decodeToken(token: string): any {
|
||||
decodeToken(token: string): unknown {
|
||||
return decode(token);
|
||||
}
|
||||
|
||||
|
||||
107
services/iam-service/src/utils/error-utils.ts
Normal file
107
services/iam-service/src/utils/error-utils.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* EN: Error handling utilities for type-safe error handling
|
||||
* VI: Tiện ích xử lý lỗi cho xử lý lỗi type-safe
|
||||
*/
|
||||
|
||||
/**
|
||||
* EN: Type guard to check if error is an Error instance
|
||||
* VI: Type guard để kiểm tra xem error có phải là Error instance không
|
||||
*/
|
||||
export function isError(error: unknown): error is Error {
|
||||
return error instanceof Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Type guard to check if error has a message property
|
||||
* VI: Type guard để kiểm tra xem error có property message không
|
||||
*/
|
||||
export function hasMessage(error: unknown): error is { message: string } {
|
||||
return (
|
||||
typeof error === 'object' &&
|
||||
error !== null &&
|
||||
'message' in error &&
|
||||
typeof (error as { message: unknown }).message === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Type guard to check if error has a code property
|
||||
* VI: Type guard để kiểm tra xem error có property code không
|
||||
*/
|
||||
export function hasCode(error: unknown): error is { code: string } {
|
||||
return (
|
||||
typeof error === 'object' &&
|
||||
error !== null &&
|
||||
'code' in error &&
|
||||
typeof (error as { code: unknown }).code === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Get error message from unknown error
|
||||
* VI: Lấy error message từ unknown error
|
||||
*/
|
||||
export function getErrorMessage(error: unknown): string {
|
||||
if (isError(error)) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
if (hasMessage(error)) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
}
|
||||
|
||||
return 'Unknown error occurred';
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Get error code from unknown error
|
||||
* VI: Lấy error code từ unknown error
|
||||
*/
|
||||
export function getErrorCode(error: unknown): string | undefined {
|
||||
if (hasCode(error)) {
|
||||
return error.code;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Format error for logging
|
||||
* VI: Format error để logging
|
||||
*/
|
||||
export function formatErrorForLogging(error: unknown): {
|
||||
message: string;
|
||||
code?: string;
|
||||
stack?: string;
|
||||
details?: unknown;
|
||||
} {
|
||||
const message = getErrorMessage(error);
|
||||
const code = getErrorCode(error);
|
||||
|
||||
const formatted: {
|
||||
message: string;
|
||||
code?: string;
|
||||
stack?: string;
|
||||
details?: unknown;
|
||||
} = { message };
|
||||
|
||||
if (code) {
|
||||
formatted.code = code;
|
||||
}
|
||||
|
||||
if (isError(error) && error.stack) {
|
||||
formatted.stack = error.stack;
|
||||
}
|
||||
|
||||
// EN: Include original error for debugging
|
||||
// VI: Bao gồm error gốc để debug
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
formatted.details = error;
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
Reference in New Issue
Block a user