koa-boot-runtime 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aiToolRegistry.d.ts +32 -0
- package/dist/aiToolRegistry.d.ts.map +1 -0
- package/dist/aiToolRegistry.js +41 -0
- package/dist/aiToolRegistry.js.map +1 -0
- package/dist/build/routes.d.ts +3 -0
- package/dist/build/routes.d.ts.map +1 -0
- package/dist/build/routes.js +4055 -0
- package/dist/build/routes.js.map +1 -0
- package/dist/build/swagger.json +6752 -0
- package/dist/common/decorators/index.d.ts +2 -0
- package/dist/common/decorators/index.d.ts.map +1 -0
- package/dist/common/decorators/index.js +18 -0
- package/dist/common/decorators/index.js.map +1 -0
- package/dist/common/decorators/validation.d.ts +33 -0
- package/dist/common/decorators/validation.d.ts.map +1 -0
- package/dist/common/decorators/validation.js +215 -0
- package/dist/common/decorators/validation.js.map +1 -0
- package/dist/common/dto.d.ts +17 -0
- package/dist/common/dto.d.ts.map +1 -0
- package/dist/common/dto.js +28 -0
- package/dist/common/dto.js.map +1 -0
- package/dist/common/enums/base.d.ts +14 -0
- package/dist/common/enums/base.d.ts.map +1 -0
- package/dist/common/enums/base.js +14 -0
- package/dist/common/enums/base.js.map +1 -0
- package/dist/common/enums/index.d.ts +8 -0
- package/dist/common/enums/index.d.ts.map +1 -0
- package/dist/common/enums/index.js +24 -0
- package/dist/common/enums/index.js.map +1 -0
- package/dist/common/enums/system.d.ts +14 -0
- package/dist/common/enums/system.d.ts.map +1 -0
- package/dist/common/enums/system.js +14 -0
- package/dist/common/enums/system.js.map +1 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +25 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/paginate.d.ts +49 -0
- package/dist/common/paginate.d.ts.map +1 -0
- package/dist/common/paginate.js +47 -0
- package/dist/common/paginate.js.map +1 -0
- package/dist/common/types/index.d.ts +8 -0
- package/dist/common/types/index.d.ts.map +1 -0
- package/dist/common/types/index.js +18 -0
- package/dist/common/types/index.js.map +1 -0
- package/dist/common/types/pagination.d.ts +76 -0
- package/dist/common/types/pagination.d.ts.map +1 -0
- package/dist/common/types/pagination.js +29 -0
- package/dist/common/types/pagination.js.map +1 -0
- package/dist/common/types/request.d.ts +66 -0
- package/dist/common/types/request.d.ts.map +1 -0
- package/dist/common/types/request.js +4 -0
- package/dist/common/types/request.js.map +1 -0
- package/dist/common/types/response.d.ts +109 -0
- package/dist/common/types/response.d.ts.map +1 -0
- package/dist/common/types/response.js +50 -0
- package/dist/common/types/response.js.map +1 -0
- package/dist/common/types/sort.d.ts +71 -0
- package/dist/common/types/sort.d.ts.map +1 -0
- package/dist/common/types/sort.js +46 -0
- package/dist/common/types/sort.js.map +1 -0
- package/dist/config/database.d.ts +12 -0
- package/dist/config/database.d.ts.map +1 -0
- package/dist/config/database.js +24 -0
- package/dist/config/database.js.map +1 -0
- package/dist/config/index.d.ts +144 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +180 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/ioc.d.ts +6 -0
- package/dist/config/ioc.d.ts.map +1 -0
- package/dist/config/ioc.js +29 -0
- package/dist/config/ioc.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +3 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +52 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/errorHandler.d.ts +3 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +40 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/logger.d.ts +3 -0
- package/dist/middleware/logger.d.ts.map +1 -0
- package/dist/middleware/logger.js +13 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware/operationLogger.d.ts +11 -0
- package/dist/middleware/operationLogger.d.ts.map +1 -0
- package/dist/middleware/operationLogger.js +155 -0
- package/dist/middleware/operationLogger.js.map +1 -0
- package/dist/middleware/permission.d.ts +23 -0
- package/dist/middleware/permission.d.ts.map +1 -0
- package/dist/middleware/permission.js +153 -0
- package/dist/middleware/permission.js.map +1 -0
- package/dist/middleware/validate.d.ts +7 -0
- package/dist/middleware/validate.d.ts.map +1 -0
- package/dist/middleware/validate.js +53 -0
- package/dist/middleware/validate.js.map +1 -0
- package/dist/middlewares.d.ts +15 -0
- package/dist/middlewares.d.ts.map +1 -0
- package/dist/middlewares.js +24 -0
- package/dist/middlewares.js.map +1 -0
- package/dist/registerRoutes.d.ts +15 -0
- package/dist/registerRoutes.d.ts.map +1 -0
- package/dist/registerRoutes.js +83 -0
- package/dist/registerRoutes.js.map +1 -0
- package/dist/system/department/department.controller.d.ts +46 -0
- package/dist/system/department/department.controller.d.ts.map +1 -0
- package/dist/system/department/department.controller.js +203 -0
- package/dist/system/department/department.controller.js.map +1 -0
- package/dist/system/department/department.model.d.ts +33 -0
- package/dist/system/department/department.model.d.ts.map +1 -0
- package/dist/system/department/department.model.js +171 -0
- package/dist/system/department/department.model.js.map +1 -0
- package/dist/system/department/department.service.d.ts +40 -0
- package/dist/system/department/department.service.d.ts.map +1 -0
- package/dist/system/department/department.service.js +99 -0
- package/dist/system/department/department.service.js.map +1 -0
- package/dist/system/dictItem/dictItem.controller.d.ts +42 -0
- package/dist/system/dictItem/dictItem.controller.d.ts.map +1 -0
- package/dist/system/dictItem/dictItem.controller.js +167 -0
- package/dist/system/dictItem/dictItem.controller.js.map +1 -0
- package/dist/system/dictItem/dictItem.model.d.ts +38 -0
- package/dist/system/dictItem/dictItem.model.d.ts.map +1 -0
- package/dist/system/dictItem/dictItem.model.js +180 -0
- package/dist/system/dictItem/dictItem.model.js.map +1 -0
- package/dist/system/dictItem/dictItem.service.d.ts +33 -0
- package/dist/system/dictItem/dictItem.service.d.ts.map +1 -0
- package/dist/system/dictItem/dictItem.service.js +97 -0
- package/dist/system/dictItem/dictItem.service.js.map +1 -0
- package/dist/system/dictType/dictType.controller.d.ts +47 -0
- package/dist/system/dictType/dictType.controller.d.ts.map +1 -0
- package/dist/system/dictType/dictType.controller.js +174 -0
- package/dist/system/dictType/dictType.controller.js.map +1 -0
- package/dist/system/dictType/dictType.model.d.ts +31 -0
- package/dist/system/dictType/dictType.model.d.ts.map +1 -0
- package/dist/system/dictType/dictType.model.js +127 -0
- package/dist/system/dictType/dictType.model.js.map +1 -0
- package/dist/system/dictType/dictType.service.d.ts +27 -0
- package/dist/system/dictType/dictType.service.d.ts.map +1 -0
- package/dist/system/dictType/dictType.service.js +74 -0
- package/dist/system/dictType/dictType.service.js.map +1 -0
- package/dist/system/employee/employee.controller.d.ts +16 -0
- package/dist/system/employee/employee.controller.d.ts.map +1 -0
- package/dist/system/employee/employee.controller.js +111 -0
- package/dist/system/employee/employee.controller.js.map +1 -0
- package/dist/system/employee/employee.model.d.ts +34 -0
- package/dist/system/employee/employee.model.d.ts.map +1 -0
- package/dist/system/employee/employee.model.js +186 -0
- package/dist/system/employee/employee.model.js.map +1 -0
- package/dist/system/employee/employee.service.d.ts +16 -0
- package/dist/system/employee/employee.service.d.ts.map +1 -0
- package/dist/system/employee/employee.service.js +49 -0
- package/dist/system/employee/employee.service.js.map +1 -0
- package/dist/system/fileUpload/fileUpload.controller.d.ts +35 -0
- package/dist/system/fileUpload/fileUpload.controller.d.ts.map +1 -0
- package/dist/system/fileUpload/fileUpload.controller.js +228 -0
- package/dist/system/fileUpload/fileUpload.controller.js.map +1 -0
- package/dist/system/fileUpload/fileUpload.model.d.ts +13 -0
- package/dist/system/fileUpload/fileUpload.model.d.ts.map +1 -0
- package/dist/system/fileUpload/fileUpload.model.js +71 -0
- package/dist/system/fileUpload/fileUpload.model.js.map +1 -0
- package/dist/system/fileUpload/fileUpload.service.d.ts +29 -0
- package/dist/system/fileUpload/fileUpload.service.d.ts.map +1 -0
- package/dist/system/fileUpload/fileUpload.service.js +61 -0
- package/dist/system/fileUpload/fileUpload.service.js.map +1 -0
- package/dist/system/loginLog/loginLog.controller.d.ts +21 -0
- package/dist/system/loginLog/loginLog.controller.d.ts.map +1 -0
- package/dist/system/loginLog/loginLog.controller.js +149 -0
- package/dist/system/loginLog/loginLog.controller.js.map +1 -0
- package/dist/system/loginLog/loginLog.model.d.ts +26 -0
- package/dist/system/loginLog/loginLog.model.d.ts.map +1 -0
- package/dist/system/loginLog/loginLog.model.js +150 -0
- package/dist/system/loginLog/loginLog.model.js.map +1 -0
- package/dist/system/loginLog/loginLog.service.d.ts +24 -0
- package/dist/system/loginLog/loginLog.service.d.ts.map +1 -0
- package/dist/system/loginLog/loginLog.service.js +87 -0
- package/dist/system/loginLog/loginLog.service.js.map +1 -0
- package/dist/system/menu/menu.controller.d.ts +46 -0
- package/dist/system/menu/menu.controller.d.ts.map +1 -0
- package/dist/system/menu/menu.controller.js +203 -0
- package/dist/system/menu/menu.controller.js.map +1 -0
- package/dist/system/menu/menu.model.d.ts +45 -0
- package/dist/system/menu/menu.model.d.ts.map +1 -0
- package/dist/system/menu/menu.model.js +254 -0
- package/dist/system/menu/menu.model.js.map +1 -0
- package/dist/system/menu/menu.service.d.ts +40 -0
- package/dist/system/menu/menu.service.d.ts.map +1 -0
- package/dist/system/menu/menu.service.js +101 -0
- package/dist/system/menu/menu.service.js.map +1 -0
- package/dist/system/operationLog/operationLog.controller.d.ts +34 -0
- package/dist/system/operationLog/operationLog.controller.d.ts.map +1 -0
- package/dist/system/operationLog/operationLog.controller.js +126 -0
- package/dist/system/operationLog/operationLog.controller.js.map +1 -0
- package/dist/system/operationLog/operationLog.model.d.ts +38 -0
- package/dist/system/operationLog/operationLog.model.d.ts.map +1 -0
- package/dist/system/operationLog/operationLog.model.js +224 -0
- package/dist/system/operationLog/operationLog.model.js.map +1 -0
- package/dist/system/operationLog/operationLog.service.d.ts +46 -0
- package/dist/system/operationLog/operationLog.service.d.ts.map +1 -0
- package/dist/system/operationLog/operationLog.service.js +109 -0
- package/dist/system/operationLog/operationLog.service.js.map +1 -0
- package/dist/system/permission/permission.controller.d.ts +18 -0
- package/dist/system/permission/permission.controller.d.ts.map +1 -0
- package/dist/system/permission/permission.controller.js +160 -0
- package/dist/system/permission/permission.controller.js.map +1 -0
- package/dist/system/permission/permission.model.d.ts +39 -0
- package/dist/system/permission/permission.model.d.ts.map +1 -0
- package/dist/system/permission/permission.model.js +220 -0
- package/dist/system/permission/permission.model.js.map +1 -0
- package/dist/system/permission/permission.service.d.ts +40 -0
- package/dist/system/permission/permission.service.d.ts.map +1 -0
- package/dist/system/permission/permission.service.js +105 -0
- package/dist/system/permission/permission.service.js.map +1 -0
- package/dist/system/role/role.controller.d.ts +16 -0
- package/dist/system/role/role.controller.d.ts.map +1 -0
- package/dist/system/role/role.controller.js +123 -0
- package/dist/system/role/role.controller.js.map +1 -0
- package/dist/system/role/role.model.d.ts +25 -0
- package/dist/system/role/role.model.d.ts.map +1 -0
- package/dist/system/role/role.model.js +133 -0
- package/dist/system/role/role.model.js.map +1 -0
- package/dist/system/role/role.service.d.ts +17 -0
- package/dist/system/role/role.service.d.ts.map +1 -0
- package/dist/system/role/role.service.js +50 -0
- package/dist/system/role/role.service.js.map +1 -0
- package/dist/system/roleMenu/roleMenu.controller.d.ts +26 -0
- package/dist/system/roleMenu/roleMenu.controller.d.ts.map +1 -0
- package/dist/system/roleMenu/roleMenu.controller.js +83 -0
- package/dist/system/roleMenu/roleMenu.controller.js.map +1 -0
- package/dist/system/roleMenu/roleMenu.model.d.ts +35 -0
- package/dist/system/roleMenu/roleMenu.model.d.ts.map +1 -0
- package/dist/system/roleMenu/roleMenu.model.js +56 -0
- package/dist/system/roleMenu/roleMenu.model.js.map +1 -0
- package/dist/system/roleMenu/roleMenu.service.d.ts +35 -0
- package/dist/system/roleMenu/roleMenu.service.d.ts.map +1 -0
- package/dist/system/roleMenu/roleMenu.service.js +77 -0
- package/dist/system/roleMenu/roleMenu.service.js.map +1 -0
- package/dist/system/rolePermission/rolePermission.controller.d.ts +36 -0
- package/dist/system/rolePermission/rolePermission.controller.d.ts.map +1 -0
- package/dist/system/rolePermission/rolePermission.controller.js +115 -0
- package/dist/system/rolePermission/rolePermission.controller.js.map +1 -0
- package/dist/system/rolePermission/rolePermission.model.d.ts +45 -0
- package/dist/system/rolePermission/rolePermission.model.d.ts.map +1 -0
- package/dist/system/rolePermission/rolePermission.model.js +87 -0
- package/dist/system/rolePermission/rolePermission.model.js.map +1 -0
- package/dist/system/rolePermission/rolePermission.service.d.ts +50 -0
- package/dist/system/rolePermission/rolePermission.service.d.ts.map +1 -0
- package/dist/system/rolePermission/rolePermission.service.js +110 -0
- package/dist/system/rolePermission/rolePermission.service.js.map +1 -0
- package/dist/system/user/user.controller.d.ts +66 -0
- package/dist/system/user/user.controller.d.ts.map +1 -0
- package/dist/system/user/user.controller.js +322 -0
- package/dist/system/user/user.controller.js.map +1 -0
- package/dist/system/user/user.model.d.ts +58 -0
- package/dist/system/user/user.model.d.ts.map +1 -0
- package/dist/system/user/user.model.js +225 -0
- package/dist/system/user/user.model.js.map +1 -0
- package/dist/system/user/user.service.d.ts +73 -0
- package/dist/system/user/user.service.d.ts.map +1 -0
- package/dist/system/user/user.service.js +388 -0
- package/dist/system/user/user.service.js.map +1 -0
- package/dist/system/userRole/userRole.controller.d.ts +33 -0
- package/dist/system/userRole/userRole.controller.d.ts.map +1 -0
- package/dist/system/userRole/userRole.controller.js +231 -0
- package/dist/system/userRole/userRole.controller.js.map +1 -0
- package/dist/system/userRole/userRole.model.d.ts +14 -0
- package/dist/system/userRole/userRole.model.d.ts.map +1 -0
- package/dist/system/userRole/userRole.model.js +58 -0
- package/dist/system/userRole/userRole.model.js.map +1 -0
- package/dist/system/userRole/userRole.service.d.ts +29 -0
- package/dist/system/userRole/userRole.service.d.ts.map +1 -0
- package/dist/system/userRole/userRole.service.js +135 -0
- package/dist/system/userRole/userRole.service.js.map +1 -0
- package/dist/systemServices.d.ts +23 -0
- package/dist/systemServices.d.ts.map +1 -0
- package/dist/systemServices.js +40 -0
- package/dist/systemServices.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +70 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/aiClient.d.ts +55 -0
- package/dist/utils/aiClient.d.ts.map +1 -0
- package/dist/utils/aiClient.js +59 -0
- package/dist/utils/aiClient.js.map +1 -0
- package/dist/utils/banner.d.ts +10 -0
- package/dist/utils/banner.d.ts.map +1 -0
- package/dist/utils/banner.js +40 -0
- package/dist/utils/banner.js.map +1 -0
- package/dist/utils/crypto.d.ts +49 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/crypto.js +113 -0
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/dataScope.d.ts +41 -0
- package/dist/utils/dataScope.d.ts.map +1 -0
- package/dist/utils/dataScope.js +130 -0
- package/dist/utils/dataScope.js.map +1 -0
- package/dist/utils/date.d.ts +48 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +145 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/emailClient.d.ts +15 -0
- package/dist/utils/emailClient.d.ts.map +1 -0
- package/dist/utils/emailClient.js +71 -0
- package/dist/utils/emailClient.js.map +1 -0
- package/dist/utils/jwt.d.ts +10 -0
- package/dist/utils/jwt.d.ts.map +1 -0
- package/dist/utils/jwt.js +31 -0
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/logger.d.ts +34 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +108 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/ossClient.d.ts +38 -0
- package/dist/utils/ossClient.d.ts.map +1 -0
- package/dist/utils/ossClient.js +92 -0
- package/dist/utils/ossClient.js.map +1 -0
- package/dist/utils/permissionSync.d.ts +10 -0
- package/dist/utils/permissionSync.d.ts.map +1 -0
- package/dist/utils/permissionSync.js +11 -0
- package/dist/utils/permissionSync.js.map +1 -0
- package/dist/utils/redisClient.d.ts +91 -0
- package/dist/utils/redisClient.d.ts.map +1 -0
- package/dist/utils/redisClient.js +246 -0
- package/dist/utils/redisClient.js.map +1 -0
- package/dist/utils/sequence.d.ts +53 -0
- package/dist/utils/sequence.d.ts.map +1 -0
- package/dist/utils/sequence.js +109 -0
- package/dist/utils/sequence.js.map +1 -0
- package/dist/utils/smsClient.d.ts +15 -0
- package/dist/utils/smsClient.d.ts.map +1 -0
- package/dist/utils/smsClient.js +115 -0
- package/dist/utils/smsClient.js.map +1 -0
- package/dist/utils/supabaseClient.d.ts +5 -0
- package/dist/utils/supabaseClient.d.ts.map +1 -0
- package/dist/utils/supabaseClient.js +17 -0
- package/dist/utils/supabaseClient.js.map +1 -0
- package/dist/utils/unipushClient.d.ts +12 -0
- package/dist/utils/unipushClient.d.ts.map +1 -0
- package/dist/utils/unipushClient.js +109 -0
- package/dist/utils/unipushClient.js.map +1 -0
- package/dist/utils/validator.d.ts +74 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +173 -0
- package/dist/utils/validator.js.map +1 -0
- package/dist/utils/wecom.d.ts +20 -0
- package/dist/utils/wecom.d.ts.map +1 -0
- package/dist/utils/wecom.js +126 -0
- package/dist/utils/wecom.js.map +1 -0
- package/package.json +84 -0
- package/templates/schema.system.prisma +283 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.operationLogger = void 0;
|
|
4
|
+
const operationLog_service_1 = require("../system/operationLog/operationLog.service");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
6
|
+
const operationLogService = new operationLog_service_1.OperationLogService();
|
|
7
|
+
/** 不需要记录日志的路径 */
|
|
8
|
+
const SKIP_PATHS = [
|
|
9
|
+
'/system/operation-log', // 日志自身的 CRUD 不记录
|
|
10
|
+
'/docs',
|
|
11
|
+
'/swagger.json',
|
|
12
|
+
];
|
|
13
|
+
/** 不需要记录日志的 HTTP 方法 */
|
|
14
|
+
const SKIP_METHODS = ['GET', 'HEAD', 'OPTIONS'];
|
|
15
|
+
/** 敏感字段,记录时需要脱敏 */
|
|
16
|
+
const SENSITIVE_FIELDS = ['password', 'token', 'secret', 'oldPassword', 'newPassword', 'confirmPassword'];
|
|
17
|
+
/**
|
|
18
|
+
* 从 URL 路径中解析模块名和操作类型
|
|
19
|
+
*
|
|
20
|
+
* 路径格式:/system/user、/system/role/{id}、/business/order/{id} 等
|
|
21
|
+
* 模块名取第一段路径(如 system、business)
|
|
22
|
+
* 操作对象取第二段路径(如 user、role、order)
|
|
23
|
+
*/
|
|
24
|
+
function parseModuleAndTarget(url) {
|
|
25
|
+
const segments = url.replace(/^\//, '').split('/');
|
|
26
|
+
return {
|
|
27
|
+
module: segments[0] || 'unknown',
|
|
28
|
+
targetType: segments[1] || 'unknown'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 根据 HTTP 方法映射操作类型
|
|
33
|
+
*/
|
|
34
|
+
function mapAction(method) {
|
|
35
|
+
switch (method.toUpperCase()) {
|
|
36
|
+
case 'POST': return 'create';
|
|
37
|
+
case 'PUT': return 'update';
|
|
38
|
+
case 'DELETE': return 'delete';
|
|
39
|
+
case 'PATCH': return 'update';
|
|
40
|
+
default: return 'query';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 对请求体中的敏感字段进行脱敏
|
|
45
|
+
*/
|
|
46
|
+
function sanitizeBody(body) {
|
|
47
|
+
if (!body || typeof body !== 'object')
|
|
48
|
+
return '';
|
|
49
|
+
const sanitized = { ...body };
|
|
50
|
+
for (const key of Object.keys(sanitized)) {
|
|
51
|
+
if (SENSITIVE_FIELDS.some(f => key.toLowerCase().includes(f.toLowerCase()))) {
|
|
52
|
+
sanitized[key] = '******';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const str = JSON.stringify(sanitized);
|
|
56
|
+
// 限制长度,避免超出字段容量
|
|
57
|
+
return str.length > 4000 ? str.substring(0, 4000) + '...(truncated)' : str;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 获取客户端真实 IP
|
|
61
|
+
*
|
|
62
|
+
* 优先从 X-Forwarded-For 头获取(适用于反向代理/负载均衡),
|
|
63
|
+
* 其次检查 X-Real-IP,最后降级到 ctx.ip。
|
|
64
|
+
* 同时对 IPv6 环回地址 ::1 做归一化处理。
|
|
65
|
+
*/
|
|
66
|
+
function getClientIP(ctx) {
|
|
67
|
+
const xff = ctx.headers['x-forwarded-for'];
|
|
68
|
+
if (xff) {
|
|
69
|
+
const first = xff.split(',')[0].trim();
|
|
70
|
+
if (first)
|
|
71
|
+
return first === '::1' ? '127.0.0.1' : first;
|
|
72
|
+
}
|
|
73
|
+
const xri = ctx.headers['x-real-ip'];
|
|
74
|
+
if (xri)
|
|
75
|
+
return xri === '::1' ? '127.0.0.1' : xri;
|
|
76
|
+
const ip = ctx.ip || ctx.request.ip;
|
|
77
|
+
return ip === '::1' ? '127.0.0.1' : ip;
|
|
78
|
+
}
|
|
79
|
+
function buildDescription(action, targetType, body) {
|
|
80
|
+
const actionMap = {
|
|
81
|
+
create: '创建',
|
|
82
|
+
update: '修改',
|
|
83
|
+
delete: '删除',
|
|
84
|
+
login: '登录',
|
|
85
|
+
export: '导出',
|
|
86
|
+
import: '导入',
|
|
87
|
+
};
|
|
88
|
+
const actionText = actionMap[action] || action;
|
|
89
|
+
const name = body?.name || body?.code || body?.username || '';
|
|
90
|
+
return name ? `${actionText} ${targetType} [${name}]` : `${actionText} ${targetType}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 判断请求是否应该跳过日志记录
|
|
94
|
+
*/
|
|
95
|
+
function shouldSkip(method, path) {
|
|
96
|
+
if (SKIP_METHODS.includes(method.toUpperCase()))
|
|
97
|
+
return true;
|
|
98
|
+
return SKIP_PATHS.some(p => path.startsWith(p));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 操作日志中间件
|
|
102
|
+
*
|
|
103
|
+
* 自动拦截 POST/PUT/DELETE 请求,记录操作日志到数据库。
|
|
104
|
+
* 必须放在 authMiddleware 之后使用,以获取 ctx.state.user 中的用户信息。
|
|
105
|
+
*
|
|
106
|
+
* 日志写入采用 fire-and-forget 模式,不阻塞响应返回。
|
|
107
|
+
*/
|
|
108
|
+
const operationLogger = async (ctx, next) => {
|
|
109
|
+
// 跳过不需要记录的方法/路径
|
|
110
|
+
if (shouldSkip(ctx.method, ctx.path)) {
|
|
111
|
+
await next();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const start = Date.now();
|
|
115
|
+
let error = null;
|
|
116
|
+
try {
|
|
117
|
+
await next();
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
error = err;
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
const duration = Date.now() - start;
|
|
125
|
+
// 从 auth 中间件中获取用户信息
|
|
126
|
+
const user = ctx.state.user;
|
|
127
|
+
// 解析模块名和操作类型
|
|
128
|
+
const { module, targetType } = parseModuleAndTarget(ctx.path);
|
|
129
|
+
const action = mapAction(ctx.method);
|
|
130
|
+
const body = ctx.request.body;
|
|
131
|
+
// 构建日志数据
|
|
132
|
+
const logData = {
|
|
133
|
+
userId: user?.id || undefined,
|
|
134
|
+
username: user?.username || 'anonymous',
|
|
135
|
+
module,
|
|
136
|
+
action,
|
|
137
|
+
targetType,
|
|
138
|
+
description: buildDescription(action, targetType, body),
|
|
139
|
+
requestMethod: ctx.method,
|
|
140
|
+
requestUrl: ctx.url,
|
|
141
|
+
requestIp: getClientIP(ctx),
|
|
142
|
+
requestBody: sanitizeBody(body),
|
|
143
|
+
responseCode: ctx.status,
|
|
144
|
+
duration,
|
|
145
|
+
status: error ? 'fail' : (ctx.status >= 400 ? 'fail' : 'success'),
|
|
146
|
+
errorMsg: error?.message || undefined,
|
|
147
|
+
};
|
|
148
|
+
// fire-and-forget:不阻塞响应,异步写入日志
|
|
149
|
+
operationLogService.createLog(logData).catch(err => {
|
|
150
|
+
logger_1.logger.error('[OperationLogger] 写入操作日志失败:', err);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
exports.operationLogger = operationLogger;
|
|
155
|
+
//# sourceMappingURL=operationLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operationLogger.js","sourceRoot":"","sources":["../../src/middleware/operationLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Middleware } from 'koa';
|
|
2
|
+
/**
|
|
3
|
+
* API 权限控制中间件
|
|
4
|
+
*
|
|
5
|
+
* 放在 authMiddleware 之后使用,依赖 ctx.state.user 中的用户角色信息。
|
|
6
|
+
* 通过 sys_permissions 表定义的 (path, method) 与 sys_role_permissions 关联,
|
|
7
|
+
* 实现基于 RBAC 的细粒度 API 访问控制。
|
|
8
|
+
*
|
|
9
|
+
* 鉴权流程:
|
|
10
|
+
* 1. 跳过白名单路径和 OPTIONS/HEAD 请求
|
|
11
|
+
* 2. 超级管理员(拥有 admin 角色)直接放行
|
|
12
|
+
* 3. 查询 sys_permissions 中匹配当前请求 (path, method) 的权限点
|
|
13
|
+
* 4. 严格模式:无匹配的权限记录 → 403 拒绝(生产推荐)
|
|
14
|
+
* 宽松模式:无匹配的权限记录 → 放行(开发默认)
|
|
15
|
+
* 5. 有匹配权限 → 检查用户角色是否关联这些权限
|
|
16
|
+
* 6. 有权限 → 放行;无权限 → 返回 403
|
|
17
|
+
*/
|
|
18
|
+
export declare const permissionMiddleware: Middleware;
|
|
19
|
+
/**
|
|
20
|
+
* 手动清空权限缓存(在权限/角色关联变更后调用)
|
|
21
|
+
*/
|
|
22
|
+
export declare function clearPermissionCache(): void;
|
|
23
|
+
//# sourceMappingURL=permission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission.d.ts","sourceRoot":"","sources":["../../src/middleware/permission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AA0FjC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAuElC,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.permissionMiddleware = void 0;
|
|
7
|
+
exports.clearPermissionCache = clearPermissionCache;
|
|
8
|
+
const database_1 = require("../config/database");
|
|
9
|
+
const types_1 = require("../common/types");
|
|
10
|
+
const config_1 = __importDefault(require("../config"));
|
|
11
|
+
const logger_1 = require("../utils/logger");
|
|
12
|
+
// ============ 配置 ============
|
|
13
|
+
/** 无需权限检查的路径白名单(tsoa basePath=/api,路由均带 /api 前缀) */
|
|
14
|
+
const PUBLIC_PATHS = [
|
|
15
|
+
'/api/system/user/login',
|
|
16
|
+
// 批量查询文件 URL(溯源页图片回显),只读接口
|
|
17
|
+
'/api/system/file-upload/batch',
|
|
18
|
+
'/docs',
|
|
19
|
+
'/swagger.json',
|
|
20
|
+
];
|
|
21
|
+
/** 正则放行(路径中含动态参数的公开接口) */
|
|
22
|
+
const PUBLIC_PATH_PATTERNS = [
|
|
23
|
+
// 消费者扫码查询溯源信息,无需登录
|
|
24
|
+
/^\/api\/traceability-codes\/[^/]+\/trace-info$/,
|
|
25
|
+
];
|
|
26
|
+
/** 超级管理员角色编码:拥有此角色的用户跳过所有权限检查 */
|
|
27
|
+
const SUPER_ADMIN_ROLE = 'admin';
|
|
28
|
+
/** 无需权限检查的 HTTP 方法(如 CORS 预检) */
|
|
29
|
+
const SKIP_METHODS = ['OPTIONS', 'HEAD'];
|
|
30
|
+
/** 以 method 为 key 缓存权限列表,TTL 60 秒 */
|
|
31
|
+
const permissionCache = new Map();
|
|
32
|
+
const CACHE_TTL = 60_000; // 60 秒
|
|
33
|
+
/**
|
|
34
|
+
* 获取指定 HTTP 方法对应的所有活跃权限点(带缓存)
|
|
35
|
+
*
|
|
36
|
+
* 缓存失效策略:调用方在权限变更后需主动清空或等待 TTL 自然过期。
|
|
37
|
+
*/
|
|
38
|
+
async function getActivePermissions(method) {
|
|
39
|
+
const cached = permissionCache.get(method);
|
|
40
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
41
|
+
return cached.permissions;
|
|
42
|
+
}
|
|
43
|
+
const permissions = await database_1.prisma.permission.findMany({
|
|
44
|
+
where: {
|
|
45
|
+
method,
|
|
46
|
+
path: { not: null },
|
|
47
|
+
status: 'active',
|
|
48
|
+
},
|
|
49
|
+
select: { id: true, path: true },
|
|
50
|
+
});
|
|
51
|
+
permissionCache.set(method, { permissions, timestamp: Date.now() });
|
|
52
|
+
return permissions;
|
|
53
|
+
}
|
|
54
|
+
// ============ 路径匹配 ============
|
|
55
|
+
/**
|
|
56
|
+
* 判断请求路径是否匹配权限路径规则
|
|
57
|
+
*
|
|
58
|
+
* 匹配规则:
|
|
59
|
+
* - 完全匹配:`/system/user` === `/system/user`
|
|
60
|
+
* - 前缀匹配:`/system/user` 匹配 `/system/user/123`、`/system/user/page`
|
|
61
|
+
* - **不匹配**:`/system/user` 不匹配 `/system/userRole`(必须带 `/` 分隔符)
|
|
62
|
+
*/
|
|
63
|
+
function pathMatches(permissionPath, requestPath) {
|
|
64
|
+
if (requestPath === permissionPath)
|
|
65
|
+
return true;
|
|
66
|
+
return requestPath.startsWith(permissionPath + '/');
|
|
67
|
+
}
|
|
68
|
+
// ============ 公开路径检查 ============
|
|
69
|
+
function isPublicPath(path) {
|
|
70
|
+
return (PUBLIC_PATHS.some(p => path.startsWith(p)) ||
|
|
71
|
+
PUBLIC_PATH_PATTERNS.some(pattern => pattern.test(path)));
|
|
72
|
+
}
|
|
73
|
+
// ============ 中间件 ============
|
|
74
|
+
/**
|
|
75
|
+
* API 权限控制中间件
|
|
76
|
+
*
|
|
77
|
+
* 放在 authMiddleware 之后使用,依赖 ctx.state.user 中的用户角色信息。
|
|
78
|
+
* 通过 sys_permissions 表定义的 (path, method) 与 sys_role_permissions 关联,
|
|
79
|
+
* 实现基于 RBAC 的细粒度 API 访问控制。
|
|
80
|
+
*
|
|
81
|
+
* 鉴权流程:
|
|
82
|
+
* 1. 跳过白名单路径和 OPTIONS/HEAD 请求
|
|
83
|
+
* 2. 超级管理员(拥有 admin 角色)直接放行
|
|
84
|
+
* 3. 查询 sys_permissions 中匹配当前请求 (path, method) 的权限点
|
|
85
|
+
* 4. 严格模式:无匹配的权限记录 → 403 拒绝(生产推荐)
|
|
86
|
+
* 宽松模式:无匹配的权限记录 → 放行(开发默认)
|
|
87
|
+
* 5. 有匹配权限 → 检查用户角色是否关联这些权限
|
|
88
|
+
* 6. 有权限 → 放行;无权限 → 返回 403
|
|
89
|
+
*/
|
|
90
|
+
const permissionMiddleware = async (ctx, next) => {
|
|
91
|
+
// 1. 跳过白名单和不需鉴权的方法
|
|
92
|
+
if (isPublicPath(ctx.path) || SKIP_METHODS.includes(ctx.method)) {
|
|
93
|
+
await next();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// 2. 获取当前用户
|
|
97
|
+
const user = ctx.state.user;
|
|
98
|
+
if (!user || !user.id) {
|
|
99
|
+
ctx.status = 401;
|
|
100
|
+
ctx.body = (0, types_1.fail)('未认证,请先登录', types_1.BizCode.UNAUTHORIZED);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// 3. 超级管理员直接放行
|
|
104
|
+
if (user.roles.includes(SUPER_ADMIN_ROLE)) {
|
|
105
|
+
await next();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// 4. 查找当前请求匹配的权限点
|
|
109
|
+
const allPermissions = await getActivePermissions(ctx.method);
|
|
110
|
+
const matchingPermissions = allPermissions.filter(p => p.path && pathMatches(p.path, ctx.path));
|
|
111
|
+
// 5. 无匹配权限记录
|
|
112
|
+
if (matchingPermissions.length === 0) {
|
|
113
|
+
if (config_1.default.permission.strictMode) {
|
|
114
|
+
// 严格模式:未注册端点默认拒绝,防止遗漏配置导致越权
|
|
115
|
+
logger_1.logger.warn(`[Permission] 未注册端点被拒绝(严格模式): ` +
|
|
116
|
+
`user=${user.username}(${user.id}), path=${ctx.method} ${ctx.path}`);
|
|
117
|
+
ctx.status = 403;
|
|
118
|
+
ctx.body = (0, types_1.fail)('当前端点未注册权限,禁止访问', types_1.BizCode.FORBIDDEN);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
// 宽松模式:未注册端点默认放行(开发环境推荐)
|
|
122
|
+
await next();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// 6. 有匹配权限 → 检查用户角色是否拥有
|
|
126
|
+
const permissionIds = matchingPermissions.map(p => p.id);
|
|
127
|
+
const hasPermission = await database_1.prisma.rolePermission.findFirst({
|
|
128
|
+
where: {
|
|
129
|
+
permissionId: { in: permissionIds },
|
|
130
|
+
role: {
|
|
131
|
+
code: { in: user.roles },
|
|
132
|
+
status: 'active',
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
if (hasPermission) {
|
|
137
|
+
await next();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// 7. 权限不足
|
|
141
|
+
logger_1.logger.warn(`[Permission] 权限不足: user=${user.username}(${user.id}), ` +
|
|
142
|
+
`path=${ctx.method} ${ctx.path}, roles=[${user.roles.join(',')}]`);
|
|
143
|
+
ctx.status = 403;
|
|
144
|
+
ctx.body = (0, types_1.fail)('权限不足,无法访问该接口', types_1.BizCode.FORBIDDEN);
|
|
145
|
+
};
|
|
146
|
+
exports.permissionMiddleware = permissionMiddleware;
|
|
147
|
+
/**
|
|
148
|
+
* 手动清空权限缓存(在权限/角色关联变更后调用)
|
|
149
|
+
*/
|
|
150
|
+
function clearPermissionCache() {
|
|
151
|
+
permissionCache.clear();
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=permission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission.js","sourceRoot":"","sources":["../../src/middleware/permission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/middleware/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAKjC;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,UAAU,CA0BnF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateRequest = validateRequest;
|
|
4
|
+
const class_transformer_1 = require("class-transformer");
|
|
5
|
+
const class_validator_1 = require("class-validator");
|
|
6
|
+
const types_1 = require("../common/types");
|
|
7
|
+
/**
|
|
8
|
+
* 请求体验证中间件
|
|
9
|
+
* 使用 class-validator 验证请求体
|
|
10
|
+
*/
|
|
11
|
+
function validateRequest(dtoClass) {
|
|
12
|
+
return async (ctx, next) => {
|
|
13
|
+
const body = ctx.request.body;
|
|
14
|
+
if (!body || Object.keys(body).length === 0) {
|
|
15
|
+
ctx.status = 400;
|
|
16
|
+
ctx.body = (0, types_1.fail)('请求体不能为空', types_1.BizCode.VALIDATION_ERROR);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const dto = (0, class_transformer_1.plainToClass)(dtoClass, body);
|
|
20
|
+
const errors = await (0, class_validator_1.validate)(dto, {
|
|
21
|
+
whitelist: true,
|
|
22
|
+
forbidNonWhitelisted: true,
|
|
23
|
+
transform: true,
|
|
24
|
+
});
|
|
25
|
+
if (errors.length > 0) {
|
|
26
|
+
const messages = formatValidationErrors(errors);
|
|
27
|
+
ctx.status = 400;
|
|
28
|
+
ctx.body = (0, types_1.fail)(messages.join('; '), types_1.BizCode.VALIDATION_ERROR);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
ctx.request.body = dto;
|
|
32
|
+
await next();
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 格式化验证错误信息
|
|
37
|
+
*/
|
|
38
|
+
function formatValidationErrors(errors) {
|
|
39
|
+
const messages = [];
|
|
40
|
+
for (const error of errors) {
|
|
41
|
+
if (error.constraints) {
|
|
42
|
+
messages.push(...Object.values(error.constraints));
|
|
43
|
+
}
|
|
44
|
+
if (error.children && error.children.length > 0) {
|
|
45
|
+
const childMessages = formatValidationErrors(error.children);
|
|
46
|
+
for (const msg of childMessages) {
|
|
47
|
+
messages.push(`${error.property}: ${msg}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return messages;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/middleware/validate.ts"],"names":[],"mappings":";;AASA,0CA0BC;AAlCD,yDAAiD;AACjD,qDAA4D;AAC5D,2CAAgD;AAEhD;;;GAGG;AACH,SAAgB,eAAe,CAAmB,QAAqB;IACrE,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,IAAA,YAAI,EAAC,SAAS,EAAE,eAAO,CAAC,gBAAgB,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAA,gCAAY,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAQ,EAAC,GAAU,EAAE;YACxC,SAAS,EAAE,IAAI;YACf,oBAAoB,EAAE,IAAI;YAC1B,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;YAChD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,IAAA,YAAI,EAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,eAAO,CAAC,gBAAgB,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QAED,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC;QACvB,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,MAAyB;IACvD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,MAAM,aAAa,GAAG,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC7D,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;gBAChC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 核心中间件聚合导出(宿主应用按需 use)。
|
|
3
|
+
*
|
|
4
|
+
* 示例:
|
|
5
|
+
* import { middlewares } from 'koa-boot-runtime';
|
|
6
|
+
* app.use(middlewares.errorHandler);
|
|
7
|
+
* app.use(middlewares.authMiddleware);
|
|
8
|
+
*/
|
|
9
|
+
export { errorHandler } from './middleware/errorHandler';
|
|
10
|
+
export { logger as requestLogger } from './middleware/logger';
|
|
11
|
+
export { authMiddleware } from './middleware/auth';
|
|
12
|
+
export { permissionMiddleware } from './middleware/permission';
|
|
13
|
+
export { operationLogger } from './middleware/operationLogger';
|
|
14
|
+
export { validateRequest } from './middleware/validate';
|
|
15
|
+
//# sourceMappingURL=middlewares.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../src/middlewares.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateRequest = exports.operationLogger = exports.permissionMiddleware = exports.authMiddleware = exports.requestLogger = exports.errorHandler = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 核心中间件聚合导出(宿主应用按需 use)。
|
|
6
|
+
*
|
|
7
|
+
* 示例:
|
|
8
|
+
* import { middlewares } from 'koa-boot-runtime';
|
|
9
|
+
* app.use(middlewares.errorHandler);
|
|
10
|
+
* app.use(middlewares.authMiddleware);
|
|
11
|
+
*/
|
|
12
|
+
var errorHandler_1 = require("./middleware/errorHandler");
|
|
13
|
+
Object.defineProperty(exports, "errorHandler", { enumerable: true, get: function () { return errorHandler_1.errorHandler; } });
|
|
14
|
+
var logger_1 = require("./middleware/logger");
|
|
15
|
+
Object.defineProperty(exports, "requestLogger", { enumerable: true, get: function () { return logger_1.logger; } });
|
|
16
|
+
var auth_1 = require("./middleware/auth");
|
|
17
|
+
Object.defineProperty(exports, "authMiddleware", { enumerable: true, get: function () { return auth_1.authMiddleware; } });
|
|
18
|
+
var permission_1 = require("./middleware/permission");
|
|
19
|
+
Object.defineProperty(exports, "permissionMiddleware", { enumerable: true, get: function () { return permission_1.permissionMiddleware; } });
|
|
20
|
+
var operationLogger_1 = require("./middleware/operationLogger");
|
|
21
|
+
Object.defineProperty(exports, "operationLogger", { enumerable: true, get: function () { return operationLogger_1.operationLogger; } });
|
|
22
|
+
var validate_1 = require("./middleware/validate");
|
|
23
|
+
Object.defineProperty(exports, "validateRequest", { enumerable: true, get: function () { return validate_1.validateRequest; } });
|
|
24
|
+
//# sourceMappingURL=middlewares.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../src/middlewares.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,0DAAyD;AAAhD,4GAAA,YAAY,OAAA;AACrB,8CAA8D;AAArD,uGAAA,MAAM,OAAiB;AAChC,0CAAmD;AAA1C,sGAAA,cAAc,OAAA;AACvB,sDAA+D;AAAtD,kHAAA,oBAAoB,OAAA;AAC7B,gEAA+D;AAAtD,kHAAA,eAAe,OAAA;AACxB,kDAAwD;AAA/C,2GAAA,eAAe,OAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type Koa from 'koa';
|
|
2
|
+
export interface RegisterRoutesOptions {
|
|
3
|
+
/** 系统 API 文档前缀,默认 '/api-docs/system' */
|
|
4
|
+
docsPrefix?: string;
|
|
5
|
+
/** 是否挂载系统 API 文档(Scalar 页面 + swagger.json),默认 true */
|
|
6
|
+
mountDocs?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 挂载系统路由(包内预生成)与系统 API 文档端点。
|
|
10
|
+
*
|
|
11
|
+
* 用户业务路由(用户项目 tsoa 生成的 RegisterRoutes)由宿主应用自行注册,
|
|
12
|
+
* 与系统路由互不干扰,对应 /api-docs/business 文档。
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerRoutes(app: Koa, options?: RegisterRoutesOptions): void;
|
|
15
|
+
//# sourceMappingURL=registerRoutes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerRoutes.d.ts","sourceRoot":"","sources":["../src/registerRoutes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAK3B,MAAM,WAAW,qBAAqB;IACpC,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,qBAA0B,GAAG,IAAI,CA0BlF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerRoutes = registerRoutes;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const router_1 = __importDefault(require("@koa/router"));
|
|
10
|
+
const config_1 = __importDefault(require("./config"));
|
|
11
|
+
const fileUpload_service_1 = require("./system/fileUpload/fileUpload.service");
|
|
12
|
+
const routes_1 = require("./build/routes");
|
|
13
|
+
/**
|
|
14
|
+
* 挂载系统路由(包内预生成)与系统 API 文档端点。
|
|
15
|
+
*
|
|
16
|
+
* 用户业务路由(用户项目 tsoa 生成的 RegisterRoutes)由宿主应用自行注册,
|
|
17
|
+
* 与系统路由互不干扰,对应 /api-docs/business 文档。
|
|
18
|
+
*/
|
|
19
|
+
function registerRoutes(app, options = {}) {
|
|
20
|
+
const { docsPrefix = '/api-docs/system', mountDocs = true } = options;
|
|
21
|
+
// 图片预览路由:/api/system/file-upload/preview/:fileNo → 302 到 OSS 原始 URL
|
|
22
|
+
// 必须挂载在系统路由之前,确保 preview 路径优先匹配
|
|
23
|
+
const previewRouter = new router_1.default();
|
|
24
|
+
const fileUploadService = new fileUpload_service_1.FileUploadService();
|
|
25
|
+
previewRouter.get('/api/system/file-upload/preview/:fileNo', async (ctx) => {
|
|
26
|
+
const record = await fileUploadService.getByFileNo(ctx.params.fileNo);
|
|
27
|
+
if (!record) {
|
|
28
|
+
ctx.status = 404;
|
|
29
|
+
ctx.body = { code: 404, message: '文件不存在' };
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
ctx.redirect(record.url);
|
|
33
|
+
});
|
|
34
|
+
app.use(previewRouter.routes());
|
|
35
|
+
// 系统路由(包内预生成,含 /api/system/**)
|
|
36
|
+
const router = new router_1.default();
|
|
37
|
+
(0, routes_1.RegisterRoutes)(router);
|
|
38
|
+
app.use(router.routes()).use(router.allowedMethods());
|
|
39
|
+
if (mountDocs) {
|
|
40
|
+
mountSystemDocs(app, docsPrefix);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function mountSystemDocs(app, prefix) {
|
|
44
|
+
const docsRouter = new router_1.default();
|
|
45
|
+
// 系统 spec JSON(随包发布的预生成 swagger.json)
|
|
46
|
+
docsRouter.get(`${prefix}/swagger.json`, async (ctx) => {
|
|
47
|
+
const specPath = path_1.default.join(__dirname, 'build', 'swagger.json');
|
|
48
|
+
try {
|
|
49
|
+
const spec = fs_1.default.readFileSync(specPath, 'utf8');
|
|
50
|
+
ctx.type = 'application/json';
|
|
51
|
+
ctx.body = spec;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
ctx.status = 404;
|
|
55
|
+
ctx.body = { code: 404, message: 'system swagger.json not found' };
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
// Scalar 文档页面(分端点挂载,与用户业务文档 /api-docs/business 分离)
|
|
59
|
+
docsRouter.get(prefix, async (ctx) => {
|
|
60
|
+
const scalarConfig = JSON.stringify({
|
|
61
|
+
theme: config_1.default.scalar.theme,
|
|
62
|
+
layout: config_1.default.scalar.layout,
|
|
63
|
+
darkMode: config_1.default.scalar.darkMode,
|
|
64
|
+
localization: {
|
|
65
|
+
locale: config_1.default.scalar.localization.locale,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
ctx.body = `<!DOCTYPE html>
|
|
69
|
+
<html>
|
|
70
|
+
<head>
|
|
71
|
+
<title>Koa-Boot System API Docs</title>
|
|
72
|
+
<meta charset="utf-8" />
|
|
73
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<script id="api-reference" data-url="${prefix}/swagger.json" data-configuration='${scalarConfig}'></script>
|
|
77
|
+
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
|
78
|
+
</body>
|
|
79
|
+
</html>`;
|
|
80
|
+
});
|
|
81
|
+
app.use(docsRouter.routes());
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=registerRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerRoutes.js","sourceRoot":"","sources":["../src/registerRoutes.ts"],"names":[],"mappings":";;;;;AAqBA,wCA0BC;AA/CD,gDAAwB;AACxB,4CAAoB;AACpB,yDAAiC;AAEjC,sDAA8B;AAC9B,+EAA2E;AAC3E,2CAAgD;AAShD;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,GAAQ,EAAE,UAAiC,EAAE;IAC1E,MAAM,EAAE,UAAU,GAAG,kBAAkB,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEtE,oEAAoE;IACpE,gCAAgC;IAChC,MAAM,aAAa,GAAG,IAAI,gBAAM,EAAE,CAAC;IACnC,MAAM,iBAAiB,GAAG,IAAI,sCAAiB,EAAE,CAAC;IAClD,aAAa,CAAC,GAAG,CAAC,yCAAyC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACzE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QACD,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhC,+BAA+B;IAC/B,MAAM,MAAM,GAAG,IAAI,gBAAM,EAAE,CAAC;IAC5B,IAAA,uBAAc,EAAC,MAAM,CAAC,CAAC;IACvB,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAEtD,IAAI,SAAS,EAAE,CAAC;QACd,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAQ,EAAE,MAAc;IAC/C,MAAM,UAAU,GAAG,IAAI,gBAAM,EAAE,CAAC;IAEhC,sCAAsC;IACtC,UAAU,CAAC,GAAG,CAAC,GAAG,MAAM,eAAe,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrD,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAC/D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC/C,GAAG,CAAC,IAAI,GAAG,kBAAkB,CAAC;YAC9B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC;QACrE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,mDAAmD;IACnD,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC;YAClC,KAAK,EAAE,gBAAM,CAAC,MAAM,CAAC,KAAK;YAC1B,MAAM,EAAE,gBAAM,CAAC,MAAM,CAAC,MAAM;YAC5B,QAAQ,EAAE,gBAAM,CAAC,MAAM,CAAC,QAAQ;YAChC,YAAY,EAAE;gBACZ,MAAM,EAAE,gBAAM,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM;aAC1C;SACF,CAAC,CAAC;QACH,GAAG,CAAC,IAAI,GAAG;;;;;;;;yCAQ0B,MAAM,sCAAsC,YAAY;;;QAGzF,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Controller } from 'tsoa';
|
|
2
|
+
import { Department, CreateDepartmentDto, UpdateDepartmentDto } from './department.model';
|
|
3
|
+
import { ApiResponse, PageResult } from '../../common';
|
|
4
|
+
export declare class DepartmentController extends Controller {
|
|
5
|
+
private departmentService;
|
|
6
|
+
/**
|
|
7
|
+
* 获取所有部门列表
|
|
8
|
+
*/
|
|
9
|
+
getAllDepartments(): Promise<ApiResponse<Department[]>>;
|
|
10
|
+
/**
|
|
11
|
+
* 获取部门树形结构
|
|
12
|
+
*/
|
|
13
|
+
getDepartmentTree(): Promise<ApiResponse<Department[]>>;
|
|
14
|
+
/**
|
|
15
|
+
* 根据负责人查询部门
|
|
16
|
+
*/
|
|
17
|
+
getDepartmentsByLeader(leaderId: string): Promise<ApiResponse<Department[]>>;
|
|
18
|
+
/**
|
|
19
|
+
* 获取指定父部门下的子部门
|
|
20
|
+
*/
|
|
21
|
+
getDepartmentsByParent(parentId: string): Promise<ApiResponse<Department[]>>;
|
|
22
|
+
/**
|
|
23
|
+
* 根据ID获取部门详情
|
|
24
|
+
*/
|
|
25
|
+
getDepartmentById(id: string): Promise<ApiResponse<Department>>;
|
|
26
|
+
/**
|
|
27
|
+
* 分页查询部门
|
|
28
|
+
*/
|
|
29
|
+
searchDepartmentsByPage(page?: number, pageSize?: number, keyword?: string): Promise<ApiResponse<{
|
|
30
|
+
list: any[];
|
|
31
|
+
pagination: PageResult<Department>['pagination'];
|
|
32
|
+
}>>;
|
|
33
|
+
/**
|
|
34
|
+
* 创建部门
|
|
35
|
+
*/
|
|
36
|
+
createDepartment(body: CreateDepartmentDto): Promise<ApiResponse<Department>>;
|
|
37
|
+
/**
|
|
38
|
+
* 更新部门
|
|
39
|
+
*/
|
|
40
|
+
updateDepartment(id: string, body: UpdateDepartmentDto): Promise<ApiResponse<any>>;
|
|
41
|
+
/**
|
|
42
|
+
* 删除部门
|
|
43
|
+
*/
|
|
44
|
+
deleteDepartment(id: string): Promise<ApiResponse<boolean>>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=department.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"department.controller.d.ts","sourceRoot":"","sources":["../../../src/system/department/department.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAYX,MAAM,MAAM,CAAC;AAEd,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAA8B,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEnF,qBAEa,oBAAqB,SAAQ,UAAU;IAClD,OAAO,CAAC,iBAAiB,CAA2B;IAEpD;;OAEG;IAEG,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IAK7D;;OAEG;IAEG,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IAK7D;;OAEG;IAEG,sBAAsB,CAClB,QAAQ,EAAE,MAAM,GACvB,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IAKrC;;OAEG;IAEG,sBAAsB,CAClB,QAAQ,EAAE,MAAM,GACvB,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IAKrC;;OAEG;IAEG,iBAAiB,CACb,EAAE,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAQnC;;OAEG;IAEG,uBAAuB,CAClB,IAAI,CAAC,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,WAAW,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAA;KAAE,CAAC,CAAC;IAK1F;;OAEG;IAGG,gBAAgB,CACZ,IAAI,EAAE,mBAAmB,GAChC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAmBnC;;OAEG;IAEG,gBAAgB,CACZ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,mBAAmB,GAChC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IA8B5B;;OAEG;IAGG,gBAAgB,CACZ,EAAE,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;CAejC"}
|