abler-api 0.1.72 → 0.1.74
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/cjs/pp-util.js +549 -782
- package/package.json +5 -2
package/dist/cjs/pp-util.js
CHANGED
|
@@ -1,102 +1,337 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var require$$0 = require('
|
|
4
|
-
var require$$1 = require('
|
|
5
|
-
var require$$2 = require('
|
|
6
|
-
var require$$
|
|
7
|
-
var require$$
|
|
8
|
-
var require$$
|
|
9
|
-
var require$$
|
|
10
|
-
var require$$1
|
|
3
|
+
var require$$0 = require('fs');
|
|
4
|
+
var require$$1$1 = require('crypto');
|
|
5
|
+
var require$$2$1 = require('basic-auth');
|
|
6
|
+
var require$$2 = require('abler-lang');
|
|
7
|
+
var require$$3 = require('abler-util');
|
|
8
|
+
var require$$4 = require('abler-db');
|
|
9
|
+
var require$$6 = require('abler-net');
|
|
10
|
+
var require$$1 = require('path');
|
|
11
|
+
var require$$2$2 = require('abler-messenger');
|
|
11
12
|
var require$$0$1 = require('node-cron');
|
|
12
13
|
|
|
13
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
15
|
|
|
15
16
|
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
|
|
16
|
-
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
|
|
17
|
+
var require$$1__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$1$1);
|
|
18
|
+
var require$$2__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$2$1);
|
|
17
19
|
var require$$2__default = /*#__PURE__*/_interopDefaultLegacy(require$$2);
|
|
18
20
|
var require$$3__default = /*#__PURE__*/_interopDefaultLegacy(require$$3);
|
|
19
21
|
var require$$4__default = /*#__PURE__*/_interopDefaultLegacy(require$$4);
|
|
20
|
-
var require$$
|
|
21
|
-
var require$$1__default
|
|
22
|
-
var require$$
|
|
22
|
+
var require$$6__default = /*#__PURE__*/_interopDefaultLegacy(require$$6);
|
|
23
|
+
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
|
|
24
|
+
var require$$2__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$2$2);
|
|
23
25
|
var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
|
|
24
26
|
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
27
|
+
const fs$1 = require$$0__default["default"];
|
|
28
|
+
const path = require$$1__default["default"];
|
|
29
|
+
const {
|
|
30
|
+
t_f: t_f$3
|
|
31
|
+
} = require$$2__default["default"];
|
|
32
|
+
const ppUtil$4 = require$$3__default["default"].ppUtil;
|
|
28
33
|
const {
|
|
29
34
|
dbUtil: dbUtil$1,
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
ppRedis,
|
|
36
|
+
kvStorage: kvStorage$1,
|
|
37
|
+
redisSimulator
|
|
38
|
+
} = require$$4__default["default"];
|
|
39
|
+
let conf$3, err$2;
|
|
40
|
+
// const dbCheck = require('../dbupdate/dd-version');
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* API服务启动时前置条件检查
|
|
44
|
+
* ok = await preconditions
|
|
45
|
+
* .setAppName(conf.thisApp)
|
|
46
|
+
* .addCheckPromise(preconditions.checkExEnvSetting())
|
|
47
|
+
* .addCheckPromise(preconditions.checkRedis())
|
|
48
|
+
* .addCheckPromise(checkDatabase())
|
|
49
|
+
* .addChecker(myChecker, args)
|
|
50
|
+
* .checkAll()
|
|
51
|
+
*/
|
|
52
|
+
class preconditions$2 {
|
|
53
|
+
static appName;
|
|
54
|
+
static checkFunctions = [];
|
|
55
|
+
static checkPromises = [];
|
|
56
|
+
static setAppName(aName) {
|
|
57
|
+
ppUtil$4.configNeeded();
|
|
58
|
+
conf$3 = ppUtil$4.appConfig;
|
|
59
|
+
err$2 = ppUtil$4.appErrCfg;
|
|
60
|
+
preconditions$2.appName = aName || conf$3.thisApp;
|
|
61
|
+
return preconditions$2;
|
|
62
|
+
}
|
|
63
|
+
static addCheckPromise(p) {
|
|
64
|
+
preconditions$2.checkPromises.push(p);
|
|
65
|
+
return preconditions$2;
|
|
66
|
+
}
|
|
67
|
+
static addChecker(checkFunc, args, blocked) {
|
|
68
|
+
preconditions$2.checkFunctions.push({
|
|
69
|
+
check: checkFunc,
|
|
70
|
+
args: args,
|
|
71
|
+
blocked: blocked
|
|
72
|
+
});
|
|
73
|
+
return preconditions$2;
|
|
74
|
+
}
|
|
75
|
+
static pushMessage(msg) {
|
|
76
|
+
if (msg) {
|
|
77
|
+
if (!preconditions$2.messages) {
|
|
78
|
+
preconditions$2.messages = [];
|
|
79
|
+
}
|
|
80
|
+
preconditions$2.messages.push(`${preconditions$2.messages.length + 1}. ${msg}`);
|
|
81
|
+
}
|
|
82
|
+
return msg;
|
|
83
|
+
}
|
|
84
|
+
static async checkAll() {
|
|
85
|
+
try {
|
|
86
|
+
// for (let i = 0; i < preconditions.checkFunctions.length; i++) {
|
|
87
|
+
// const f = preconditions.checkFunctions[i];
|
|
88
|
+
// // preconditions.addCheckPromise(f.check(f.args));
|
|
89
|
+
// preconditions.pushMessage(await f.check(f.args));
|
|
90
|
+
// }
|
|
91
|
+
while (preconditions$2.checkFunctions.length > 0) {
|
|
92
|
+
const f = preconditions$2.checkFunctions.shift();
|
|
93
|
+
if (preconditions$2.pushMessage(await f.check(f.args)) && f.blocked) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// for (let i = 0; i < preconditions.checkPromises.length; i++) {
|
|
99
|
+
// preconditions.pushMessage(await preconditions.checkPromises[i]);
|
|
100
|
+
// }
|
|
101
|
+
while (preconditions$2.checkPromises.length > 0) {
|
|
102
|
+
const p = preconditions$2.checkPromises.shift();
|
|
103
|
+
preconditions$2.pushMessage(await p);
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
preconditions$2.pushMessage(e.message);
|
|
107
|
+
}
|
|
108
|
+
let text = "";
|
|
109
|
+
if (preconditions$2.messages) {
|
|
110
|
+
text = t_f$3("*** 由于以下原因,%s 尚不能正常提供服务:\n\n", preconditions$2.appName) + preconditions$2.messages.join("\n\n") + "\n\n*** 请检查以上各项条件,修复后重新启动服务";
|
|
111
|
+
console.log("\n" + text);
|
|
112
|
+
// for (let i = 0; i < preconditions.messages.length; i++) {
|
|
113
|
+
// console.log(preconditions.messages[i]);
|
|
114
|
+
// }
|
|
115
|
+
}
|
|
116
|
+
if (!(await fs$1.async_exists("../log"))) {
|
|
117
|
+
await fs$1.async_mkdir("../log");
|
|
118
|
+
}
|
|
119
|
+
await fs$1.async_writeFile(`../log/preconditions`, text);
|
|
120
|
+
return !text;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 检查器
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 检查本机外部配置文件版本
|
|
127
|
+
*/
|
|
128
|
+
static async checkExEnvSetting(loadjs) {
|
|
129
|
+
return await checkExEnvSetting(loadjs);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* redis 可用性检查
|
|
134
|
+
*/
|
|
135
|
+
static async checkRedis() {
|
|
136
|
+
return await checkRedis();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 初始化数据库连接
|
|
141
|
+
*/
|
|
142
|
+
static async initDb() {
|
|
143
|
+
return await initDb();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 初始化键值对存储器
|
|
148
|
+
*/
|
|
149
|
+
static async initKvStorage(dbSql) {
|
|
150
|
+
return await initKvStorage(dbSql);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// /**
|
|
154
|
+
// * 数据库可用性及业务数据版本版本检查
|
|
155
|
+
// */
|
|
156
|
+
// static async checkDatabase() {
|
|
157
|
+
// return await checkDatabase();
|
|
158
|
+
// }
|
|
159
|
+
}
|
|
160
|
+
async function createEnvSettingFile(fileName, lastEnvSettingEx) {
|
|
161
|
+
try {
|
|
162
|
+
const cfgText = await ppUtil$4.doCreateEnvSettingFile(fileName, lastEnvSettingEx);
|
|
163
|
+
if (cfgText.indexOf(`cfgVersion: "${conf$3._envSetting.cfgVersion}"`) > 0) {
|
|
164
|
+
console.log(t_f$3("\n*** 已創建新的本機環境配置文件\n%s\n请檢查各項內容是否正确(此项更新服务可正常运行)\n\n", fileName));
|
|
165
|
+
return "";
|
|
166
|
+
}
|
|
167
|
+
return t_f$3("已創建新的本機環境配置文件\n%s\n请檢查並正確設置各項內容,然後將配置版本號修改為%s", fileName, conf$3._envSettings.default.cfgVersion);
|
|
168
|
+
} catch (e) {
|
|
169
|
+
return t_f$3("創建本機環境配置文件失敗\n《%s》\n%s", fileName, err$2.ERROR(e).message);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function checkExEnvSetting(loadjs) {
|
|
173
|
+
if (conf$3._envSetting.localSettingImported) return "";
|
|
174
|
+
try {
|
|
175
|
+
let fileName = conf$3.getEnvSettingFileName();
|
|
176
|
+
if (!fs$1.existsSync(fileName)) {
|
|
177
|
+
return await createEnvSettingFile(fileName);
|
|
178
|
+
}
|
|
179
|
+
let envSettingEx = loadjs(fileName);
|
|
180
|
+
if (envSettingEx.cfgVersion !== conf$3._envSettings.default.cfgVersion) {
|
|
181
|
+
if (envSettingEx.cfgVersion !== "0.0") {
|
|
182
|
+
let fp = path.parse(fileName);
|
|
183
|
+
let lastVerFileName = path.join(fp.dir, fp.name + envSettingEx.cfgVersion + fp.ext);
|
|
184
|
+
if (!fs$1.existsSync(lastVerFileName)) {
|
|
185
|
+
fs$1.renameSync(fileName, lastVerFileName);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
let msg = await createEnvSettingFile(fileName, envSettingEx);
|
|
189
|
+
if (msg) {
|
|
190
|
+
return msg;
|
|
191
|
+
}
|
|
192
|
+
delete require.cache[fileName];
|
|
193
|
+
}
|
|
194
|
+
ppUtil$4.importExEnvSetting(conf$3._envSetting, fileName, loadjs);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
return t_f$3("导入本机环境配置失败\n%s", e.stack);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// async function checkDatabase() {
|
|
201
|
+
// return dbCheck.check().then(info => info.updateMessage);
|
|
202
|
+
// }
|
|
203
|
+
|
|
204
|
+
async function checkRedis() {
|
|
205
|
+
if (!conf$3.redis.enabled) return "";
|
|
206
|
+
const redis = ppRedis.newClient("kv");
|
|
207
|
+
// console.log(`checkRedis begin:`);
|
|
208
|
+
await ppUtil$4.wait(15 * 1000, param => {
|
|
209
|
+
if (redis.ready && redis.connected || redis.error) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
}).catch(e => {
|
|
213
|
+
redis.error = e;
|
|
214
|
+
});
|
|
215
|
+
if (redis.error) {
|
|
216
|
+
console.log(t_f$3("未能成功連接 redis: %s,請檢查相關設置", redis.error));
|
|
217
|
+
return t_f$3("未能成功連接 redis: %s,請檢查相關設置", redis.error);
|
|
218
|
+
}
|
|
219
|
+
// console.log(`checkRedis done:`);
|
|
220
|
+
// console.log(redis);
|
|
221
|
+
}
|
|
222
|
+
async function initDb() {
|
|
223
|
+
try {
|
|
224
|
+
dbUtil$1.config(conf$3, err$2);
|
|
225
|
+
} catch (e) {
|
|
226
|
+
if (e.reason === 'bad decrypt') {
|
|
227
|
+
e = new Error(t_f$3("解密数据库密码(%s)失败", conf$3.dbconn.dbpwd));
|
|
228
|
+
}
|
|
229
|
+
// if (e.reason === 'bad decrypt') {
|
|
230
|
+
// e = new Error(`解密Redis密码(${conf.redis.password})失败`);
|
|
231
|
+
// }
|
|
232
|
+
return t_f$3("初始化数据库连接失败(%s)", e.message);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function initKvStorage(dbSql) {
|
|
236
|
+
try {
|
|
237
|
+
kvStorage$1.config(conf$3, err$2);
|
|
238
|
+
if (conf$3.redis.enabled) {
|
|
239
|
+
kvStorage$1.setRedis(ppRedis.newClient("kv"));
|
|
240
|
+
} else {
|
|
241
|
+
kvStorage$1.setRedis(new redisSimulator(dbSql));
|
|
242
|
+
}
|
|
243
|
+
} catch (e) {
|
|
244
|
+
// if (e.reason === 'bad decrypt') {
|
|
245
|
+
// e = new Error(`解密Redis密码(${conf.redis.password})失败`);
|
|
246
|
+
// }
|
|
247
|
+
return t_f$3("初始化键值对存储器失败(%s)", e.message);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
var ppPrecond = preconditions$2;
|
|
251
|
+
|
|
252
|
+
const fs = require$$0__default["default"];
|
|
253
|
+
const crypto = require$$1__default$1["default"];
|
|
254
|
+
const getBasicAuthorization = require$$2__default$1["default"];
|
|
32
255
|
const {
|
|
33
|
-
|
|
256
|
+
t_f: t_f$2,
|
|
257
|
+
t
|
|
258
|
+
} = require$$2__default["default"];
|
|
259
|
+
const ppUtil$3 = require$$3__default["default"].ppUtil;
|
|
260
|
+
const {
|
|
261
|
+
dbUtil,
|
|
262
|
+
kvStorage
|
|
34
263
|
} = require$$4__default["default"];
|
|
35
|
-
const
|
|
36
|
-
|
|
264
|
+
const {
|
|
265
|
+
netUtil: netUtil$1
|
|
266
|
+
} = require$$6__default["default"];
|
|
267
|
+
const preconditions$1 = ppPrecond;
|
|
268
|
+
let conf$2, appSetting, err$1, dbSql;
|
|
37
269
|
const pnToken = "access_token",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
pnApiSecret = "apiSecret",
|
|
43
|
-
|
|
44
|
-
const MD5 = ppUtil$
|
|
45
|
-
|
|
46
|
-
|
|
270
|
+
hnToken = pnToken,
|
|
271
|
+
pnApiKey = "apiKey",
|
|
272
|
+
hnApiKey = pnApiKey.toLowerCase(),
|
|
273
|
+
// 我们接收到的 headers 中的字段名总是全小写的
|
|
274
|
+
pnApiSecret = "apiSecret",
|
|
275
|
+
hnApiSecret = pnApiSecret.toLowerCase();
|
|
276
|
+
const MD5 = ppUtil$3.MD5,
|
|
277
|
+
moveProperty = ppUtil$3.moveProperty;
|
|
47
278
|
class apiUtil$2 {
|
|
48
|
-
static debugFlag = ppUtil$
|
|
49
|
-
|
|
50
|
-
static testFlag = ppUtil$4.newGuid();
|
|
279
|
+
static debugFlag = ppUtil$3.newGuid(); //应用必须设置,否则谁也不知道是啥
|
|
280
|
+
static testFlag = ppUtil$3.newGuid();
|
|
51
281
|
static envId_dev = "?";
|
|
52
282
|
static _validateBasicAuth = function (userName, password) {
|
|
53
283
|
throw {
|
|
54
284
|
status: 500,
|
|
55
285
|
message: 'no basic auth validator'
|
|
56
286
|
};
|
|
57
|
-
};
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// static apiCallRecSaver;
|
|
58
290
|
|
|
59
291
|
static config(appConfig, appErrCfg, appDbSql) {
|
|
60
|
-
conf$
|
|
61
|
-
appSetting = conf$
|
|
62
|
-
err$
|
|
292
|
+
conf$2 = appConfig;
|
|
293
|
+
appSetting = conf$2?.appSetting;
|
|
294
|
+
err$1 = appErrCfg;
|
|
63
295
|
dbSql = appDbSql;
|
|
64
|
-
ppUtil$
|
|
65
|
-
kvStorage
|
|
296
|
+
ppUtil$3.config(appConfig, appErrCfg);
|
|
297
|
+
kvStorage.config(appConfig, appErrCfg);
|
|
66
298
|
apiUtil$2.debugFlag = appSetting?.debugFlag || apiUtil$2.debugFlag;
|
|
67
|
-
apiUtil$2.testFlag = appSetting?.testFlag || apiUtil$2.testFlag;
|
|
68
|
-
|
|
299
|
+
apiUtil$2.testFlag = appSetting?.testFlag || apiUtil$2.testFlag;
|
|
300
|
+
// apiUtil.apiCallRecSaver = apiCallRecSaver;
|
|
301
|
+
preconditions$1.setAppName();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
//#region ===== 需要应用系统重写的方法
|
|
69
305
|
|
|
70
306
|
/**
|
|
71
307
|
* 根据机构标识获取机构的 ApiSecret
|
|
72
308
|
* @param companyId
|
|
73
309
|
* @returns {*}
|
|
74
310
|
*/
|
|
75
|
-
|
|
76
|
-
|
|
77
311
|
static _getApiSecret(companyId) {
|
|
78
|
-
return ppUtil$
|
|
312
|
+
return ppUtil$3.newGuid();
|
|
79
313
|
}
|
|
314
|
+
|
|
80
315
|
/**
|
|
81
316
|
* 保存 API 调用记录,应用系统必须重写此方法
|
|
82
317
|
* @param rec
|
|
83
318
|
* @param responseData
|
|
84
319
|
* @returns {Promise<unknown>}
|
|
85
320
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
321
|
static async _saveApiCallRec(rec, responseData) {
|
|
89
322
|
return false;
|
|
90
323
|
}
|
|
324
|
+
|
|
91
325
|
/**
|
|
92
326
|
* 检查API调用签名是否已经完成了验证
|
|
93
327
|
* @param req
|
|
94
328
|
*/
|
|
95
|
-
|
|
96
|
-
|
|
97
329
|
static signatureVerified(req) {
|
|
98
330
|
return req?.signatureVerified;
|
|
99
|
-
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
//#endregion
|
|
334
|
+
|
|
100
335
|
//#region ===== API服务相关工具
|
|
101
336
|
|
|
102
337
|
/**
|
|
@@ -104,16 +339,12 @@ class apiUtil$2 {
|
|
|
104
339
|
* @param req
|
|
105
340
|
* @returns {*}
|
|
106
341
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
342
|
static extractParams(req) {
|
|
110
343
|
if (!req._requestParams) {
|
|
111
344
|
if (req.method === "POST" || req.method === "PUT") {
|
|
112
345
|
let contentType = req.headers["content-type"] || "application/json";
|
|
113
|
-
|
|
114
346
|
if (contentType.startsWith("multipart/form-data")) {
|
|
115
347
|
req._requestParams = new Object();
|
|
116
|
-
|
|
117
348
|
for (let k in req.body) {
|
|
118
349
|
req._requestParams[k] = req.body[k];
|
|
119
350
|
}
|
|
@@ -123,14 +354,11 @@ class apiUtil$2 {
|
|
|
123
354
|
} else {
|
|
124
355
|
req._requestParams = req.query;
|
|
125
356
|
}
|
|
126
|
-
|
|
127
357
|
if (req.headers["content-type"] !== "application/json") {
|
|
128
358
|
const obj = req._requestParams;
|
|
129
|
-
|
|
130
359
|
for (let key in obj) {
|
|
131
360
|
if (!obj.hasOwnProperty(key)) continue;
|
|
132
361
|
let value = obj[key];
|
|
133
|
-
|
|
134
362
|
if (typeof value === "string" && value.length > 0) {
|
|
135
363
|
if (value[0] === "{" || value[0] === "[") {
|
|
136
364
|
try {
|
|
@@ -138,31 +366,24 @@ class apiUtil$2 {
|
|
|
138
366
|
continue;
|
|
139
367
|
} catch (e) {}
|
|
140
368
|
}
|
|
141
|
-
|
|
142
369
|
let x = JSON.hbDateConv(key, value);
|
|
143
|
-
|
|
144
370
|
if (x !== value) {
|
|
145
371
|
obj[key] = x;
|
|
146
372
|
}
|
|
147
373
|
}
|
|
148
374
|
}
|
|
149
375
|
}
|
|
150
|
-
|
|
151
376
|
if (req.params) {
|
|
152
377
|
req._requestParams = Object.assign(req.params, req._requestParams);
|
|
153
378
|
}
|
|
154
|
-
|
|
155
379
|
apiUtil$2.setParamsFunctions(req._requestParams);
|
|
156
380
|
}
|
|
157
|
-
|
|
158
381
|
return req._requestParams;
|
|
159
382
|
}
|
|
160
|
-
|
|
161
383
|
static extractTokenData(req) {
|
|
162
384
|
if (req.tokenData) {
|
|
163
385
|
return req.tokenData;
|
|
164
386
|
}
|
|
165
|
-
|
|
166
387
|
let params = apiUtil$2.extractParams(req);
|
|
167
388
|
let tokenData = {
|
|
168
389
|
apiKey: req.headers[hnApiKey] || params[pnApiKey],
|
|
@@ -171,38 +392,34 @@ class apiUtil$2 {
|
|
|
171
392
|
};
|
|
172
393
|
return tokenData;
|
|
173
394
|
}
|
|
395
|
+
|
|
174
396
|
/**
|
|
175
397
|
* 为从传入请求中解出的参数对象设置一些函数属性,包括 asNumber, asBool
|
|
176
398
|
* @param params
|
|
177
399
|
*/
|
|
178
|
-
|
|
179
|
-
|
|
180
400
|
static setParamsFunctions(params) {
|
|
181
|
-
ppUtil$
|
|
401
|
+
ppUtil$3.defUnenumProp(params, "asNumber", function (name, minValue, maxValue, defaultValue) {
|
|
182
402
|
// if (!this.hasOwnProperty(name)) // {} 定义的对象没有 hasOwnProperty 函数
|
|
183
403
|
if (this[name] === undefined) return defaultValue;
|
|
184
404
|
let result = +this[name];
|
|
185
|
-
|
|
186
405
|
if (typeof result !== "number" || result < minValue || result > maxValue) {
|
|
187
|
-
throw [err$
|
|
406
|
+
throw [err$1.INVALID_PARAM, t_f$2("参数 %s 必须是 %s ~ %s 之间的数字", name, minValue, maxValue)];
|
|
188
407
|
}
|
|
189
|
-
|
|
190
408
|
return result;
|
|
191
409
|
});
|
|
192
|
-
ppUtil$
|
|
410
|
+
ppUtil$3.defUnenumProp(params, "asBool", function (name, defaultValue) {
|
|
193
411
|
if (this[name] === undefined) return defaultValue;
|
|
194
412
|
let result = JSON.parse(this[name]);
|
|
195
413
|
return !!result;
|
|
196
414
|
});
|
|
197
415
|
}
|
|
416
|
+
|
|
198
417
|
/**
|
|
199
418
|
* 将返回结果转向到指定地址或者通过response发送返回结果
|
|
200
419
|
* @param res
|
|
201
420
|
* @param redirectUrl
|
|
202
421
|
* @param data
|
|
203
422
|
*/
|
|
204
|
-
|
|
205
|
-
|
|
206
423
|
static sendOrRedirect(res, redirectUrl, data) {
|
|
207
424
|
if (redirectUrl) {
|
|
208
425
|
redirectUrl = netUtil$1.urlAppendParams(redirectUrl, data, true);
|
|
@@ -211,14 +428,13 @@ class apiUtil$2 {
|
|
|
211
428
|
res.send(data);
|
|
212
429
|
}
|
|
213
430
|
}
|
|
431
|
+
|
|
214
432
|
/**
|
|
215
433
|
* 生成 API 成功返回结果
|
|
216
434
|
* @param data
|
|
217
435
|
* @param req
|
|
218
436
|
* @returns {{datetime: Date, success: boolean, stateCode: number, message: string}}
|
|
219
437
|
*/
|
|
220
|
-
|
|
221
|
-
|
|
222
438
|
static apiSuccess(data, req, spOrderNum) {
|
|
223
439
|
let response = {
|
|
224
440
|
success: true,
|
|
@@ -226,93 +442,80 @@ class apiUtil$2 {
|
|
|
226
442
|
message: '',
|
|
227
443
|
datetime: new Date()
|
|
228
444
|
};
|
|
229
|
-
|
|
230
445
|
if (spOrderNum) {
|
|
231
446
|
response.spOrderNum = spOrderNum;
|
|
232
447
|
}
|
|
233
|
-
|
|
234
448
|
if (req && req.headers) {
|
|
235
449
|
let userAgent = req.headers["user-agent"];
|
|
236
|
-
|
|
237
450
|
if (userAgent && userAgent.startsWith("Postman")) {
|
|
238
451
|
response._elapse = (new Date().valueOf() - req.headers.timestamp) / 1000;
|
|
239
452
|
}
|
|
240
453
|
}
|
|
241
|
-
|
|
242
454
|
if (data && data._message_) {
|
|
243
455
|
response.message = data._message_;
|
|
244
456
|
delete data._message_;
|
|
245
457
|
}
|
|
246
|
-
|
|
247
458
|
response.data = data;
|
|
248
459
|
if (Array.isArray(data) && typeof data.recordCount != 'undefined') response.recordCount = data.recordCount;
|
|
249
460
|
return response;
|
|
250
461
|
}
|
|
462
|
+
|
|
251
463
|
/**
|
|
252
464
|
* 生成 API 失败返回结果
|
|
253
465
|
* @param error
|
|
254
466
|
* @param req
|
|
255
467
|
* @returns {*}
|
|
256
468
|
*/
|
|
257
|
-
|
|
258
|
-
|
|
259
469
|
static apiFail(error, req, spOrderNum) {
|
|
260
470
|
configNeeded();
|
|
261
|
-
let response = err$
|
|
471
|
+
let response = err$1.ERROR(error, err$1.errorLangParamFlag + ppUtil$3.getMsgLang(req));
|
|
262
472
|
response.datetime = new Date();
|
|
263
|
-
|
|
264
473
|
if (spOrderNum) {
|
|
265
474
|
response.spOrderNum = spOrderNum;
|
|
266
475
|
}
|
|
267
|
-
|
|
268
476
|
if (req && req.headers) {
|
|
269
477
|
let userAgent = req.headers["user-agent"];
|
|
270
|
-
|
|
271
478
|
if (userAgent && userAgent.startsWith("Postman")) {
|
|
272
479
|
response._elapse = (new Date().valueOf() - req.headers.timestamp) / 1000;
|
|
273
480
|
}
|
|
274
481
|
}
|
|
275
|
-
|
|
276
482
|
return response;
|
|
277
483
|
}
|
|
484
|
+
|
|
278
485
|
/**
|
|
279
486
|
* 生成面向服务商的API成功返回结果
|
|
280
487
|
* @param data
|
|
281
488
|
* @param req
|
|
282
489
|
* @returns {*}
|
|
283
490
|
*/
|
|
284
|
-
|
|
285
|
-
|
|
286
491
|
static spoApiSucc(data, req) {
|
|
287
492
|
let params = apiUtil$2.extractParams(req);
|
|
288
493
|
return apiUtil$2.apiSuccess(data, req, params.spOrderNum);
|
|
289
494
|
}
|
|
495
|
+
|
|
290
496
|
/**
|
|
291
497
|
* 生成面向服务商的API失败返回结果
|
|
292
498
|
* @param error
|
|
293
499
|
* @param req
|
|
294
500
|
* @returns {*}
|
|
295
501
|
*/
|
|
296
|
-
|
|
297
|
-
|
|
298
502
|
static spoApiFail(error, req) {
|
|
299
503
|
let params = apiUtil$2.extractParams(req);
|
|
300
504
|
return apiUtil$2.apiFail(error, req, params.spOrderNum);
|
|
301
505
|
}
|
|
506
|
+
|
|
302
507
|
/**
|
|
303
508
|
* API 服务结束,发送响应
|
|
304
509
|
* @param response
|
|
305
510
|
* @param promise
|
|
306
511
|
*/
|
|
307
|
-
|
|
308
|
-
|
|
309
512
|
static sendResponse(response, promise) {
|
|
310
513
|
promise.then(function (data) {
|
|
311
514
|
if (!response.finished) {
|
|
312
515
|
try {
|
|
313
516
|
response.send(data);
|
|
314
517
|
} catch (e) {
|
|
315
|
-
console.log(
|
|
518
|
+
console.log(t_f$2("response.send 出错了,req.url: %s, response:", response.req.url), response);
|
|
316
519
|
console.log("异常信息", e);
|
|
317
520
|
}
|
|
318
521
|
}
|
|
@@ -323,13 +526,12 @@ class apiUtil$2 {
|
|
|
323
526
|
}
|
|
324
527
|
});
|
|
325
528
|
}
|
|
529
|
+
|
|
326
530
|
/**
|
|
327
531
|
* API 服务结束,包装数据并发送响应
|
|
328
532
|
* @param response
|
|
329
533
|
* @param promise
|
|
330
534
|
*/
|
|
331
|
-
|
|
332
|
-
|
|
333
535
|
static async responseOf(response, promise) {
|
|
334
536
|
promise.then(function (data) {
|
|
335
537
|
// console.log('RES:', apiSuccess(data));
|
|
@@ -339,64 +541,58 @@ class apiUtil$2 {
|
|
|
339
541
|
if (!response.finished) response.send(apiUtil$2.apiFail(error, response.req));
|
|
340
542
|
});
|
|
341
543
|
}
|
|
544
|
+
|
|
342
545
|
/**
|
|
343
546
|
* 面向服务商的API结束,发送响应
|
|
344
547
|
* @param response
|
|
345
548
|
* @param promise
|
|
346
549
|
*/
|
|
347
|
-
|
|
348
|
-
|
|
349
550
|
static async spoApiResponse(response, promise) {
|
|
350
551
|
promise.then(function (result) {
|
|
351
552
|
let responseData = apiUtil$2.spoApiSucc(result, response.req);
|
|
352
|
-
|
|
353
553
|
apiUtil$2._saveApiCallRec(response.req.apiCallRec, responseData);
|
|
354
|
-
|
|
355
554
|
if (!response.finished) response.send(responseData);
|
|
356
555
|
}, function (error) {
|
|
357
556
|
// console.log('ERROR:', error);
|
|
358
557
|
let responseData = apiUtil$2.spoApiFail(error, response.req);
|
|
359
|
-
|
|
360
558
|
apiUtil$2._saveApiCallRec(response.req.apiCallRec, responseData);
|
|
361
|
-
|
|
362
559
|
if (!response.finished) response.send(responseData);
|
|
363
560
|
});
|
|
364
561
|
}
|
|
562
|
+
|
|
365
563
|
/**
|
|
366
564
|
* 从请求参数中获取查询参数
|
|
367
|
-
|
|
565
|
+
* @param req
|
|
368
566
|
* @param res
|
|
369
567
|
* @returns {*}
|
|
370
568
|
*/
|
|
371
|
-
|
|
372
|
-
|
|
373
569
|
static getQueryOptions(req, res) {
|
|
374
|
-
req.headers.timestamp = new Date().valueOf();
|
|
375
|
-
|
|
570
|
+
req.headers.timestamp = new Date().valueOf();
|
|
571
|
+
// let options = {replacements: {}};
|
|
376
572
|
let options = {};
|
|
377
573
|
let parameters = apiUtil$2.extractParams(req);
|
|
378
|
-
|
|
379
574
|
for (let qryParam in parameters) {
|
|
380
575
|
if (qryParam !== 'token') {
|
|
381
576
|
if (['start', 'limit', 'orderby', 'orderBy'].indexOf(qryParam) >= 0) {
|
|
382
577
|
options[qryParam] = parameters[qryParam];
|
|
383
578
|
delete parameters[qryParam];
|
|
384
|
-
}
|
|
579
|
+
}
|
|
580
|
+
// else
|
|
385
581
|
// options.replacements[qryParam] = parameters[qryParam];
|
|
386
|
-
|
|
387
582
|
}
|
|
388
583
|
}
|
|
389
|
-
|
|
390
584
|
if (options.limit && !options.start) {
|
|
391
585
|
options.start = 0;
|
|
392
586
|
}
|
|
393
|
-
|
|
394
587
|
if (options.orderby) {
|
|
395
588
|
options.orderBy = options.orderby;
|
|
396
|
-
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// options.__debug__ = req.headers['__debug__'] && req.headers['__debug__'] == "true";
|
|
397
592
|
|
|
593
|
+
options.replacements = parameters;
|
|
398
594
|
|
|
399
|
-
|
|
595
|
+
// if (arguments.length > 1) //其后的每个参数是要求必须存在的参数名称
|
|
400
596
|
// {
|
|
401
597
|
// for(i=1; i<arguments.length; i++){
|
|
402
598
|
// var paramName = arguments[i];
|
|
@@ -408,14 +604,13 @@ class apiUtil$2 {
|
|
|
408
604
|
options.userInfo = req.userInfo;
|
|
409
605
|
return apiUtil$2.setOptionsPropFuncions(options, res);
|
|
410
606
|
}
|
|
607
|
+
|
|
411
608
|
/**
|
|
412
609
|
* 为API请求 options 设置属性
|
|
413
610
|
* @param options
|
|
414
611
|
* @param res
|
|
415
612
|
* @returns {{identifyLimit}|*}
|
|
416
613
|
*/
|
|
417
|
-
|
|
418
|
-
|
|
419
614
|
static setOptionsPropFuncions(options, res) {
|
|
420
615
|
// if (!options.identifyLimit) {
|
|
421
616
|
// // 根据企业标识获取身份认证限制相关设置,如果没有传递企业标识,
|
|
@@ -451,9 +646,9 @@ class apiUtil$2 {
|
|
|
451
646
|
enumerable: false
|
|
452
647
|
});
|
|
453
648
|
}
|
|
454
|
-
|
|
455
649
|
return options;
|
|
456
650
|
}
|
|
651
|
+
|
|
457
652
|
/**
|
|
458
653
|
* 从请求头获取token
|
|
459
654
|
* @param req
|
|
@@ -461,64 +656,53 @@ class apiUtil$2 {
|
|
|
461
656
|
* @param noErr
|
|
462
657
|
* @returns {Promise<*>}
|
|
463
658
|
*/
|
|
464
|
-
|
|
465
|
-
|
|
466
659
|
static extractToken(req, res, noErr) {
|
|
467
660
|
configNeeded();
|
|
468
|
-
|
|
469
661
|
if (!req.accessToken) {
|
|
470
662
|
let token = req.header('Authorization');
|
|
471
|
-
|
|
472
663
|
if (token && token.startsWith('Bearer ')) {
|
|
473
664
|
token = token.substring(7);
|
|
474
665
|
} else {
|
|
475
666
|
//检查post的信息或者url查询参数或者头信息
|
|
476
667
|
token = req.headers[hnToken] || req.headers['x-access-token']; //向后兼容
|
|
477
668
|
}
|
|
478
|
-
|
|
479
669
|
if (!token) {
|
|
480
670
|
let params = apiUtil$2.extractParams(req);
|
|
481
671
|
token = params[pnToken];
|
|
482
|
-
|
|
483
672
|
if (token) {
|
|
484
673
|
delete params[pnToken];
|
|
485
674
|
} else if (params.token) {
|
|
486
675
|
token = params.token; //向后兼容
|
|
487
|
-
|
|
488
676
|
delete params.token;
|
|
489
677
|
} else {
|
|
490
678
|
// 如果没有token,则返回错误
|
|
491
|
-
console.log(err$
|
|
492
|
-
|
|
679
|
+
console.log(err$1.TOKEN_NEEDED);
|
|
493
680
|
if (res) {
|
|
494
|
-
res.send(err$
|
|
681
|
+
res.send(err$1.ERROR(err$1.TOKEN_NEEDED));
|
|
495
682
|
} else if (!noErr) {
|
|
496
|
-
throw err$
|
|
683
|
+
throw err$1.TOKEN_NEEDED;
|
|
497
684
|
}
|
|
498
685
|
}
|
|
499
686
|
}
|
|
500
|
-
|
|
501
687
|
req.accessToken = token;
|
|
502
688
|
}
|
|
503
|
-
|
|
504
689
|
return req.accessToken;
|
|
505
690
|
}
|
|
691
|
+
|
|
506
692
|
/**
|
|
507
693
|
* 检查是不是内部调用,应用系统可替换此函数实施更隐秘的检查
|
|
508
694
|
* @param req
|
|
509
695
|
* @returns {Promise<boolean|undefined>}
|
|
510
696
|
*/
|
|
511
|
-
|
|
512
|
-
|
|
513
697
|
static async checkInternalToken(req) {
|
|
514
698
|
// return await checkInternalToken(req);
|
|
515
699
|
const params = apiUtil$2.extractParams(req);
|
|
516
700
|
req.accessToken = req.accessToken || apiUtil$2.extractToken(req);
|
|
517
|
-
|
|
518
|
-
if (req.accessToken === MD5(ppUtil$4.commonHashDisturbing)) {
|
|
701
|
+
if (req.accessToken === MD5(ppUtil$3.commonHashDisturbing)) {
|
|
519
702
|
//todo: 检查IP
|
|
520
703
|
params.__internal__ = true;
|
|
521
|
-
req.ignoreToken = true;
|
|
704
|
+
req.ignoreToken = true;
|
|
705
|
+
// if (params.idNum || params.personId) {
|
|
522
706
|
// return queryPersonUser(params.idNum, params.personId)
|
|
523
707
|
// .then(async userInfo => {
|
|
524
708
|
// if (!userInfo) {
|
|
@@ -532,20 +716,18 @@ class apiUtil$2 {
|
|
|
532
716
|
// } else {
|
|
533
717
|
// return true
|
|
534
718
|
// }
|
|
535
|
-
|
|
536
719
|
return true;
|
|
537
720
|
} else {
|
|
538
721
|
// console.log('token error.', req.accessToken);
|
|
539
|
-
throw err$
|
|
722
|
+
throw err$1.TOKEN_INVALID;
|
|
540
723
|
}
|
|
541
724
|
}
|
|
725
|
+
|
|
542
726
|
/**
|
|
543
727
|
* 检查请求是否存在合法的token,若不存在则抛出异常
|
|
544
728
|
* @param req
|
|
545
729
|
* @returns {Promise<void>}
|
|
546
730
|
*/
|
|
547
|
-
|
|
548
|
-
|
|
549
731
|
static async checkRequestToken(req) {
|
|
550
732
|
req.accessToken = req.accessToken || apiUtil$2.extractToken(req);
|
|
551
733
|
const tokenKey = apiUtil$2.userTokenStoreKey(req.accessToken);
|
|
@@ -559,39 +741,35 @@ class apiUtil$2 {
|
|
|
559
741
|
return await apiUtil$2.checkInternalToken(req);
|
|
560
742
|
});
|
|
561
743
|
}
|
|
744
|
+
|
|
562
745
|
/**
|
|
563
746
|
* 检查是不是调试模式
|
|
564
747
|
* @param req
|
|
565
748
|
* @returns {*|boolean|boolean}
|
|
566
749
|
*/
|
|
567
|
-
|
|
568
|
-
|
|
569
750
|
static isDebugMode(req) {
|
|
570
751
|
if (req.__debug__ === undefined) {
|
|
571
752
|
let dbgToken = req.headers['__debug__'] || req.headers[apiUtil$2.debugFlag];
|
|
572
|
-
|
|
573
753
|
if (dbgToken) {
|
|
574
754
|
let envId = process.env.ECS_DEPLOY_ID;
|
|
575
|
-
req.__debug__ = dbgToken && dbgToken === MD5(req.headers.timestamp, ppUtil$
|
|
755
|
+
req.__debug__ = dbgToken && dbgToken === MD5(req.headers.timestamp, ppUtil$3.commonHashDisturbing) && (envId === "florist_longdan" || envId === "shuzi");
|
|
576
756
|
} else {
|
|
577
757
|
req.__debug__ = false;
|
|
578
|
-
}
|
|
579
|
-
|
|
758
|
+
}
|
|
759
|
+
// console.log("__debug__:", req.__debug__, "dbgToken:", dbgToken);
|
|
580
760
|
}
|
|
581
|
-
|
|
582
|
-
|
|
761
|
+
return req.__debug__;
|
|
762
|
+
// return req.headers["postman-token"] || req.headers['__debug__'] && req.headers['__debug__'] == "true";
|
|
583
763
|
}
|
|
764
|
+
|
|
584
765
|
/**
|
|
585
766
|
* 检查是不是测试模式
|
|
586
767
|
* @param req
|
|
587
768
|
* @returns {*|boolean}
|
|
588
769
|
*/
|
|
589
|
-
|
|
590
|
-
|
|
591
770
|
static isTestMode(req) {
|
|
592
771
|
if (req.__postman__ === undefined) {
|
|
593
772
|
let dbgToken = req.headers["__postman__"] || req.headers[apiUtil$2.testFlag];
|
|
594
|
-
|
|
595
773
|
if (dbgToken) {
|
|
596
774
|
let envId = process.env.ECS_DEPLOY_ID;
|
|
597
775
|
let testToken = MD5(req.headers.timestamp, apiUtil$2.extractToken(req, null, true) || req.headers.apikey);
|
|
@@ -600,65 +778,59 @@ class apiUtil$2 {
|
|
|
600
778
|
req.__postman__ = false;
|
|
601
779
|
}
|
|
602
780
|
}
|
|
603
|
-
|
|
604
781
|
return req.__postman__;
|
|
605
782
|
}
|
|
783
|
+
|
|
606
784
|
/**
|
|
607
785
|
* 获取令牌过期时长
|
|
608
786
|
* @param req
|
|
609
787
|
* @returns {any}
|
|
610
788
|
*/
|
|
611
|
-
|
|
612
|
-
|
|
613
789
|
static tokenExpireTime(req) {
|
|
614
790
|
return apiUtil$2.isDebugMode(req) ? 30 * 24 * 60 * 60 : apiUtil$2.isTestMode(req) ? 4 * 60 * 60 : appSetting.tokenExpireTime;
|
|
615
791
|
}
|
|
792
|
+
|
|
616
793
|
/**
|
|
617
794
|
* 获取用户令牌保存键
|
|
618
795
|
* @param token
|
|
619
796
|
* @returns {string}
|
|
620
797
|
*/
|
|
621
|
-
|
|
622
|
-
|
|
623
798
|
static userTokenStoreKey(token) {
|
|
624
799
|
return "ut_" + token;
|
|
625
800
|
}
|
|
801
|
+
|
|
626
802
|
/**
|
|
627
803
|
* 获取机构令牌保存键
|
|
628
804
|
* @param token
|
|
629
805
|
* @returns {string}
|
|
630
806
|
*/
|
|
631
|
-
|
|
632
|
-
|
|
633
807
|
static apiTokenStoreKey(token) {
|
|
634
808
|
return "api_" + token;
|
|
635
809
|
}
|
|
810
|
+
|
|
636
811
|
/**
|
|
637
812
|
* 判断是不是香港身份证
|
|
638
813
|
* @param idNum
|
|
639
814
|
* @returns {boolean}
|
|
640
815
|
*/
|
|
641
|
-
|
|
642
|
-
|
|
643
816
|
static checkIsHKIC(idNum) {
|
|
644
817
|
return idNum.length === 8;
|
|
645
818
|
}
|
|
819
|
+
|
|
646
820
|
/**
|
|
647
821
|
* 将身份证号码暂存到用户信息中
|
|
648
822
|
* @param userInfo
|
|
649
823
|
* @param idNum
|
|
650
824
|
* @returns {*}
|
|
651
825
|
*/
|
|
652
|
-
|
|
653
|
-
|
|
654
826
|
static setUserIdNo(userInfo, idNum) {
|
|
655
827
|
if (userInfo && idNum) {
|
|
656
828
|
userInfo._idNo = idNum;
|
|
657
829
|
userInfo.isHKIC = apiUtil$2.checkIsHKIC(idNum);
|
|
658
830
|
}
|
|
659
|
-
|
|
660
831
|
return userInfo;
|
|
661
832
|
}
|
|
833
|
+
|
|
662
834
|
/**
|
|
663
835
|
* 暂存令牌
|
|
664
836
|
* @param token
|
|
@@ -667,53 +839,46 @@ class apiUtil$2 {
|
|
|
667
839
|
* @param req
|
|
668
840
|
* @returns {Promise<void>}
|
|
669
841
|
*/
|
|
670
|
-
|
|
671
|
-
|
|
672
842
|
static async storeToken(token, tokenData, dataId, req) {
|
|
673
843
|
// let timeout = tokenData.clientIp.substring(0, 8) == "192.168." ? 90 * 24 : 1;
|
|
674
844
|
let timeout = apiUtil$2.tokenExpireTime(req);
|
|
675
|
-
|
|
676
845
|
if (req.certPublicKey) {
|
|
677
846
|
tokenData.certPublicKey = req.certPublicKey;
|
|
678
847
|
}
|
|
679
|
-
|
|
680
|
-
await kvStorage$1.storeObj(token, tokenData, timeout);
|
|
681
|
-
|
|
848
|
+
await kvStorage.storeObj(token, tokenData, timeout);
|
|
682
849
|
if (dataId) {
|
|
683
|
-
await kvStorage
|
|
850
|
+
await kvStorage.restoreValue("token_" + dataId).then(async oldToken => {
|
|
684
851
|
if (oldToken !== token) {
|
|
685
|
-
await kvStorage
|
|
852
|
+
await kvStorage.unstoreValue(oldToken);
|
|
686
853
|
} else {
|
|
687
854
|
dataId = "";
|
|
688
855
|
}
|
|
689
856
|
}, function (e) {}).then(async () => {
|
|
690
|
-
if (dataId !== "") await kvStorage
|
|
857
|
+
if (dataId !== "") await kvStorage.storeValue("token_" + dataId, token, timeout);
|
|
691
858
|
});
|
|
692
859
|
}
|
|
693
860
|
}
|
|
861
|
+
|
|
694
862
|
/**
|
|
695
863
|
* 恢复令牌数据
|
|
696
864
|
* @param accessToken
|
|
697
865
|
* @param expireTime
|
|
698
866
|
* @returns {Promise<any>}
|
|
699
867
|
*/
|
|
700
|
-
|
|
701
|
-
|
|
702
868
|
static async restoreTokenData(accessToken, expireTime) {
|
|
703
|
-
return await kvStorage
|
|
869
|
+
return await kvStorage.restoreObj(accessToken, expireTime);
|
|
704
870
|
}
|
|
871
|
+
|
|
705
872
|
/**
|
|
706
873
|
* 创建 API 调用记录
|
|
707
874
|
* @param tokenData
|
|
708
875
|
* @param req
|
|
709
876
|
* @returns {any}
|
|
710
877
|
*/
|
|
711
|
-
|
|
712
|
-
|
|
713
878
|
static createApiCallRec(tokenData, req) {
|
|
714
879
|
if (!req.apiCallRec) {
|
|
715
880
|
if (req.apiCallRecId) {
|
|
716
|
-
return dbUtil
|
|
881
|
+
return dbUtil.dbQueryOne(dbSql.loadApiUsage, {
|
|
717
882
|
replacements: {
|
|
718
883
|
id: req.apiCallRecId
|
|
719
884
|
}
|
|
@@ -722,10 +887,10 @@ class apiUtil$2 {
|
|
|
722
887
|
return req.apiCallRec;
|
|
723
888
|
});
|
|
724
889
|
} else {
|
|
725
|
-
let params = apiUtil$2.extractParams(req);
|
|
726
|
-
|
|
890
|
+
let params = apiUtil$2.extractParams(req);
|
|
891
|
+
// let contentLength = parseInt(req.headers["content-length"]) || 0;
|
|
727
892
|
let rec = {
|
|
728
|
-
id: ppUtil$
|
|
893
|
+
id: ppUtil$3.newGuid(),
|
|
729
894
|
companyId: tokenData.apiKey || '',
|
|
730
895
|
orderId: params.orderId || '',
|
|
731
896
|
signerId: params.signerId || '',
|
|
@@ -750,54 +915,44 @@ class apiUtil$2 {
|
|
|
750
915
|
resultInfo: params.resultInfo || '',
|
|
751
916
|
resultData: params.resultData || ''
|
|
752
917
|
};
|
|
753
|
-
|
|
754
918
|
if (rec.secret !== "") {
|
|
755
|
-
rec.secret = ppUtil$
|
|
919
|
+
rec.secret = ppUtil$3.getEncAse192(rec.secret);
|
|
756
920
|
}
|
|
757
|
-
|
|
758
921
|
req.apiCallRec = rec;
|
|
759
922
|
}
|
|
760
923
|
}
|
|
761
|
-
|
|
762
924
|
return req.apiCallRec;
|
|
763
|
-
|
|
764
925
|
function _getBodyLogStr(req) {
|
|
765
926
|
let contentLength = parseInt(req.headers["content-length"]) || 0;
|
|
766
927
|
if (contentLength < 500) return req.rawBody || '';
|
|
767
928
|
let tempBody = {};
|
|
768
|
-
|
|
769
929
|
for (let key in req.body) {
|
|
770
930
|
let value = req.body[key];
|
|
771
|
-
|
|
772
931
|
if (typeof value == 'string' && value.length > 500) {
|
|
773
932
|
value = value.substring(0, 31) + '...(' + value.length + ')';
|
|
774
933
|
}
|
|
775
|
-
|
|
776
934
|
tempBody[key] = value;
|
|
777
935
|
}
|
|
778
|
-
|
|
779
936
|
return JSON.stringify(tempBody);
|
|
780
937
|
}
|
|
781
938
|
}
|
|
939
|
+
|
|
782
940
|
/**
|
|
783
941
|
* 查询机构信息
|
|
784
942
|
* @param companyId
|
|
785
943
|
* @param nullable
|
|
786
944
|
* @returns {Promise<null|*>}
|
|
787
945
|
*/
|
|
788
|
-
|
|
789
|
-
|
|
790
946
|
static async queryCompanyInfo(companyId, nullable) {
|
|
791
|
-
return await dbUtil
|
|
947
|
+
return await dbUtil.dbQueryOne(dbSql.queryCompanyInfo, {
|
|
792
948
|
companyId
|
|
793
949
|
}, nullable);
|
|
794
950
|
}
|
|
951
|
+
|
|
795
952
|
/**
|
|
796
953
|
* 获取企业有效证书
|
|
797
954
|
* @param companyId: 企业标识
|
|
798
955
|
*/
|
|
799
|
-
|
|
800
|
-
|
|
801
956
|
static async getCompanyCertificate(companyId) {
|
|
802
957
|
let certInfo = {
|
|
803
958
|
// 正式启用的证书
|
|
@@ -807,26 +962,26 @@ class apiUtil$2 {
|
|
|
807
962
|
certSpare: null,
|
|
808
963
|
certSpareId: ''
|
|
809
964
|
};
|
|
810
|
-
return await dbUtil
|
|
965
|
+
return await dbUtil.dbQueryOne(dbSql.queryCertDataByOwner, {
|
|
811
966
|
ownerId: companyId,
|
|
812
967
|
applyId: "company"
|
|
813
968
|
}, false).then(certRec => {
|
|
814
969
|
// console.log('当前证书:\n', certRec);
|
|
815
970
|
// checkCertStatus(certRec);
|
|
816
971
|
let certData = JSON.parse(certRec.certBody);
|
|
817
|
-
let pubKeyData = Buffer.from(certData.cert, "base64").toString();
|
|
818
|
-
|
|
972
|
+
let pubKeyData = Buffer.from(certData.cert, "base64").toString();
|
|
973
|
+
// 公司正式证书
|
|
819
974
|
certInfo.certLiving = pubKeyData;
|
|
820
975
|
certInfo.certLivingId = certRec.id;
|
|
821
|
-
return dbUtil
|
|
976
|
+
return dbUtil.dbQueryOne(dbSql.queryCertDataByOwner, {
|
|
822
977
|
ownerId: companyId,
|
|
823
978
|
applyId: "company_spare"
|
|
824
979
|
}, false).then(certRec1 => {
|
|
825
980
|
// console.log('备用证书:\n', certRec1);
|
|
826
981
|
// checkCertStatus(certRec1);
|
|
827
982
|
let certData1 = JSON.parse(certRec1.certBody);
|
|
828
|
-
let pubKeyData1 = Buffer.from(certData1.cert, "base64").toString();
|
|
829
|
-
|
|
983
|
+
let pubKeyData1 = Buffer.from(certData1.cert, "base64").toString();
|
|
984
|
+
// 公司备用证书
|
|
830
985
|
certInfo.certSpare = pubKeyData1;
|
|
831
986
|
certInfo.certSpareId = certRec1.id;
|
|
832
987
|
}).catch(e => {
|
|
@@ -837,55 +992,45 @@ class apiUtil$2 {
|
|
|
837
992
|
return certInfo;
|
|
838
993
|
}).catch(e => {
|
|
839
994
|
console.log('获取企业证书失败:\n', e);
|
|
840
|
-
throw [err$
|
|
995
|
+
throw [err$1.ACCESS_REFUSED, t_f$2("获取企业证书失败:%s", err$1.ERROR(e).message)];
|
|
841
996
|
});
|
|
842
997
|
}
|
|
998
|
+
|
|
843
999
|
/**
|
|
844
1000
|
* 验证API调用签名
|
|
845
1001
|
* @param tokenData
|
|
846
1002
|
* @param req
|
|
847
1003
|
* @returns {Promise<*|boolean>}
|
|
848
1004
|
*/
|
|
849
|
-
|
|
850
|
-
|
|
851
1005
|
static async verifyApiSignature(tokenData, req) {
|
|
852
1006
|
try {
|
|
853
1007
|
if (!req.headers.timestamp) {
|
|
854
|
-
throw [err$
|
|
1008
|
+
throw [err$1.ACCESS_REFUSED, t_f$2("必须在请求头中设置时戳")];
|
|
855
1009
|
}
|
|
856
|
-
|
|
857
1010
|
let timestamp = parseInt(req.headers.timestamp);
|
|
858
1011
|
let currentTime = new Date().valueOf();
|
|
859
1012
|
let maxTimeDiff = apiUtil$2.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$2.isTestMode(req) ? 4 * 3600 : 100; // 100
|
|
860
|
-
|
|
861
1013
|
if (timestamp.toString() == "NaN" || currentTime < timestamp - 5000 || currentTime - timestamp > maxTimeDiff * 1000) {
|
|
862
|
-
throw [err$
|
|
1014
|
+
throw [err$1.ACCESS_REFUSED, t_f$2("时戳(%s)无效,当前时戳:%s,时差 %s秒", timestamp, currentTime, (currentTime - timestamp) / 1000)];
|
|
863
1015
|
}
|
|
864
|
-
|
|
865
1016
|
let signature = req.headers.signature;
|
|
866
|
-
|
|
867
1017
|
if (!signature) {
|
|
868
|
-
throw [err$
|
|
1018
|
+
throw [err$1.ACCESS_REFUSED, t_f$2("必须在请求头中提供签名")];
|
|
869
1019
|
}
|
|
870
|
-
|
|
871
1020
|
let signData = apiUtil$2.extractToken(req, null, true) || tokenData.apiKey;
|
|
872
1021
|
signData += timestamp;
|
|
873
|
-
|
|
874
1022
|
if (apiUtil$2.isDebugMode(req) || apiUtil$2.isTestMode(req)) {
|
|
875
1023
|
let publicKey = req.headers.publickey || req.body.publicKey || req.query.publicKey;
|
|
876
|
-
|
|
877
1024
|
if (publicKey) {
|
|
878
1025
|
publicKey = decodeURIComponent(publicKey);
|
|
879
1026
|
tokenData.certPublicKey = publicKey;
|
|
880
1027
|
req.certPublicKey = publicKey;
|
|
881
1028
|
}
|
|
882
1029
|
}
|
|
883
|
-
|
|
884
1030
|
if (tokenData.certPublicKey) {
|
|
885
1031
|
let verifyResult = doVerify(signData, signature, tokenData.certPublicKey);
|
|
886
1032
|
return await verifyResult;
|
|
887
1033
|
}
|
|
888
|
-
|
|
889
1034
|
return apiUtil$2.getCompanyCertificate(tokenData.apiKey).then(info => {
|
|
890
1035
|
tokenData.certPublicKey = info.certLiving;
|
|
891
1036
|
tokenData.certPublicKeySpare = info.certSpare;
|
|
@@ -893,7 +1038,6 @@ class apiUtil$2 {
|
|
|
893
1038
|
tokenData.certSpareId = info.certSpareId;
|
|
894
1039
|
req.certPublicKey = info.certLiving;
|
|
895
1040
|
let token = apiUtil$2.extractToken(req, null, true);
|
|
896
|
-
|
|
897
1041
|
if (token) {
|
|
898
1042
|
apiUtil$2.storeToken(apiUtil$2.apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
|
|
899
1043
|
}
|
|
@@ -904,29 +1048,25 @@ class apiUtil$2 {
|
|
|
904
1048
|
// return Promise.reject(e);
|
|
905
1049
|
throw e;
|
|
906
1050
|
}
|
|
907
|
-
|
|
908
1051
|
function doVerify(signData, signature) {
|
|
909
1052
|
let verify = crypto.createVerify('SHA256');
|
|
910
1053
|
verify.write(signData);
|
|
911
1054
|
verify.end();
|
|
912
1055
|
let verifyOK = false;
|
|
913
|
-
|
|
914
1056
|
try {
|
|
915
1057
|
// 先用正式证书验证
|
|
916
1058
|
verifyOK = verify.verify(tokenData.certPublicKey, signature, 'base64');
|
|
917
1059
|
} catch (e) {
|
|
918
1060
|
console.log("SPO服务签名验证异常(正式证书), ", e);
|
|
919
1061
|
verifyOK = false;
|
|
920
|
-
|
|
921
1062
|
if (!tokenData.certPublicKeySpare) {
|
|
922
1063
|
throw {
|
|
923
|
-
eo: err$
|
|
924
|
-
msgArgv: "签名验证异常",
|
|
1064
|
+
eo: err$1.ACCESS_REFUSED,
|
|
1065
|
+
msgArgv: t("签名验证异常"),
|
|
925
1066
|
data: e
|
|
926
1067
|
};
|
|
927
1068
|
}
|
|
928
1069
|
}
|
|
929
|
-
|
|
930
1070
|
if (!verifyOK && tokenData.certPublicKeySpare) {
|
|
931
1071
|
try {
|
|
932
1072
|
// 再用备用证书验证
|
|
@@ -934,18 +1074,17 @@ class apiUtil$2 {
|
|
|
934
1074
|
verifySpare.write(signData);
|
|
935
1075
|
verifySpare.end();
|
|
936
1076
|
verifyOK = verifySpare.verify(tokenData.certPublicKeySpare, signature, 'base64');
|
|
937
|
-
|
|
938
1077
|
if (verifyOK) {
|
|
939
1078
|
// 备用证书验证成功了,则将备用证书替换为正式证书
|
|
940
|
-
console.log(
|
|
941
|
-
return dbUtil
|
|
942
|
-
let p1 = dbUtil
|
|
1079
|
+
console.log(t_f$2("公司(%s)备用证书验签成功,正式启用...", tokenData.apiKey));
|
|
1080
|
+
return dbUtil.dbTrans(trans => {
|
|
1081
|
+
let p1 = dbUtil.dbExec(dbSql.deleteCertRecById, {
|
|
943
1082
|
replacements: {
|
|
944
1083
|
id: tokenData.certLivingId
|
|
945
1084
|
},
|
|
946
1085
|
transaction: trans
|
|
947
1086
|
});
|
|
948
|
-
let p2 = dbUtil
|
|
1087
|
+
let p2 = dbUtil.dbExec(dbSql.spareCertToLiving, {
|
|
949
1088
|
replacements: {
|
|
950
1089
|
id: tokenData.certSpareId
|
|
951
1090
|
},
|
|
@@ -958,59 +1097,51 @@ class apiUtil$2 {
|
|
|
958
1097
|
delete tokenData.certSpareId;
|
|
959
1098
|
delete tokenData.certPublicKeySpare;
|
|
960
1099
|
let token = apiUtil$2.extractToken(req);
|
|
961
|
-
|
|
962
1100
|
if (token) {
|
|
963
1101
|
apiUtil$2.storeToken(apiUtil$2.apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
|
|
964
1102
|
}
|
|
965
|
-
|
|
966
|
-
console.log(`公司(${tokenData.apiKey})备用证书成功转换为正式证书`);
|
|
1103
|
+
console.log(t_f$2("公司(%s)备用证书成功转换为正式证书", tokenData.apiKey));
|
|
967
1104
|
});
|
|
968
1105
|
}
|
|
969
1106
|
} catch (e) {
|
|
970
1107
|
console.log("SPO服务签名验证异常(备用证书), ", e);
|
|
971
1108
|
throw {
|
|
972
|
-
eo: err$
|
|
973
|
-
msgArgv: "签名验证异常(spare)",
|
|
1109
|
+
eo: err$1.ACCESS_REFUSED,
|
|
1110
|
+
msgArgv: t("签名验证异常(spare)"),
|
|
974
1111
|
data: e
|
|
975
1112
|
};
|
|
976
1113
|
}
|
|
977
1114
|
}
|
|
978
|
-
|
|
979
1115
|
if (!verifyOK) {
|
|
980
1116
|
console.log("SPO服务签名验证失败, tokenData: ", tokenData);
|
|
981
|
-
throw [err$
|
|
1117
|
+
throw [err$1.ACCESS_REFUSED, t("签名验证未通过")];
|
|
982
1118
|
}
|
|
983
|
-
|
|
984
1119
|
return verifyOK;
|
|
985
1120
|
}
|
|
986
1121
|
}
|
|
1122
|
+
|
|
987
1123
|
/**
|
|
988
1124
|
* 检查API调用之合法性
|
|
989
1125
|
* @param tokenData
|
|
990
1126
|
* @param req
|
|
991
1127
|
* @returns {Promise<any>}
|
|
992
1128
|
*/
|
|
993
|
-
|
|
994
|
-
|
|
995
1129
|
static async checkApiCallValid(tokenData, req) {
|
|
996
1130
|
if (!tokenData.companyInfo) {
|
|
997
1131
|
tokenData.companyInfo = await apiUtil$2.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
|
|
998
1132
|
console.log("执行企业信息查询发生异常", e);
|
|
999
|
-
throw [err$
|
|
1133
|
+
throw [err$1.API_KEY_INVALID, t("执行企业信息查询发生异常:") + e.message || ""];
|
|
1000
1134
|
});
|
|
1001
1135
|
}
|
|
1002
|
-
|
|
1003
1136
|
const companyInfo = tokenData.companyInfo;
|
|
1004
|
-
|
|
1005
1137
|
if (companyInfo != null) {
|
|
1006
1138
|
let secret = apiUtil$2._getApiSecret(tokenData.apiKey);
|
|
1007
|
-
|
|
1008
|
-
|
|
1139
|
+
if (secret !== tokenData.apiSecret) throw err$1.API_SCREPT_INVALID;
|
|
1140
|
+
// 不再检查 IP 白名单,改为验证证书签名
|
|
1009
1141
|
// console.log("fromIp:", tokenData.clientIp, "ipWhiteList:", companyInfo.ipWhiteList);
|
|
1010
1142
|
// let whiteList = companyInfo.ipWhiteList || "";
|
|
1011
1143
|
// // 没有设置ip白名单的就不检查了
|
|
1012
1144
|
// if (whiteList == "" || ipMatched(tokenData.clientIp, whiteList + ",127.0.0.1,1"))
|
|
1013
|
-
|
|
1014
1145
|
if (apiUtil$2.signatureVerified(req)) return companyInfo;
|
|
1015
1146
|
return apiUtil$2.verifyApiSignature(tokenData, req).then(x => {
|
|
1016
1147
|
return companyInfo;
|
|
@@ -1018,30 +1149,26 @@ class apiUtil$2 {
|
|
|
1018
1149
|
throw e;
|
|
1019
1150
|
});
|
|
1020
1151
|
}
|
|
1021
|
-
|
|
1022
|
-
throw [err$2.API_KEY_INVALID, tokenData.apiKey];
|
|
1152
|
+
throw [err$1.API_KEY_INVALID, tokenData.apiKey];
|
|
1023
1153
|
}
|
|
1154
|
+
|
|
1024
1155
|
/**
|
|
1025
1156
|
* 检查令牌数据是否存在
|
|
1026
1157
|
* @param token
|
|
1027
1158
|
* @returns {*}
|
|
1028
1159
|
*/
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
1160
|
static tokenDataExist(token) {
|
|
1032
|
-
return kvStorage
|
|
1161
|
+
return kvStorage.stored(token);
|
|
1033
1162
|
}
|
|
1034
|
-
|
|
1035
1163
|
static parametersOK(params) {
|
|
1036
1164
|
configNeeded();
|
|
1037
1165
|
let paramSufix = params._param_sufix || "";
|
|
1038
|
-
|
|
1039
1166
|
for (let i = 1; i < arguments.length; i++) {
|
|
1040
1167
|
let paramName = arguments[i];
|
|
1041
1168
|
let paramExists = false;
|
|
1042
|
-
|
|
1043
1169
|
if (paramName.includes("/")) {
|
|
1044
|
-
let names = paramName.split("/");
|
|
1170
|
+
let names = paramName.split("/");
|
|
1171
|
+
// if (params[names[0]]) {
|
|
1045
1172
|
// paramExists = true;
|
|
1046
1173
|
// } else {
|
|
1047
1174
|
// if (params[names[1]]) {
|
|
@@ -1050,62 +1177,51 @@ class apiUtil$2 {
|
|
|
1050
1177
|
// delete params[names[1]];
|
|
1051
1178
|
// }
|
|
1052
1179
|
// }
|
|
1053
|
-
|
|
1054
1180
|
for (let ind in names) {
|
|
1055
1181
|
let name = names[ind];
|
|
1056
|
-
|
|
1057
1182
|
if (typeof params[name] != 'undefined') {
|
|
1058
1183
|
paramExists = true;
|
|
1059
1184
|
break;
|
|
1060
1185
|
}
|
|
1061
|
-
|
|
1062
1186
|
if (paramSufix != "" && typeof params[name + paramSufix] != 'undefined') {
|
|
1063
1187
|
paramExists = true;
|
|
1064
1188
|
break;
|
|
1065
1189
|
}
|
|
1066
1190
|
}
|
|
1067
|
-
|
|
1068
|
-
paramName = `${paramName} 之一`;
|
|
1191
|
+
paramName = t_f$2("%s 之一", paramName);
|
|
1069
1192
|
} else {
|
|
1070
1193
|
paramExists = typeof params[paramName] != 'undefined' || typeof params[paramName + paramSufix] != 'undefined';
|
|
1071
1194
|
}
|
|
1072
|
-
|
|
1073
|
-
if (!paramExists) return ppUtil$4.errorPormise(err$2.ERROR(err$2.PARAMETER_NEEDED, paramName));
|
|
1195
|
+
if (!paramExists) return ppUtil$3.errorPormise(err$1.ERROR(err$1.PARAMETER_NEEDED, paramName));
|
|
1074
1196
|
}
|
|
1075
|
-
|
|
1076
1197
|
return Promise.resolve(paramSufix);
|
|
1077
1198
|
}
|
|
1199
|
+
|
|
1078
1200
|
/**
|
|
1079
1201
|
* 获取客户端IP地址
|
|
1080
1202
|
* @param req
|
|
1081
1203
|
* @returns {*|string|string}
|
|
1082
1204
|
*/
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
1205
|
static getClientIp(req) {
|
|
1086
1206
|
if (!req.hasOwnProperty("clientIp")) {
|
|
1087
|
-
let ip = req.headers["x-real-ip"] || req.headers["x-true-ip"] || req.headers['x-forwarded-for'] || req.headers['x-forward-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.headers['host'] || "";
|
|
1088
|
-
|
|
1207
|
+
let ip = req.headers["x-real-ip"] || req.headers["x-true-ip"] || req.headers['x-forwarded-for'] || req.headers['x-forward-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.headers['host'] || "";
|
|
1208
|
+
// console.log("Request IP:", ip, "req: ", req);
|
|
1089
1209
|
if (ip.indexOf(",") >= 0) {
|
|
1090
1210
|
ip = ip.split(',')[0];
|
|
1091
1211
|
}
|
|
1092
|
-
|
|
1093
1212
|
if (ip.indexOf(":") >= 0) {
|
|
1094
1213
|
ip = ip.substring(ip.lastIndexOf(':') + 1);
|
|
1095
1214
|
}
|
|
1096
|
-
|
|
1097
1215
|
req.clientIp = ip;
|
|
1098
1216
|
}
|
|
1099
|
-
|
|
1100
1217
|
return req.clientIp;
|
|
1101
1218
|
}
|
|
1219
|
+
|
|
1102
1220
|
/**
|
|
1103
1221
|
* 获取与本机一起提供服务的所有主机
|
|
1104
1222
|
* @param params
|
|
1105
1223
|
* @returns {{port: (number|number), hosts: [string]}}
|
|
1106
1224
|
*/
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
1225
|
static getEnvHosts(params) {
|
|
1110
1226
|
configNeeded();
|
|
1111
1227
|
return {
|
|
@@ -1113,50 +1229,44 @@ class apiUtil$2 {
|
|
|
1113
1229
|
port: appSetting.listenPort || +params.port || 8443
|
|
1114
1230
|
};
|
|
1115
1231
|
}
|
|
1232
|
+
|
|
1116
1233
|
/**
|
|
1117
1234
|
* 检查指定的host和发送请求的ip是不是自己的ip
|
|
1118
1235
|
* @param host
|
|
1119
1236
|
* @param req
|
|
1120
1237
|
* @returns {Promise<*>}
|
|
1121
1238
|
*/
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
1239
|
static async hostIsMySelf(host, req) {
|
|
1125
1240
|
let clientIp = apiUtil$2.getClientIp(req);
|
|
1126
|
-
|
|
1127
1241
|
try {
|
|
1128
|
-
return !!ppUtil$
|
|
1242
|
+
return !!ppUtil$3.getMyIp({
|
|
1129
1243
|
hosts: [host, clientIp]
|
|
1130
1244
|
});
|
|
1131
1245
|
} catch (e) {
|
|
1132
1246
|
return false;
|
|
1133
1247
|
}
|
|
1134
1248
|
}
|
|
1249
|
+
|
|
1135
1250
|
/**
|
|
1136
1251
|
* 检查是否应该把请求转发到其它服务器,若是则转发
|
|
1137
1252
|
* @param options
|
|
1138
1253
|
* @returns {Promise<boolean>}
|
|
1139
1254
|
*/
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
1255
|
static async checkForwardsHost(options) {
|
|
1143
1256
|
configNeeded();
|
|
1144
1257
|
const params = options.replacements;
|
|
1145
1258
|
const myEnvHosts = apiUtil$2.getEnvHosts(params);
|
|
1146
|
-
const myIp = ppUtil$
|
|
1259
|
+
const myIp = ppUtil$3.getMyIp();
|
|
1147
1260
|
const host = params.host || myIp;
|
|
1148
|
-
if (!myEnvHosts.hosts.contains(host)) throw [err$
|
|
1149
|
-
|
|
1261
|
+
if (!myEnvHosts.hosts.contains(host)) throw [err$1.ACCESS_REFUSED, t_f$2("环境%s貌似无此主机:%s", conf$2.envId, params.host)];
|
|
1150
1262
|
if (!apiUtil$2.hostIsMySelf(host, options._res.req)) {
|
|
1151
1263
|
let result = await apiUtil$2.forwardsTo(host, myEnvHosts.port, params, options._res.req, myIp);
|
|
1152
|
-
|
|
1153
1264
|
options._res.send(result);
|
|
1154
|
-
|
|
1155
1265
|
return true;
|
|
1156
1266
|
}
|
|
1157
|
-
|
|
1158
1267
|
return false;
|
|
1159
1268
|
}
|
|
1269
|
+
|
|
1160
1270
|
/**
|
|
1161
1271
|
* 将收到的请求转发到另一台主机
|
|
1162
1272
|
* @param anotherIp
|
|
@@ -1166,181 +1276,157 @@ class apiUtil$2 {
|
|
|
1166
1276
|
* @param lanClient
|
|
1167
1277
|
* @returns {Promise<*>}
|
|
1168
1278
|
*/
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
1279
|
static async forwardsTo(anotherIp, port, params, req, lanClient) {
|
|
1172
1280
|
let url = anotherIp.indexOf("://") > 0 ? anotherIp : `${req.headers.scheme}://${anotherIp}:${port}${req.originalUrl}`;
|
|
1173
|
-
|
|
1174
1281
|
if (url.indexOf("?") > 0) {
|
|
1175
1282
|
url = url.substring(0, url.indexOf("?"));
|
|
1176
1283
|
}
|
|
1177
|
-
|
|
1178
1284
|
let reqOptions = {
|
|
1179
1285
|
method: req.method,
|
|
1180
1286
|
url: url,
|
|
1181
1287
|
data: params
|
|
1182
1288
|
};
|
|
1183
1289
|
let result = await netUtil$1.apiRequest(reqOptions);
|
|
1184
|
-
|
|
1185
1290
|
if (result.status !== 200) {
|
|
1186
|
-
console.log(
|
|
1187
|
-
throw [err$
|
|
1291
|
+
console.log(t_f$2("访问 %s 出错", reqOptions.url), result.status, result.res.statusMessage);
|
|
1292
|
+
throw [err$1.EXCEPTION, `[${result.status}] - ${result.res.statusMessage}`];
|
|
1188
1293
|
}
|
|
1189
|
-
|
|
1190
1294
|
return result.data;
|
|
1191
1295
|
}
|
|
1296
|
+
|
|
1192
1297
|
/**
|
|
1193
1298
|
* 解析配置项路径
|
|
1194
1299
|
* @param keyPath
|
|
1195
1300
|
* @returns {{parent: null, parentKey: string, value, key: string}}
|
|
1196
1301
|
*/
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
1302
|
static parseCfgPath(keyPath) {
|
|
1200
1303
|
let keys = Array.isArray(keyPath) ? keyPath : keyPath.split(".");
|
|
1201
1304
|
let parentKey = "";
|
|
1202
1305
|
let key = "config";
|
|
1203
|
-
let value = conf$
|
|
1306
|
+
let value = conf$2;
|
|
1204
1307
|
let parent = null;
|
|
1205
|
-
|
|
1206
1308
|
for (let i = 0; i < keys.length; i++) {
|
|
1207
1309
|
parent = value;
|
|
1208
1310
|
parentKey += (parentKey ? "." : "") + key;
|
|
1209
1311
|
key = keys[i];
|
|
1210
1312
|
value = parent[key];
|
|
1211
|
-
|
|
1212
1313
|
if (value === undefined) {
|
|
1213
|
-
throw [err$
|
|
1314
|
+
throw [err$1.INVALID_PARAM, t_f$2("无此配置项: %s", key)];
|
|
1214
1315
|
}
|
|
1215
1316
|
}
|
|
1216
|
-
|
|
1217
1317
|
return {
|
|
1218
1318
|
parent,
|
|
1219
1319
|
parentKey,
|
|
1220
1320
|
key,
|
|
1221
1321
|
value
|
|
1222
1322
|
};
|
|
1223
|
-
}
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
//#endregion
|
|
1326
|
+
|
|
1224
1327
|
//region ====中间件
|
|
1225
1328
|
|
|
1226
1329
|
/**
|
|
1227
1330
|
* 检查令牌,若存在则将其的用户信息置入req,否则返回错误信息
|
|
1228
1331
|
*/
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
1332
|
static async $checkToken(req, res, next) {
|
|
1232
1333
|
try {
|
|
1233
1334
|
await apiUtil$2.checkRequestToken(req);
|
|
1234
1335
|
next();
|
|
1235
1336
|
} catch (e) {
|
|
1236
|
-
res.send(err$
|
|
1337
|
+
res.send(err$1.ERROR(e));
|
|
1237
1338
|
}
|
|
1238
|
-
|
|
1239
1339
|
return false;
|
|
1240
1340
|
}
|
|
1341
|
+
|
|
1241
1342
|
/**
|
|
1242
1343
|
* 检查令牌,若存在则将其用户信息置入req
|
|
1243
1344
|
*/
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
1345
|
static async $getToken(req, res, next) {
|
|
1247
1346
|
function extractToken(req, res) {
|
|
1248
1347
|
if (!req.accessToken) {
|
|
1249
1348
|
//检查post的信息或者url查询参数或者头信息
|
|
1250
1349
|
let token = req.headers["access_token"] || req.headers['x-access-token']; //向后兼容
|
|
1251
|
-
|
|
1252
1350
|
if (!token) {
|
|
1253
1351
|
let params = apiUtil$2.extractParams(req);
|
|
1254
1352
|
token = params["access_token"];
|
|
1255
|
-
|
|
1256
1353
|
if (token) {
|
|
1257
1354
|
delete params["access_token"];
|
|
1258
1355
|
} else if (params.token) {
|
|
1259
1356
|
token = params.token; //向后兼容
|
|
1260
|
-
|
|
1261
|
-
|
|
1357
|
+
delete params.token;
|
|
1358
|
+
// } else if (res) {
|
|
1262
1359
|
// // 如果没有token,则返回错误
|
|
1263
1360
|
// console.log(err.TOKEN_NEEDED);
|
|
1264
1361
|
// res.send(err.ERROR(err.TOKEN_NEEDED));
|
|
1265
1362
|
}
|
|
1266
1363
|
}
|
|
1267
|
-
|
|
1268
1364
|
req.accessToken = token;
|
|
1269
1365
|
}
|
|
1270
|
-
|
|
1271
1366
|
return req.accessToken;
|
|
1272
1367
|
}
|
|
1273
|
-
|
|
1274
1368
|
try {
|
|
1275
1369
|
if (extractToken(req, res)) {
|
|
1276
1370
|
await apiUtil$2.restoreTokenData(apiUtil$2.userTokenStoreKey(req.accessToken), apiUtil$2.tokenExpireTime(req)).then(function (data) {
|
|
1277
1371
|
req.userInfo = apiUtil$2.setUserIdNo(data, data._idNo);
|
|
1278
|
-
}, function (e) {
|
|
1372
|
+
}, function (e) {
|
|
1373
|
+
|
|
1374
|
+
//no token
|
|
1279
1375
|
});
|
|
1280
1376
|
}
|
|
1281
|
-
|
|
1282
1377
|
return true;
|
|
1283
1378
|
} catch (e) {
|
|
1284
|
-
res.send(err$
|
|
1379
|
+
res.send(err$1.ERROR(e));
|
|
1285
1380
|
return false;
|
|
1286
1381
|
}
|
|
1287
1382
|
}
|
|
1383
|
+
|
|
1288
1384
|
/**
|
|
1289
1385
|
* 标识此请求已经完成了签名验证或者无需进行签名验证
|
|
1290
1386
|
*/
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
1387
|
static $signatureVerified(req, res, next) {
|
|
1294
1388
|
req.signatureVerified = true;
|
|
1295
1389
|
next();
|
|
1296
1390
|
}
|
|
1391
|
+
|
|
1297
1392
|
/**
|
|
1298
1393
|
* 标识此请求是从前端发过来的,比如移动端、PC浏览器等,区别于SPO一般的服务端后台请求。
|
|
1299
1394
|
* 如果在请求参数中包含有签名参数,则将其移到请求头中
|
|
1300
1395
|
*/
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
1396
|
static $isMobile(req, res, next) {
|
|
1304
1397
|
req.isMobile = true;
|
|
1305
|
-
|
|
1306
1398
|
if (!apiUtil$2.signatureVerified(req)) {
|
|
1307
1399
|
let params = apiUtil$2.extractParams(req);
|
|
1308
1400
|
moveProperty(params, req.headers, "access_token");
|
|
1309
1401
|
moveProperty(params, req.headers, "timestamp");
|
|
1310
|
-
|
|
1311
1402
|
if (moveProperty(params, req.headers, "signature")) {
|
|
1312
1403
|
req.headers.signature = decodeURIComponent(req.headers.signature);
|
|
1313
1404
|
}
|
|
1314
1405
|
}
|
|
1315
|
-
|
|
1316
1406
|
next();
|
|
1317
1407
|
}
|
|
1408
|
+
|
|
1318
1409
|
/**
|
|
1319
1410
|
* 检查企业 API 调用合法性 (apiKey, apiSecret)
|
|
1320
1411
|
* @param req
|
|
1321
1412
|
* @param res
|
|
1322
1413
|
* @param next
|
|
1323
1414
|
*/
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
1415
|
static $checkApiKeyOld(req, res, next) {
|
|
1327
1416
|
//检查post的信息或者url查询参数或者头信息
|
|
1328
1417
|
const tokenData = apiUtil$2.extractTokenData(req);
|
|
1329
1418
|
const params = apiUtil$2.extractParams(req);
|
|
1330
1419
|
apiUtil$2.createApiCallRec(tokenData, req);
|
|
1331
1420
|
let errResponse = null;
|
|
1332
|
-
|
|
1333
1421
|
if (!tokenData.clientIp) {
|
|
1334
|
-
errResponse = apiUtil$2.spoApiFail(err$
|
|
1422
|
+
errResponse = apiUtil$2.spoApiFail(err$1.GET_CLIENTIP_FAIL, req);
|
|
1335
1423
|
} else if (!tokenData.apiKey) {
|
|
1336
|
-
errResponse = apiUtil$2.spoApiFail([err$
|
|
1424
|
+
errResponse = apiUtil$2.spoApiFail([err$1.PARAMETER_NEEDED, "apiKey"], req);
|
|
1337
1425
|
} else if (!tokenData.apiSecret) {
|
|
1338
|
-
errResponse = apiUtil$2.spoApiFail([err$
|
|
1426
|
+
errResponse = apiUtil$2.spoApiFail([err$1.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1339
1427
|
}
|
|
1340
|
-
|
|
1341
1428
|
if (errResponse != null) {
|
|
1342
1429
|
apiUtil$2._saveApiCallRec(req.apiCallRec, errResponse);
|
|
1343
|
-
|
|
1344
1430
|
apiUtil$2.sendOrRedirect(res, params.redirectUrl || params.callbackUrl, errResponse);
|
|
1345
1431
|
} else {
|
|
1346
1432
|
apiUtil$2.checkApiCallValid(tokenData, req).then(companyInfo => {
|
|
@@ -1350,32 +1436,26 @@ class apiUtil$2 {
|
|
|
1350
1436
|
}, e => {
|
|
1351
1437
|
console.log('apiCallInvalid:', e);
|
|
1352
1438
|
let errResponse = apiUtil$2.spoApiFail(e, req);
|
|
1353
|
-
|
|
1354
1439
|
apiUtil$2._saveApiCallRec(req.apiCallRec, errResponse);
|
|
1355
|
-
|
|
1356
1440
|
apiUtil$2.sendOrRedirect(res, params.redirectUrl || params.callbackUrl, errResponse);
|
|
1357
1441
|
});
|
|
1358
1442
|
}
|
|
1359
1443
|
}
|
|
1444
|
+
|
|
1360
1445
|
/**
|
|
1361
1446
|
* 检查机构令牌
|
|
1362
1447
|
*/
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
1448
|
static $checkApiKey(req, res, next) {
|
|
1366
1449
|
if (req.ignoreToken) {
|
|
1367
1450
|
next();
|
|
1368
1451
|
return;
|
|
1369
1452
|
}
|
|
1370
|
-
|
|
1371
1453
|
let accessToken = apiUtil$2.extractToken(req);
|
|
1372
|
-
|
|
1373
1454
|
if (!accessToken) {
|
|
1374
|
-
res.send(apiUtil$2.spoApiFail(err$
|
|
1375
|
-
|
|
1455
|
+
res.send(apiUtil$2.spoApiFail(err$1.TOKEN_NEEDED, req));
|
|
1456
|
+
// apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
|
|
1376
1457
|
return;
|
|
1377
1458
|
}
|
|
1378
|
-
|
|
1379
1459
|
apiUtil$2.restoreTokenData(apiUtil$2.apiTokenStoreKey(accessToken)).then(p => {
|
|
1380
1460
|
// req.headers[hnApiKey] = p.apiKey || '';
|
|
1381
1461
|
// req.headers[hnApiSecret] = p.apiSecret || '';
|
|
@@ -1387,15 +1467,15 @@ class apiUtil$2 {
|
|
|
1387
1467
|
} else {
|
|
1388
1468
|
p.clientIp = apiUtil$2.getClientIp(req);
|
|
1389
1469
|
}
|
|
1390
|
-
|
|
1391
1470
|
req.isApiCall = true;
|
|
1392
1471
|
req.tokenData = p;
|
|
1393
1472
|
return apiUtil$2.$checkApiKeyOld(req, res, next);
|
|
1394
1473
|
}).catch(e => {
|
|
1395
1474
|
const params = apiUtil$2.extractParams(req);
|
|
1396
|
-
apiUtil$2.sendOrRedirect(res, params.redirectUrl || params.callbackUrl, apiUtil$2.spoApiFail(err$
|
|
1475
|
+
apiUtil$2.sendOrRedirect(res, params.redirectUrl || params.callbackUrl, apiUtil$2.spoApiFail(err$1.TOKEN_INVALID, req));
|
|
1397
1476
|
});
|
|
1398
1477
|
}
|
|
1478
|
+
|
|
1399
1479
|
/**
|
|
1400
1480
|
* 检查请求令牌,允许个人用户令牌和机构令牌,若不存在或不合法,则返回错误信息
|
|
1401
1481
|
* @param req
|
|
@@ -1403,31 +1483,25 @@ class apiUtil$2 {
|
|
|
1403
1483
|
* @param next
|
|
1404
1484
|
* @returns {Promise<void|boolean|boolean|undefined>}
|
|
1405
1485
|
*/
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
1486
|
static async $checkTokenOrApiKey(req, res, next) {
|
|
1409
1487
|
let accessToken = apiUtil$2.extractToken(req, res);
|
|
1410
|
-
|
|
1411
1488
|
if (accessToken) {
|
|
1412
1489
|
let tokenExist = await apiUtil$2.tokenDataExist(apiUtil$2.userTokenStoreKey(accessToken));
|
|
1413
|
-
|
|
1414
1490
|
if (tokenExist) {
|
|
1415
1491
|
return await apiUtil$2.$checkToken(req, res, next);
|
|
1416
1492
|
}
|
|
1417
|
-
|
|
1418
1493
|
tokenExist = await apiUtil$2.tokenDataExist(apiUtil$2.apiTokenStoreKey(accessToken));
|
|
1419
|
-
|
|
1420
1494
|
if (tokenExist) {
|
|
1421
1495
|
return apiUtil$2.$checkApiKey(req, res, next);
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
|
|
1496
|
+
}
|
|
1497
|
+
// 如果给定的token不存在,看看是不是平台内部调用
|
|
1425
1498
|
return await apiUtil$2.checkInternalToken(req).catch(e => {
|
|
1426
1499
|
res.send(apiUtil$2.apiFail(e, req));
|
|
1427
1500
|
return false;
|
|
1428
1501
|
});
|
|
1429
1502
|
}
|
|
1430
1503
|
}
|
|
1504
|
+
|
|
1431
1505
|
/**
|
|
1432
1506
|
* 基本验证,应用系统应该预先设置验证函数 _validateBasicAuth(userName, password)
|
|
1433
1507
|
* @param req
|
|
@@ -1435,12 +1509,9 @@ class apiUtil$2 {
|
|
|
1435
1509
|
* @param next
|
|
1436
1510
|
* @returns {Promise<*>}
|
|
1437
1511
|
*/
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
1512
|
static async $basicAuth(req, res, next) {
|
|
1441
1513
|
try {
|
|
1442
1514
|
const authorization = getBasicAuthorization(req);
|
|
1443
|
-
|
|
1444
1515
|
if (!authorization) {
|
|
1445
1516
|
throw {
|
|
1446
1517
|
status: 401,
|
|
@@ -1451,7 +1522,6 @@ class apiUtil$2 {
|
|
|
1451
1522
|
}
|
|
1452
1523
|
};
|
|
1453
1524
|
}
|
|
1454
|
-
|
|
1455
1525
|
if (!(await apiUtil$2._validateBasicAuth(authorization.name, authorization.pass, req, res, next))) {
|
|
1456
1526
|
throw {
|
|
1457
1527
|
status: 401,
|
|
@@ -1470,422 +1540,158 @@ class apiUtil$2 {
|
|
|
1470
1540
|
} catch {}
|
|
1471
1541
|
res.set('WWW-Authenticate', `Basic realm=validate fail`);
|
|
1472
1542
|
}
|
|
1473
|
-
|
|
1474
1543
|
return res.status(e.status || 500).send(e.error || e);
|
|
1475
1544
|
}
|
|
1476
|
-
|
|
1477
1545
|
next();
|
|
1478
|
-
} //#endregion
|
|
1479
|
-
//region ====一些通用服务功能
|
|
1480
|
-
|
|
1481
|
-
/**
|
|
1482
|
-
* 获取配置数据
|
|
1483
|
-
* @param options
|
|
1484
|
-
* @returns {Promise<boolean|*>}
|
|
1485
|
-
*/
|
|
1486
|
-
// api/config/appSetting.ossEnabled
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
static async getConfigValue(options) {
|
|
1490
|
-
configNeeded();
|
|
1491
|
-
const params = options.replacements;
|
|
1492
|
-
let cfgItem = params._cfgItem;
|
|
1493
|
-
delete params._cfgItem;
|
|
1494
|
-
if (await apiUtil$2.checkForwardsHost(options)) return true;
|
|
1495
|
-
let c = apiUtil$2.parseCfgPath(cfgItem);
|
|
1496
|
-
delete c.parent;
|
|
1497
|
-
c.host = ppUtil$4.getMyIp();
|
|
1498
|
-
return c;
|
|
1499
|
-
}
|
|
1500
|
-
/**
|
|
1501
|
-
* 设置配置数据
|
|
1502
|
-
* @param options
|
|
1503
|
-
* @returns {Promise<*>}
|
|
1504
|
-
*/
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
static async setConfigValue(options) {
|
|
1508
|
-
configNeeded();
|
|
1509
|
-
const params = options.replacements;
|
|
1510
|
-
let cfgItem = params._cfgItem;
|
|
1511
|
-
delete params._cfgItem; // if (await checkForwardsHost(options))
|
|
1512
|
-
// return true;
|
|
1513
|
-
|
|
1514
|
-
await apiUtil$2.parametersOK(params, "value");
|
|
1515
|
-
let c = apiUtil$2.parseCfgPath(cfgItem);
|
|
1516
|
-
|
|
1517
|
-
if (typeof c.value === "object") {
|
|
1518
|
-
throw [err$2.ACCESS_REFUSED, `暂不支持修改复杂配置`];
|
|
1519
|
-
} // c.oldValue = c.value;
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
c.newValue = params.value;
|
|
1523
|
-
c.parent[c.key] = c.newValue;
|
|
1524
|
-
delete c.parent;
|
|
1525
|
-
c.host = ppUtil$4.getMyIp();
|
|
1526
|
-
return c; // 应用层自行处理多机同步
|
|
1527
|
-
}
|
|
1528
|
-
/**
|
|
1529
|
-
* 修改重启标志文件
|
|
1530
|
-
* 前提,PM2监视 restart,please.flag 文件,此文件若被修改则重启服务进程
|
|
1531
|
-
* 此服务假设 restart,please.flag 文件最后一行是一个整数,此整数+1后保存
|
|
1532
|
-
* @param options
|
|
1533
|
-
* @returns {Promise<number>}
|
|
1534
|
-
*/
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
static async updateRestartFlag(options) {
|
|
1538
|
-
const fileName = `restart,please.flag`;
|
|
1539
|
-
let text = await fs$1.async_readFile(fileName, 'utf8');
|
|
1540
|
-
const lines = text.split('\r\n');
|
|
1541
|
-
const n = +lines[lines.length - 1] + 1;
|
|
1542
|
-
lines[lines.length - 1] = ' '.repeat(50) + n.toString();
|
|
1543
|
-
text = lines.join('\r\n');
|
|
1544
|
-
await fs$1.async_writeFile(fileName, text);
|
|
1545
|
-
return n;
|
|
1546
|
-
}
|
|
1547
|
-
/**
|
|
1548
|
-
* 创建验证码对象
|
|
1549
|
-
* npm i svg-captcha
|
|
1550
|
-
* npm i svg2png
|
|
1551
|
-
*/
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
static createSvgCaptcha(options) {
|
|
1555
|
-
const captcha = svgCaptcha.create({
|
|
1556
|
-
inverse: options.hasOwnProperty('inverse') ? options.inverse : false,
|
|
1557
|
-
fontSize: options.fontSize || 48,
|
|
1558
|
-
noise: options.noise || 2,
|
|
1559
|
-
width: options.width || 150,
|
|
1560
|
-
height: options.height || 75,
|
|
1561
|
-
size: options.size || 4,
|
|
1562
|
-
charPreset: options.charPreset || '0123456789',
|
|
1563
|
-
ignoreChars: options.ignoreChars || '0oli',
|
|
1564
|
-
color: options.hasOwnProperty('color') ? options.color : true,
|
|
1565
|
-
background: options.background || '#cc9966'
|
|
1566
|
-
});
|
|
1567
|
-
return captcha;
|
|
1568
|
-
} //#endregion
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
function configNeeded() {
|
|
1574
|
-
if (!conf$3 || !err$2) {
|
|
1575
|
-
ppUtil$4.configNeeded();
|
|
1576
|
-
conf$3 = ppUtil$4.appConfig;
|
|
1577
|
-
appSetting = conf$3.appSetting;
|
|
1578
|
-
err$2 = ppUtil$4.appErrCfg;
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
var ppUtilApi = apiUtil$2;
|
|
1583
|
-
|
|
1584
|
-
const fs = require$$5__default["default"];
|
|
1585
|
-
const path = require$$1__default$1["default"];
|
|
1586
|
-
const ppUtil$3 = require$$2__default["default"].ppUtil;
|
|
1587
|
-
const {
|
|
1588
|
-
dbUtil,
|
|
1589
|
-
ppRedis,
|
|
1590
|
-
kvStorage,
|
|
1591
|
-
redisSimulator
|
|
1592
|
-
} = require$$3__default["default"];
|
|
1593
|
-
let conf$2, err$1; // const dbCheck = require('../dbupdate/dd-version');
|
|
1594
|
-
|
|
1595
|
-
/**
|
|
1596
|
-
* API服务启动时前置条件检查
|
|
1597
|
-
* ok = await preconditions
|
|
1598
|
-
* .setAppName(conf.thisApp)
|
|
1599
|
-
* .addCheckPromise(preconditions.checkExEnvSetting())
|
|
1600
|
-
* .addCheckPromise(preconditions.checkRedis())
|
|
1601
|
-
* .addCheckPromise(checkDatabase())
|
|
1602
|
-
* .addChecker(myChecker, args)
|
|
1603
|
-
* .checkAll()
|
|
1604
|
-
*/
|
|
1605
|
-
|
|
1606
|
-
class preconditions$1 {
|
|
1607
|
-
static appName;
|
|
1608
|
-
static checkFunctions = [];
|
|
1609
|
-
static checkPromises = [];
|
|
1610
|
-
|
|
1611
|
-
static setAppName(aName) {
|
|
1612
|
-
ppUtil$3.configNeeded();
|
|
1613
|
-
conf$2 = ppUtil$3.appConfig;
|
|
1614
|
-
err$1 = ppUtil$3.appErrCfg;
|
|
1615
|
-
preconditions$1.appName = aName || conf$2.thisApp;
|
|
1616
|
-
return preconditions$1;
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
static addCheckPromise(p) {
|
|
1620
|
-
preconditions$1.checkPromises.push(p);
|
|
1621
|
-
return preconditions$1;
|
|
1622
|
-
}
|
|
1623
|
-
|
|
1624
|
-
static addChecker(checkFunc, args, blocked) {
|
|
1625
|
-
preconditions$1.checkFunctions.push({
|
|
1626
|
-
check: checkFunc,
|
|
1627
|
-
args: args,
|
|
1628
|
-
blocked: blocked
|
|
1629
|
-
});
|
|
1630
|
-
return preconditions$1;
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
static pushMessage(msg) {
|
|
1634
|
-
if (msg) {
|
|
1635
|
-
if (!preconditions$1.messages) {
|
|
1636
|
-
preconditions$1.messages = [];
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
preconditions$1.messages.push(`${preconditions$1.messages.length + 1}. ${msg}`);
|
|
1640
|
-
}
|
|
1641
|
-
|
|
1642
|
-
return msg;
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
static async checkAll() {
|
|
1646
|
-
try {
|
|
1647
|
-
// for (let i = 0; i < preconditions.checkFunctions.length; i++) {
|
|
1648
|
-
// const f = preconditions.checkFunctions[i];
|
|
1649
|
-
// // preconditions.addCheckPromise(f.check(f.args));
|
|
1650
|
-
// preconditions.pushMessage(await f.check(f.args));
|
|
1651
|
-
// }
|
|
1652
|
-
while (preconditions$1.checkFunctions.length > 0) {
|
|
1653
|
-
const f = preconditions$1.checkFunctions.shift();
|
|
1654
|
-
|
|
1655
|
-
if (preconditions$1.pushMessage(await f.check(f.args)) && f.blocked) {
|
|
1656
|
-
break;
|
|
1657
|
-
}
|
|
1658
|
-
} // for (let i = 0; i < preconditions.checkPromises.length; i++) {
|
|
1659
|
-
// preconditions.pushMessage(await preconditions.checkPromises[i]);
|
|
1660
|
-
// }
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
while (preconditions$1.checkPromises.length > 0) {
|
|
1664
|
-
const p = preconditions$1.checkPromises.shift();
|
|
1665
|
-
preconditions$1.pushMessage(await p);
|
|
1666
|
-
}
|
|
1667
|
-
} catch (e) {
|
|
1668
|
-
preconditions$1.pushMessage(e.message);
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
let text = "";
|
|
1672
|
-
|
|
1673
|
-
if (preconditions$1.messages) {
|
|
1674
|
-
text = `*** 由于以下原因,${preconditions$1.appName} 尚不能正常提供服务:\n\n` + preconditions$1.messages.join("\n\n") + "\n\n*** 请检查以上各项条件,修复后重新启动服务";
|
|
1675
|
-
console.log("\n" + text); // for (let i = 0; i < preconditions.messages.length; i++) {
|
|
1676
|
-
// console.log(preconditions.messages[i]);
|
|
1677
|
-
// }
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
|
-
if (!(await fs.async_exists("../log"))) {
|
|
1681
|
-
await fs.async_mkdir("../log");
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
|
-
await fs.async_writeFile(`../log/preconditions`, text);
|
|
1685
|
-
return !text;
|
|
1686
|
-
} // 检查器
|
|
1687
|
-
|
|
1688
|
-
/**
|
|
1689
|
-
* 检查本机外部配置文件版本
|
|
1690
|
-
*/
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
static async checkExEnvSetting(loadjs) {
|
|
1694
|
-
return await checkExEnvSetting(loadjs);
|
|
1695
1546
|
}
|
|
1696
|
-
/**
|
|
1697
|
-
* redis 可用性检查
|
|
1698
|
-
*/
|
|
1699
1547
|
|
|
1548
|
+
//#endregion
|
|
1549
|
+
|
|
1550
|
+
//region ====一些通用服务功能
|
|
1700
1551
|
|
|
1701
|
-
static async checkRedis() {
|
|
1702
|
-
return await checkRedis();
|
|
1703
|
-
}
|
|
1704
1552
|
/**
|
|
1705
|
-
*
|
|
1553
|
+
* 获取配置数据
|
|
1554
|
+
* @param options
|
|
1555
|
+
* @returns {Promise<boolean|*>}
|
|
1706
1556
|
*/
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1557
|
+
// api/config/appSetting.ossEnabled
|
|
1558
|
+
static async getConfigValue(options) {
|
|
1559
|
+
configNeeded();
|
|
1560
|
+
const params = options.replacements;
|
|
1561
|
+
let cfgItem = params._cfgItem;
|
|
1562
|
+
delete params._cfgItem;
|
|
1563
|
+
if (await apiUtil$2.checkForwardsHost(options)) return true;
|
|
1564
|
+
let c = apiUtil$2.parseCfgPath(cfgItem);
|
|
1565
|
+
delete c.parent;
|
|
1566
|
+
c.host = ppUtil$3.getMyIp();
|
|
1567
|
+
return c;
|
|
1711
1568
|
}
|
|
1569
|
+
|
|
1712
1570
|
/**
|
|
1713
|
-
*
|
|
1571
|
+
* 设置配置数据
|
|
1572
|
+
* @param options
|
|
1573
|
+
* @returns {Promise<*>}
|
|
1714
1574
|
*/
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
async function createEnvSettingFile(fileName, lastEnvSettingEx) {
|
|
1730
|
-
try {
|
|
1731
|
-
const cfgText = await ppUtil$3.doCreateEnvSettingFile(fileName, lastEnvSettingEx);
|
|
1732
|
-
|
|
1733
|
-
if (cfgText.indexOf(`cfgVersion: "${conf$2._envSetting.cfgVersion}"`) > 0) {
|
|
1734
|
-
console.log(`\n*** 已創建新的本機環境配置文件\n${fileName}\n请檢查各項內容是否正确(此项更新服务可正常运行)\n\n`);
|
|
1735
|
-
return "";
|
|
1575
|
+
static async setConfigValue(options) {
|
|
1576
|
+
configNeeded();
|
|
1577
|
+
const params = options.replacements;
|
|
1578
|
+
let cfgItem = params._cfgItem;
|
|
1579
|
+
delete params._cfgItem;
|
|
1580
|
+
// if (await checkForwardsHost(options))
|
|
1581
|
+
// return true;
|
|
1582
|
+
await apiUtil$2.parametersOK(params, "value");
|
|
1583
|
+
let c = apiUtil$2.parseCfgPath(cfgItem);
|
|
1584
|
+
if (typeof c.value === "object") {
|
|
1585
|
+
throw [err$1.ACCESS_REFUSED, t_f$2("暂不支持修改复杂配置")];
|
|
1736
1586
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1587
|
+
// c.oldValue = c.value;
|
|
1588
|
+
c.newValue = params.value;
|
|
1589
|
+
c.parent[c.key] = c.newValue;
|
|
1590
|
+
delete c.parent;
|
|
1591
|
+
c.host = ppUtil$3.getMyIp();
|
|
1592
|
+
return c;
|
|
1593
|
+
// 应用层自行处理多机同步
|
|
1741
1594
|
}
|
|
1742
|
-
}
|
|
1743
1595
|
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
if (!fs.existsSync(lastVerFileName)) {
|
|
1762
|
-
fs.renameSync(fileName, lastVerFileName);
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
|
-
let msg = await createEnvSettingFile(fileName, envSettingEx);
|
|
1767
|
-
|
|
1768
|
-
if (msg) {
|
|
1769
|
-
return msg;
|
|
1770
|
-
}
|
|
1771
|
-
|
|
1772
|
-
delete require.cache[fileName];
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
|
-
ppUtil$3.importExEnvSetting(conf$2._envSetting, fileName, loadjs);
|
|
1776
|
-
} catch (e) {
|
|
1777
|
-
return `导入本机环境配置失败\n${e.stack}`;
|
|
1596
|
+
/**
|
|
1597
|
+
* 修改重启标志文件
|
|
1598
|
+
* 前提,PM2监视 restart,please.flag 文件,此文件若被修改则重启服务进程
|
|
1599
|
+
* 此服务假设 restart,please.flag 文件最后一行是一个整数,此整数+1后保存
|
|
1600
|
+
* @param options
|
|
1601
|
+
* @returns {Promise<number>}
|
|
1602
|
+
*/
|
|
1603
|
+
static async updateRestartFlag(options) {
|
|
1604
|
+
const fileName = `restart,please.flag`;
|
|
1605
|
+
let text = await fs.async_readFile(fileName, 'utf8');
|
|
1606
|
+
const lines = text.split('\r\n');
|
|
1607
|
+
const n = +lines[lines.length - 1] + 1;
|
|
1608
|
+
lines[lines.length - 1] = ' '.repeat(50) + n.toString();
|
|
1609
|
+
text = lines.join('\r\n');
|
|
1610
|
+
await fs.async_writeFile(fileName, text);
|
|
1611
|
+
return n;
|
|
1778
1612
|
}
|
|
1779
|
-
} // async function checkDatabase() {
|
|
1780
|
-
// return dbCheck.check().then(info => info.updateMessage);
|
|
1781
|
-
// }
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
async function checkRedis() {
|
|
1785
|
-
if (!conf$2.redis.enabled) return "";
|
|
1786
|
-
const redis = ppRedis.newClient("kv"); // console.log(`checkRedis begin:`);
|
|
1787
|
-
|
|
1788
|
-
await ppUtil$3.wait(15 * 1000, param => {
|
|
1789
|
-
if (redis.ready && redis.connected || redis.error) {
|
|
1790
|
-
return true;
|
|
1791
|
-
}
|
|
1792
|
-
}).catch(e => {
|
|
1793
|
-
redis.error = e;
|
|
1794
|
-
});
|
|
1795
|
-
|
|
1796
|
-
if (redis.error) {
|
|
1797
|
-
console.log(`未能成功連接 redis: ${redis.error},請檢查相關設置`);
|
|
1798
|
-
return `未能成功連接 redis: ${redis.error},請檢查相關設置`;
|
|
1799
|
-
} // console.log(`checkRedis done:`);
|
|
1800
|
-
// console.log(redis);
|
|
1801
|
-
|
|
1802
|
-
}
|
|
1803
|
-
|
|
1804
|
-
async function initDb() {
|
|
1805
|
-
try {
|
|
1806
|
-
dbUtil.config(conf$2, err$1);
|
|
1807
|
-
} catch (e) {
|
|
1808
|
-
if (e.reason === 'bad decrypt') {
|
|
1809
|
-
e = new Error(`解密数据库密码(${conf$2.dbconn.dbpwd})失败`);
|
|
1810
|
-
} // if (e.reason === 'bad decrypt') {
|
|
1811
|
-
// e = new Error(`解密Redis密码(${conf.redis.password})失败`);
|
|
1812
|
-
// }
|
|
1813
1613
|
|
|
1814
|
-
|
|
1815
|
-
|
|
1614
|
+
/**
|
|
1615
|
+
* 创建验证码对象
|
|
1616
|
+
* npm i svg-captcha
|
|
1617
|
+
* npm i svg2png
|
|
1618
|
+
*/
|
|
1619
|
+
static createSvgCaptcha(options) {
|
|
1620
|
+
const captcha = svgCaptcha.create({
|
|
1621
|
+
inverse: options.hasOwnProperty('inverse') ? options.inverse : false,
|
|
1622
|
+
fontSize: options.fontSize || 48,
|
|
1623
|
+
noise: options.noise || 2,
|
|
1624
|
+
width: options.width || 150,
|
|
1625
|
+
height: options.height || 75,
|
|
1626
|
+
size: options.size || 4,
|
|
1627
|
+
charPreset: options.charPreset || '0123456789',
|
|
1628
|
+
ignoreChars: options.ignoreChars || '0oli',
|
|
1629
|
+
color: options.hasOwnProperty('color') ? options.color : true,
|
|
1630
|
+
background: options.background || '#cc9966'
|
|
1631
|
+
});
|
|
1632
|
+
return captcha;
|
|
1816
1633
|
}
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
|
-
async function initKvStorage(dbSql) {
|
|
1820
|
-
try {
|
|
1821
|
-
kvStorage.config(conf$2, err$1);
|
|
1822
1634
|
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
// }
|
|
1832
|
-
return `初始化键值对存储器失败(${e.message})`;
|
|
1635
|
+
//#endregion
|
|
1636
|
+
}
|
|
1637
|
+
function configNeeded() {
|
|
1638
|
+
if (!conf$2 || !err$1) {
|
|
1639
|
+
ppUtil$3.configNeeded();
|
|
1640
|
+
conf$2 = ppUtil$3.appConfig;
|
|
1641
|
+
appSetting = conf$2.appSetting;
|
|
1642
|
+
err$1 = ppUtil$3.appErrCfg;
|
|
1833
1643
|
}
|
|
1834
1644
|
}
|
|
1835
|
-
|
|
1836
|
-
var ppPrecond = preconditions$1;
|
|
1837
|
-
|
|
1838
|
-
// 若 redis 可用,则使用基于 redis 的消息订阅发布系统
|
|
1839
|
-
// 若 redis 不可用,则将消息转发到其它主机
|
|
1645
|
+
var ppUtilApi = apiUtil$2;
|
|
1840
1646
|
|
|
1841
1647
|
const {
|
|
1842
|
-
|
|
1648
|
+
t_f: t_f$1
|
|
1843
1649
|
} = require$$2__default["default"];
|
|
1844
|
-
const
|
|
1650
|
+
const {
|
|
1651
|
+
ppUtil: ppUtil$2
|
|
1652
|
+
} = require$$3__default["default"];
|
|
1653
|
+
const RedisMessenger = require$$2__default$2["default"];
|
|
1845
1654
|
const {
|
|
1846
1655
|
netUtil
|
|
1847
|
-
} = require$$
|
|
1656
|
+
} = require$$6__default["default"];
|
|
1848
1657
|
let conf$1;
|
|
1849
1658
|
|
|
1659
|
+
/**
|
|
1660
|
+
* 普通消息系统
|
|
1661
|
+
* =
|
|
1662
|
+
* 若 redis 可用,则使用基于 redis 的消息订阅发布系统
|
|
1663
|
+
* 若 redis 不可用,则将消息转发到其它主机
|
|
1664
|
+
*/
|
|
1850
1665
|
class commonMessenger$2 {
|
|
1851
1666
|
static myMsgAddr = "";
|
|
1852
1667
|
static redisMessenger = null;
|
|
1853
1668
|
static onMessage = [];
|
|
1854
|
-
|
|
1855
1669
|
static initMessenger(appConfig, appErrCfg, msgChannel) {
|
|
1856
1670
|
conf$1 = appConfig;
|
|
1857
1671
|
commonMessenger$2.redisMessenger = conf$1.redis.enabled ? new RedisMessenger(appConfig, appErrCfg, msgChannel).subscribe(msgChannel) : null;
|
|
1858
1672
|
commonMessenger$2.myMsgAddr = commonMessenger$2.getMyMsgAddr();
|
|
1859
1673
|
}
|
|
1860
|
-
|
|
1861
1674
|
static getMyMsgAddr() {
|
|
1862
1675
|
if (!conf$1.myMsgAddr) {
|
|
1863
1676
|
conf$1.pm_id = process.env.pm_id || "0";
|
|
1864
1677
|
let myIp = ppUtil$2.getMyIp();
|
|
1865
|
-
|
|
1866
1678
|
if (commonMessenger$2.redisMessenger) {
|
|
1867
1679
|
myIp = `${conf$1.pm_id}@${myIp}`;
|
|
1868
1680
|
}
|
|
1869
|
-
|
|
1870
1681
|
conf$1.myMsgAddr = myIp;
|
|
1871
1682
|
console.log(`myMsgAddr: `, conf$1.myMsgAddr);
|
|
1872
1683
|
}
|
|
1873
|
-
|
|
1874
1684
|
return conf$1.myMsgAddr;
|
|
1875
1685
|
}
|
|
1876
|
-
|
|
1877
1686
|
static setMessageHandle(messageHandle, msgChannel) {
|
|
1878
1687
|
if (commonMessenger$2.redisMessenger) {
|
|
1879
1688
|
return commonMessenger$2.redisMessenger.setMessageHandle(messageHandle, msgChannel);
|
|
1880
1689
|
}
|
|
1881
|
-
|
|
1882
1690
|
if (commonMessenger$2.onMessage.indexOf(messageHandle) < 0) {
|
|
1883
1691
|
commonMessenger$2.onMessage.push(messageHandle);
|
|
1884
1692
|
}
|
|
1885
|
-
|
|
1886
1693
|
return commonMessenger$2;
|
|
1887
1694
|
}
|
|
1888
|
-
|
|
1889
1695
|
static async publishMessage(message, msgChannel) {
|
|
1890
1696
|
if (commonMessenger$2.redisMessenger) {
|
|
1891
1697
|
return commonMessenger$2.redisMessenger.publish(message, msgChannel);
|
|
@@ -1896,7 +1702,6 @@ class commonMessenger$2 {
|
|
|
1896
1702
|
} else {
|
|
1897
1703
|
for (let i = 0; i < conf$1.appSetting.serverHosts.length; i++) {
|
|
1898
1704
|
message.destAddr = conf$1.appSetting.serverHosts[i];
|
|
1899
|
-
|
|
1900
1705
|
if (message.destAddr !== conf$1.myMsgAddr) {
|
|
1901
1706
|
await forwardMessage(message);
|
|
1902
1707
|
}
|
|
@@ -1904,13 +1709,10 @@ class commonMessenger$2 {
|
|
|
1904
1709
|
}
|
|
1905
1710
|
}
|
|
1906
1711
|
}
|
|
1907
|
-
|
|
1908
1712
|
static async handleInternalMessage(options) {
|
|
1909
1713
|
const message = options.replacements;
|
|
1910
|
-
|
|
1911
1714
|
for (let i = 0; i < commonMessenger$2.onMessage.length; i++) {
|
|
1912
1715
|
const appMsgHandle = commonMessenger$2.onMessage[i];
|
|
1913
|
-
|
|
1914
1716
|
try {
|
|
1915
1717
|
await appMsgHandle(message);
|
|
1916
1718
|
} catch (e) {
|
|
@@ -1918,9 +1720,7 @@ class commonMessenger$2 {
|
|
|
1918
1720
|
}
|
|
1919
1721
|
}
|
|
1920
1722
|
}
|
|
1921
|
-
|
|
1922
1723
|
}
|
|
1923
|
-
|
|
1924
1724
|
async function forwardMessage(message) {
|
|
1925
1725
|
let reqOptions = {
|
|
1926
1726
|
url: `https://${message.destAddr}:${conf$1.appSetting.listenPort}/api/message`,
|
|
@@ -1928,30 +1728,33 @@ async function forwardMessage(message) {
|
|
|
1928
1728
|
data: message
|
|
1929
1729
|
};
|
|
1930
1730
|
let res = await netUtil.apiRequest(reqOptions).catch(e => {
|
|
1931
|
-
console.log(
|
|
1731
|
+
console.log(t_f$1("转发消息失败, url: %s", reqOptions.url), e);
|
|
1932
1732
|
throw e;
|
|
1933
1733
|
});
|
|
1934
1734
|
return res.data;
|
|
1935
1735
|
}
|
|
1936
|
-
|
|
1937
1736
|
var ppMessengerEx = commonMessenger$2;
|
|
1938
1737
|
|
|
1939
|
-
/**
|
|
1940
|
-
* CSCA 自动任务
|
|
1941
|
-
* ==============
|
|
1942
|
-
*/
|
|
1943
1738
|
const CRON = require$$0__default$1["default"];
|
|
1944
1739
|
const {
|
|
1945
|
-
|
|
1740
|
+
t_f
|
|
1946
1741
|
} = require$$2__default["default"];
|
|
1742
|
+
const {
|
|
1743
|
+
ppUtil: ppUtil$1
|
|
1744
|
+
} = require$$3__default["default"];
|
|
1947
1745
|
const apiUtil$1 = ppUtilApi;
|
|
1948
1746
|
const commonMessenger$1 = ppMessengerEx;
|
|
1949
1747
|
const MT_SCHEDULE_STATE = 'schedule-state',
|
|
1950
|
-
|
|
1748
|
+
MT_SCHEDULE_STATE_REPLY = 'schedule-state-reply';
|
|
1951
1749
|
let conf, err;
|
|
1952
1750
|
|
|
1751
|
+
/**
|
|
1752
|
+
* CSCA 自动任务
|
|
1753
|
+
* ==============
|
|
1754
|
+
*/
|
|
1953
1755
|
class schedule$1 {
|
|
1954
1756
|
static tasks = {};
|
|
1757
|
+
|
|
1955
1758
|
/**
|
|
1956
1759
|
* 注册一个计划任务
|
|
1957
1760
|
* @param taskName
|
|
@@ -1961,18 +1764,15 @@ class schedule$1 {
|
|
|
1961
1764
|
* @param autoStart
|
|
1962
1765
|
* @returns {Promise<{}|{}|{cron: *, _message_: string}|any>}
|
|
1963
1766
|
*/
|
|
1964
|
-
|
|
1965
1767
|
static async registerTask(taskName, taskCaption, cronExp, taskFunc, autoStart) {
|
|
1966
1768
|
if (!this.envAllowed()) return {};
|
|
1967
1769
|
let task = this.findTask(taskName);
|
|
1968
|
-
|
|
1969
1770
|
if (task) {
|
|
1970
1771
|
if (task.cronExp !== cronExp || task.taskFunc !== taskFunc) {
|
|
1971
1772
|
this.stop(taskName);
|
|
1972
1773
|
task = null;
|
|
1973
1774
|
}
|
|
1974
1775
|
}
|
|
1975
|
-
|
|
1976
1776
|
if (!task) {
|
|
1977
1777
|
task = {
|
|
1978
1778
|
name: taskName,
|
|
@@ -1983,23 +1783,19 @@ class schedule$1 {
|
|
|
1983
1783
|
doScheduleTask: async function () {
|
|
1984
1784
|
let self = this;
|
|
1985
1785
|
if (this._pp_task) self = this._pp_task;
|
|
1986
|
-
console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'),
|
|
1786
|
+
console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'), t_f("开始执行%s任务 ...", self.caption));
|
|
1987
1787
|
await self.taskFunc();
|
|
1988
|
-
console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'),
|
|
1788
|
+
console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'), t_f("%s任务执行结束", self.caption));
|
|
1989
1789
|
}
|
|
1990
1790
|
};
|
|
1991
1791
|
this.tasks[taskName] = task;
|
|
1992
|
-
|
|
1993
1792
|
if (autoStart) {
|
|
1994
1793
|
return await this.start(task);
|
|
1995
1794
|
}
|
|
1996
|
-
|
|
1997
1795
|
return this.getTaskInfo(task, "任务已注册。");
|
|
1998
1796
|
}
|
|
1999
|
-
|
|
2000
1797
|
return this.getTaskInfo(task, "任务已存在。");
|
|
2001
1798
|
}
|
|
2002
|
-
|
|
2003
1799
|
static getTaskInfo(task, msg) {
|
|
2004
1800
|
// return Object.assign({_message_: msg}, task);
|
|
2005
1801
|
return {
|
|
@@ -2010,75 +1806,62 @@ class schedule$1 {
|
|
|
2010
1806
|
_message_: msg
|
|
2011
1807
|
};
|
|
2012
1808
|
}
|
|
1809
|
+
|
|
2013
1810
|
/**
|
|
2014
1811
|
* 启动任务
|
|
2015
1812
|
* @param taskOrName
|
|
2016
1813
|
* @param cronExp
|
|
2017
1814
|
* @returns {Promise<{}|{cron: *, _message_: string}>}
|
|
2018
1815
|
*/
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
1816
|
static async start(taskOrName, cronExp) {
|
|
2022
1817
|
if (!this.envAllowed()) return {};
|
|
2023
1818
|
let task = taskOrName;
|
|
2024
|
-
|
|
2025
1819
|
if (typeof task === "string") {
|
|
2026
1820
|
task = this.findTask(taskOrName);
|
|
2027
1821
|
}
|
|
2028
|
-
|
|
2029
|
-
if (!task) throw [err.INVALID_PARAM, `任务${taskOrName}不存在`];
|
|
1822
|
+
if (!task) throw [err.INVALID_PARAM, t_f("任务%s不存在", taskOrName)];
|
|
2030
1823
|
cronExp = cronExp || task.cronExp;
|
|
2031
|
-
|
|
2032
1824
|
if (task.cronExp !== cronExp) {
|
|
2033
1825
|
this.stop(task);
|
|
2034
1826
|
task.cronExp = cronExp;
|
|
2035
1827
|
}
|
|
2036
|
-
|
|
2037
1828
|
if (task.schedule) {
|
|
2038
1829
|
return this.getTaskInfo(task, "任务已启动,无需重复启动。");
|
|
2039
1830
|
}
|
|
2040
|
-
|
|
2041
1831
|
task.schedule = CRON.schedule(cronExp, task.doScheduleTask);
|
|
2042
1832
|
task.schedule._task._pp_task = task;
|
|
2043
1833
|
return this.getTaskInfo(task, "任务已启动。");
|
|
2044
1834
|
}
|
|
1835
|
+
|
|
2045
1836
|
/**
|
|
2046
1837
|
* 停止任务
|
|
2047
1838
|
* @param taskOrName
|
|
2048
1839
|
* @returns {Promise<{}|{cron: *, _message_: string}|{_message_: string}>}
|
|
2049
1840
|
*/
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
1841
|
static async stop(taskOrName) {
|
|
2053
1842
|
if (!this.envAllowed()) return {};
|
|
2054
1843
|
let task = taskOrName;
|
|
2055
|
-
|
|
2056
1844
|
if (typeof task === "string") {
|
|
2057
1845
|
task = this.findTask(taskOrName);
|
|
2058
1846
|
}
|
|
2059
|
-
|
|
2060
|
-
if (!task) throw [err.INVALID_PARAM, `任务${taskOrName}不存在`];
|
|
2061
|
-
|
|
1847
|
+
if (!task) throw [err.INVALID_PARAM, t_f("任务%s不存在", taskOrName)];
|
|
2062
1848
|
if (task.schedule) {
|
|
2063
1849
|
task.schedule.stop();
|
|
2064
1850
|
task.schedule = null;
|
|
2065
1851
|
return this.getTaskInfo(task, "任务已停止。");
|
|
2066
1852
|
}
|
|
2067
|
-
|
|
2068
1853
|
return this.getTaskInfo(task, "任务未启动,无需停止。");
|
|
2069
1854
|
}
|
|
1855
|
+
|
|
2070
1856
|
/**
|
|
2071
1857
|
* 获取或设置当前状态(来自远程的API调用)
|
|
2072
1858
|
* @param options
|
|
2073
1859
|
* @returns {Promise<unknown>}
|
|
2074
1860
|
*/
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
1861
|
static async state(options) {
|
|
2078
|
-
const params = options.replacements;
|
|
2079
|
-
|
|
1862
|
+
const params = options.replacements;
|
|
1863
|
+
// await commonMessenger.parametersOK(params, "taskName");
|
|
2080
1864
|
const req = options._res.req;
|
|
2081
|
-
|
|
2082
1865
|
if (req) {
|
|
2083
1866
|
if (req.method === 'GET') {
|
|
2084
1867
|
delete params.state;
|
|
@@ -2086,16 +1869,15 @@ class schedule$1 {
|
|
|
2086
1869
|
await apiUtil$1.parametersOK(params, 'taskName', "state");
|
|
2087
1870
|
}
|
|
2088
1871
|
}
|
|
2089
|
-
|
|
2090
1872
|
if (this.envAllowed()) {
|
|
2091
1873
|
return this._state(params);
|
|
2092
|
-
}
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
// 环境变量启用计划任务,但当前环境不能执行,
|
|
2093
1877
|
// 说明收到此API请求的进程不是第一个进程,或者此前服务器不是第一台服务器,
|
|
2094
1878
|
// 这种情况下,将此请求作为消息发布出去,
|
|
2095
1879
|
// 第一台服务器的第一个进程收到消息后进行处理,再将结果作为消息发布,
|
|
2096
1880
|
// 本进程收到处理结果后果作为响应发送回客户端
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
1881
|
if (process.env.SCHEDULE_ENABLED) {
|
|
2100
1882
|
let replyId = ppUtil$1.newGuid();
|
|
2101
1883
|
return await new Promise((resolve, reject) => {
|
|
@@ -2105,7 +1887,6 @@ class schedule$1 {
|
|
|
2105
1887
|
resolve(message.result);
|
|
2106
1888
|
return;
|
|
2107
1889
|
}
|
|
2108
|
-
|
|
2109
1890
|
if (message._type === MT_SCHEDULE_STATE) {
|
|
2110
1891
|
if (schedule$1.enabled()) {
|
|
2111
1892
|
message.result = schedule$1._state(message.params);
|
|
@@ -2131,85 +1912,71 @@ class schedule$1 {
|
|
|
2131
1912
|
}, 2 * 60 * 1000);
|
|
2132
1913
|
});
|
|
2133
1914
|
}
|
|
2134
|
-
|
|
2135
1915
|
return {
|
|
2136
1916
|
_message_: "此环境无自动任务"
|
|
2137
1917
|
};
|
|
2138
1918
|
}
|
|
2139
|
-
|
|
2140
1919
|
static async _state(params) {
|
|
2141
1920
|
let apiResult = {};
|
|
2142
1921
|
let task;
|
|
2143
|
-
|
|
2144
1922
|
if (params.taskName) {
|
|
2145
1923
|
task = this.findTask(params.taskName);
|
|
2146
|
-
if (!task) throw [err.INVALID_PARAM,
|
|
1924
|
+
if (!task) throw [err.INVALID_PARAM, t_f("任务%s不存在", params.taskName)];
|
|
2147
1925
|
}
|
|
2148
|
-
|
|
2149
1926
|
if (params.state) {
|
|
2150
1927
|
if ("started" === params.state) {
|
|
2151
1928
|
apiResult = await this.start(task, params.cron);
|
|
2152
1929
|
} else if ("stopped" === params.state) {
|
|
2153
1930
|
apiResult = await this.stop(task);
|
|
2154
1931
|
} else {
|
|
2155
|
-
throw [err.INVALID_PARAM,
|
|
1932
|
+
throw [err.INVALID_PARAM, t_f("(%s), 只能是 started/stopped", params.state)];
|
|
2156
1933
|
}
|
|
2157
|
-
|
|
2158
1934
|
if (params.runOnce) {
|
|
2159
1935
|
task = this.findTask(params.taskName);
|
|
2160
|
-
apiResult._message_ += "\n正在手动执行任务";
|
|
2161
|
-
|
|
1936
|
+
apiResult._message_ += "\n正在手动执行任务";
|
|
1937
|
+
// await
|
|
2162
1938
|
task.doScheduleTask();
|
|
2163
1939
|
}
|
|
2164
|
-
|
|
2165
1940
|
return this.getTaskInfo(task, apiResult._message_);
|
|
2166
1941
|
}
|
|
2167
|
-
|
|
2168
1942
|
if (task) {
|
|
2169
1943
|
return this.getTaskInfo(task);
|
|
2170
1944
|
}
|
|
2171
|
-
|
|
2172
1945
|
const result = [];
|
|
2173
|
-
|
|
2174
1946
|
for (let k in this.tasks) {
|
|
2175
1947
|
result.push(this.getTaskInfo(this.tasks[k]));
|
|
2176
1948
|
}
|
|
2177
|
-
|
|
2178
1949
|
return result;
|
|
2179
1950
|
}
|
|
2180
|
-
|
|
2181
1951
|
static deleteTask(taskName) {
|
|
2182
1952
|
delete this.tasks[taskName];
|
|
2183
1953
|
}
|
|
2184
|
-
|
|
2185
1954
|
static findTask(taskName) {
|
|
2186
1955
|
return this.tasks[taskName];
|
|
2187
1956
|
}
|
|
1957
|
+
|
|
2188
1958
|
/**
|
|
2189
1959
|
* 确定当前进程环境是否启用自动任务
|
|
2190
1960
|
*/
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
1961
|
static envAllowed() {
|
|
2194
1962
|
if (!conf) {
|
|
2195
1963
|
ppUtil$1.configNeeded();
|
|
2196
1964
|
conf = ppUtil$1.appConfig;
|
|
2197
1965
|
err = ppUtil$1.appErrCfg;
|
|
2198
1966
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
!!process.env.SCHEDULE_ENABLED
|
|
2202
|
-
|
|
1967
|
+
let enabled =
|
|
1968
|
+
// PM2配置中指定了环境变量 SCHEDULE_ENABLED
|
|
1969
|
+
!!process.env.SCHEDULE_ENABLED
|
|
1970
|
+
// 如果PM2启动了多个进程,则只在第一个进程执行
|
|
1971
|
+
&& process.env.NODE_APP_INSTANCE === '0';
|
|
1972
|
+
// // 如果有多台服务器,则只在第一台执行
|
|
2203
1973
|
// if (enabled && conf.appSetting.serverHosts && (conf.appSetting.serverHosts.length > 1)) {
|
|
2204
1974
|
// enabled = conf.myMsgAddr.indexOf(conf.appSetting.serverHosts[0]) === 0;
|
|
2205
1975
|
// }
|
|
2206
1976
|
// todo: 暂时取消此限制,要通过配置设定
|
|
2207
|
-
|
|
2208
1977
|
return enabled;
|
|
2209
1978
|
}
|
|
2210
|
-
|
|
2211
1979
|
}
|
|
2212
|
-
|
|
2213
1980
|
var ppSchedule = schedule$1;
|
|
2214
1981
|
|
|
2215
1982
|
const apiUtil = ppUtilApi;
|