abler-api 0.1.25 → 0.1.28
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 +451 -263
- package/dist/es/pp-util.js +447 -261
- package/package.json +1 -1
package/dist/es/pp-util.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import require$$0
|
|
1
|
+
import require$$0 from 'crypto';
|
|
2
2
|
import require$$1 from 'abler-util';
|
|
3
3
|
import require$$2 from 'abler-db';
|
|
4
4
|
import require$$3 from 'abler-net';
|
|
5
|
-
import require$$0$
|
|
5
|
+
import require$$0$1 from 'fs';
|
|
6
6
|
import require$$1$1 from 'path';
|
|
7
|
+
import require$$1$2 from 'abler-messenger';
|
|
8
|
+
import require$$0$2 from 'node-cron';
|
|
7
9
|
|
|
8
|
-
const crypto = require$$0
|
|
10
|
+
const crypto = require$$0;
|
|
9
11
|
const ppUtil$4 = require$$1.ppUtil;
|
|
10
12
|
const {
|
|
11
13
|
dbUtil,
|
|
12
14
|
kvStorage
|
|
13
15
|
} = require$$2;
|
|
14
16
|
const netUtil$1 = require$$3;
|
|
15
|
-
let conf$
|
|
17
|
+
let conf$3, appSetting$1, err$2, dbSql;
|
|
16
18
|
const pnToken = "access_token",
|
|
17
19
|
hnToken = pnToken,
|
|
18
20
|
pnApiKey = "apiKey",
|
|
@@ -23,7 +25,7 @@ pnApiSecret = "apiSecret",
|
|
|
23
25
|
const MD5 = ppUtil$4.MD5,
|
|
24
26
|
moveProperty = ppUtil$4.moveProperty;
|
|
25
27
|
|
|
26
|
-
class apiUtil$
|
|
28
|
+
class apiUtil$2 {
|
|
27
29
|
static debugFlag = ppUtil$4.newGuid(); //应用必须设置,否则谁也不知道是啥
|
|
28
30
|
|
|
29
31
|
static testFlag = ppUtil$4.newGuid();
|
|
@@ -31,11 +33,11 @@ class apiUtil$1 {
|
|
|
31
33
|
|
|
32
34
|
static config(appConfig, appErrCfg, appDbSql) {
|
|
33
35
|
ppUtil$4.config(appConfig, appErrCfg);
|
|
34
|
-
conf$
|
|
35
|
-
appSetting$1 = conf$
|
|
36
|
-
err$
|
|
37
|
-
apiUtil$
|
|
38
|
-
apiUtil$
|
|
36
|
+
conf$3 = appConfig;
|
|
37
|
+
appSetting$1 = conf$3?.appSetting;
|
|
38
|
+
err$2 = appErrCfg, dbSql = appDbSql;
|
|
39
|
+
apiUtil$2.debugFlag = appSetting$1?.debugFlag || apiUtil$2.debugFlag;
|
|
40
|
+
apiUtil$2.testFlag = appSetting$1?.testFlag || apiUtil$2.testFlag; // apiUtil.apiCallRecSaver = apiCallRecSaver;
|
|
39
41
|
} //#region ===== 需要应用系统重写的方法
|
|
40
42
|
|
|
41
43
|
/**
|
|
@@ -123,7 +125,7 @@ class apiUtil$1 {
|
|
|
123
125
|
req._requestParams = Object.assign(req.params, req._requestParams);
|
|
124
126
|
}
|
|
125
127
|
|
|
126
|
-
apiUtil$
|
|
128
|
+
apiUtil$2.setParamsFunctions(req._requestParams);
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
return req._requestParams;
|
|
@@ -134,11 +136,11 @@ class apiUtil$1 {
|
|
|
134
136
|
return req.tokenData;
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
let params = apiUtil$
|
|
139
|
+
let params = apiUtil$2.extractParams(req);
|
|
138
140
|
let tokenData = {
|
|
139
141
|
apiKey: req.headers[hnApiKey] || params[pnApiKey],
|
|
140
142
|
apiSecret: req.headers[hnApiSecret] || params[pnApiSecret],
|
|
141
|
-
clientIp: apiUtil$
|
|
143
|
+
clientIp: apiUtil$2.getClientIp(req)
|
|
142
144
|
};
|
|
143
145
|
return tokenData;
|
|
144
146
|
}
|
|
@@ -155,7 +157,7 @@ class apiUtil$1 {
|
|
|
155
157
|
let result = +this[name];
|
|
156
158
|
|
|
157
159
|
if (typeof result !== "number" || result < minValue || result > maxValue) {
|
|
158
|
-
throw [err$
|
|
160
|
+
throw [err$2.INVALID_PARAM, `参数 ${name} 必须是 ${minValue} ~ ${maxValue} 之间的数字`];
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
return result;
|
|
@@ -225,7 +227,7 @@ class apiUtil$1 {
|
|
|
225
227
|
|
|
226
228
|
static apiFail(error, req) {
|
|
227
229
|
configNeeded();
|
|
228
|
-
let response = err$
|
|
230
|
+
let response = err$2.ERROR(error, err$2.errorLangParamFlag + ppUtil$4.getMsgLang(req));
|
|
229
231
|
response.datetime = new Date();
|
|
230
232
|
|
|
231
233
|
if (req && req.headers) {
|
|
@@ -247,8 +249,8 @@ class apiUtil$1 {
|
|
|
247
249
|
|
|
248
250
|
|
|
249
251
|
static spoApiSucc(data, req) {
|
|
250
|
-
let params = apiUtil$
|
|
251
|
-
return apiUtil$
|
|
252
|
+
let params = apiUtil$2.extractParams(req);
|
|
253
|
+
return apiUtil$2.apiSuccess(data, req, params.spOrderNum);
|
|
252
254
|
}
|
|
253
255
|
/**
|
|
254
256
|
* 生成面向服务商的API失败返回结果
|
|
@@ -259,8 +261,8 @@ class apiUtil$1 {
|
|
|
259
261
|
|
|
260
262
|
|
|
261
263
|
static spoApiFail(error, req) {
|
|
262
|
-
let params = apiUtil$
|
|
263
|
-
return apiUtil$
|
|
264
|
+
let params = apiUtil$2.extractParams(req);
|
|
265
|
+
return apiUtil$2.apiFail(error, req, params.spOrderNum);
|
|
264
266
|
}
|
|
265
267
|
/**
|
|
266
268
|
* API 服务结束,发送响应
|
|
@@ -297,10 +299,10 @@ class apiUtil$1 {
|
|
|
297
299
|
static async responseOf(response, promise) {
|
|
298
300
|
promise.then(function (data) {
|
|
299
301
|
// console.log('RES:', apiSuccess(data));
|
|
300
|
-
if (!response.finished) response.send(apiUtil$
|
|
302
|
+
if (!response.finished) response.send(apiUtil$2.apiSuccess(data, response.req));
|
|
301
303
|
}, function (error) {
|
|
302
304
|
console.log('ERROR:', error);
|
|
303
|
-
if (!response.finished) response.send(apiUtil$
|
|
305
|
+
if (!response.finished) response.send(apiUtil$2.apiFail(error, response.req));
|
|
304
306
|
});
|
|
305
307
|
}
|
|
306
308
|
/**
|
|
@@ -312,16 +314,16 @@ class apiUtil$1 {
|
|
|
312
314
|
|
|
313
315
|
static async spoApiResponse(response, promise) {
|
|
314
316
|
promise.then(function (result) {
|
|
315
|
-
let responseData = apiUtil$
|
|
317
|
+
let responseData = apiUtil$2.spoApiSucc(result, response.req);
|
|
316
318
|
|
|
317
|
-
apiUtil$
|
|
319
|
+
apiUtil$2._saveApiCallRec(response.req.apiCallRec, responseData);
|
|
318
320
|
|
|
319
321
|
if (!response.finished) response.send(responseData);
|
|
320
322
|
}, function (error) {
|
|
321
323
|
console.log('ERROR:', error);
|
|
322
|
-
let responseData = apiUtil$
|
|
324
|
+
let responseData = apiUtil$2.spoApiFail(error, response.req);
|
|
323
325
|
|
|
324
|
-
apiUtil$
|
|
326
|
+
apiUtil$2._saveApiCallRec(response.req.apiCallRec, responseData);
|
|
325
327
|
|
|
326
328
|
if (!response.finished) response.send(responseData);
|
|
327
329
|
});
|
|
@@ -338,7 +340,7 @@ class apiUtil$1 {
|
|
|
338
340
|
req.headers.timestamp = new Date().valueOf(); // let options = {replacements: {}};
|
|
339
341
|
|
|
340
342
|
let options = {};
|
|
341
|
-
let parameters = apiUtil$
|
|
343
|
+
let parameters = apiUtil$2.extractParams(req);
|
|
342
344
|
|
|
343
345
|
for (let qryParam in parameters) {
|
|
344
346
|
if (qryParam !== 'token') {
|
|
@@ -370,7 +372,7 @@ class apiUtil$1 {
|
|
|
370
372
|
// }
|
|
371
373
|
|
|
372
374
|
options.userInfo = req.userInfo;
|
|
373
|
-
return apiUtil$
|
|
375
|
+
return apiUtil$2.setOptionsPropFuncions(options, res);
|
|
374
376
|
}
|
|
375
377
|
/**
|
|
376
378
|
* 为API请求 options 设置属性
|
|
@@ -435,7 +437,7 @@ class apiUtil$1 {
|
|
|
435
437
|
let token = req.headers[hnToken] || req.headers['x-access-token']; //向后兼容
|
|
436
438
|
|
|
437
439
|
if (!token) {
|
|
438
|
-
let params = apiUtil$
|
|
440
|
+
let params = apiUtil$2.extractParams(req);
|
|
439
441
|
token = params[pnToken];
|
|
440
442
|
|
|
441
443
|
if (token) {
|
|
@@ -446,12 +448,12 @@ class apiUtil$1 {
|
|
|
446
448
|
delete params.token;
|
|
447
449
|
} else {
|
|
448
450
|
// 如果没有token,则返回错误
|
|
449
|
-
console.log(err$
|
|
451
|
+
console.log(err$2.TOKEN_NEEDED);
|
|
450
452
|
|
|
451
453
|
if (res) {
|
|
452
|
-
res.send(err$
|
|
454
|
+
res.send(err$2.ERROR(err$2.TOKEN_NEEDED));
|
|
453
455
|
} else if (!noErr) {
|
|
454
|
-
throw err$
|
|
456
|
+
throw err$2.TOKEN_NEEDED;
|
|
455
457
|
}
|
|
456
458
|
}
|
|
457
459
|
}
|
|
@@ -470,8 +472,8 @@ class apiUtil$1 {
|
|
|
470
472
|
|
|
471
473
|
static async checkInternalToken(req) {
|
|
472
474
|
// return await checkInternalToken(req);
|
|
473
|
-
const params = apiUtil$
|
|
474
|
-
req.accessToken = req.accessToken || apiUtil$
|
|
475
|
+
const params = apiUtil$2.extractParams(req);
|
|
476
|
+
req.accessToken = req.accessToken || apiUtil$2.extractToken(req);
|
|
475
477
|
|
|
476
478
|
if (req.accessToken === MD5(ppUtil$4.idNumDisturbing)) {
|
|
477
479
|
//todo: 检查IP
|
|
@@ -494,7 +496,7 @@ class apiUtil$1 {
|
|
|
494
496
|
return true;
|
|
495
497
|
} else {
|
|
496
498
|
// console.log('token error.', req.accessToken);
|
|
497
|
-
throw err$
|
|
499
|
+
throw err$2.TOKEN_INVALID;
|
|
498
500
|
}
|
|
499
501
|
}
|
|
500
502
|
/**
|
|
@@ -505,16 +507,16 @@ class apiUtil$1 {
|
|
|
505
507
|
|
|
506
508
|
|
|
507
509
|
static async checkRequestToken(req) {
|
|
508
|
-
req.accessToken = req.accessToken || apiUtil$
|
|
509
|
-
const tokenKey = apiUtil$
|
|
510
|
-
const expireTime = apiUtil$
|
|
511
|
-
return await apiUtil$
|
|
512
|
-
req.userInfo = apiUtil$
|
|
510
|
+
req.accessToken = req.accessToken || apiUtil$2.extractToken(req);
|
|
511
|
+
const tokenKey = apiUtil$2.userTokenStoreKey(req.accessToken);
|
|
512
|
+
const expireTime = apiUtil$2.tokenExpireTime(req);
|
|
513
|
+
return await apiUtil$2.restoreTokenData(tokenKey, expireTime).then(async function (data) {
|
|
514
|
+
req.userInfo = apiUtil$2.setUserIdNo(data, data._idNo);
|
|
513
515
|
if (req.tokenValidater) await req.tokenValidater(req.userInfo, req);
|
|
514
516
|
return true;
|
|
515
517
|
}, async function (e) {
|
|
516
518
|
// 如果给定的token不存在,看看是不是平台内部调用
|
|
517
|
-
return await apiUtil$
|
|
519
|
+
return await apiUtil$2.checkInternalToken(req);
|
|
518
520
|
});
|
|
519
521
|
}
|
|
520
522
|
/**
|
|
@@ -526,7 +528,7 @@ class apiUtil$1 {
|
|
|
526
528
|
|
|
527
529
|
static isDebugMode(req) {
|
|
528
530
|
if (req.__debug__ === undefined) {
|
|
529
|
-
let dbgToken = req.headers['__debug__'] || req.headers[apiUtil$
|
|
531
|
+
let dbgToken = req.headers['__debug__'] || req.headers[apiUtil$2.debugFlag];
|
|
530
532
|
|
|
531
533
|
if (dbgToken) {
|
|
532
534
|
let envId = process.env.ECS_DEPLOY_ID;
|
|
@@ -548,11 +550,11 @@ class apiUtil$1 {
|
|
|
548
550
|
|
|
549
551
|
static isTestMode(req) {
|
|
550
552
|
if (req.__postman__ === undefined) {
|
|
551
|
-
let dbgToken = req.headers["__postman__"] || req.headers[apiUtil$
|
|
553
|
+
let dbgToken = req.headers["__postman__"] || req.headers[apiUtil$2.testFlag];
|
|
552
554
|
|
|
553
555
|
if (dbgToken) {
|
|
554
556
|
let envId = process.env.ECS_DEPLOY_ID;
|
|
555
|
-
let testToken = MD5(req.headers.timestamp, apiUtil$
|
|
557
|
+
let testToken = MD5(req.headers.timestamp, apiUtil$2.extractToken(req, null, true) || req.headers.apikey);
|
|
556
558
|
req.__postman__ = dbgToken === testToken && (envId.indexOf("myfacesign.com") < 0 || envId.indexOf(".dev.") > 0);
|
|
557
559
|
} else {
|
|
558
560
|
req.__postman__ = false;
|
|
@@ -569,7 +571,7 @@ class apiUtil$1 {
|
|
|
569
571
|
|
|
570
572
|
|
|
571
573
|
static tokenExpireTime(req) {
|
|
572
|
-
return apiUtil$
|
|
574
|
+
return apiUtil$2.isDebugMode(req) ? 30 * 24 * 60 * 60 : apiUtil$2.isTestMode(req) ? 4 * 60 * 60 : appSetting$1.tokenExpireTime;
|
|
573
575
|
}
|
|
574
576
|
/**
|
|
575
577
|
* 获取用户令牌保存键
|
|
@@ -612,7 +614,7 @@ class apiUtil$1 {
|
|
|
612
614
|
static setUserIdNo(userInfo, idNum) {
|
|
613
615
|
if (userInfo && idNum) {
|
|
614
616
|
userInfo._idNo = idNum;
|
|
615
|
-
userInfo.isHKIC = apiUtil$
|
|
617
|
+
userInfo.isHKIC = apiUtil$2.checkIsHKIC(idNum);
|
|
616
618
|
}
|
|
617
619
|
|
|
618
620
|
return userInfo;
|
|
@@ -629,7 +631,7 @@ class apiUtil$1 {
|
|
|
629
631
|
|
|
630
632
|
static async storeToken(token, tokenData, dataId, req) {
|
|
631
633
|
// let timeout = tokenData.clientIp.substring(0, 8) == "192.168." ? 90 * 24 : 1;
|
|
632
|
-
let timeout = apiUtil$
|
|
634
|
+
let timeout = apiUtil$2.tokenExpireTime(req);
|
|
633
635
|
|
|
634
636
|
if (req.certPublicKey) {
|
|
635
637
|
tokenData.certPublicKey = req.certPublicKey;
|
|
@@ -777,7 +779,7 @@ class apiUtil$1 {
|
|
|
777
779
|
return certInfo;
|
|
778
780
|
}).catch(e => {
|
|
779
781
|
console.log('获取企业证书失败:\n', e);
|
|
780
|
-
throw [err$
|
|
782
|
+
throw [err$2.ACCESS_REFUSED, `获取企业证书失败:${err$2.ERROR(e).message}`];
|
|
781
783
|
});
|
|
782
784
|
}
|
|
783
785
|
/**
|
|
@@ -791,27 +793,27 @@ class apiUtil$1 {
|
|
|
791
793
|
static async verifyApiSignature(tokenData, req) {
|
|
792
794
|
try {
|
|
793
795
|
if (!req.headers.timestamp) {
|
|
794
|
-
throw [err$
|
|
796
|
+
throw [err$2.ACCESS_REFUSED, `必须在请求头中设置时戳`];
|
|
795
797
|
}
|
|
796
798
|
|
|
797
799
|
let timestamp = parseInt(req.headers.timestamp);
|
|
798
800
|
let currentTime = new Date().valueOf();
|
|
799
|
-
let maxTimeDiff = apiUtil$
|
|
801
|
+
let maxTimeDiff = apiUtil$2.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$2.isTestMode(req) ? 4 * 3600 : 100; // 100
|
|
800
802
|
|
|
801
803
|
if (timestamp.toString() == "NaN" || currentTime < timestamp - 5000 || currentTime - timestamp > maxTimeDiff * 1000) {
|
|
802
|
-
throw [err$
|
|
804
|
+
throw [err$2.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
|
|
803
805
|
}
|
|
804
806
|
|
|
805
807
|
let signature = req.headers.signature;
|
|
806
808
|
|
|
807
809
|
if (!signature) {
|
|
808
|
-
throw [err$
|
|
810
|
+
throw [err$2.ACCESS_REFUSED, `必须在请求头中提供签名`];
|
|
809
811
|
}
|
|
810
812
|
|
|
811
|
-
let signData = apiUtil$
|
|
813
|
+
let signData = apiUtil$2.extractToken(req, null, true) || tokenData.apiKey;
|
|
812
814
|
signData += timestamp;
|
|
813
815
|
|
|
814
|
-
if (apiUtil$
|
|
816
|
+
if (apiUtil$2.isDebugMode(req) || apiUtil$2.isTestMode(req)) {
|
|
815
817
|
let publicKey = req.headers.publickey || req.body.publicKey || req.query.publicKey;
|
|
816
818
|
|
|
817
819
|
if (publicKey) {
|
|
@@ -826,16 +828,16 @@ class apiUtil$1 {
|
|
|
826
828
|
return await verifyResult;
|
|
827
829
|
}
|
|
828
830
|
|
|
829
|
-
return apiUtil$
|
|
831
|
+
return apiUtil$2.getCompanyCertificate(tokenData.apiKey).then(info => {
|
|
830
832
|
tokenData.certPublicKey = info.certLiving;
|
|
831
833
|
tokenData.certPublicKeySpare = info.certSpare;
|
|
832
834
|
tokenData.certLivingId = info.certLivingId;
|
|
833
835
|
tokenData.certSpareId = info.certSpareId;
|
|
834
836
|
req.certPublicKey = info.certLiving;
|
|
835
|
-
let token = apiUtil$
|
|
837
|
+
let token = apiUtil$2.extractToken(req, null, true);
|
|
836
838
|
|
|
837
839
|
if (token) {
|
|
838
|
-
apiUtil$
|
|
840
|
+
apiUtil$2.storeToken(apiUtil$2.apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
|
|
839
841
|
}
|
|
840
842
|
}).then(() => {
|
|
841
843
|
return doVerify(signData, signature, tokenData.certPublicKey);
|
|
@@ -860,7 +862,7 @@ class apiUtil$1 {
|
|
|
860
862
|
|
|
861
863
|
if (!tokenData.certPublicKeySpare) {
|
|
862
864
|
throw {
|
|
863
|
-
eo: err$
|
|
865
|
+
eo: err$2.ACCESS_REFUSED,
|
|
864
866
|
msgArgv: "签名验证异常",
|
|
865
867
|
data: e
|
|
866
868
|
};
|
|
@@ -897,10 +899,10 @@ class apiUtil$1 {
|
|
|
897
899
|
delete tokenData.certLivingId;
|
|
898
900
|
delete tokenData.certSpareId;
|
|
899
901
|
delete tokenData.certPublicKeySpare;
|
|
900
|
-
let token = apiUtil$
|
|
902
|
+
let token = apiUtil$2.extractToken(req);
|
|
901
903
|
|
|
902
904
|
if (token) {
|
|
903
|
-
apiUtil$
|
|
905
|
+
apiUtil$2.storeToken(apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
|
|
904
906
|
}
|
|
905
907
|
|
|
906
908
|
console.log(`公司(${tokenData.apiKey})备用证书成功转换为正式证书`);
|
|
@@ -909,7 +911,7 @@ class apiUtil$1 {
|
|
|
909
911
|
} catch (e) {
|
|
910
912
|
console.log("SPO服务签名验证异常(备用证书), ", e);
|
|
911
913
|
throw {
|
|
912
|
-
eo: err$
|
|
914
|
+
eo: err$2.ACCESS_REFUSED,
|
|
913
915
|
msgArgv: "签名验证异常(spare)",
|
|
914
916
|
data: e
|
|
915
917
|
};
|
|
@@ -918,7 +920,7 @@ class apiUtil$1 {
|
|
|
918
920
|
|
|
919
921
|
if (!verifyOK) {
|
|
920
922
|
console.log("SPO服务签名验证失败, tokenData: ", tokenData);
|
|
921
|
-
throw [err$
|
|
923
|
+
throw [err$2.ACCESS_REFUSED, "签名验证未通过"];
|
|
922
924
|
}
|
|
923
925
|
|
|
924
926
|
return verifyOK;
|
|
@@ -934,32 +936,32 @@ class apiUtil$1 {
|
|
|
934
936
|
|
|
935
937
|
static async checkApiCallValid(tokenData, req) {
|
|
936
938
|
if (!tokenData.companyInfo) {
|
|
937
|
-
tokenData.companyInfo = await apiUtil$
|
|
939
|
+
tokenData.companyInfo = await apiUtil$2.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
|
|
938
940
|
console.log("执行企业信息查询发生异常", e);
|
|
939
|
-
throw [err$
|
|
941
|
+
throw [err$2.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
|
|
940
942
|
});
|
|
941
943
|
}
|
|
942
944
|
|
|
943
945
|
const companyInfo = tokenData.companyInfo;
|
|
944
946
|
|
|
945
947
|
if (companyInfo != null) {
|
|
946
|
-
let secret = apiUtil$
|
|
948
|
+
let secret = apiUtil$2._getApiSecret(tokenData.apiKey);
|
|
947
949
|
|
|
948
|
-
if (secret !== tokenData.apiSecret) throw err$
|
|
950
|
+
if (secret !== tokenData.apiSecret) throw err$2.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
|
|
949
951
|
// console.log("fromIp:", tokenData.clientIp, "ipWhiteList:", companyInfo.ipWhiteList);
|
|
950
952
|
// let whiteList = companyInfo.ipWhiteList || "";
|
|
951
953
|
// // 没有设置ip白名单的就不检查了
|
|
952
954
|
// if (whiteList == "" || ipMatched(tokenData.clientIp, whiteList + ",127.0.0.1,1"))
|
|
953
955
|
|
|
954
|
-
if (apiUtil$
|
|
955
|
-
return apiUtil$
|
|
956
|
+
if (apiUtil$2.signatureVerified()) return companyInfo;
|
|
957
|
+
return apiUtil$2.verifyApiSignature(tokenData, req).then(x => {
|
|
956
958
|
return companyInfo;
|
|
957
959
|
}, e => {
|
|
958
960
|
throw e;
|
|
959
961
|
});
|
|
960
962
|
}
|
|
961
963
|
|
|
962
|
-
throw [err$
|
|
964
|
+
throw [err$2.API_KEY_INVALID, tokenData.apiKey];
|
|
963
965
|
}
|
|
964
966
|
/**
|
|
965
967
|
* 检查令牌数据是否存在
|
|
@@ -1010,7 +1012,7 @@ class apiUtil$1 {
|
|
|
1010
1012
|
paramExists = typeof params[paramName] != 'undefined' || typeof params[paramName + paramSufix] != 'undefined';
|
|
1011
1013
|
}
|
|
1012
1014
|
|
|
1013
|
-
if (!paramExists) return ppUtil$4.errorPormise(err$
|
|
1015
|
+
if (!paramExists) return ppUtil$4.errorPormise(err$2.ERROR(err$2.PARAMETER_NEEDED, paramName));
|
|
1014
1016
|
}
|
|
1015
1017
|
|
|
1016
1018
|
return Promise.resolve(paramSufix);
|
|
@@ -1058,7 +1060,7 @@ class apiUtil$1 {
|
|
|
1058
1060
|
|
|
1059
1061
|
|
|
1060
1062
|
static async hostIsMySelf(host, req) {
|
|
1061
|
-
let clientIp = apiUtil$
|
|
1063
|
+
let clientIp = apiUtil$2.getClientIp(req);
|
|
1062
1064
|
return ppUtil$4.getMyIp({
|
|
1063
1065
|
hosts: [host, clientIp]
|
|
1064
1066
|
});
|
|
@@ -1073,13 +1075,13 @@ class apiUtil$1 {
|
|
|
1073
1075
|
static async checkForwardsHost(options) {
|
|
1074
1076
|
configNeeded();
|
|
1075
1077
|
const params = options.replacements;
|
|
1076
|
-
const myEnvHosts = apiUtil$
|
|
1078
|
+
const myEnvHosts = apiUtil$2.getEnvHosts(params);
|
|
1077
1079
|
const myIp = ppUtil$4.getMyIp();
|
|
1078
1080
|
const host = params.host || myIp;
|
|
1079
|
-
if (!myEnvHosts.hosts.contains(host)) throw [err$
|
|
1081
|
+
if (!myEnvHosts.hosts.contains(host)) throw [err$2.ACCESS_REFUSED, `环境${conf$3.envId}貌似无此主机:${params.host}`];
|
|
1080
1082
|
|
|
1081
|
-
if (!apiUtil$
|
|
1082
|
-
let result = await apiUtil$
|
|
1083
|
+
if (!apiUtil$2.hostIsMySelf(host, options._res.req)) {
|
|
1084
|
+
let result = await apiUtil$2.forwardsTo(host, myEnvHosts.port, params, options._res.req, myIp);
|
|
1083
1085
|
|
|
1084
1086
|
options._res.send(result);
|
|
1085
1087
|
|
|
@@ -1115,7 +1117,7 @@ class apiUtil$1 {
|
|
|
1115
1117
|
|
|
1116
1118
|
if (result.status !== 200) {
|
|
1117
1119
|
console.log(`访问 ${reqOptions.url} 出错`, result.status, result.res.statusMessage);
|
|
1118
|
-
throw [err$
|
|
1120
|
+
throw [err$2.EXCEPTION, `[${result.status}] - ${result.res.statusMessage}`];
|
|
1119
1121
|
}
|
|
1120
1122
|
|
|
1121
1123
|
return result.data;
|
|
@@ -1131,7 +1133,7 @@ class apiUtil$1 {
|
|
|
1131
1133
|
let keys = Array.isArray(keyPath) ? keyPath : keyPath.split(".");
|
|
1132
1134
|
let parentKey = "";
|
|
1133
1135
|
let key = "config";
|
|
1134
|
-
let value = conf$
|
|
1136
|
+
let value = conf$3;
|
|
1135
1137
|
let parent = null;
|
|
1136
1138
|
|
|
1137
1139
|
for (let i = 0; i < keys.length; i++) {
|
|
@@ -1141,7 +1143,7 @@ class apiUtil$1 {
|
|
|
1141
1143
|
value = parent[key];
|
|
1142
1144
|
|
|
1143
1145
|
if (value === undefined) {
|
|
1144
|
-
throw [err$
|
|
1146
|
+
throw [err$2.INVALID_PARAM, `无此配置项: ${key}`];
|
|
1145
1147
|
}
|
|
1146
1148
|
}
|
|
1147
1149
|
|
|
@@ -1161,10 +1163,10 @@ class apiUtil$1 {
|
|
|
1161
1163
|
|
|
1162
1164
|
static async $checkToken(req, res, next) {
|
|
1163
1165
|
try {
|
|
1164
|
-
await apiUtil$
|
|
1166
|
+
await apiUtil$2.checkRequestToken(req);
|
|
1165
1167
|
await next();
|
|
1166
1168
|
} catch (e) {
|
|
1167
|
-
res.send(err$
|
|
1169
|
+
res.send(err$2.ERROR(e));
|
|
1168
1170
|
}
|
|
1169
1171
|
|
|
1170
1172
|
return false;
|
|
@@ -1181,7 +1183,7 @@ class apiUtil$1 {
|
|
|
1181
1183
|
let token = req.headers["access_token"] || req.headers['x-access-token']; //向后兼容
|
|
1182
1184
|
|
|
1183
1185
|
if (!token) {
|
|
1184
|
-
let params = apiUtil$
|
|
1186
|
+
let params = apiUtil$2.extractParams(req);
|
|
1185
1187
|
token = params["access_token"];
|
|
1186
1188
|
|
|
1187
1189
|
if (token) {
|
|
@@ -1204,15 +1206,15 @@ class apiUtil$1 {
|
|
|
1204
1206
|
|
|
1205
1207
|
try {
|
|
1206
1208
|
if (extractToken(req, res)) {
|
|
1207
|
-
await apiUtil$
|
|
1208
|
-
req.userInfo = apiUtil$
|
|
1209
|
+
await apiUtil$2.restoreTokenData(apiUtil$2.userTokenStoreKey(req.accessToken), apiUtil$2.tokenExpireTime(req)).then(function (data) {
|
|
1210
|
+
req.userInfo = apiUtil$2.setUserIdNo(data, data._idNo);
|
|
1209
1211
|
}, function (e) {//no token
|
|
1210
1212
|
});
|
|
1211
1213
|
}
|
|
1212
1214
|
|
|
1213
1215
|
return true;
|
|
1214
1216
|
} catch (e) {
|
|
1215
|
-
res.send(err$
|
|
1217
|
+
res.send(err$2.ERROR(e));
|
|
1216
1218
|
return false;
|
|
1217
1219
|
}
|
|
1218
1220
|
}
|
|
@@ -1235,7 +1237,7 @@ class apiUtil$1 {
|
|
|
1235
1237
|
req.isMobile = true;
|
|
1236
1238
|
|
|
1237
1239
|
if (!req.signatureVerified) {
|
|
1238
|
-
let params = apiUtil$
|
|
1240
|
+
let params = apiUtil$2.extractParams(req);
|
|
1239
1241
|
moveProperty(params, req.headers, "access_token");
|
|
1240
1242
|
moveProperty(params, req.headers, "timestamp");
|
|
1241
1243
|
|
|
@@ -1256,25 +1258,25 @@ class apiUtil$1 {
|
|
|
1256
1258
|
|
|
1257
1259
|
static $checkApiKeyOld(req, res, next) {
|
|
1258
1260
|
//检查post的信息或者url查询参数或者头信息
|
|
1259
|
-
let tokenData = apiUtil$
|
|
1260
|
-
let params = apiUtil$
|
|
1261
|
-
apiUtil$
|
|
1261
|
+
let tokenData = apiUtil$2.extractTokenData(req);
|
|
1262
|
+
let params = apiUtil$2.extractParams(req);
|
|
1263
|
+
apiUtil$2.createApiCallRec(tokenData, req);
|
|
1262
1264
|
let errResponse = null;
|
|
1263
1265
|
|
|
1264
1266
|
if (!tokenData.clientIp) {
|
|
1265
|
-
errResponse = apiUtil$
|
|
1267
|
+
errResponse = apiUtil$2.spoApiFail(err$2.GET_CLIENTIP_FAIL, req);
|
|
1266
1268
|
} else if (!tokenData.apiKey) {
|
|
1267
|
-
errResponse = apiUtil$
|
|
1269
|
+
errResponse = apiUtil$2.spoApiFail([err$2.PARAMETER_NEEDED, "apiKey"], req);
|
|
1268
1270
|
} else if (!tokenData.apiSecret) {
|
|
1269
|
-
errResponse = apiUtil$
|
|
1271
|
+
errResponse = apiUtil$2.spoApiFail([err$2.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1270
1272
|
}
|
|
1271
1273
|
|
|
1272
1274
|
if (errResponse != null) {
|
|
1273
|
-
apiUtil$
|
|
1275
|
+
apiUtil$2._saveApiCallRec(req.apiCallRec, errResponse);
|
|
1274
1276
|
|
|
1275
|
-
apiUtil$
|
|
1277
|
+
apiUtil$2.sendOrRedirect(req, res, errResponse);
|
|
1276
1278
|
} else {
|
|
1277
|
-
apiUtil$
|
|
1279
|
+
apiUtil$2.checkApiCallValid(tokenData, req).then(companyInfo => {
|
|
1278
1280
|
params.companyId = params.companyId || companyInfo.companyId;
|
|
1279
1281
|
req.companyInfo = companyInfo;
|
|
1280
1282
|
next();
|
|
@@ -1282,9 +1284,9 @@ class apiUtil$1 {
|
|
|
1282
1284
|
console.log('apiCallInvalid:', e);
|
|
1283
1285
|
let errResponse = spoApiFail(e, req);
|
|
1284
1286
|
|
|
1285
|
-
apiUtil$
|
|
1287
|
+
apiUtil$2._saveApiCallRec(req.apiCallRec, errResponse);
|
|
1286
1288
|
|
|
1287
|
-
apiUtil$
|
|
1289
|
+
apiUtil$2.sendOrRedirect(req, res, errResponse);
|
|
1288
1290
|
});
|
|
1289
1291
|
}
|
|
1290
1292
|
}
|
|
@@ -1299,31 +1301,31 @@ class apiUtil$1 {
|
|
|
1299
1301
|
return;
|
|
1300
1302
|
}
|
|
1301
1303
|
|
|
1302
|
-
let accessToken = apiUtil$
|
|
1304
|
+
let accessToken = apiUtil$2.extractToken(req);
|
|
1303
1305
|
|
|
1304
1306
|
if (!accessToken) {
|
|
1305
|
-
res.send(apiUtil$
|
|
1307
|
+
res.send(apiUtil$2.spoApiFail(err$2.TOKEN_NEEDED, req)); // apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
|
|
1306
1308
|
|
|
1307
1309
|
return;
|
|
1308
1310
|
}
|
|
1309
1311
|
|
|
1310
|
-
apiUtil$
|
|
1312
|
+
apiUtil$2.restoreTokenData(apiUtil$2.apiTokenStoreKey(accessToken)).then(p => {
|
|
1311
1313
|
// req.headers[hnApiKey] = p.apiKey || '';
|
|
1312
1314
|
// req.headers[hnApiSecret] = p.apiSecret || '';
|
|
1313
1315
|
if (req.isMobile) {
|
|
1314
1316
|
// GET 请求的应该都是H5页面,由手机前端发起,需要把headers中的请求方ip换成服务端的
|
|
1315
1317
|
// todo: 如何在API访问记录中记住请求者(手机端)的真实IP
|
|
1316
|
-
req.headers['x-phone-ip'] = apiUtil$
|
|
1318
|
+
req.headers['x-phone-ip'] = apiUtil$2.getClientIp(req);
|
|
1317
1319
|
req.headers['x-real-ip'] = p.clientIp;
|
|
1318
1320
|
} else {
|
|
1319
|
-
p.clientIp = apiUtil$
|
|
1321
|
+
p.clientIp = apiUtil$2.getClientIp(req);
|
|
1320
1322
|
}
|
|
1321
1323
|
|
|
1322
1324
|
req.isApiCall = true;
|
|
1323
1325
|
req.tokenData = p;
|
|
1324
|
-
return apiUtil$
|
|
1326
|
+
return apiUtil$2.$checkApiKeyOld(req, res, next);
|
|
1325
1327
|
}).catch(e => {
|
|
1326
|
-
apiUtil$
|
|
1328
|
+
apiUtil$2.sendOrRedirect(req, res, apiUtil$2.spoApiFail(err$2.TOKEN_INVALID, req));
|
|
1327
1329
|
});
|
|
1328
1330
|
}
|
|
1329
1331
|
/**
|
|
@@ -1336,24 +1338,24 @@ class apiUtil$1 {
|
|
|
1336
1338
|
|
|
1337
1339
|
|
|
1338
1340
|
static async $checkTokenOrApiKey(req, res, next) {
|
|
1339
|
-
let accessToken = apiUtil$
|
|
1341
|
+
let accessToken = apiUtil$2.extractToken(req, res);
|
|
1340
1342
|
|
|
1341
1343
|
if (accessToken) {
|
|
1342
|
-
let tokenExist = await apiUtil$
|
|
1344
|
+
let tokenExist = await apiUtil$2.tokenDataExist(apiUtil$2.userTokenStoreKey(accessToken));
|
|
1343
1345
|
|
|
1344
1346
|
if (tokenExist) {
|
|
1345
|
-
return await apiUtil$
|
|
1347
|
+
return await apiUtil$2.$checkToken(req, res, next);
|
|
1346
1348
|
}
|
|
1347
1349
|
|
|
1348
|
-
tokenExist = await apiUtil$
|
|
1350
|
+
tokenExist = await apiUtil$2.tokenDataExist(apiUtil$2.apiTokenStoreKey(accessToken));
|
|
1349
1351
|
|
|
1350
1352
|
if (tokenExist) {
|
|
1351
|
-
return apiUtil$
|
|
1353
|
+
return apiUtil$2.$checkApiKey(req, res, next);
|
|
1352
1354
|
} // 如果给定的token不存在,看看是不是平台内部调用
|
|
1353
1355
|
|
|
1354
1356
|
|
|
1355
|
-
return await apiUtil$
|
|
1356
|
-
res.send(apiUtil$
|
|
1357
|
+
return await apiUtil$2.checkInternalToken(req).catch(e => {
|
|
1358
|
+
res.send(apiUtil$2.apiFail(e, req));
|
|
1357
1359
|
return false;
|
|
1358
1360
|
});
|
|
1359
1361
|
}
|
|
@@ -1373,8 +1375,8 @@ class apiUtil$1 {
|
|
|
1373
1375
|
const params = options.replacements;
|
|
1374
1376
|
let item = params.item;
|
|
1375
1377
|
delete params.item;
|
|
1376
|
-
if (await apiUtil$
|
|
1377
|
-
let c = apiUtil$
|
|
1378
|
+
if (await apiUtil$2.checkForwardsHost(options)) return true;
|
|
1379
|
+
let c = apiUtil$2.parseCfgPath(item);
|
|
1378
1380
|
delete c.parent;
|
|
1379
1381
|
c.host = ppUtil$4.getMyIp();
|
|
1380
1382
|
return c;
|
|
@@ -1393,11 +1395,11 @@ class apiUtil$1 {
|
|
|
1393
1395
|
delete params.item; // if (await checkForwardsHost(options))
|
|
1394
1396
|
// return true;
|
|
1395
1397
|
|
|
1396
|
-
await apiUtil$
|
|
1397
|
-
let c = apiUtil$
|
|
1398
|
+
await apiUtil$2.parametersOK(params, "value");
|
|
1399
|
+
let c = apiUtil$2.parseCfgPath(item);
|
|
1398
1400
|
|
|
1399
1401
|
if (typeof c.value === "object") {
|
|
1400
|
-
throw [err$
|
|
1402
|
+
throw [err$2.ACCESS_REFUSED, `暂不支持修改复杂配置`];
|
|
1401
1403
|
} // c.oldValue = c.value;
|
|
1402
1404
|
|
|
1403
1405
|
|
|
@@ -1412,21 +1414,21 @@ class apiUtil$1 {
|
|
|
1412
1414
|
}
|
|
1413
1415
|
|
|
1414
1416
|
function configNeeded() {
|
|
1415
|
-
if (!conf$
|
|
1417
|
+
if (!conf$3 || !err$2) {
|
|
1416
1418
|
ppUtil$4.configNeeded();
|
|
1417
|
-
conf$
|
|
1418
|
-
appSetting$1 = conf$
|
|
1419
|
-
err$
|
|
1419
|
+
conf$3 = ppUtil$4.appConfig;
|
|
1420
|
+
appSetting$1 = conf$3.appSetting;
|
|
1421
|
+
err$2 = ppUtil$4.appErrCfg;
|
|
1420
1422
|
}
|
|
1421
1423
|
}
|
|
1422
1424
|
|
|
1423
|
-
var ppUtilApi = apiUtil$
|
|
1425
|
+
var ppUtilApi = apiUtil$2;
|
|
1424
1426
|
|
|
1425
|
-
const fs = require$$0$
|
|
1427
|
+
const fs = require$$0$1;
|
|
1426
1428
|
const path = require$$1$1;
|
|
1427
1429
|
const ppUtil$3 = require$$1.ppUtil;
|
|
1428
1430
|
const redisUtil = require$$2.redisUtil;
|
|
1429
|
-
let conf$
|
|
1431
|
+
let conf$2, err$1; // const dbCheck = require('../dbupdate/dd-version');
|
|
1430
1432
|
|
|
1431
1433
|
/**
|
|
1432
1434
|
* API服务启动时前置条件检查
|
|
@@ -1446,9 +1448,9 @@ class preconditions$1 {
|
|
|
1446
1448
|
|
|
1447
1449
|
static setAppName(aName) {
|
|
1448
1450
|
ppUtil$3.configNeeded();
|
|
1449
|
-
conf$
|
|
1450
|
-
err = ppUtil$3.appErrCfg;
|
|
1451
|
-
preconditions$1.appName = aName || conf$
|
|
1451
|
+
conf$2 = ppUtil$3.appConfig;
|
|
1452
|
+
err$1 = ppUtil$3.appErrCfg;
|
|
1453
|
+
preconditions$1.appName = aName || conf$2.thisApp;
|
|
1452
1454
|
return preconditions$1;
|
|
1453
1455
|
}
|
|
1454
1456
|
|
|
@@ -1529,20 +1531,20 @@ async function createEnvSettingFile(fileName) {
|
|
|
1529
1531
|
try {
|
|
1530
1532
|
const cfgText = await ppUtil$3.doCreateEnvSettingFile(fileName);
|
|
1531
1533
|
|
|
1532
|
-
if (cfgText.indexOf(`cfgVersion: "${conf$
|
|
1534
|
+
if (cfgText.indexOf(`cfgVersion: "${conf$2._envSetting.cfgVersion}"`) > 0) {
|
|
1533
1535
|
console.log(`\n*** 已創建新的本機環境配置文件\n${fileName}\n请檢查各項內容是否正确(此项更新服务可正常运行)\n\n`);
|
|
1534
1536
|
return "";
|
|
1535
1537
|
}
|
|
1536
1538
|
|
|
1537
|
-
return `已創建新的本機環境配置文件\n${fileName}\n请檢查並正確設置各項內容,然後將配置版本號修改為${conf$
|
|
1539
|
+
return `已創建新的本機環境配置文件\n${fileName}\n请檢查並正確設置各項內容,然後將配置版本號修改為${conf$2._envSettings.default.cfgVersion}`;
|
|
1538
1540
|
} catch (e) {
|
|
1539
|
-
return `創建本機環境配置文件失敗\n《${fileName}》\n${err.ERROR(e).message}`;
|
|
1541
|
+
return `創建本機環境配置文件失敗\n《${fileName}》\n${err$1.ERROR(e).message}`;
|
|
1540
1542
|
}
|
|
1541
1543
|
}
|
|
1542
1544
|
|
|
1543
1545
|
async function checkExEnvSetting(loadjs) {
|
|
1544
|
-
if (!conf$
|
|
1545
|
-
let fileName = conf$
|
|
1546
|
+
if (!conf$2._envSetting.localSettingImported) {
|
|
1547
|
+
let fileName = conf$2.getEnvSettingFileName();
|
|
1546
1548
|
|
|
1547
1549
|
if (!fs.existsSync(fileName)) {
|
|
1548
1550
|
return await createEnvSettingFile(fileName);
|
|
@@ -1550,7 +1552,7 @@ async function checkExEnvSetting(loadjs) {
|
|
|
1550
1552
|
|
|
1551
1553
|
let envSettingEx = loadjs(fileName);
|
|
1552
1554
|
|
|
1553
|
-
if (envSettingEx.cfgVersion !== conf$
|
|
1555
|
+
if (envSettingEx.cfgVersion !== conf$2._envSettings.default.cfgVersion) {
|
|
1554
1556
|
if (envSettingEx.cfgVersion !== "0.0") {
|
|
1555
1557
|
let fp = path.parse(fileName);
|
|
1556
1558
|
let newFileName = path.join(fp.dir, fp.name + envSettingEx.cfgVersion + fp.ext);
|
|
@@ -1569,7 +1571,7 @@ async function checkExEnvSetting(loadjs) {
|
|
|
1569
1571
|
|
|
1570
1572
|
|
|
1571
1573
|
async function checkRedis() {
|
|
1572
|
-
if (!conf$
|
|
1574
|
+
if (!conf$2.redis.enabled) return "";
|
|
1573
1575
|
const redis = redisUtil.newClient("io"); // console.log(`checkRedis begin:`);
|
|
1574
1576
|
|
|
1575
1577
|
await ppUtil$3.wait(15 * 1000, param => {
|
|
@@ -1590,209 +1592,393 @@ async function checkRedis() {
|
|
|
1590
1592
|
|
|
1591
1593
|
var ppPrecond = preconditions$1;
|
|
1592
1594
|
|
|
1593
|
-
|
|
1595
|
+
// 若 redis 可用,则使用基于 redis 的消息订阅发布系统
|
|
1596
|
+
// 若 redis 不可用,则将消息转发到其它主机
|
|
1594
1597
|
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1598
|
+
const {
|
|
1599
|
+
ppUtil: ppUtil$2
|
|
1600
|
+
} = require$$1;
|
|
1601
|
+
const RedisMessenger = require$$1$2;
|
|
1602
|
+
const {
|
|
1603
|
+
netUtil
|
|
1604
|
+
} = require$$3;
|
|
1605
|
+
let conf$1;
|
|
1606
|
+
|
|
1607
|
+
class commonMessenger$2 {
|
|
1608
|
+
static myMsgAddr = "";
|
|
1609
|
+
static redisMessenger = null;
|
|
1610
|
+
static onMessage = [];
|
|
1600
1611
|
|
|
1601
|
-
|
|
1612
|
+
static initMessenger(appConfig, appErrCfg, msgChannel) {
|
|
1613
|
+
conf$1 = appConfig;
|
|
1614
|
+
this.redisMessenger = conf$1.redis.enabled ? new RedisMessenger(appConfig, appErrCfg, msgChannel).subscribe(msgChannel) : null;
|
|
1615
|
+
this.myMsgAddr = commonMessenger$2.getMyMsgAddr();
|
|
1616
|
+
}
|
|
1602
1617
|
|
|
1618
|
+
static getMyMsgAddr() {
|
|
1619
|
+
if (!conf$1.myMsgAddr) {
|
|
1620
|
+
conf$1.pm_id = process.env.pm_id || "0";
|
|
1621
|
+
let myIp = ppUtil$2.getMyIp();
|
|
1603
1622
|
|
|
1604
|
-
|
|
1623
|
+
if (this.redisMessenger) {
|
|
1624
|
+
myIp = `${conf$1.pm_id}@${myIp}`;
|
|
1625
|
+
}
|
|
1605
1626
|
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
if (appConfig) {
|
|
1609
|
-
redis.config(appConfig, appErrCfg);
|
|
1627
|
+
conf$1.myMsgAddr = myIp;
|
|
1628
|
+
console.log(`myMsgAddr: `, conf$1.myMsgAddr);
|
|
1610
1629
|
}
|
|
1611
1630
|
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
this.publisher = redis.newClient("publisher");
|
|
1615
|
-
this.subscriber = redis.newClient("subscriber");
|
|
1616
|
-
this.subscriber.on("subscribe", function (channel, count) {
|
|
1617
|
-
console.log("chanel subscribed :", channel, count);
|
|
1618
|
-
});
|
|
1619
|
-
this.subscriber.on("message", this.handleMessage);
|
|
1631
|
+
return conf$1.myMsgAddr;
|
|
1620
1632
|
}
|
|
1621
1633
|
|
|
1622
|
-
setMessageHandle(
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
const appMsgHandles = Messenger.onmessage[channel];
|
|
1634
|
+
static setMessageHandle(messageHandle) {
|
|
1635
|
+
if (this.redisMessenger) {
|
|
1636
|
+
return this.redisMessenger.setMessageHandle(messageHandle, msgChannel);
|
|
1637
|
+
}
|
|
1627
1638
|
|
|
1628
|
-
|
|
1629
|
-
|
|
1639
|
+
if (commonMessenger$2.onMessage.indexOf(messageHandle) < 0) {
|
|
1640
|
+
commonMessenger$2.onMessage.push(messageHandle);
|
|
1630
1641
|
}
|
|
1631
1642
|
|
|
1632
|
-
|
|
1633
|
-
return this;
|
|
1643
|
+
return commonMessenger$2;
|
|
1634
1644
|
}
|
|
1635
1645
|
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1646
|
+
static async publishMessage(message) {
|
|
1647
|
+
if (this.redisMessenger) {
|
|
1648
|
+
return this.redisMessenger.publish(message, msgChannel);
|
|
1649
|
+
} else {
|
|
1650
|
+
//没有消息处理器,则将消息转发到目标地址(不支持pm2多进程)
|
|
1651
|
+
if (message.destAddr) {
|
|
1652
|
+
await forwardMessage(message);
|
|
1653
|
+
} else {
|
|
1654
|
+
for (let i = 0; i < conf$1.appSetting.serverHosts.length; i++) {
|
|
1655
|
+
message.destAddr = conf$1.appSetting.serverHosts[i];
|
|
1656
|
+
|
|
1657
|
+
if (message.destAddr !== conf$1.myMsgAddr) {
|
|
1658
|
+
await forwardMessage(message);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1640
1663
|
}
|
|
1641
1664
|
|
|
1642
|
-
async
|
|
1643
|
-
|
|
1644
|
-
let appMsgHandles = Messenger.onmessage[channel] || [];
|
|
1665
|
+
static async handleInternalMessage(options) {
|
|
1666
|
+
const message = options.replacements;
|
|
1645
1667
|
|
|
1646
|
-
for (let i = 0; i <
|
|
1647
|
-
const appMsgHandle =
|
|
1668
|
+
for (let i = 0; i < commonMessenger$2.onMessage.length; i++) {
|
|
1669
|
+
const appMsgHandle = commonMessenger$2.onMessage[i];
|
|
1648
1670
|
|
|
1649
1671
|
try {
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
appMsgHandle(msgObj);
|
|
1672
|
+
await appMsgHandle(message);
|
|
1653
1673
|
} catch (e) {
|
|
1654
1674
|
console.log(e);
|
|
1655
1675
|
}
|
|
1656
1676
|
}
|
|
1657
1677
|
}
|
|
1658
1678
|
|
|
1659
|
-
async publish(message, channel) {
|
|
1660
|
-
channel = channel || this.channel;
|
|
1661
|
-
let msgStr = typeof message === "object" ? JSON.stringify(message) : message.toString();
|
|
1662
|
-
console.log(`通道[${channel}]发布消息:`, message);
|
|
1663
|
-
await this.publisher.publish(channel, msgStr);
|
|
1664
|
-
return this;
|
|
1665
|
-
}
|
|
1666
|
-
|
|
1667
1679
|
}
|
|
1668
1680
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1681
|
+
async function forwardMessage(message) {
|
|
1682
|
+
let reqOptions = {
|
|
1683
|
+
url: `https://${message.destAddr}:${appSetting.listenPort}/api/message`,
|
|
1684
|
+
method: "POST",
|
|
1685
|
+
data: message
|
|
1686
|
+
};
|
|
1687
|
+
let res = await netUtil.apiRequest(reqOptions).catch(e => {
|
|
1688
|
+
console.log(`转发消息失败, url: ${reqOptions.url}`, e);
|
|
1689
|
+
throw e;
|
|
1690
|
+
});
|
|
1691
|
+
return res.data;
|
|
1692
|
+
}
|
|
1673
1693
|
|
|
1674
|
-
|
|
1675
|
-
// 若 redis 不可用,则将消息转发到其它主机
|
|
1694
|
+
var ppMessengerEx = commonMessenger$2;
|
|
1676
1695
|
|
|
1677
|
-
|
|
1696
|
+
/**
|
|
1697
|
+
* CSCA 自动任务
|
|
1698
|
+
* ==============
|
|
1699
|
+
*/
|
|
1700
|
+
const CRON = require$$0$2;
|
|
1678
1701
|
const {
|
|
1679
|
-
|
|
1680
|
-
} = require$$
|
|
1681
|
-
|
|
1702
|
+
ppUtil: ppUtil$1
|
|
1703
|
+
} = require$$1;
|
|
1704
|
+
const apiUtil$1 = ppUtilApi;
|
|
1705
|
+
const commonMessenger$1 = ppMessengerEx;
|
|
1706
|
+
const MT_SCHEDULE_STATE = 'schedule-state',
|
|
1707
|
+
MT_SCHEDULE_STATE_REPLY = 'schedule-state-reply';
|
|
1708
|
+
let conf, err;
|
|
1709
|
+
|
|
1710
|
+
class schedule$1 {
|
|
1711
|
+
static tasks = {};
|
|
1712
|
+
/**
|
|
1713
|
+
* 注册一个计划任务
|
|
1714
|
+
* @param taskName
|
|
1715
|
+
* @param taskCaption
|
|
1716
|
+
* @param cronExp
|
|
1717
|
+
* @param taskFunc
|
|
1718
|
+
* @param autoStart
|
|
1719
|
+
* @returns {Promise<{}|{}|{cron: *, _message_: string}|any>}
|
|
1720
|
+
*/
|
|
1682
1721
|
|
|
1683
|
-
|
|
1684
|
-
|
|
1722
|
+
static async registerTask(taskName, taskCaption, cronExp, taskFunc, autoStart) {
|
|
1723
|
+
if (!conf) {
|
|
1724
|
+
ppUtil$1.configNeeded();
|
|
1725
|
+
conf = ppUtil$1.appConfig;
|
|
1726
|
+
err = ppUtil$1.appErrCfg;
|
|
1727
|
+
}
|
|
1685
1728
|
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1729
|
+
if (!this.envAllowed()) return {};
|
|
1730
|
+
let task = this.findTask(taskName);
|
|
1731
|
+
|
|
1732
|
+
if (task) {
|
|
1733
|
+
if (task.cronExp !== cronExp || task.taskFunc !== taskFunc) {
|
|
1734
|
+
this.stop(taskName);
|
|
1735
|
+
task = null;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1693
1738
|
|
|
1694
|
-
|
|
1695
|
-
|
|
1739
|
+
if (!task) {
|
|
1740
|
+
task = {
|
|
1741
|
+
name: taskName,
|
|
1742
|
+
caption: taskCaption,
|
|
1743
|
+
cronExp: cronExp,
|
|
1744
|
+
taskFunc: taskFunc,
|
|
1745
|
+
schedule: null,
|
|
1746
|
+
doScheduleTask: async function () {
|
|
1747
|
+
let self = this;
|
|
1748
|
+
if (this._pp_task) self = this._pp_task;
|
|
1749
|
+
console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'), `开始执行${self.caption}任务 ...`);
|
|
1750
|
+
await self.taskFunc();
|
|
1751
|
+
console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'), `${self.caption}任务执行结束`);
|
|
1696
1752
|
}
|
|
1753
|
+
};
|
|
1754
|
+
this.tasks[taskName] = task;
|
|
1755
|
+
|
|
1756
|
+
if (autoStart) {
|
|
1757
|
+
return await this.start(task);
|
|
1697
1758
|
}
|
|
1759
|
+
|
|
1760
|
+
return this.getTaskInfo(task, "任务已注册。");
|
|
1698
1761
|
}
|
|
1762
|
+
|
|
1763
|
+
return this.getTaskInfo(task, "任务已存在。");
|
|
1699
1764
|
}
|
|
1700
1765
|
|
|
1701
|
-
static
|
|
1702
|
-
|
|
1703
|
-
|
|
1766
|
+
static getTaskInfo(task, msg) {
|
|
1767
|
+
// return Object.assign({_message_: msg}, task);
|
|
1768
|
+
return {
|
|
1769
|
+
name: task.name,
|
|
1770
|
+
caption: task.caption,
|
|
1771
|
+
cronExp: task.cronExp,
|
|
1772
|
+
state: task.schedule ? "started" : "stopped",
|
|
1773
|
+
_message_: msg
|
|
1774
|
+
};
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* 启动任务
|
|
1778
|
+
* @param taskOrName
|
|
1779
|
+
* @param cronExp
|
|
1780
|
+
* @returns {Promise<{}|{cron: *, _message_: string}>}
|
|
1781
|
+
*/
|
|
1782
|
+
|
|
1783
|
+
|
|
1784
|
+
static async start(taskOrName, cronExp) {
|
|
1785
|
+
if (!this.envAllowed()) return {};
|
|
1786
|
+
let task = taskOrName;
|
|
1787
|
+
|
|
1788
|
+
if (typeof task === "string") {
|
|
1789
|
+
task = this.findTask(taskOrName);
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
if (!task) throw [err.INVALID_PARAM, `任务${taskOrName}不存在`];
|
|
1793
|
+
cronExp = cronExp || task.cronExp;
|
|
1794
|
+
|
|
1795
|
+
if (task.cronExp !== cronExp) {
|
|
1796
|
+
this.stop(task);
|
|
1797
|
+
task.cronExp = cronExp;
|
|
1704
1798
|
}
|
|
1705
1799
|
|
|
1706
|
-
|
|
1800
|
+
if (task.schedule) {
|
|
1801
|
+
return this.getTaskInfo(task, "任务已启动,无需重复启动。");
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
task.schedule = CRON.schedule(cronExp, task.doScheduleTask);
|
|
1805
|
+
task.schedule._task._pp_task = task;
|
|
1806
|
+
return this.getTaskInfo(task, "任务已启动。");
|
|
1707
1807
|
}
|
|
1808
|
+
/**
|
|
1809
|
+
* 停止任务
|
|
1810
|
+
* @param taskOrName
|
|
1811
|
+
* @returns {Promise<{}|{cron: *, _message_: string}|{_message_: string}>}
|
|
1812
|
+
*/
|
|
1708
1813
|
|
|
1709
|
-
static async handleInternalMessage(options) {
|
|
1710
|
-
const message = options.replacements;
|
|
1711
1814
|
|
|
1712
|
-
|
|
1713
|
-
|
|
1815
|
+
static async stop(taskOrName) {
|
|
1816
|
+
if (!this.envAllowed()) return {};
|
|
1817
|
+
let task = taskOrName;
|
|
1714
1818
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
appMsgHandle(message);
|
|
1718
|
-
} catch (e) {
|
|
1719
|
-
console.log(e);
|
|
1720
|
-
}
|
|
1819
|
+
if (typeof task === "string") {
|
|
1820
|
+
task = this.findTask(taskOrName);
|
|
1721
1821
|
}
|
|
1722
|
-
}
|
|
1723
1822
|
|
|
1724
|
-
}
|
|
1823
|
+
if (!task) throw [err.INVALID_PARAM, `任务${taskOrName}不存在`];
|
|
1725
1824
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1825
|
+
if (task.schedule) {
|
|
1826
|
+
task.schedule.stop();
|
|
1827
|
+
task.schedule = null;
|
|
1828
|
+
return this.getTaskInfo(task, "任务已停止。");
|
|
1829
|
+
}
|
|
1729
1830
|
|
|
1730
|
-
|
|
1731
|
-
conf = appConfig;
|
|
1732
|
-
this.redisMessenger = conf.redis.enabled ? new RedisMessenger(appConfig, appErrCfg, msgChannel).subscribe(msgChannel) : null;
|
|
1733
|
-
this.myMsgAddr = commonMessenger$1.getMyMsgAddr();
|
|
1831
|
+
return this.getTaskInfo(task, "任务未启动,无需停止。");
|
|
1734
1832
|
}
|
|
1833
|
+
/**
|
|
1834
|
+
* 获取或设置当前状态(来自远程的API调用)
|
|
1835
|
+
* @param options
|
|
1836
|
+
* @returns {Promise<unknown>}
|
|
1837
|
+
*/
|
|
1735
1838
|
|
|
1736
|
-
static getMyMsgAddr() {
|
|
1737
|
-
if (!conf.myMsgAddr) {
|
|
1738
|
-
conf.pm_id = process.env.pm_id || "0";
|
|
1739
|
-
let myIp = ppUtil.getMyIp();
|
|
1740
1839
|
|
|
1741
|
-
|
|
1742
|
-
|
|
1840
|
+
static async state(options) {
|
|
1841
|
+
const params = options.replacements; // await commonMessenger.parametersOK(params, "taskName");
|
|
1842
|
+
|
|
1843
|
+
const req = options._res.req;
|
|
1844
|
+
|
|
1845
|
+
if (req) {
|
|
1846
|
+
if (req.method === 'GET') {
|
|
1847
|
+
delete params.state;
|
|
1848
|
+
} else {
|
|
1849
|
+
await apiUtil$1.parametersOK(params, 'taskName', "state");
|
|
1743
1850
|
}
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
if (this.envAllowed()) {
|
|
1854
|
+
return this._state(params);
|
|
1855
|
+
} // 环境变量启用计划任务,但当前环境不能执行,
|
|
1856
|
+
// 说明收到此API请求的进程不是第一个进程,或者此前服务器不是第一台服务器,
|
|
1857
|
+
// 这种情况下,将此请求作为消息发布出去,
|
|
1858
|
+
// 第一台服务器的第一个进程收到消息后进行处理,再将结果作为消息发布,
|
|
1859
|
+
// 本进程收到处理结果后果作为响应发送回客户端
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
if (process.env.SCHEDULE_ENABLED) {
|
|
1863
|
+
let replyId = ppUtil$1.newGuid();
|
|
1864
|
+
return await new Promise((resolve, reject) => {
|
|
1865
|
+
commonMessenger$1.setMessageHandle(message => {
|
|
1866
|
+
if (message._type === MT_SCHEDULE_STATE_REPLY && message.replyId === replyId) {
|
|
1867
|
+
replyId = '';
|
|
1868
|
+
resolve(message.result);
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1744
1871
|
|
|
1745
|
-
|
|
1746
|
-
|
|
1872
|
+
if (message._type === MT_SCHEDULE_STATE) {
|
|
1873
|
+
if (schedule$1.enabled()) {
|
|
1874
|
+
message.result = schedule$1._state(message.params);
|
|
1875
|
+
message._type = MT_SCHEDULE_STATE_REPLY;
|
|
1876
|
+
message.destAddr = message.replyAddr;
|
|
1877
|
+
commonMessenger$1.publishMessage(message);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
commonMessenger$1.publishMessage({
|
|
1882
|
+
_type: MT_SCHEDULE_STATE,
|
|
1883
|
+
replyId,
|
|
1884
|
+
replyAddr: conf.myMsgAddr,
|
|
1885
|
+
params
|
|
1886
|
+
}).catch(e => {
|
|
1887
|
+
replyId = '';
|
|
1888
|
+
reject(e);
|
|
1889
|
+
});
|
|
1890
|
+
setTimeout(() => {
|
|
1891
|
+
if (replyId) {
|
|
1892
|
+
reject("schedule.state: 等待处理结果超时");
|
|
1893
|
+
}
|
|
1894
|
+
}, 2 * 60 * 1000);
|
|
1895
|
+
});
|
|
1747
1896
|
}
|
|
1748
1897
|
|
|
1749
|
-
return
|
|
1898
|
+
return {
|
|
1899
|
+
_message_: "此环境无自动任务"
|
|
1900
|
+
};
|
|
1750
1901
|
}
|
|
1751
1902
|
|
|
1752
|
-
static
|
|
1753
|
-
|
|
1754
|
-
|
|
1903
|
+
static async _state(params) {
|
|
1904
|
+
let apiResult = {};
|
|
1905
|
+
let task;
|
|
1906
|
+
|
|
1907
|
+
if (params.taskName) {
|
|
1908
|
+
task = this.findTask(params.taskName);
|
|
1909
|
+
if (!task) throw [err.INVALID_PARAM, `任务${params.taskName}不存在`];
|
|
1755
1910
|
}
|
|
1756
1911
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1912
|
+
if (params.state) {
|
|
1913
|
+
if ("started" === params.state) {
|
|
1914
|
+
apiResult = await this.start(task, params.cron);
|
|
1915
|
+
} else if ("stopped" === params.state) {
|
|
1916
|
+
apiResult = await this.stop(task);
|
|
1917
|
+
} else {
|
|
1918
|
+
throw [err.INVALID_PARAM, `(${params.state}), 只能是 started/stopped`];
|
|
1919
|
+
}
|
|
1759
1920
|
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1921
|
+
if (params.runOnce) {
|
|
1922
|
+
task = this.findTask(params.taskName);
|
|
1923
|
+
apiResult._message_ += "\n正在手动执行任务"; // await
|
|
1924
|
+
|
|
1925
|
+
task.doScheduleTask();
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
return this.getTaskInfo(task, apiResult._message_);
|
|
1765
1929
|
}
|
|
1930
|
+
|
|
1931
|
+
if (task) {
|
|
1932
|
+
return this.getTaskInfo(task);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
const result = [];
|
|
1936
|
+
|
|
1937
|
+
for (let k in this.tasks) {
|
|
1938
|
+
result.push(this.getTaskInfo(this.tasks[k]));
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
return result;
|
|
1766
1942
|
}
|
|
1767
1943
|
|
|
1768
|
-
static
|
|
1769
|
-
|
|
1944
|
+
static deleteTask(taskName) {
|
|
1945
|
+
delete this.tasks[taskName];
|
|
1770
1946
|
}
|
|
1771
1947
|
|
|
1772
|
-
|
|
1948
|
+
static findTask(taskName) {
|
|
1949
|
+
return this.tasks[taskName];
|
|
1950
|
+
}
|
|
1951
|
+
/**
|
|
1952
|
+
* 确定当前进程环境是否启用自动任务
|
|
1953
|
+
* @returns {Promise<void>}
|
|
1954
|
+
*/
|
|
1955
|
+
|
|
1956
|
+
|
|
1957
|
+
static envAllowed() {
|
|
1958
|
+
let enabled = // PM2配置中指定了环境变量 SCHEDULE_ENABLED
|
|
1959
|
+
!!process.env.SCHEDULE_ENABLED // 如果PM2启动了多个进程,则只在第一个进程执行
|
|
1960
|
+
&& process.env.NODE_APP_INSTANCE === '0'; // 如果有多台服务器,则只在第一台执行
|
|
1961
|
+
|
|
1962
|
+
if (enabled && conf.appSetting.serverHosts && conf.appSetting.serverHosts.length > 1) {
|
|
1963
|
+
enabled = conf.myMsgAddr.indexOf(conf.appSetting.serverHosts[0]) === 0;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
return enabled;
|
|
1967
|
+
}
|
|
1773
1968
|
|
|
1774
|
-
async function forwardMessage(message) {
|
|
1775
|
-
let reqOptions = {
|
|
1776
|
-
url: `https://${message.destAddr}:${appSetting.listenPort}/api/message`,
|
|
1777
|
-
method: "POST",
|
|
1778
|
-
data: message
|
|
1779
|
-
};
|
|
1780
|
-
let res = await netUtil.apiRequest(reqOptions).catch(e => {
|
|
1781
|
-
console.log(`转发消息失败, url: ${reqOptions.url}`, e);
|
|
1782
|
-
throw e;
|
|
1783
|
-
});
|
|
1784
|
-
return res.data;
|
|
1785
1969
|
}
|
|
1786
1970
|
|
|
1787
|
-
var
|
|
1971
|
+
var ppSchedule = schedule$1;
|
|
1788
1972
|
|
|
1789
1973
|
const apiUtil = ppUtilApi;
|
|
1790
1974
|
const preconditions = ppPrecond;
|
|
1791
1975
|
const commonMessenger = ppMessengerEx;
|
|
1792
|
-
|
|
1976
|
+
const schedule = ppSchedule;
|
|
1977
|
+
var ppUtil = {
|
|
1793
1978
|
apiUtil,
|
|
1794
1979
|
preconditions,
|
|
1795
|
-
commonMessenger
|
|
1980
|
+
commonMessenger,
|
|
1981
|
+
schedule
|
|
1796
1982
|
};
|
|
1797
1983
|
|
|
1798
|
-
export { ppUtil
|
|
1984
|
+
export { ppUtil as default };
|