midway-fatcms 0.0.11 → 0.0.13
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/configuration.d.ts +0 -2
- package/dist/configuration.js +14 -12
- package/dist/controller/gateway/CrudMtdGatewayController.js +2 -1
- package/dist/controller/gateway/DocGatewayController.js +7 -5
- package/dist/controller/gateway/PublicApiController.js +32 -3
- package/dist/controller/gateway/StaticController.d.ts +0 -2
- package/dist/controller/gateway/StaticController.js +4 -39
- package/dist/controller/home.controller.js +2 -1
- package/dist/controller/manage/AccountRoleManageApi.d.ts +2 -1
- package/dist/controller/manage/AccountRoleManageApi.js +34 -0
- package/dist/controller/manage/DataDictManageApi.d.ts +2 -0
- package/dist/controller/manage/DataDictManageApi.js +41 -9
- package/dist/controller/manage/DocManageApi.js +2 -2
- package/dist/controller/manage/UserAccountManageApi.js +4 -3
- package/dist/controller/render/AppRenderController.js +7 -6
- package/dist/libs/crud-pro/CrudPro.d.ts +0 -1
- package/dist/libs/crud-pro/CrudPro.js +2 -11
- package/dist/libs/crud-pro/exceptions.d.ts +6 -0
- package/dist/libs/crud-pro/exceptions.js +6 -0
- package/dist/libs/crud-pro/models/keys.d.ts +1 -0
- package/dist/libs/crud-pro/models/keys.js +1 -0
- package/dist/libs/crud-pro/services/CrudProExecuteFuncService.js +2 -2
- package/dist/libs/crud-pro/services/CrudProFieldUpdateService.js +3 -0
- package/dist/libs/crud-pro/services/CrudProTableMetaService.js +2 -2
- package/dist/libs/crud-pro/utils/DatabaseName.js +11 -0
- package/dist/libs/crud-pro/utils/DateTimeUtils.js +1 -1
- package/dist/libs/crud-pro/utils/SqlErrorParseUtils.d.ts +22 -0
- package/dist/libs/crud-pro/utils/SqlErrorParseUtils.js +219 -0
- package/dist/libs/utils/functions.d.ts +8 -1
- package/dist/libs/utils/functions.js +29 -1
- package/dist/service/AuthService.js +1 -1
- package/dist/service/anyapi/AnyApiService.js +1 -1
- package/dist/service/crudstd/CrudStdService.js +8 -3
- package/dist/service/curd/CurdMixByDictService.js +1 -1
- package/dist/service/curd/CurdMixBySysConfigService.js +1 -1
- package/dist/service/curd/CurdMixByWorkbenchService.js +1 -1
- package/dist/service/curd/fixCfgModel.js +3 -1
- package/dist/service/proxyapi/ProxyApiLoadService.js +3 -0
- package/package.json +1 -1
- package/src/configuration.ts +18 -11
- package/src/controller/gateway/CrudMtdGatewayController.ts +2 -1
- package/src/controller/gateway/DocGatewayController.ts +9 -5
- package/src/controller/gateway/PublicApiController.ts +39 -4
- package/src/controller/gateway/StaticController.ts +11 -40
- package/src/controller/home.controller.ts +3 -1
- package/src/controller/manage/AccountRoleManageApi.ts +38 -0
- package/src/controller/manage/DataDictManageApi.ts +48 -11
- package/src/controller/manage/DocManageApi.ts +2 -2
- package/src/controller/manage/UserAccountManageApi.ts +4 -3
- package/src/controller/render/AppRenderController.ts +9 -7
- package/src/libs/crud-pro/CrudPro.ts +2 -12
- package/src/libs/crud-pro/exceptions.ts +6 -0
- package/src/libs/crud-pro/models/keys.ts +1 -0
- package/src/libs/crud-pro/services/CrudProExecuteFuncService.ts +3 -2
- package/src/libs/crud-pro/services/CrudProFieldUpdateService.ts +5 -0
- package/src/libs/crud-pro/services/CrudProTableMetaService.ts +2 -2
- package/src/libs/crud-pro/utils/DatabaseName.ts +12 -0
- package/src/libs/crud-pro/utils/DateTimeUtils.ts +1 -1
- package/src/libs/crud-pro/utils/SqlErrorParseUtils.ts +236 -0
- package/src/libs/utils/functions.ts +37 -2
- package/src/service/AuthService.ts +2 -2
- package/src/service/anyapi/AnyApiService.ts +2 -2
- package/src/service/crudstd/CrudStdService.ts +9 -4
- package/src/service/curd/CurdMixByDictService.ts +1 -1
- package/src/service/curd/CurdMixBySysConfigService.ts +1 -1
- package/src/service/curd/CurdMixByWorkbenchService.ts +1 -1
- package/src/service/curd/fixCfgModel.ts +3 -1
- package/src/service/proxyapi/ProxyApiLoadService.ts +4 -1
|
@@ -43,6 +43,9 @@ class CrudProFieldUpdateService extends CrudProServiceBase_1.CrudProServiceBase
|
|
|
43
43
|
}
|
|
44
44
|
catch (e) {
|
|
45
45
|
this.logger.error('getUpdateNewValueByCfg->executeFuncCfg', e);
|
|
46
|
+
if (e instanceof exceptions_1.CommonException) {
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
46
49
|
throw new exceptions_1.CommonException(exceptions_1.Exceptions.UPDATE_EXCEPTION, key + '.' + e);
|
|
47
50
|
}
|
|
48
51
|
return result;
|
|
@@ -142,11 +142,11 @@ class CrudProTableMetaService extends CrudProServiceBase_1.CrudProServiceBase {
|
|
|
142
142
|
async loadMySQLAllTableInfos(query) {
|
|
143
143
|
const dbUtil = { sqlDatabase: query.sqlDatabase, sqlDbType: query.sqlDbType };
|
|
144
144
|
// 获取物理表
|
|
145
|
-
const tableSql = `SHOW TABLES
|
|
145
|
+
const tableSql = `SHOW TABLES`;
|
|
146
146
|
const tableRes = await this.executeUnsafeQuery(dbUtil, tableSql);
|
|
147
147
|
const tableNames = (tableRes.rows || []).map((row) => Object.values(row)[0]);
|
|
148
148
|
// 获取视图
|
|
149
|
-
const viewSql = `SHOW FULL TABLES
|
|
149
|
+
const viewSql = `SHOW FULL TABLES WHERE Table_type = 'VIEW'`;
|
|
150
150
|
const viewRes = await this.executeUnsafeQuery(dbUtil, viewSql);
|
|
151
151
|
const viewNames = (viewRes.rows || []).map((row) => Object.values(row)[0]);
|
|
152
152
|
const tables = [
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toDatabaseNameStr = exports.parseDatabaseName = exports.SPLIT_CONST = void 0;
|
|
4
4
|
const keys_1 = require("../models/keys");
|
|
5
|
+
const global_config_1 = require("../../global-config/global-config");
|
|
5
6
|
const SPLIT_CONST = '_________';
|
|
6
7
|
exports.SPLIT_CONST = SPLIT_CONST;
|
|
7
8
|
const PREFIX_MYSQL = `${keys_1.SqlDbType.mysql}${SPLIT_CONST}`;
|
|
@@ -27,6 +28,16 @@ function parseDatabaseName(databaseName) {
|
|
|
27
28
|
dbName: dbNameArr[1],
|
|
28
29
|
};
|
|
29
30
|
}
|
|
31
|
+
const gConfig = global_config_1.GLOBAL_STATIC_CONFIG.getConfig();
|
|
32
|
+
// 访问系统库
|
|
33
|
+
if (databaseName === 'fatcms' || databaseName === gConfig.SystemDbName) {
|
|
34
|
+
if (dbNameArr.length === 1) {
|
|
35
|
+
return {
|
|
36
|
+
dbType: gConfig.SystemDbType,
|
|
37
|
+
dbName: dbNameArr[0],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
30
41
|
if (dbNameArr.length === 1) {
|
|
31
42
|
return {
|
|
32
43
|
dbType: keys_1.SqlDbType.mysql,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CommonException } from '../exceptions';
|
|
2
|
+
declare const SqlErrorParseUtils: {
|
|
3
|
+
/**
|
|
4
|
+
* 从驱动原始错误中提取可读 SQL 错误信息(兼容 MySQL / PostgreSQL / SQL Server)
|
|
5
|
+
*/
|
|
6
|
+
getSqlErrorMessage(e: any): string;
|
|
7
|
+
isDuplicateEntryError(e: any, sqlMessage?: string): boolean;
|
|
8
|
+
isNoSuchTableError(e: any, sqlMessage?: string): boolean;
|
|
9
|
+
/** 外键约束:父记录被引用,无法删除或修改 */
|
|
10
|
+
isForeignKeyParentReferencedError(e: any, sqlMessage?: string): boolean;
|
|
11
|
+
/** 外键约束:关联的主数据不存在 */
|
|
12
|
+
isForeignKeyParentNotFoundError(e: any, sqlMessage?: string): boolean;
|
|
13
|
+
isNotNullViolationError(e: any, sqlMessage?: string): boolean;
|
|
14
|
+
isDataTooLongError(e: any, sqlMessage?: string): boolean;
|
|
15
|
+
isBadFieldError(e: any, sqlMessage?: string): boolean;
|
|
16
|
+
isDeadlockError(e: any, sqlMessage?: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* 将数据库驱动原始错误规范化为 CommonException
|
|
19
|
+
*/
|
|
20
|
+
parseRunSqlException(e: any): CommonException;
|
|
21
|
+
};
|
|
22
|
+
export { SqlErrorParseUtils };
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqlErrorParseUtils = void 0;
|
|
4
|
+
const exceptions_1 = require("../exceptions");
|
|
5
|
+
const SqlErrorParseUtils = {
|
|
6
|
+
/**
|
|
7
|
+
* 从驱动原始错误中提取可读 SQL 错误信息(兼容 MySQL / PostgreSQL / SQL Server)
|
|
8
|
+
*/
|
|
9
|
+
getSqlErrorMessage(e) {
|
|
10
|
+
return '' + ((e === null || e === void 0 ? void 0 : e.sqlMessage) || (e === null || e === void 0 ? void 0 : e.message) || '');
|
|
11
|
+
},
|
|
12
|
+
isDuplicateEntryError(e, sqlMessage) {
|
|
13
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
14
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_DUP_ENTRY) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
// MySQL
|
|
18
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_DUP_ENTRY' || (e === null || e === void 0 ? void 0 : e.errno) === 1062) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
// PostgreSQL
|
|
22
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '23505') {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
// SQL Server
|
|
26
|
+
if ((e === null || e === void 0 ? void 0 : e.number) === 2627 || (e === null || e === void 0 ? void 0 : e.number) === 2601) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return /duplicate key/i.test(message)
|
|
30
|
+
|| /unique constraint/i.test(message)
|
|
31
|
+
|| /unique key constraint/i.test(message)
|
|
32
|
+
|| message.startsWith('Duplicate entry');
|
|
33
|
+
},
|
|
34
|
+
isNoSuchTableError(e, sqlMessage) {
|
|
35
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
36
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_NO_SUCH_TABLE) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
// MySQL
|
|
40
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_NO_SUCH_TABLE' || (e === null || e === void 0 ? void 0 : e.errno) === 1146) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
// PostgreSQL
|
|
44
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '42P01') {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
// SQL Server
|
|
48
|
+
if ((e === null || e === void 0 ? void 0 : e.number) === 208) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return /doesn't exist/i.test(message)
|
|
52
|
+
|| /does not exist/i.test(message)
|
|
53
|
+
|| /invalid object name/i.test(message)
|
|
54
|
+
|| /no such table/i.test(message);
|
|
55
|
+
},
|
|
56
|
+
/** 外键约束:父记录被引用,无法删除或修改 */
|
|
57
|
+
isForeignKeyParentReferencedError(e, sqlMessage) {
|
|
58
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
59
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_FK_PARENT_REFERENCED) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_ROW_IS_REFERENCED_2' || (e === null || e === void 0 ? void 0 : e.errno) === 1451) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return /Cannot delete or update a parent row/i.test(message)
|
|
66
|
+
|| /update or delete on table .* violates foreign key constraint/i.test(message)
|
|
67
|
+
|| /DELETE statement conflicted with the REFERENCE constraint/i.test(message)
|
|
68
|
+
|| /UPDATE statement conflicted with the REFERENCE constraint/i.test(message);
|
|
69
|
+
},
|
|
70
|
+
/** 外键约束:关联的主数据不存在 */
|
|
71
|
+
isForeignKeyParentNotFoundError(e, sqlMessage) {
|
|
72
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
73
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_FK_PARENT_NOT_FOUND) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_NO_REFERENCED_ROW_2' || (e === null || e === void 0 ? void 0 : e.errno) === 1452) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
// PostgreSQL / SQL Server 与父记录被引用共用错误码,需靠消息区分
|
|
80
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '23503' || (e === null || e === void 0 ? void 0 : e.number) === 547) {
|
|
81
|
+
return /insert or update on table/i.test(message)
|
|
82
|
+
|| /INSERT statement conflicted with the FOREIGN KEY constraint/i.test(message)
|
|
83
|
+
|| /INSERT statement conflicted with the REFERENCE constraint/i.test(message)
|
|
84
|
+
|| /violates foreign key constraint/i.test(message);
|
|
85
|
+
}
|
|
86
|
+
return /Cannot add or update a child row/i.test(message)
|
|
87
|
+
|| /insert or update on table .* violates foreign key constraint/i.test(message);
|
|
88
|
+
},
|
|
89
|
+
isNotNullViolationError(e, sqlMessage) {
|
|
90
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
91
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_NOT_NULL) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_BAD_NULL_ERROR' || (e === null || e === void 0 ? void 0 : e.errno) === 1048) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '23502') {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
if ((e === null || e === void 0 ? void 0 : e.number) === 515) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
return /cannot be null/i.test(message)
|
|
104
|
+
|| /null value in column/i.test(message)
|
|
105
|
+
|| /violates not-null constraint/i.test(message)
|
|
106
|
+
|| /Cannot insert the value NULL into column/i.test(message);
|
|
107
|
+
},
|
|
108
|
+
isDataTooLongError(e, sqlMessage) {
|
|
109
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
110
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_DATA_TOO_LONG) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_DATA_TOO_LONG' || (e === null || e === void 0 ? void 0 : e.errno) === 1406) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '22001') {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
if ((e === null || e === void 0 ? void 0 : e.number) === 2628 || (e === null || e === void 0 ? void 0 : e.number) === 8152) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return /data too long/i.test(message)
|
|
123
|
+
|| /value too long/i.test(message)
|
|
124
|
+
|| /string data, right truncation/i.test(message)
|
|
125
|
+
|| /would be truncated/i.test(message);
|
|
126
|
+
},
|
|
127
|
+
isBadFieldError(e, sqlMessage) {
|
|
128
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
129
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_BAD_FIELD) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_BAD_FIELD_ERROR' || (e === null || e === void 0 ? void 0 : e.errno) === 1054) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '42703') {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
if ((e === null || e === void 0 ? void 0 : e.number) === 207) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
return /unknown column/i.test(message)
|
|
142
|
+
|| /Invalid column name/i.test(message);
|
|
143
|
+
},
|
|
144
|
+
isDeadlockError(e, sqlMessage) {
|
|
145
|
+
const message = sqlMessage !== null && sqlMessage !== void 0 ? sqlMessage : SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
146
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_DEADLOCK) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === 'ER_LOCK_DEADLOCK' || (e === null || e === void 0 ? void 0 : e.errno) === 1213) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
if ((e === null || e === void 0 ? void 0 : e.code) === '40P01') {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if ((e === null || e === void 0 ? void 0 : e.number) === 1205) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
return /deadlock/i.test(message);
|
|
159
|
+
},
|
|
160
|
+
/**
|
|
161
|
+
* 将数据库驱动原始错误规范化为 CommonException
|
|
162
|
+
*/
|
|
163
|
+
parseRunSqlException(e) {
|
|
164
|
+
if (e instanceof exceptions_1.CommonException) {
|
|
165
|
+
return e;
|
|
166
|
+
}
|
|
167
|
+
const sqlMessage = SqlErrorParseUtils.getSqlErrorMessage(e);
|
|
168
|
+
const rules = [
|
|
169
|
+
{
|
|
170
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_DUP_ENTRY,
|
|
171
|
+
match: SqlErrorParseUtils.isDuplicateEntryError,
|
|
172
|
+
message: '此条数据已存在,不能重复创建',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_NO_SUCH_TABLE,
|
|
176
|
+
match: SqlErrorParseUtils.isNoSuchTableError,
|
|
177
|
+
message: (message) => '查询的表不存在:' + message,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_FK_PARENT_REFERENCED,
|
|
181
|
+
match: SqlErrorParseUtils.isForeignKeyParentReferencedError,
|
|
182
|
+
message: '无法删除或修改:该数据已被其他记录引用,请先解除关联后再试',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_FK_PARENT_NOT_FOUND,
|
|
186
|
+
match: SqlErrorParseUtils.isForeignKeyParentNotFoundError,
|
|
187
|
+
message: '无法保存:所关联的数据不存在或已被删除',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_NOT_NULL,
|
|
191
|
+
match: SqlErrorParseUtils.isNotNullViolationError,
|
|
192
|
+
message: '操作失败:必填字段不能为空',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_DATA_TOO_LONG,
|
|
196
|
+
match: SqlErrorParseUtils.isDataTooLongError,
|
|
197
|
+
message: '操作失败:输入内容超出字段长度限制',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_BAD_FIELD,
|
|
201
|
+
match: SqlErrorParseUtils.isBadFieldError,
|
|
202
|
+
message: '操作失败:字段配置有误,请联系管理员检查表结构或接口配置',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
code: exceptions_1.Exceptions.RUN_SQL_EXCEPTION_ER_DEADLOCK,
|
|
206
|
+
match: SqlErrorParseUtils.isDeadlockError,
|
|
207
|
+
message: '操作失败:系统繁忙,请稍后重试',
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
for (const rule of rules) {
|
|
211
|
+
if (rule.match(e, sqlMessage)) {
|
|
212
|
+
const message = typeof rule.message === 'function' ? rule.message(sqlMessage) : rule.message;
|
|
213
|
+
return new exceptions_1.CommonException(rule.code, message);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return e;
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
exports.SqlErrorParseUtils = SqlErrorParseUtils;
|
|
@@ -8,4 +8,11 @@ declare function getCurrentFullMoment(): string;
|
|
|
8
8
|
* @returns 仅包含 ASCII 字符返回 true,否则返回 false;非字符串输入返回 false
|
|
9
9
|
*/
|
|
10
10
|
declare function isOnlyAscii(str: string): boolean;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* 如果entity不存在删除属性或属性为0,表示未删除
|
|
13
|
+
* @param entity
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
declare function isEntityDeleted(entity: any): boolean;
|
|
17
|
+
declare function isEntityOK(entity: any): boolean;
|
|
18
|
+
export { createUniqueId, parseJsonObject, parseStringTrimArray, getCurrentFullMoment, isOnlyAscii, isEntityDeleted, isEntityOK };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isOnlyAscii = exports.getCurrentFullMoment = exports.parseStringTrimArray = exports.parseJsonObject = exports.createUniqueId = void 0;
|
|
3
|
+
exports.isEntityOK = exports.isEntityDeleted = exports.isOnlyAscii = exports.getCurrentFullMoment = exports.parseStringTrimArray = exports.parseJsonObject = exports.createUniqueId = void 0;
|
|
4
4
|
const md5 = require("md5");
|
|
5
5
|
const moment = require("moment");
|
|
6
6
|
let createUniqueIdIndex = 0;
|
|
@@ -97,3 +97,31 @@ function isOnlyAscii(str) {
|
|
|
97
97
|
return true;
|
|
98
98
|
}
|
|
99
99
|
exports.isOnlyAscii = isOnlyAscii;
|
|
100
|
+
/**
|
|
101
|
+
* 如果entity不存在删除属性或属性为0,表示未删除
|
|
102
|
+
* @param entity
|
|
103
|
+
* @returns
|
|
104
|
+
*/
|
|
105
|
+
function isEntityDeleted(entity) {
|
|
106
|
+
if (!entity) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
const deletedAt = Number(entity.deleted_at);
|
|
110
|
+
if (deletedAt && deletedAt > 0) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
const deletedAt2 = Number(entity.deletedAt);
|
|
114
|
+
if (deletedAt2 && deletedAt2 > 0) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
exports.isEntityDeleted = isEntityDeleted;
|
|
120
|
+
function isEntityOK(entity) {
|
|
121
|
+
if (!entity) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const isOK = (entity === null || entity === void 0 ? void 0 : entity.status) === 1 || (entity === null || entity === void 0 ? void 0 : entity.status) === '1';
|
|
125
|
+
return isOK && !isEntityDeleted(entity);
|
|
126
|
+
}
|
|
127
|
+
exports.isEntityOK = isEntityOK;
|
|
@@ -119,7 +119,7 @@ let AuthService = class AuthService extends BaseService_1.BaseService {
|
|
|
119
119
|
const { publicKey, privateKey } = await AsymmetricCrypto_1.AsymmetricCrypto.generateKeyPair();
|
|
120
120
|
const sessionInfo = {
|
|
121
121
|
nickName: userAccount.nick_name,
|
|
122
|
-
avatar: userAccount.avatar,
|
|
122
|
+
avatar: userAccount.avatar || "",
|
|
123
123
|
roleCodes,
|
|
124
124
|
functionCodes,
|
|
125
125
|
loginName,
|
|
@@ -32,7 +32,7 @@ const lruCache = new lru_cache_1.LRUCache({
|
|
|
32
32
|
let AnyApiService = class AnyApiService extends ApiBaseService_1.ApiBaseService {
|
|
33
33
|
async executeAnyApiMethod(methodCode, headers, body, query) {
|
|
34
34
|
const anyApi = await this.getAnyApiMethod(methodCode);
|
|
35
|
-
if (!
|
|
35
|
+
if (!(0, functions_1.isEntityOK)(anyApi)) {
|
|
36
36
|
throw new devops_1.BizException('接口不存在或已下线:' + methodCode);
|
|
37
37
|
}
|
|
38
38
|
const isSupport = await this.workbenchService.isSupportCurrentWorkbench(anyApi.workbench_code_array);
|
|
@@ -62,12 +62,15 @@ let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseServic
|
|
|
62
62
|
var _a;
|
|
63
63
|
const appCode = stdAction.appCode;
|
|
64
64
|
const appInfo = await this.getParsedCrudStdAppForSettingKey(stdAction);
|
|
65
|
-
if (!
|
|
65
|
+
if (!(0, functions_1.isEntityOK)(appInfo)) {
|
|
66
66
|
throw new devops_1.BizException('应用不存在或已下线:' + appCode);
|
|
67
67
|
}
|
|
68
68
|
const stdCrudCfgObj = appInfo.stdCrudCfgObj;
|
|
69
69
|
//删除策略
|
|
70
70
|
const deleteStrategy = _.get(stdCrudCfgObj, 'othersSetting.values.deleteStrategy');
|
|
71
|
+
// 自动
|
|
72
|
+
const enableStandardUpdateCfg = _.get(stdCrudCfgObj, 'othersSetting.values.enableStandardUpdateCfg');
|
|
73
|
+
const enableStandardUpdateCfgCondition = _.get(stdCrudCfgObj, 'othersSetting.values.enableStandardUpdateCfgCondition');
|
|
71
74
|
const databaseName = stdCrudCfgObj.tableBaseInfo.databaseName;
|
|
72
75
|
const { dbType, dbName } = (0, DatabaseName_1.parseDatabaseName)(databaseName);
|
|
73
76
|
const cfgModel = {
|
|
@@ -76,7 +79,9 @@ let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseServic
|
|
|
76
79
|
sqlTable: getExecuteTableNameBySettingKey(appInfo, stdAction, sqlSimpleName),
|
|
77
80
|
sqlSimpleName,
|
|
78
81
|
updateCfg: {},
|
|
79
|
-
enableSoftDelete: deleteStrategy === 'soft'
|
|
82
|
+
enableSoftDelete: deleteStrategy === 'soft',
|
|
83
|
+
enableStandardUpdateCfg: Array.isArray(enableStandardUpdateCfg) && enableStandardUpdateCfg.length > 0 ? enableStandardUpdateCfg : ['by', 'at'],
|
|
84
|
+
enableStandardUpdateCfgCondition: Array.isArray(enableStandardUpdateCfgCondition) && enableStandardUpdateCfgCondition.length > 0 ? enableStandardUpdateCfgCondition : false, // 默认为false
|
|
80
85
|
};
|
|
81
86
|
// 接口返回最大值
|
|
82
87
|
const maxLimit = _.get(stdCrudCfgObj, 'othersSetting.values.maxLimit');
|
|
@@ -203,7 +208,7 @@ let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseServic
|
|
|
203
208
|
*/
|
|
204
209
|
async executeStdActionByReq(stdAction, params) {
|
|
205
210
|
const appInfo = await this.getParsedCrudStdAppForSettingKey(stdAction);
|
|
206
|
-
if (!
|
|
211
|
+
if (!(0, functions_1.isEntityOK)(appInfo)) {
|
|
207
212
|
throw new devops_1.BizException('应用不存在或已下线:' + stdAction.appCode);
|
|
208
213
|
}
|
|
209
214
|
const actionsMap = appInfo.actionsMap;
|
|
@@ -59,7 +59,7 @@ let CurdMixByDictService = class CurdMixByDictService {
|
|
|
59
59
|
let selectedRows = [];
|
|
60
60
|
if (noCacheCodes.length > 0) {
|
|
61
61
|
const res1 = await this.curdProService.executeCrudByCfg({
|
|
62
|
-
condition: { dict_code: { $in: noCacheCodes }, deleted_at: 0 },
|
|
62
|
+
condition: { dict_code: { $in: noCacheCodes }, deleted_at: 0, status: 1 },
|
|
63
63
|
}, {
|
|
64
64
|
sqlTable: SystemTables_1.SystemTables.sys_data_dict_item,
|
|
65
65
|
sqlSimpleName: keys_1.KeysOfSimpleSQL.SIMPLE_QUERY,
|
|
@@ -47,7 +47,7 @@ let CurdMixBySysConfigService = class CurdMixBySysConfigService {
|
|
|
47
47
|
}
|
|
48
48
|
const { SystemDbName, SystemDbType } = global_config_1.GLOBAL_STATIC_CONFIG.getConfig();
|
|
49
49
|
const res1 = await this.curdProService.executeCrudByCfg({
|
|
50
|
-
condition: { config_code: { $in: notCachedCodes }, deleted_at: 0 },
|
|
50
|
+
condition: { config_code: { $in: notCachedCodes }, deleted_at: 0, status: 1 },
|
|
51
51
|
}, {
|
|
52
52
|
sqlTable: SystemTables_1.SystemTables.sys_configs,
|
|
53
53
|
sqlSimpleName: keys_1.KeysOfSimpleSQL.SIMPLE_QUERY,
|
|
@@ -34,7 +34,7 @@ let CurdMixByWorkbenchService = CurdMixByWorkbenchService_1 = class CurdMixByWor
|
|
|
34
34
|
const service = await ctx.requestContext.getAsync(CurdMixByWorkbenchService_1);
|
|
35
35
|
const reqJson = {
|
|
36
36
|
columns: 'workbench_code,workbench_name,workbench_domain',
|
|
37
|
-
condition: { deleted_at: 0 },
|
|
37
|
+
condition: { deleted_at: 0, status: 1 },
|
|
38
38
|
};
|
|
39
39
|
const res = await service.curdProService.executeCrudByCfg(reqJson, {
|
|
40
40
|
sqlTable: SystemTables_1.SystemTables.sys_workbench,
|
|
@@ -30,7 +30,7 @@ function fixCfgModel(cfgModel) {
|
|
|
30
30
|
return enableStandardUpdateCfg;
|
|
31
31
|
}
|
|
32
32
|
// update 、insert 添加 by
|
|
33
|
-
return ['by']; // 创建/修改语句默认添加by
|
|
33
|
+
return ['by', 'at']; // 创建/修改语句默认添加by
|
|
34
34
|
};
|
|
35
35
|
const getConditionCfgArray = () => {
|
|
36
36
|
// 明确有配置
|
|
@@ -47,10 +47,12 @@ function fixCfgModel(cfgModel) {
|
|
|
47
47
|
const mapping = {
|
|
48
48
|
'condition.created_by': { contextAsString: bizmodels_1.CTX_VISITOR_ID },
|
|
49
49
|
'condition.created_account_type': { contextAsString: bizmodels_1.CTX_VISITOR_ACCOUNT_TYPE },
|
|
50
|
+
'data.created_at': { functionName: 'getCurrentTimeString' },
|
|
50
51
|
'data.created_by': { contextAsString: bizmodels_1.CTX_VISITOR_ID },
|
|
51
52
|
'data.created_avatar': { contextAsString: bizmodels_1.CTX_VISITOR_AVATAR },
|
|
52
53
|
'data.created_nickname': { contextAsString: bizmodels_1.CTX_VISITOR_NICKNAME },
|
|
53
54
|
'data.created_account_type': { contextAsString: bizmodels_1.CTX_VISITOR_ACCOUNT_TYPE },
|
|
55
|
+
'data.modified_at': { functionName: 'getCurrentTimeString' },
|
|
54
56
|
'data.modified_by': { contextAsString: bizmodels_1.CTX_VISITOR_ID },
|
|
55
57
|
'data.modified_avatar': { contextAsString: bizmodels_1.CTX_VISITOR_AVATAR },
|
|
56
58
|
'data.modified_nickname': { contextAsString: bizmodels_1.CTX_VISITOR_NICKNAME },
|
|
@@ -115,6 +115,9 @@ let ProxyApiLoadService = class ProxyApiLoadService extends BaseService_1.BaseSe
|
|
|
115
115
|
});
|
|
116
116
|
const rows0 = res.getResRows();
|
|
117
117
|
const rows = rows0.filter(s => {
|
|
118
|
+
if (!(0, functions_1.isEntityOK)(s)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
118
121
|
if (!s.workbench_code_array) {
|
|
119
122
|
throw new exceptions_1.CommonException('IS_SUPPORT_CURRENT_WORKBENCH', '未配置支持的站点字段');
|
|
120
123
|
}
|
package/package.json
CHANGED
package/src/configuration.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Configuration, App
|
|
1
|
+
import { Configuration, App } from '@midwayjs/core';
|
|
2
2
|
import * as koa from '@midwayjs/koa';
|
|
3
3
|
import * as validate from '@midwayjs/validate';
|
|
4
4
|
import * as info from '@midwayjs/info';
|
|
@@ -45,9 +45,6 @@ export class ContainerLifeCycle {
|
|
|
45
45
|
@App()
|
|
46
46
|
app: koa.Application;
|
|
47
47
|
|
|
48
|
-
@Inject()
|
|
49
|
-
redisService: RedisService;
|
|
50
|
-
|
|
51
48
|
async onConfigLoad(): Promise<any> {
|
|
52
49
|
const config = this.app.getConfig();
|
|
53
50
|
const logger = this.app.getLogger();
|
|
@@ -110,13 +107,23 @@ export class ContainerLifeCycle {
|
|
|
110
107
|
* 会通过 Redis 广播通知所有节点刷新缓存。
|
|
111
108
|
*/
|
|
112
109
|
private async initCacheRefreshRedis() {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
setTimeout(async () => {
|
|
111
|
+
|
|
112
|
+
const app = this.app;
|
|
113
|
+
const ctx: koa.IMidwayKoaContext = app.createAnonymousContext();
|
|
114
|
+
const redisService = await ctx.requestContext.getAsync(RedisService);
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
initCacheRefreshPublishClient(redisService);
|
|
118
|
+
initCacheRefreshSubscriber(redisService);
|
|
119
|
+
this.app.getLogger().info('ContainerLifeCycle ==> initCacheRefreshRedis success');
|
|
120
|
+
} catch (e) {
|
|
121
|
+
// Redis 未配置或不可用时,降级为单节点模式(仅刷新本节点缓存)
|
|
122
|
+
this.app.getLogger().warn('ContainerLifeCycle ==> initCacheRefreshRedis Redis不可用,降级为单节点模式:', e.message);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
}, 1000 * 60);
|
|
126
|
+
|
|
120
127
|
}
|
|
121
128
|
|
|
122
129
|
/**
|
|
@@ -10,6 +10,7 @@ import { CurdMixService } from '@/service/curd/CurdMixService';
|
|
|
10
10
|
import { IRequestCfgModel2 } from '@/models/bizmodels';
|
|
11
11
|
import { parseDatabaseName } from '@/libs/crud-pro/utils/DatabaseName';
|
|
12
12
|
import { GLOBAL_STATIC_CONFIG } from '@/libs/global-config/global-config';
|
|
13
|
+
import { isEntityOK } from '@/libs/utils/functions';
|
|
13
14
|
|
|
14
15
|
const QUERY_AS_LIST = ['condition', 'data'];
|
|
15
16
|
|
|
@@ -53,7 +54,7 @@ export class CrudMtdGatewayController extends ApiBaseService {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
const methodInfo = (await this.curdProService.getCachedCfgByMethod(methodCode)) as any;
|
|
56
|
-
if (!methodInfo || methodInfo
|
|
57
|
+
if (!methodInfo || !isEntityOK(methodInfo)) {
|
|
57
58
|
return CommonResult.errorRes('接口不存在或已下线: ' + methodCode);
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -6,6 +6,7 @@ import { GLOBAL_STATIC_CONFIG } from '@/libs/global-config/global-config';
|
|
|
6
6
|
import { KeysOfSimpleSQL } from '@/libs/crud-pro/models/keys';
|
|
7
7
|
import { WorkbenchService } from '@/service/WorkbenchService';
|
|
8
8
|
import { CommonResult } from '@/libs/utils/common-dto';
|
|
9
|
+
import { isEntityOK } from '@/libs/utils/functions';
|
|
9
10
|
import { getRealIpSafe } from '@/libs/utils/fatcms-request';
|
|
10
11
|
|
|
11
12
|
function checkIsNumber(value: string, name: string) {
|
|
@@ -91,13 +92,16 @@ export class DocGatewayController extends BaseApiController {
|
|
|
91
92
|
}
|
|
92
93
|
);
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
|
|
95
96
|
const docObj = res.getOneObj();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
|
|
98
|
+
if (!isEntityOK(docObj)) {
|
|
99
|
+
return CommonResult.errorRes("文档不存在");
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
// 更新PV数据
|
|
103
|
+
const pv: number = parseInt(docObj.pv) || 0;
|
|
104
|
+
await this.updateDocPV(docId, docLibId, pv);
|
|
101
105
|
return res;
|
|
102
106
|
}
|
|
103
107
|
|
|
@@ -160,7 +164,7 @@ export class DocGatewayController extends BaseApiController {
|
|
|
160
164
|
);
|
|
161
165
|
const docLibInfo = s.getOneObj();
|
|
162
166
|
|
|
163
|
-
if (!docLibInfo) {
|
|
167
|
+
if (!isEntityOK(docLibInfo)) {
|
|
164
168
|
throw '此文档库查询失败';
|
|
165
169
|
}
|
|
166
170
|
|