doomiwork 3.7.1 → 3.7.3

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.
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doomiwork",
3
- "version": "3.7.1",
3
+ "version": "3.7.3",
4
4
  "description": "doomisoft nodejs web framework",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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,60 +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 = matchValue.match(charReg);
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
  }
67
- }else{ ////数组形式的参数,目前框架不支持,统一认为为sql注入攻击,全部忽略
68
+ } else { ////数组形式的参数,目前框架不支持,统一认为为sql注入攻击,全部忽略
69
+ // console.log(`参数非法==>类型${typeof (keyValue)}:${matchValue} = ${keyValue}`)
68
70
  parseKeyWordIsNull = true;
69
71
  keyValue = ''
70
72
  }
71
- sql=sql.replace(ele,keyValue);
73
+ sql = sql.replace(ele, keyValue);
72
74
  });
73
75
  if (!allowNull && parseKeyWordIsNull) return '';
74
76
  return sql;
75
77
  }
76
78
 
77
- static appendSearchCondition2Count(originSql,searchCondition){
79
+ static appendSearchCondition2Count(originSql, searchCondition) {
78
80
  ///如果包含了这个特定的字符,则替换
79
- if (originSql.indexOf('#APPENDSEARCH#')>=0)
80
- return originSql.replace('#APPENDSEARCH#',searchCondition);
81
- return originSql + ' '+ searchCondition;
81
+ if (originSql.indexOf('#APPENDSEARCH#') >= 0)
82
+ return originSql.replace('#APPENDSEARCH#', searchCondition);
83
+ return originSql + ' ' + searchCondition;
82
84
  }
83
85
  /**
84
86
  * 校验参数的类型
@@ -87,9 +89,9 @@ class RequestParser {
87
89
  * @param {*} defaultValue
88
90
  * @returns
89
91
  */
90
- static validatorParamsType(value,dataType,defaultValue=null){
92
+ static validatorParamsType(value, dataType, defaultValue = null) {
91
93
  if (!value || !dataType) return value;
92
- switch (dataType.toLowerCase()){
94
+ switch (dataType.toLowerCase()) {
93
95
  case 'guid': ///限制长度为36位的GUID
94
96
  if (value.length != 36 || value.split('-').length != 5) return defaultValue;
95
97
  break;
@@ -112,21 +114,21 @@ class RequestParser {
112
114
  * 检查是否有Sql注入的风险
113
115
  * @param {*} sql
114
116
  */
115
- static checkSqlInjection(sql){
116
- if(!sql) return sql;
117
+ static checkSqlInjection(sql) {
118
+ if (!sql) return sql;
117
119
  let sqlError = sql.match(FORBID_SQL_KEYWORD); //strict ? sql.match(FORBID_SQL_KEYWORD_STRICT):sql.match(FORBID_SQL_KEYWORD);
118
- if (sqlError && sqlError.length>0) return '';
120
+ if (sqlError && sqlError.length > 0) return '';
119
121
  return sql;
120
122
  }
121
123
  /*
122
124
  * 列表请求上下文中获取需要的信息
123
125
  * 如Page ,PageSize , Sort 等等
124
126
  */
125
- static getListInfo(req,cfgType=0,dao) {
127
+ static getListInfo(req, cfgType = 0, dao) {
126
128
  const dataKey = utility.ifNull(req.dataKey, req.query.datakey);
127
129
  ///确认是否是需要导出Excel
128
- const export2Excel =(req.query.exportexcel+"").toLowerCase()==="true";
129
- 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;
130
132
  req.pageSize = req.query.rows || req.body.rows || 100;
131
133
  req.sort = req.query.sort || req.body.sort;
132
134
  ///防止sortSql 注入
@@ -135,7 +137,7 @@ class RequestParser {
135
137
  req.sort = this.checkSqlInjection(req.sort);
136
138
  }
137
139
  //防止注入式Sql
138
- if (isNaN(req.pageSize)){
140
+ if (isNaN(req.pageSize)) {
139
141
  req.pageSize = 30;
140
142
  }
141
143
  //防止注入式Sql
@@ -143,61 +145,61 @@ class RequestParser {
143
145
  req.page = 1;
144
146
  }
145
147
  ///最大允许获取100条数据
146
- req.pageSize = Math.min(req.pageSize,100);
148
+ req.pageSize = Math.min(req.pageSize, 100);
147
149
  let order = (req.body.order || req.query.order || '').trim().toLowerCase();
148
- if (order && req.sort){
149
- if (ORDER_STRING.indexOf(order)>=0) {
150
+ if (order && req.sort) {
151
+ if (ORDER_STRING.indexOf(order) >= 0) {
150
152
  req.sort = req.sort + ' ' + order
151
153
  }
152
154
  }
153
155
  //req.order =req.sort? utility.ifNull((req.body.order || req.query.order), ""):'';
154
156
  if (dataKey) {
155
- req.dataConfig = dataconfig.getConfig(dataKey,cfgType);
157
+ req.dataConfig = dataconfig.getConfig(dataKey, cfgType);
156
158
  if (req.dataConfig && req.dataConfig.list) {
157
159
  req.sqltype = req.dataConfig.list.sqltype || 'sql';
158
160
  req.fieldsMapping = req.dataConfig.list.field;
159
161
  req.footerMapping = req.dataConfig.list.footer;
160
162
  /**解析查询条件 */
161
163
  req.searchCondition = this.getSearchCondition({ request: req, refer: req.dataConfig.list.search });
162
- /**排序方式 */
164
+ /**排序方式 *///
163
165
  req.sort = req.sort || req.dataConfig.list.sort;
164
- /**来自req请求参数中的过滤条件 */
165
- let clientFilter = this.checkSqlInjection(this.parseAndReplaceSql(req,req.query.clientFilter),false);
166
-
167
- let listsql='';
166
+ /**来自req请求参数中的过滤条件 */
167
+ let clientFilter = this.checkSqlInjection(this.parseAndReplaceSql(req,req.query.clientFilter),false);
168
+
169
+ let listsql = '';
168
170
  ///是否有列表尾部的统计SQL
169
171
  let countsql = '';
170
- switch (req.sqltype){
171
- case "sql":
172
- listsql = req.dataConfig.list.sql;
173
- countsql = req.dataConfig.list.countsql;
172
+ switch (req.sqltype) {
173
+ case "sql":
174
+ listsql = req.dataConfig.list.sql;
175
+ countsql = req.dataConfig.list.countsql;
174
176
  break;
175
177
  case "property":
176
178
  if (dao && dao.constantsql) {
177
- listsql = dao.constantsql[listsql].list;
178
- countsql = dao.constantsql[listsql].countsql;
179
+ listsql = dao.constantsql[listsql].list;
180
+ countsql = dao.constantsql[listsql].countsql;
179
181
  }
180
182
  break;
181
183
  case "func":
182
- if (dao && dao[listsql] && typeof(dao[listsql])==='function' )
183
- listsql = dao[listsql]();
184
+ if (dao && dao[listsql] && typeof (dao[listsql]) === 'function')
185
+ listsql = dao[listsql]();
184
186
  break;
185
187
  }
186
188
  /**根据过滤条件、排序条件、分页获取的方式,和原始sql拼接成最终获取数据的sql */
187
- req.listSql = this.parseAndReplaceSql(req,listsql) +
188
- ' ' + req.searchCondition + clientFilter +
189
- //(utility.isNullOrEmpty(req.sort) ? '' : (' order by ' + (req.sort+' '+req.order))) +
190
- (req.sort ? (' order by ' + req.sort ):'') +
191
- (export2Excel?'':' limit ' + req.pageSize + ' OFFSET ' + (req.page - 1) * req.pageSize) +
192
- /////在Sql中再放入获取总记录数的语句
193
- ';SELECT FOUND_ROWS() AS total;';
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;';
194
196
  /*** 如果存在汇总列的sql,则把SQL放置在最末尾 */
195
- if(countsql){
197
+ if (countsql) {
196
198
  req.countSql = true;
197
- req.listSql+= this.appendSearchCondition2Count(
198
- this.parseAndReplaceSql(req,countsql),
199
- req.searchCondition)+';'
200
- }
199
+ req.listSql += this.appendSearchCondition2Count(
200
+ this.parseAndReplaceSql(req, countsql),
201
+ req.searchCondition) + ';'
202
+ }
201
203
  }
202
204
  }
203
205
  }
@@ -211,7 +213,7 @@ class RequestParser {
211
213
  req.dataConfig = dataconfig.getConfig(dataKey);
212
214
  if (req.dataConfig && req.dataConfig.detail) {
213
215
  ///主键存储
214
- req.primary=req.dataConfig.detail.primary;
216
+ req.primary = req.dataConfig.detail.primary;
215
217
  req.fieldsMapping = req.dataConfig.detail.field;
216
218
  req.primaryIsAutoIncrease = req.dataConfig.detail.primaryIsAutoIncrease;
217
219
  }