-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdaemon.js
More file actions
2311 lines (2061 loc) · 180 KB
/
Copy pathdaemon.js
File metadata and controls
2311 lines (2061 loc) · 180 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*! 力控科技版权所有 */
(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./daemon/bin/www.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "../../daemon/config/default-config.json":
/*!********************************!*\
!*** external "./config.json" ***!
\********************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = require("./config.json");
/***/ }),
/***/ "./daemon/app.js":
/*!***********************!*\
!*** ./daemon/app.js ***!
\***********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
const Koa = __webpack_require__(/*! koa */ "koa")
const views = __webpack_require__(/*! koa-views */ "koa-views")
const json = __webpack_require__(/*! koa-json */ "koa-json")
const onerror = __webpack_require__(/*! koa-onerror */ "koa-onerror")
const bodyparser = __webpack_require__(/*! koa-bodyparser */ "koa-bodyparser")
const logger = __webpack_require__(/*! koa-logger */ "koa-logger")
const ejs = __webpack_require__(/*! ejs */ "ejs");
const Jwt = __webpack_require__(/*! ./libs/jwt */ "./daemon/libs/jwt.js");
const indexRoute = __webpack_require__(/*! ./routes/index-routes */ "./daemon/routes/index-routes.js");
const serviceRoute = __webpack_require__(/*! ./routes/service-routes */ "./daemon/routes/service-routes.js")
const apiv2Route = __webpack_require__(/*! ./routes/apiv2-routes */ "./daemon/routes/apiv2-routes.js")
const dataServerRoute = __webpack_require__(/*! ./routes/data-server-routes */ "./daemon/routes/data-server-routes.js");
const dataSourceRoute = __webpack_require__(/*! ./routes/data-source-routes */ "./daemon/routes/data-source-routes.js");
const sqlServerRoute = __webpack_require__(/*! ./routes/sql-server-routes */ "./daemon/routes/sql-server-routes.js");
const c2k = __webpack_require__(/*! koa2-connect */ "koa2-connect");
const app = new Koa()
// error handler
//onerror(app)
app.use(bodyparser({
enableTypes: ['json', 'form', 'text']
}))
app.use(json());
//app.use(logger())
app.use(__webpack_require__(/*! koa-static */ "koa-static")(__dirname + '/views'))
app.use(views(__dirname + '/views', {
map: { html: 'ejs' }
}))
// logger
// app.use(async (ctx, next) => {
// const start = new Date()
// await next()
// const ms = new Date() - start
// console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
// })
//鉴权中间件
app.use(async (ctx, next) => {
//不需要鉴权的请求路径
let ignorePath = ["/login/users", "/"];
let reqPath = ctx.request.path.replace(/^\/apiv2/, "");
//不需要鉴权的请求路径正则
let ignorePathRex = [/\/service/, /\/data/, /\/static\/images/, /\/sql/];
let isIgnore = false;
for (let i = 0; i < ignorePathRex.length; i++) {
if (ignorePathRex[i].test(reqPath)) {
isIgnore = true;
break;
}
}
if (ignorePath.indexOf(reqPath) >= 0 || isIgnore) {
await next();
return;
}
//用户请求token
let userReqToken = ctx.headers["authorization"];
if (!userReqToken) {
ctx.status = 401;
ctx.body = `{"retCode":0,"error":"非法请求"}`;
return;
}
let jwt = new Jwt(License.pcid.toString());
//验证token
let chkToken = jwt.verifyToken(userReqToken);
if (chkToken == 0) {
ctx.status = 401;
//token解析失败,返回非法请求
ctx.body = `{"retCode":0,"error":"非法请求"}`;
return;
} else if (chkToken == 1) {
ctx.status = 401;
//token解析登录保留超时
ctx.body = `{"retCode":-1,"error":"登录超时"}`;
return;
}
await next();
})
/**
* 解决koa2-connect将express中间件转换为koa2中间件时丢失body数据的bug
*/
app.use((ctx, next) => {
let methodArr = ['POST', 'PATCH'];
if (methodArr.indexOf(ctx.method) >= 0 && ctx.request.body) {
ctx.req.body = ctx.request.body;
}
next();
})
//前端文件
app.use(indexRoute.routes(), indexRoute.allowedMethods())
//data-server服务
app.use(dataServerRoute.routes(), dataServerRoute.allowedMethods());
//操作数据源
app.use(dataSourceRoute.routes(), dataSourceRoute.allowedMethods());
//sql-server服务
app.use(sqlServerRoute.routes(), sqlServerRoute.allowedMethods());
//apiv2代理相关
app.use(apiv2Route.routes(), apiv2Route.allowedMethods())
//daemon与下属服务通讯
app.use(serviceRoute.routes(), serviceRoute.allowedMethods())
// error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
module.exports = app
/***/ }),
/***/ "./daemon/bin/www.js":
/*!***************************!*\
!*** ./daemon/bin/www.js ***!
\***************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
/**
* Module dependencies.
*/
//daemon全局配置
global.config = __webpack_require__(/*! ../config/default-config.json */ "../../daemon/config/default-config.json");
//debug
global.__debug = ""; //debug模式
if (process.argv[2] && process.argv[2] === "debug") {
__debug = process.argv[2];
}
const public_modules = __webpack_require__(/*! ../libs/public-modules */ "./daemon/libs/public-modules.js");
const app = __webpack_require__(/*! ../app */ "./daemon/app.js");
const debug = __webpack_require__(/*! debug */ "debug")('demo:server');
const http = __webpack_require__(/*! http */ "http");
const c2k = __webpack_require__(/*! koa2-connect */ "koa2-connect");
const cluster = __webpack_require__(/*! cluster */ "cluster");
const { createProxyMiddleware } = __webpack_require__(/*! http-proxy-middleware */ "http-proxy-middleware");
//工作进程的最大数量
const MAXSUBCOUNT = __webpack_require__(/*! os */ "os").cpus().length;
process.env.PORT = config.port;
let port = normalizePort(process.env.PORT || '3000');
if (cluster.isMaster) {
console.log(`[DAEMON-主 进 程${process.pid}] 启动`);
//启动下属服务
manager.init();
//衍生出来的子进程个数不能超过服务器cpu个数
if (config.subCount > MAXSUBCOUNT) {
config.subCount = MAXSUBCOUNT;
}
for (let i = 0; i < config.subCount; i++) {
cluster.fork();
}
//监听工作进程消息
Object.keys(cluster.workers).forEach(item => {
cluster.workers[item].on("message", msg => {
//主进程分发消息给工作进程
sendMsgToWorker(msg);
})
})
//处理进程退出
cluster.on('exit', (worker, code, signal) => {
console.log(`[DAEMON-工作进程${process.pid}] 退出`);
});
} else if (cluster.isWorker) {
License.init();
//创建http服务
let server = http.createServer(app.callback());
//监听端口
server.listen(port);
//real-server存在多个,动态创建中间件
global.createProxy = function (proxyInfo) {
app.use(c2k(proxyInfo.proxy));
}
server.on('upgrade', (response, socket, head) => {
//real-server名称,decodeURI用于解决中文乱码
let serverName = decodeURI(response.url.split("/")[2]);
if (realServer[serverName]) {
realServer[serverName].proxy.upgrade(response, socket, head);
}
});
server.on('error', onError);
server.on('listening', onListening);
//监听主进程消息
process.on("message", msg => {
if (!msg.action) return;
let action = msg.action;
let data = msg.data;
let serverName = data.name;
switch (action) {
case "updateRealServer":
//新启动的服务或者是重启的服务
if (!realServer[serverName] || realServer[serverName].port != data.port) {
realServer.curPort = data.port;
//realServer全局对象增加新的server对象
realServer[serverName] = {
"port": data.port,
"proxy": createProxyMiddleware({
target: `ws://localhost:${data.port}/`,
changeOrigin: true,
ws: true
})
}
createProxy(realServer[serverName].proxy);
}
break;
case "updateDataServer":
//新启动的服务或者是重启的服务
if (!dataServer[serverName] || dataServer[serverName].port != data.port) {
//累计端口
dataServer.curPort = data.port;
//记录当前服务使用端口
dataServer[serverName] = data.port;
createDataServerRouter(data.port);
}
break;
case "updateSqlServer":
//新启动的服务或者是重启的服务
if (!sqlServer[serverName] || sqlServer[serverName].port != data.port) {
console.log(`${process.pid}:${JSON.stringify(sqlServer[serverName])}:${data.port}`);
//累计端口
sqlServer.curPort = data.port;
//记录当前服务使用端口
sqlServer[serverName] = data.port;
createSqlServerRouter(data.port, serverName);
}
break;
}
});
//http "error"事件监听
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
//处理已知的监听事件错误
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
//http "listening"事件监听
function onListening() {
console.log(`[DAEMON-工作进程${process.pid}] 启动`);
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
}
//规范端口
function normalizePort(val) {
let port = parseInt(val, 10);
if (isNaN(port)) return val;
if (port >= 0) return port;
return false;
}
function sendMsgToWorker(msg) {
Object.keys(cluster.workers).forEach(item => {
cluster.workers[item].send(msg);
})
}
/***/ }),
/***/ "./daemon/libs/authentication.js":
/*!***************************************!*\
!*** ./daemon/libs/authentication.js ***!
\***************************************/
/*! no static exports found */
/***/ (function(module, exports) {
/*
创建人:zhangwf
作用:前台用户相关
*/
module.exports = new class authentication {
constructor(){
}
lonin(){
}
Verification(){
//用户登陆验证
}
logout(){
}
register(){
}
}();
/***/ }),
/***/ "./daemon/libs/data-source/data-source.js":
/*!************************************************!*\
!*** ./daemon/libs/data-source/data-source.js ***!
\************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
/**
* apiv2的service层
*/
const manager = __webpack_require__(/*! ../manager */ "./daemon/libs/manager.js");
class DataSource {
/**
* 创建数据源
* @param {*} param
*/
async dataSourceCreate(param) {
let cmd = manager.spliceCmdLine([param]);
let res = manager.startDataSource(cmd);
return res;
}
//更新数据源
dataSourceUpdate(param) {
let cmd = "";
//全局对象中的server对象,不在realServer中就是在sqlServer中
let server = global["realServer"];
if (!server) {
server = global["sqlServer"];
}
let res = false;
let preName = param.preName;
//删除全局对象中旧的server
delete server[param.preName];
//删除旧的realServer进程
cmd = `pm2 delete ${preName}`;
res = manager.startServer(cmd);
//启动新的realServer
cmd = manager.spliceCmdLine([param]);
res = manager.startDataSource(cmd);
return res;
}
//删除数据源
async dataSourceDelete(param) {
let serverName = param.name;
//全局对象中的server对象,不在realServer中就是在sqlServer中
let server = global["realServer"];
if (!server) {
server = global["sqlServer"];
}
//删除全局对象中旧的realServer
delete server[serverName];
//删除旧的realServer进程
let cmd = `pm2 delete ${serverName}`;
manager.startServer(cmd);
return true;
}
}
let dataSource = null;
if (dataSource === null) {
dataSource = new DataSource();
}
module.exports = dataSource;
/***/ }),
/***/ "./daemon/libs/jwt.js":
/*!****************************!*\
!*** ./daemon/libs/jwt.js ***!
\****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// 引入模块依赖
const fs = __webpack_require__(/*! fs */ "fs");
const path = __webpack_require__(/*! path */ "path");
const jwt = __webpack_require__(/*! jsonwebtoken */ "jsonwebtoken");
// 创建 token 类
module.exports = class Jwt {
constructor(key) {
this.data = null;
this._id = null; // 用户自定义 存放userid
this._date = null; // 过期时间
this._creatDate = null; // 创建时间
this.cert = key;
this.beOverdue = 7 * 24 * 60 * 60
}
// 重新生成 token
refreshToken() {
let data = this.data;
let created = Math.floor(Date.now() / 1000);
let token = jwt.sign({
data,
exp: created + this.beOverdue, // 过期时间
iat: created, // 创建时间
}, this.cert);
return token;
}
//生成token
generateToken(data) {
if (data) {
this.data = data;
}
data = this.data;
let created = Math.floor(Date.now() / 1000);
let token = jwt.sign({
data,
exp: created + this.beOverdue, // 过期时间
iat: created, // 创建时间
}, this.cert);
return token;
}
// 校验token
verifyToken(data) {
if (data) {
this.data = data;
}
let token = this.data;
let res;
try {
let result = jwt.verify(token, this.cert) || {};
this._id = result.data;
this._date = result.exp;
this._creatDate = result.iat;
let {exp = 0} = result, current = Math.floor(Date.now() / 1000);
if (current <= exp) {
res = result.data || {};
}else{
res = 1;
}
} catch (e) {
res = 0;
}
return res;
}
}
/***/ }),
/***/ "./daemon/libs/license.js":
/*!********************************!*\
!*** ./daemon/libs/license.js ***!
\********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
//http://momentjs.cn/docs/#/query/
//https://www.liangzl.com/get-article-detail-166356.html
const fs = __webpack_require__(/*! fs */ "fs");
const si = __webpack_require__(/*! systeminformation */ "systeminformation");
const crypto = __webpack_require__(/*! crypto */ "crypto");
const moment = __webpack_require__(/*! moment */ "moment");
const { exec } = __webpack_require__(/*! child_process */ "child_process");
class License {
static async init() {
return await new Promise(async (resolve, reject) => {
moment.locale('zh-cn');
License.startTime = moment().format("YYYY-MM-DD HH:mm:ss");
if (fs.existsSync('./license.lic')) {
//打包后读当前
let info = fs.readFileSync('./license.lic', "utf-8");
await License.parseContent(info);
resolve();
} else if (fs.existsSync('../license.lic')) {
//源码模式下读取上一级目录文件
let info = fs.readFileSync('../license.lic', "utf-8");
await License.parseContent(info);
resolve();
} else {
//文件不存在,无授权,自动生成文件
//代码干扰
const key1 = '9vApxLk5G3PAsJrM';
const iv1 = 'FnJL7EDzjqWjcaY9';
//真实key
const key2 = '9vApxLLDFESXCC5G3PAsJrM';
const iv2 = 'FnJL7Edkfaldsfj9';
let pcid = await License.getPcid();
const writeContent1 = License.genSign(pcid.toString(), key2);
fs.writeFile("./safe-dog.smt", writeContent1, function (err) {
console.log("未检测到授权,演示运行时间60分钟!");
console.log("生成授权信息文件:safe-dog.smt,请发送此文件到本公司进行授权操作!");
resolve();
});
}
//开启授权检查
License.checkDog();
})
}
//10分钟一检查
static checkDog() {
//增加防杀代码,禁止屏蔽settimer
if (Object.keys(License.dogInfo).length <= 0) {
//无授权
} else {
//授权是否过期 开始日期和有效天数,必须存在
if (License.dogInfo.beginTime && License.dogInfo.availableDay) {
//当前时间大于狗里面时间 小于有效期范围
let begin = moment(License.dogInfo.beginTime, "YYYY-MM-DD HH:mm:ss");
let end = moment(begin).add(License.dogInfo.availableDay, "days");
if (moment().isBetween(begin, end, null, '[]')) {
License.hasLicense = true;
//周期喂狗,程序内部随机检查,防止爆破
License.eatDogTime = moment().format("YYYY-MM-DD HH:mm:ss");
} else {
//授权到期 用户机器时间小于授权中时间
License.hasLicense = false;
}
}
}
if (!License.hasLicense) {
//授权无效时,当前时间大于启动时间,退出。(如果是中途授权无效,则回立即退出)
let timeOut = moment(License.startTime).add(1, "hours");
if (moment().isAfter(timeOut)) {
//通知其他程序退出
//授权到期,退出pm2中所有服务
exec("pm2 delete all", (err, stdout, stderr) => {
console.log("[DAEMON]授权到期,服务退出");
//自己退出
process.exit();
});
}
}
setTimeout(License.checkDog, 1000 /* * 60 * 10 */);
}
//ture 有授权,false无
static license() {
return License.hasLicense;
}
//上次喂狗时间,不应该超过一小时,超过认为被爆破掉
static eatTime() {
return License.eatDogTime
}
static async parseContent(content) {
try {
//代码干扰
const key1 = '9vApxLk5G3PAsJrM';
const iv1 = 'FnJL7EDzjqWjcaY9';
//真实key
const key2 = '9vApxLLDFESXCC5G3PAsJrM';
const iv2 = 'FnJL7Edkfaldsfj9';
let pcid = await License.getPcid();
if (pcid > 0) {
let license = License.deSign(content, pcid.toString(), iv2);
License.dogInfo = JSON.parse(license);
}
} catch (error) {
console.log(error);
}
}
static async getPcid() {
if (License.pcid > 0) {
return License.pcid;
}
function convertStringToInt(content, isdisk = true) {
//最大60字符
if (content.length > 60) {
content = content.substring(0, 60);
}
let id = 0;
for (let i = 0; i < content.length; i++) {
//硬盘字符串长,*2,否则可能溢出,mac由于固定,并且长度较短*10
id *= isdisk ? 2 : 9;
switch (content.charAt(i)) {
case '0': id += 0; break;
case '1': id += 1; break;
case '2': id += 2; break;
case '3': id += 3; break;
case '4': id += 4; break;
case '5': id += 5; break;
case '6': id += 6; break;
case '7': id += 7; break;
case '8': id += 8; break;
case '9': id += 9; break;
case 'a': case 'A': id += 10; break;
case 'b': case 'B': id += 11; break;
case 'c': case 'C': id += 12; break;
case 'd': case 'D': id += 13; break;
case 'e': case 'E': id += 14; break;
case 'f': case 'F': id += 15; break;
case 'g': case 'G': id += 16; break;
case 'h': case 'H': id += 17; break;
case 'i': case 'I': id += 18; break;
case 'j': case 'J': id += 19; break;
case 'k': case 'K': id += 20; break;
case 'l': case 'L': id += 21; break;
case 'm': case 'M': id += 22; break;
case 'n': case 'N': id += 23; break;
case 'o': case 'O': id += 24; break;
case 'p': case 'P': id += 25; break;
case 'q': case 'Q': id += 26; break;
case 'r': case 'R': id += 27; break;
case 's': case 'S': id += 28; break;
case 't': case 'T': id += 29; break;
case 'u': case 'U': id += 30; break;
case 'v': case 'V': id += 31; break;
case 'w': case 'W': id += 32; break;
case 'x': case 'X': id += 33; break;
case 'y': case 'Y': id += 34; break;
case 'z': case 'Z': id += 35; break;
}
}
id = Math.abs(id);
if (id > 268435455) {
id %= 268435456
}
return id;
}
return await new Promise(async (resolve, reject) => {
let disk = await si.diskLayout();
if (disk.length > 0) {
//win7 无法拿到硬盘 win10可以
//取第一个硬盘
License.pcid = convertStringToInt(disk[0].name + disk[0].firmwareRevision + disk[0].serialNum);
}
//硬盘失败查询mac
if (License.pcid <= 0) {
let defaultNetName = await si.networkInterfaceDefault();
let netList = await si.networkInterfaces();
let defaultNet = netList.find((network) => {
if (network.iface == defaultNetName || network.ifaceName == defaultNetName) {
return true;
}
});
if (!defaultNet) {
//没有找到默认的,取第一个,如果有的话
if (netList.length > 0) {
defaultNet = netList[0];
}
}
License.pcid = convertStringToInt(defaultNet.mac, false);
}
resolve(License.pcid);
});
}
//加密
static genSign(src, key, iv) {
// let sign = '';
// const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
// sign += cipher.update(src, 'utf8', 'hex');
// sign += cipher.final('hex');
// return sign;
const cipher = crypto.createCipher('aes192', key);
var crypted = cipher.update(src, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
// 解密
static deSign(sign, key, iv) {
// let src = '';
// const cipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
// src += cipher.update(sign, 'hex', 'utf8');
// src += cipher.final('utf8');
// return src;
const decipher = crypto.createDecipher('aes192', key);
var decrypted = decipher.update(sign, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
//服务的启动时间
License.startTime = {};
License.hasLicense = false;
//防止爆破,喂狗时间
License.eatDogTime = {};
//授权信息
License.dogInfo = {};
License.pcid = 0;
module.exports = License;
module.exports.License = License;
module.exports.default = License;
/***/ }),
/***/ "./daemon/libs/log-manager.js":
/*!************************************!*\
!*** ./daemon/libs/log-manager.js ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports) {
/*
创建人:zhangwf
作用:集群日志相关操作
*/
module.exports = new class logManager {
constructor(){
}
init(){
}
}();
/***/ }),
/***/ "./daemon/libs/manager.js":
/*!********************************!*\
!*** ./daemon/libs/manager.js ***!
\********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
/*
创建人:zhangwf
作用:用于命令响应
*/
const { execSync } = __webpack_require__(/*! child_process */ "child_process");
const fs = __webpack_require__(/*! fs */ "fs");
const request = __webpack_require__(/*! request */ "request");
const PgDaemon = __webpack_require__(/*! ./pg-daemon */ "./daemon/libs/pg-daemon.js");
module.exports = new class Manager {
constructor() {
}
async init() {
await License.init();
await this.startSubservice();
}
async getRealServerInfo() {
return await new Promise((resolve, reject) => {
resolve({ "name": "dd" });
});
}
async startSubservice() {
try {
//在此启动下属服务
console.log(`[DAEMON-主 进 程${process.pid}] 开始通知子服务启动`);
//postgrest-sql启动相关
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:postgre-sql 已授权,开始启动`);
const pgDaemon = new PgDaemon(__debug);
let isConnect = await pgDaemon.start();
if (isConnect == false) {
console.log(`[DAEMON-主 进 程${process.pid}] postgre-sql 启动失败,启动过程停止,请检查配置信息后重新启动!`);
return;
}
console.log(`[DAEMON-主 进 程${process.pid}] postgre-sql启动完成`);
//授权信息验证
if ((License && License.dogInfo) && License.dogInfo.server == undefined) {
console.log(`[DAEMON-主 进 程${process.pid}] 没有服务端相关授权,启动完成`);
return;
}
//生成配置文件夹
if (!fs.existsSync("./config")) {
fs.mkdirSync("./config");
}
//TODO realServer与sqlServer权限暂时聚集在一块,以后再做拆分
if ((fs.existsSync("real-server.js") && License.dogInfo.server.realServer) ||
(License.dogInfo.server.realServer && __debug !== '') ||
(fs.existsSync("sql-server.js") && License.dogInfo.server.sqlServer) ||
(License.dogInfo.server.sqlServer && __debug !== '')) {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:real-server与sql-server 已授权,开始启动`);
let comDataSourceArr = await this.getAllComDataSources();
let cmdLineArr = await this.spliceCmdLine(comDataSourceArr);
//启动数据源
this.startDataSource(cmdLineArr);
} else {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:real-server与sql-server 无授权`);
}
if ((fs.existsSync("data-server.js") && License.dogInfo.server.dataServer) ||
(License.dogInfo.server.dataServer && __debug !== '')) {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:data-server 已授权,开始启动`);
let script = './data-server.js';
if (__debug !== '') {
script = '../data-server/bin/www.js';
}
let pm2Config = {
"apps": [
{
"name": "data-server",
"cwd": "./",
"script": `${script}`,
"log_date_format": "YYYY-MM-DD HH:mm:ss",
"error_file": `./logs/data-server-error.log`,
"out_file": `./logs/data-server-log.log`,
"max_memory_restart": "1G"
}
]
}
await fs.writeFileSync("./config/data-server.json", JSON.stringify(pm2Config));
await this.startServer(`pm2 start ./config/data-server.json`);
} else {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:data-server 无授权`);
}
if (fs.existsSync("io-erver.js") && License.dogInfo.system.ioServer) {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:io-erver 已授权,开始启动`);
result = await this.startServer("start node io-erver");
if (result != true) {
console.log(result);
}
} else {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:io-erver 无授权`);
}
if (fs.existsSync("ai-erver.js") && License.dogInfo.system.aiServer) {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:ai-erver 已授权,开始启动`);
result = await this.startServer("start node ai-erver");
if (result != true) {
console.log(result);
}
} else {
console.log(`[DAEMON-主 进 程${process.pid}] 子服务:ai-erver 无授权`);
}
} catch (error) {
console.log(error);
process.exit(0);
}
}
/**
* 由命令启动服务
* @param {String} cmd 命令
*/
startServer(cmd) {
try {
execSync(cmd);
return true;
} catch (error) {
throw Error(error);
}
}
/**
* 公司所有的数据源
* @returns 处理好的数据源object
*/
async getAllComDataSources() {
let reqUrl = `http://${config.pgsql.pgsqlIp}:${config.pgsql.pgsqlPort}/companys`;
let allCompanys = await this.requestGet(reqUrl);
//数据源数组
let dataSourceArr = [];
for (let i = 0; i < allCompanys.length; i++) {
let curCompany = allCompanys[i];
if (curCompany.extend === null) continue;
//数据源
let allDataSource = curCompany["extend"]["dataSource"];
if (allDataSource) {
for (let j = 0; j < allDataSource.length; j++) {
let dataSource = allDataSource[j];
let dsObj = {};
Object.keys(dataSource).forEach(key => {
if (dataSource[key]) {
dsObj[key] = dataSource[key];
}
});
dataSourceArr.push(dsObj);
}
}
}
return dataSourceArr;
}
/**
* HTTP GET
* @param {string} url 请求url
*/