doomiwork 3.7.0 → 3.7.2
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/core/controller.js
CHANGED
|
@@ -78,6 +78,12 @@ class controller {
|
|
|
78
78
|
result = await instance[actionType.func](req, datakey);
|
|
79
79
|
////执行完CRUD方法之后的处理
|
|
80
80
|
result = await instance.afterCRUD(result,actionType,datakey,url,req,res)
|
|
81
|
+
|
|
82
|
+
//CJJ add
|
|
83
|
+
if (req.query.exportexcel === 'true' && result.buffer && result.successed) {
|
|
84
|
+
res.attachment('export.xlsx');
|
|
85
|
+
return res.end(result.buffer);
|
|
86
|
+
}
|
|
81
87
|
return res.json(result)
|
|
82
88
|
})
|
|
83
89
|
}
|
package/core/database/daoBase.js
CHANGED
|
@@ -128,8 +128,8 @@ class mysqlDao extends dao{
|
|
|
128
128
|
async update(Sql, model, id) {return this.executeSql(Sql, [model, id]);}
|
|
129
129
|
///删除记录
|
|
130
130
|
async delete(Sql, id,userid) {
|
|
131
|
-
|
|
132
|
-
if (result.successed && this.tableoption.logicDelete && userid && (this.tableoption.logDeleteBy || this.tableoption.logDeleteDate)){
|
|
131
|
+
return this.executeSql(Sql, id);
|
|
132
|
+
/*if (result.successed && this.tableoption.logicDelete && userid && (this.tableoption.logDeleteBy || this.tableoption.logDeleteDate)){
|
|
133
133
|
let sqlLog = `update ${this.tableoption.tableName} set ? where ${this.tableoption.primaryKey}=? ${this.tableoption.forcefilter}`;
|
|
134
134
|
let model = {};
|
|
135
135
|
if (this.tableoption.logDeleteBy){
|
|
@@ -141,6 +141,7 @@ class mysqlDao extends dao{
|
|
|
141
141
|
if (Object.keys(model).length>0) this.executeSql(sqlLog, [model, id]);
|
|
142
142
|
}
|
|
143
143
|
return result;
|
|
144
|
+
*/
|
|
144
145
|
}
|
|
145
146
|
/**
|
|
146
147
|
* 获取对应数据的权限设置
|
|
@@ -117,7 +117,7 @@ class Database {
|
|
|
117
117
|
if (err) {
|
|
118
118
|
this.logger.error("Database Query Error :" + err, sqlCommand);
|
|
119
119
|
this.logError(null, '数据库操作错误:' + err + sqlCommand)
|
|
120
|
-
return success(Object.assign(apiResult.DB_EXECUTE_FAILED, { errmessage: err.message }));
|
|
120
|
+
return success(Object.assign(apiResult.DB_EXECUTE_FAILED, { errmessage:'数据库操作错误'}));// err.message }));
|
|
121
121
|
}
|
|
122
122
|
return success({ successed: true, rows: rows });//,fields:fields});
|
|
123
123
|
});
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
const keyParse = require('./keywordparse');
|
|
3
3
|
const dataconfig = require('../configuration/dataconfig').getCurrent();
|
|
4
4
|
const mysql = require('mysql');
|
|
5
|
-
const ORDER_STRING= ['asc','desc']
|
|
6
|
-
const FORBID_SQL_KEYWORD = /;|(--)|(\bWHERE\b)|(\bSHOW\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;
|
|
5
|
+
const ORDER_STRING = ['asc', 'desc']
|
|
6
|
+
const FORBID_SQL_KEYWORD = /;|(--)|(\bWHERE\b)|(\bSHOW\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;
|
|
7
7
|
const Moment = require('moment');
|
|
8
8
|
// const FORBID_SQL_KEYWORD_STRICT = /;|(--)|(\bOR\b)|(\bAND\b)|(\bWHERE\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;
|
|
9
9
|
|
|
@@ -25,57 +25,62 @@ class RequestParser {
|
|
|
25
25
|
/*
|
|
26
26
|
解析sql字符串中特殊的占位符
|
|
27
27
|
*/
|
|
28
|
-
static parseAndReplaceSql(req,sql,allowNull=true){
|
|
28
|
+
static parseAndReplaceSql(req, sql, allowNull = true) {
|
|
29
29
|
if (!sql) return '';
|
|
30
30
|
///定义正则准备查找sql中的特定关键字
|
|
31
|
-
const matched=sql.match(/@.*?@/g);
|
|
32
|
-
if (!matched || matched.length<=0) return sql;
|
|
31
|
+
const matched = sql.match(/@.*?@/g);
|
|
32
|
+
if (!matched || matched.length <= 0) return sql;
|
|
33
33
|
let parseKeyWordIsNull = false;
|
|
34
34
|
|
|
35
35
|
const charReg = /\s+|:|=/gi
|
|
36
|
-
matched.forEach(ele=>{
|
|
37
|
-
let matchValue = ele.substring(1,ele.length-1);
|
|
36
|
+
matched.forEach(ele => {
|
|
37
|
+
let matchValue = ele.substring(1, ele.length - 1);
|
|
38
38
|
///不允许特殊字符出现
|
|
39
|
-
let notdo =
|
|
40
|
-
if (notdo && notdo.length>0)return;
|
|
39
|
+
let notdo = matchValue.match(charReg);
|
|
40
|
+
if (notdo && notdo.length > 0) return;
|
|
41
41
|
|
|
42
42
|
//if (matchValue.indexOf(' ')>=0 || matchValue.indexOf(':')>=0 || matchValue.indexOf('=')>=0) return;
|
|
43
43
|
let noQuoteProtect = matchValue[0] == '!';
|
|
44
|
-
if (noQuoteProtect){
|
|
44
|
+
if (noQuoteProtect) {
|
|
45
45
|
matchValue = matchValue.substring(1);
|
|
46
46
|
}
|
|
47
47
|
///是否有格式要求
|
|
48
48
|
let validformat = matchValue.split('|');
|
|
49
49
|
matchValue = validformat[0];
|
|
50
|
-
let keyValue = utility.ifNull(keyParse.parseKeyValue(req, matchValue),'');
|
|
51
|
-
if(!keyValue) {
|
|
50
|
+
let keyValue = utility.ifNull(keyParse.parseKeyValue(req, matchValue), '');
|
|
51
|
+
if (!keyValue) {
|
|
52
52
|
parseKeyWordIsNull = true;
|
|
53
|
-
}else if (typeof(keyValue)==='string'){
|
|
54
|
-
keyValue = noQuoteProtect ? this.checkSqlInjection(mysql.escape(keyValue)):mysql.escape(keyValue)
|
|
53
|
+
} else if (typeof (keyValue) === 'string') {
|
|
54
|
+
keyValue = noQuoteProtect ? this.checkSqlInjection(mysql.escape(keyValue)) : mysql.escape(keyValue)
|
|
55
55
|
keyValue = keyValue.substr(1, keyValue.length - 2);
|
|
56
56
|
///验证参数的格式合法性
|
|
57
|
-
if (keyValue && validformat.length>1){
|
|
57
|
+
if (keyValue && validformat.length > 1) {
|
|
58
|
+
// console.log(`参数格式合法检查==>${validformat[1]}:${matchValue} = ${keyValue}`)
|
|
58
59
|
keyValue = this.validatorParamsType(keyValue, validformat[1], validformat[2])
|
|
59
60
|
}
|
|
60
|
-
if (!keyValue){
|
|
61
|
+
if (!keyValue) {
|
|
61
62
|
parseKeyWordIsNull = true;
|
|
62
63
|
}
|
|
63
64
|
///没有引号保护下发现了sql注入,则用1=0不返回任何结果
|
|
64
65
|
if (!keyValue && noQuoteProtect) {
|
|
65
66
|
keyValue = '1=0'
|
|
66
67
|
}
|
|
68
|
+
} else { ////数组形式的参数,目前框架不支持,统一认为为sql注入攻击,全部忽略
|
|
69
|
+
console.log(`参数非法==>类型${typeof (keyValue)}:${matchValue} = ${keyValue}`)
|
|
70
|
+
parseKeyWordIsNull = true;
|
|
71
|
+
keyValue = ''
|
|
67
72
|
}
|
|
68
|
-
sql=sql.replace(ele,keyValue);
|
|
73
|
+
sql = sql.replace(ele, keyValue);
|
|
69
74
|
});
|
|
70
75
|
if (!allowNull && parseKeyWordIsNull) return '';
|
|
71
76
|
return sql;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
static appendSearchCondition2Count(originSql,searchCondition){
|
|
79
|
+
static appendSearchCondition2Count(originSql, searchCondition) {
|
|
75
80
|
///如果包含了这个特定的字符,则替换
|
|
76
|
-
if (originSql.indexOf('#APPENDSEARCH#')>=0)
|
|
77
|
-
return originSql.replace('#APPENDSEARCH#',searchCondition);
|
|
78
|
-
return originSql + ' '+ searchCondition;
|
|
81
|
+
if (originSql.indexOf('#APPENDSEARCH#') >= 0)
|
|
82
|
+
return originSql.replace('#APPENDSEARCH#', searchCondition);
|
|
83
|
+
return originSql + ' ' + searchCondition;
|
|
79
84
|
}
|
|
80
85
|
/**
|
|
81
86
|
* 校验参数的类型
|
|
@@ -84,9 +89,9 @@ class RequestParser {
|
|
|
84
89
|
* @param {*} defaultValue
|
|
85
90
|
* @returns
|
|
86
91
|
*/
|
|
87
|
-
static validatorParamsType(value,dataType,defaultValue=null){
|
|
92
|
+
static validatorParamsType(value, dataType, defaultValue = null) {
|
|
88
93
|
if (!value || !dataType) return value;
|
|
89
|
-
switch (dataType.toLowerCase()){
|
|
94
|
+
switch (dataType.toLowerCase()) {
|
|
90
95
|
case 'guid': ///限制长度为36位的GUID
|
|
91
96
|
if (value.length != 36 || value.split('-').length != 5) return defaultValue;
|
|
92
97
|
break;
|
|
@@ -109,21 +114,21 @@ class RequestParser {
|
|
|
109
114
|
* 检查是否有Sql注入的风险
|
|
110
115
|
* @param {*} sql
|
|
111
116
|
*/
|
|
112
|
-
static checkSqlInjection(sql){
|
|
113
|
-
if(!sql) return sql;
|
|
117
|
+
static checkSqlInjection(sql) {
|
|
118
|
+
if (!sql) return sql;
|
|
114
119
|
let sqlError = sql.match(FORBID_SQL_KEYWORD); //strict ? sql.match(FORBID_SQL_KEYWORD_STRICT):sql.match(FORBID_SQL_KEYWORD);
|
|
115
|
-
if (sqlError && sqlError.length>0) return '';
|
|
120
|
+
if (sqlError && sqlError.length > 0) return '';
|
|
116
121
|
return sql;
|
|
117
122
|
}
|
|
118
123
|
/*
|
|
119
124
|
* 列表请求上下文中获取需要的信息
|
|
120
125
|
* 如Page ,PageSize , Sort 等等
|
|
121
126
|
*/
|
|
122
|
-
static getListInfo(req,cfgType=0,dao) {
|
|
127
|
+
static getListInfo(req, cfgType = 0, dao) {
|
|
123
128
|
const dataKey = utility.ifNull(req.dataKey, req.query.datakey);
|
|
124
129
|
///确认是否是需要导出Excel
|
|
125
|
-
const export2Excel =(req.query.exportexcel+"").toLowerCase()==="true";
|
|
126
|
-
req.page = req.query.page || req.body.page|| 1;
|
|
130
|
+
const export2Excel = (req.query.exportexcel + "").toLowerCase() === "true";
|
|
131
|
+
req.page = req.query.page || req.body.page || 1;
|
|
127
132
|
req.pageSize = req.query.rows || req.body.rows || 100;
|
|
128
133
|
req.sort = req.query.sort || req.body.sort;
|
|
129
134
|
///防止sortSql 注入
|
|
@@ -132,7 +137,7 @@ class RequestParser {
|
|
|
132
137
|
req.sort = this.checkSqlInjection(req.sort);
|
|
133
138
|
}
|
|
134
139
|
//防止注入式Sql
|
|
135
|
-
if (isNaN(req.pageSize)){
|
|
140
|
+
if (isNaN(req.pageSize)) {
|
|
136
141
|
req.pageSize = 30;
|
|
137
142
|
}
|
|
138
143
|
//防止注入式Sql
|
|
@@ -140,61 +145,61 @@ class RequestParser {
|
|
|
140
145
|
req.page = 1;
|
|
141
146
|
}
|
|
142
147
|
///最大允许获取100条数据
|
|
143
|
-
req.pageSize = Math.min(req.pageSize,100);
|
|
148
|
+
req.pageSize = Math.min(req.pageSize, 100);
|
|
144
149
|
let order = (req.body.order || req.query.order || '').trim().toLowerCase();
|
|
145
|
-
if (order && req.sort){
|
|
146
|
-
if (ORDER_STRING.indexOf(order)>=0) {
|
|
150
|
+
if (order && req.sort) {
|
|
151
|
+
if (ORDER_STRING.indexOf(order) >= 0) {
|
|
147
152
|
req.sort = req.sort + ' ' + order
|
|
148
153
|
}
|
|
149
154
|
}
|
|
150
155
|
//req.order =req.sort? utility.ifNull((req.body.order || req.query.order), ""):'';
|
|
151
156
|
if (dataKey) {
|
|
152
|
-
req.dataConfig = dataconfig.getConfig(dataKey,cfgType);
|
|
157
|
+
req.dataConfig = dataconfig.getConfig(dataKey, cfgType);
|
|
153
158
|
if (req.dataConfig && req.dataConfig.list) {
|
|
154
159
|
req.sqltype = req.dataConfig.list.sqltype || 'sql';
|
|
155
160
|
req.fieldsMapping = req.dataConfig.list.field;
|
|
156
161
|
req.footerMapping = req.dataConfig.list.footer;
|
|
157
162
|
/**解析查询条件 */
|
|
158
163
|
req.searchCondition = this.getSearchCondition({ request: req, refer: req.dataConfig.list.search });
|
|
159
|
-
/**排序方式
|
|
160
|
-
req.sort = req.
|
|
161
|
-
/**来自req请求参数中的过滤条件 */
|
|
162
|
-
let clientFilter = this.checkSqlInjection(this.parseAndReplaceSql(req,req.query.clientFilter),false);
|
|
163
|
-
|
|
164
|
-
let listsql='';
|
|
164
|
+
/**排序方式 */// req.sort || //稍后恢复
|
|
165
|
+
req.sort = req.dataConfig.list.sort;
|
|
166
|
+
/**来自req请求参数中的过滤条件 */ //稍后恢复
|
|
167
|
+
let clientFilter = '';// this.checkSqlInjection(this.parseAndReplaceSql(req,req.query.clientFilter),false);
|
|
168
|
+
|
|
169
|
+
let listsql = '';
|
|
165
170
|
///是否有列表尾部的统计SQL
|
|
166
171
|
let countsql = '';
|
|
167
|
-
switch (req.sqltype){
|
|
168
|
-
case "sql":
|
|
169
|
-
listsql
|
|
170
|
-
countsql
|
|
172
|
+
switch (req.sqltype) {
|
|
173
|
+
case "sql":
|
|
174
|
+
listsql = req.dataConfig.list.sql;
|
|
175
|
+
countsql = req.dataConfig.list.countsql;
|
|
171
176
|
break;
|
|
172
177
|
case "property":
|
|
173
178
|
if (dao && dao.constantsql) {
|
|
174
|
-
listsql
|
|
175
|
-
countsql
|
|
179
|
+
listsql = dao.constantsql[listsql].list;
|
|
180
|
+
countsql = dao.constantsql[listsql].countsql;
|
|
176
181
|
}
|
|
177
182
|
break;
|
|
178
183
|
case "func":
|
|
179
|
-
if (dao && dao[listsql] && typeof(dao[listsql])==='function'
|
|
180
|
-
|
|
184
|
+
if (dao && dao[listsql] && typeof (dao[listsql]) === 'function')
|
|
185
|
+
listsql = dao[listsql]();
|
|
181
186
|
break;
|
|
182
187
|
}
|
|
183
188
|
/**根据过滤条件、排序条件、分页获取的方式,和原始sql拼接成最终获取数据的sql */
|
|
184
|
-
req.listSql =
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
req.listSql = this.parseAndReplaceSql(req, listsql) +
|
|
190
|
+
' ' + req.searchCondition + clientFilter +
|
|
191
|
+
//(utility.isNullOrEmpty(req.sort) ? '' : (' order by ' + (req.sort+' '+req.order))) +
|
|
192
|
+
(req.sort ? (' order by ' + req.sort) : '') +
|
|
193
|
+
(export2Excel ? '' : ' limit ' + Number(req.pageSize) + ' OFFSET ' + (Number(req.page) - 1) * Number(req.pageSize)) +
|
|
194
|
+
/////在Sql中再放入获取总记录数的语句
|
|
195
|
+
';SELECT FOUND_ROWS() AS total;';
|
|
191
196
|
/*** 如果存在汇总列的sql,则把SQL放置在最末尾 */
|
|
192
|
-
if(countsql){
|
|
197
|
+
if (countsql) {
|
|
193
198
|
req.countSql = true;
|
|
194
|
-
req.listSql+= this.appendSearchCondition2Count(
|
|
195
|
-
this.parseAndReplaceSql(req,countsql),
|
|
196
|
-
req.searchCondition)+';'
|
|
197
|
-
}
|
|
199
|
+
req.listSql += this.appendSearchCondition2Count(
|
|
200
|
+
this.parseAndReplaceSql(req, countsql),
|
|
201
|
+
req.searchCondition) + ';'
|
|
202
|
+
}
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
205
|
}
|
|
@@ -208,7 +213,7 @@ class RequestParser {
|
|
|
208
213
|
req.dataConfig = dataconfig.getConfig(dataKey);
|
|
209
214
|
if (req.dataConfig && req.dataConfig.detail) {
|
|
210
215
|
///主键存储
|
|
211
|
-
req.primary=req.dataConfig.detail.primary;
|
|
216
|
+
req.primary = req.dataConfig.detail.primary;
|
|
212
217
|
req.fieldsMapping = req.dataConfig.detail.field;
|
|
213
218
|
req.primaryIsAutoIncrease = req.dataConfig.detail.primaryIsAutoIncrease;
|
|
214
219
|
}
|