w-web-api 1.0.52 → 1.0.55

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.
Files changed (78) hide show
  1. package/README.md +1 -1
  2. package/dist/css/app.cad4a1ca.css +1 -0
  3. package/dist/index.tmp +4 -2
  4. package/dist/js/app-legacy.7687b23b.js +1 -0
  5. package/dist/js/app.7687b23b.js +1 -0
  6. package/dist/js/chunk-vendors-legacy.4c27cf51.js +15 -0
  7. package/dist/js/chunk-vendors.4c27cf51.js +15 -0
  8. package/dist/w-web-api.umd.js +2 -2
  9. package/dist/w-web-api.umd.js.map +1 -1
  10. package/docs/WWebApi.html +2 -2
  11. package/docs/index.html +1 -1
  12. package/docs/{WWebApi.mjs.html → server_WWebApi.mjs.html} +113 -66
  13. package/docs/src_components_Common_CheckYesNo.vue.html +187 -0
  14. package/g.getSettings.mjs +3 -0
  15. package/logs/2026-06-19T16.log +6 -0
  16. package/logs/2026-06-20T11.log +4 -0
  17. package/logs/2026-06-20T14.log +2 -0
  18. package/logs/2026-06-21T20.log +1 -0
  19. package/logs/2026-06-21T21.log +4 -0
  20. package/logs/2026-06-22T07.log +12 -0
  21. package/logs/2026-06-22T08.log +808 -0
  22. package/logs/2026-06-22T09.log +104 -0
  23. package/logs/2026-06-22T10.log +26 -0
  24. package/logs/2026-06-22T11.log +860 -0
  25. package/logs/2026-06-22T12.log +430 -0
  26. package/logs/2026-06-22T23.log +1547 -0
  27. package/logs/2026-06-23T00.log +473 -0
  28. package/logs/2026-06-23T08.log +231 -0
  29. package/logs/2026-06-23T09.log +179 -0
  30. package/logs/2026-07-01T11.log +488 -0
  31. package/logs/2026-07-09T22.log +370 -0
  32. package/logs/2026-07-09T23.log +370 -0
  33. package/logs/2026-07-10T12.log +284 -0
  34. package/logs/2026-07-10T13.log +777 -0
  35. package/logs/2026-07-11T17.log +2 -0
  36. package/package.json +20 -15
  37. package/public/index.html +9 -2
  38. package/server/WWebApi.mjs +110 -63
  39. package/server/procApis.mjs +62 -0
  40. package/server/procLang.mjs +372 -66
  41. package/server/procProxy.mjs +120 -0
  42. package/server/srLog.mjs +30 -0
  43. package/server/staLogs/filterVpfsByWindow.mjs +27 -0
  44. package/server/staLogs/staEvent.mjs +131 -0
  45. package/server/staLogs/test_staEvent.mjs +198 -0
  46. package/settings.json +18 -0
  47. package/src/App.vue +11 -7
  48. package/src/assets/scalar-ui.css +113 -0
  49. package/src/components/Common/CheckYes.vue +102 -0
  50. package/src/components/Common/CheckYesNo.vue +115 -0
  51. package/src/components/Common/LoadingWinBar.vue +114 -0
  52. package/src/components/Layout.vue +8 -26
  53. package/src/components/LayoutContent.vue +299 -350
  54. package/src/components/LayoutContentEdit.vue +577 -0
  55. package/src/components/LayoutContentStats.vue +485 -0
  56. package/src/components/LayoutContentTest.vue +781 -0
  57. package/src/components/MdPanel.vue +80 -58
  58. package/src/main.js +11 -8
  59. package/src/plugins/mUI.mjs +19 -39
  60. package/src/schema/tables/apis.mjs +30 -0
  61. package/src/store/mutations.mjs +0 -14
  62. package/src/store/types.mjs +0 -3
  63. package/srv.mjs +50 -20
  64. package/tableTags.json +1 -1
  65. package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +246 -0
  66. package/.github/workflows/ci-test.yml +0 -24
  67. package/.vscode/launch.json +0 -18
  68. package/db/wapis/apis/data.mdb +0 -0
  69. package/db/wapis/apis/lock.mdb +0 -0
  70. package/dist/css/app.b5cf2ef5.css +0 -1
  71. package/dist/js/app-legacy.927b5679.js +0 -1
  72. package/dist/js/app.927b5679.js +0 -1
  73. package/dist/js/chunk-vendors-legacy.ffb0c6c5.js +0 -13
  74. package/dist/js/chunk-vendors.ffb0c6c5.js +0 -13
  75. package/src/plugins/mDataSelectorSchema.mjs +0 -30
  76. package/src/plugins/mShare.mjs +0 -44
  77. package/tableTags-web-api.json +0 -1
  78. package/test/all.test.mjs +0 -10
@@ -0,0 +1,2 @@
1
+ {"level":30,"time":1783763274489,"pid":20076,"hostname":"semi-win-dev3","event":"verifyClientUser","from":"getUserByToken","userId":"id-for-admin"}
2
+ {"level":30,"time":1783763274490,"pid":20076,"hostname":"semi-win-dev3","event":"api/getUserByToken","userId":"id-for-admin"}
package/package.json CHANGED
@@ -1,40 +1,45 @@
1
1
  {
2
2
  "name": "w-web-api",
3
- "version": "1.0.52",
3
+ "version": "1.0.55",
4
4
  "main": "dist/w-web-api.umd.js",
5
5
  "dependencies": {
6
6
  "@mdi/js": "^7.4.47",
7
- "axios": "^1.13.6",
8
- "lodash-es": "^4.17.23",
7
+ "axios": "^1.18.1",
8
+ "lodash-es": "^4.18.1",
9
9
  "showdown": "^2.1.0",
10
- "w-component-vue": "^2.4.44",
11
- "w-data-collector": "^1.0.22",
12
- "w-serv-hapi": "^1.0.72",
13
- "w-serv-orm": "^1.0.38",
14
- "w-ui-loginout": "^1.0.10",
15
- "wsemi": "^1.8.43"
10
+ "w-component-vue": "^2.4.74",
11
+ "w-data-collector": "^1.0.23",
12
+ "w-serv-hapi": "^1.0.73",
13
+ "w-serv-orm": "^1.0.40",
14
+ "w-ui-loginout": "^1.0.11",
15
+ "w-syslog": "^1.0.10",
16
+ "wsemi": "^1.8.66"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@vue/cli-plugin-babel": "^5.0.8",
19
20
  "@vue/cli-plugin-eslint": "^5.0.8",
20
21
  "@vue/cli-service": "^5.0.8",
21
22
  "eslint": "^8.37.0",
22
- "eslint-config-standard": "^17.0.0",
23
+ "eslint-config-standard": "^17.1.0",
23
24
  "eslint-friendly-formatter": "^4.0.1",
24
25
  "eslint-plugin-import": "^2.27.5",
25
- "eslint-plugin-node": "^11.1.0",
26
+ "eslint-plugin-n": "^16.6.2",
26
27
  "eslint-plugin-promise": "^6.1.1",
27
- "eslint-plugin-standard": "^4.1.0",
28
28
  "eslint-plugin-vue": "^9.10.0",
29
+ "pixelmatch": "^7.2.0",
30
+ "playwright": "^1.61.1",
31
+ "pngjs": "^7.0.0",
29
32
  "vue": "^2.6.14",
30
33
  "vuex": "^3.6.2",
31
- "w-orm-lmdb": "^1.0.3",
32
- "w-package-tools": "^1.1.3"
34
+ "w-orm-lmdb": "^1.0.8",
35
+ "w-screenctl": "^1.0.4",
36
+ "w-package-tools": "^1.1.11"
33
37
  },
34
38
  "scripts": {
35
39
  "serve": "vue-cli-service serve",
36
40
  "build": "vue-cli-service build",
37
- "test": "mocha --parallel --timeout 60000",
41
+ "test:unit": "node server/staLogs/test_staEvent.mjs",
42
+ "test": "node server/staLogs/test_staEvent.mjs && mocha --timeout 300000",
38
43
  "lint": "vue-cli-service lint",
39
44
  "deploy": "gh-pages -d docs"
40
45
  },
package/public/index.html CHANGED
@@ -7,10 +7,10 @@
7
7
  <title></title>
8
8
 
9
9
  <!-- mdi font -->
10
- <link href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" rel="stylesheet">
10
+ <link _href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" rel="stylesheet">
11
11
 
12
12
  <!-- fontawesome -->
13
- <link href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css" rel="stylesheet">
13
+ <link _href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css" rel="stylesheet">
14
14
 
15
15
  <!-- ___pmwapi___ -->
16
16
  <script>
@@ -19,6 +19,13 @@
19
19
  }
20
20
  </script>
21
21
 
22
+ <!-- ___pmwperm___ -->
23
+ <script>
24
+ window.___pmwperm___={
25
+ language: '{language}',
26
+ }
27
+ </script>
28
+
22
29
  </head>
23
30
  <body style="font-family:'Microsoft JhengHei','Avenir','Helvetica', 'Arial', 'sans-serif'; padding:0px; margin:0px;">
24
31
  <noscript>
@@ -26,6 +26,10 @@ import replace from 'wsemi/src/replace.mjs'
26
26
  import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs'
27
27
  import WServOrm from 'w-serv-orm/src/WServOrm.mjs'
28
28
  import procLang from './procLang.mjs'
29
+ import procProxy from './procProxy.mjs'
30
+ import procApis from './procApis.mjs'
31
+ import staEvent from './staLogs/staEvent.mjs'
32
+ import srLogInit from './srLog.mjs'
29
33
  import ds from '../src/schema/index.mjs'
30
34
 
31
35
 
@@ -226,6 +230,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
226
230
  //params
227
231
  let showLanguage = get(opt, 'showLanguage', 'y')
228
232
  let language = get(opt, 'language', 'eng')
233
+ let logFd = get(opt, 'logFd', './logs') //srLog 寫入 + staEvent 統計共用之 log 資料夾
229
234
 
230
235
 
231
236
  //kpLangExt
@@ -247,11 +252,45 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
247
252
  wp = WServOrm(ds, WOrm, url, db, optWServOrm)
248
253
  }
249
254
  catch (err) {
250
- console.log(err)
255
+ //ORM 為必要依賴:初始化失敗即 fail-fast,不以 wp={} 帶 undefined woItems/procOrm 殘缺啟動(與建構子其餘必要依賴一致)
256
+ console.log('WServOrm init failed', err)
257
+ throw err
251
258
  }
252
259
  let { woItems, procOrm } = wp
253
260
 
254
261
 
262
+ //srLog(後端 log;錯誤一律 log err-key 供識別,對齊 w-web-sso)
263
+ let srLog = srLogInit(opt)
264
+
265
+ //maskTok:debug console.log 不印完整 token/authorization(憑證),僅前 4 碼 + ***,避免憑證落入 stdout
266
+ let maskTok = (t) => isestr(t) ? (strleft(t, 4) + '***') : t
267
+
268
+ //kpFunExt 邊界統一處理:成功記 info(供 staEvent 統計呼叫頻率);catch 後端錯誤 → srLog 該 err-key →
269
+ //原樣 re-reject(前端依 key 查自己 lang 顯示)。event 統一加 'kpfun-' 前綴 → 專用事件、與 api/verifyConn 區分。
270
+ let wrapErrLog = (event, fn) => {
271
+ let ev = 'kpfun-' + event
272
+ return async (...args) => {
273
+ try {
274
+ let result = await fn(...args)
275
+ srLog.info({ event: ev }) //成功也記 info
276
+ return result
277
+ }
278
+ catch (err) {
279
+ srLog.error({ event: ev, err })
280
+ return Promise.reject(err)
281
+ }
282
+ }
283
+ }
284
+
285
+
286
+ //procProxy
287
+ let { proxyRequest } = procProxy({ srLog })
288
+
289
+
290
+ //procApis
291
+ let { getApisList, saveApi, deleteApi } = procApis({ woItems, procOrm, ds })
292
+
293
+
255
294
  //getWebInfor
256
295
  let getWebInfor = (userId) => {
257
296
  return {
@@ -274,26 +313,26 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
274
313
  if (!isestr(id)) {
275
314
  console.log('user', user)
276
315
  console.log('can not get the userId')
277
- return Promise.reject(`can not get the userId`)
316
+ return Promise.reject('errUserIdMissing')
278
317
  }
279
318
  let email = get(user, 'email', '')
280
319
  if (!isestr(email)) {
281
320
  console.log('user', user)
282
321
  console.log('can not get the email of user')
283
- return Promise.reject(`can not get the email of user`)
322
+ return Promise.reject('errUserEmailMissing')
284
323
  }
285
324
  let name = get(user, 'name', '')
286
325
  if (!isestr(name)) {
287
326
  console.log('user', user)
288
327
  console.log('can not get userName')
289
- return Promise.reject(`can not get userName`)
328
+ return Promise.reject('errUserNameMissing')
290
329
  }
291
330
  let isAdmin = get(user, 'isAdmin', '')
292
331
  if (isAdmin !== 'y' && isAdmin !== 'n') {
293
332
  console.log('user', user)
294
333
  console.log('user.isAdmin is not y or n', user.isAdmin)
295
334
  console.log('can not get the role of user')
296
- return Promise.reject(`can not get the role of user`)
335
+ return Promise.reject('errUserRoleMissing')
297
336
  }
298
337
  return true
299
338
  }
@@ -309,14 +348,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
309
348
  }
310
349
 
311
350
  //check
312
- if (true) {
313
- // if (!iseobj(userSelf)) {
314
- // console.log(`token`, token)
315
- // console.log(`can not find the user from token`)
316
- // return Promise.reject(`can not find the user from token`)
317
- // }
318
- await checkUser(userSelf)
319
- }
351
+ await checkUser(userSelf)
320
352
 
321
353
  return userSelf
322
354
  }
@@ -355,9 +387,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
355
387
  if (!b) {
356
388
  console.log('user', user)
357
389
  console.log(`user does not have permission`)
358
- return Promise.reject(`user does not have permission`)
390
+ return Promise.reject('errUserNoPermission')
359
391
  }
360
392
 
393
+ srLog.info({ event: 'verifyClientUser', from, userId: get(user, 'id', '') }) //瀏覽使用者驗證通過
361
394
  return user
362
395
  }
363
396
 
@@ -380,7 +413,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
380
413
  if (!iseobj(user)) {
381
414
  console.log(`token`, token)
382
415
  console.log(`can not find the user from token`)
383
- return Promise.reject(`can not find the user from token`)
416
+ return Promise.reject('errUserNotFound')
384
417
  }
385
418
 
386
419
  //verifyAppUser
@@ -393,9 +426,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
393
426
  if (!b) {
394
427
  console.log('user', user)
395
428
  console.log(`user does not have permission`)
396
- return Promise.reject(`user does not have permission`)
429
+ return Promise.reject('errUserNoPermission')
397
430
  }
398
431
 
432
+ srLog.info({ event: 'verifyAppUser', from, userId: get(user, 'id', '') }) //應用程式使用者驗證通過
399
433
  return user
400
434
  }
401
435
 
@@ -422,7 +456,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
422
456
  if (!iseobj(payload)) {
423
457
  console.log('payload', payload)
424
458
  console.log(`invalid payload in req`)
425
- return Promise.reject(`invalid payload in req`)
459
+ return Promise.reject('errPayloadInvalid')
426
460
  }
427
461
 
428
462
  //group
@@ -432,7 +466,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
432
466
  if (!isestr(group)) {
433
467
  console.log('payload', payload)
434
468
  console.log(`invalid group in payload`)
435
- return Promise.reject(`invalid group in payload`)
469
+ return Promise.reject('errGroupInvalid')
436
470
  }
437
471
 
438
472
  //rows
@@ -442,7 +476,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
442
476
  if (!isearr(rows)) {
443
477
  console.log('payload', payload)
444
478
  console.log(`invalid rows in payload`)
445
- return Promise.reject(`invalid rows in payload`)
479
+ return Promise.reject('errRowsInvalid')
446
480
  }
447
481
 
448
482
  //r
@@ -482,7 +516,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
482
516
  console.log('inp', inp)
483
517
  console.log('group', group)
484
518
  console.log(`invalid group`)
485
- return Promise.reject(`invalid group`)
519
+ return Promise.reject('errGroupInvalid')
486
520
  }
487
521
 
488
522
  //rows
@@ -493,7 +527,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
493
527
  if (!isearr(rows)) {
494
528
  console.log('inp', inp)
495
529
  console.log('keyTable', keyTable)
496
- return Promise.reject(`invalid rows`)
530
+ return Promise.reject('errRowsInvalid')
497
531
  }
498
532
 
499
533
  //save from
@@ -564,6 +598,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
564
598
  c = replace(c, '/mapi/', '{sfd}/') //方法同genEntry
565
599
  c = replace(c, '{sfd}', subfolder)
566
600
  c = replace(c, '{urlRedirect}', urlRedirect)
601
+ c = replace(c, '{language}', language) //注入初始語系 → window.___pmwperm___.language(前端 getLang 之來源之一)
567
602
  fs.writeFileSync(fpEntryOut, c, 'utf8')
568
603
  }
569
604
  catch (err) {
@@ -589,10 +624,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
589
624
  //check
590
625
  if (!isestr(token)) {
591
626
  console.log('req.query', get(req, 'query'))
592
- console.log('token', token)
627
+ console.log('token', maskTok(token))
593
628
  console.log('[API]getUserByToken/check token: invalid token')
594
- console.log(`token does not have permission`)
595
- return Promise.reject(`token does not have permission`)
629
+ return Promise.reject('errTokenNoPermission')
596
630
  }
597
631
 
598
632
  //getAndVerifyClientUser
@@ -600,12 +634,12 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
600
634
 
601
635
  //check
602
636
  if (!iseobj(user)) {
603
- console.log('token', token)
637
+ console.log('token', maskTok(token))
604
638
  console.log('[API]getUserByToken/check user: invalid user')
605
- console.log(`token does not have permission`)
606
- return Promise.reject(`token does not have permission`)
639
+ return Promise.reject('errTokenNoPermission')
607
640
  }
608
641
 
642
+ srLog.info({ event: 'api/getUserByToken', userId: get(user, 'id', '') })
609
643
  return user
610
644
  }
611
645
 
@@ -636,8 +670,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
636
670
  // console.log('req.query', get(req, 'query'))
637
671
  // console.log('token', token)
638
672
  // console.log('[API]getAPIsList/check token: invalid token')
639
- // console.log(`token does not have permission`)
640
- // return Promise.reject(`token does not have permission`)
673
+ // return Promise.reject('errTokenNoPermission')
641
674
  // }
642
675
 
643
676
  // //getAndVerifyClientUser
@@ -647,8 +680,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
647
680
  // if (!iseobj(user)) {
648
681
  // console.log('token', token)
649
682
  // console.log('[API]getAPIsList/check user: invalid user')
650
- // console.log(`token does not have permission`)
651
- // return Promise.reject(`token does not have permission`)
683
+ // return Promise.reject('errTokenNoPermission')
652
684
  // }
653
685
 
654
686
  // //getAPIsList
@@ -685,8 +717,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
685
717
  // console.log('req.query', get(req, 'query'))
686
718
  // console.log('token', token)
687
719
  // console.log('[API]updateAPIs/check token: invalid token')
688
- // console.log(`token does not have permission`)
689
- // return Promise.reject(`token does not have permission`)
720
+ // return Promise.reject('errTokenNoPermission')
690
721
  // }
691
722
 
692
723
  // //getAndVerifyClientUser
@@ -696,8 +727,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
696
727
  // if (!iseobj(user)) {
697
728
  // console.log('token', token)
698
729
  // console.log('[API]updateAPIs/check user: invalid user')
699
- // console.log(`token does not have permission`)
700
- // return Promise.reject(`token does not have permission`)
730
+ // return Promise.reject('errTokenNoPermission')
701
731
  // }
702
732
 
703
733
  // //parsePayload
@@ -735,10 +765,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
735
765
  //check
736
766
  if (!isestr(token)) {
737
767
  console.log('req.query', get(req, 'query'))
738
- console.log('token', token)
768
+ console.log('token', maskTok(token))
739
769
  console.log('[API]syncAndReplaceTabs/check token: invalid token')
740
- console.log(`token does not have permission`)
741
- return Promise.reject(`token does not have permission`)
770
+ return Promise.reject('errTokenNoPermission')
742
771
  }
743
772
 
744
773
  //keyTable
@@ -749,15 +778,14 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
749
778
  console.log('req.query', get(req, 'query'))
750
779
  console.log('keyTable', keyTable)
751
780
  console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable')
752
- console.log(`token does not have permission`)
753
- return Promise.reject(`token does not have permission`)
781
+ return Promise.reject('errKeyTableInvalid')
754
782
  }
755
783
 
756
784
  //check keyTable
757
785
  let allowedTables = ['apis']
758
786
  if (!allowedTables.includes(keyTable)) {
759
787
  console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable)
760
- return Promise.reject(`invalid keyTable: ${keyTable}`)
788
+ return Promise.reject('errKeyTableInvalid')
761
789
  }
762
790
 
763
791
  //getAndVerifyAppUser
@@ -765,10 +793,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
765
793
 
766
794
  //check
767
795
  if (!iseobj(user)) {
768
- console.log('token', token)
796
+ console.log('token', maskTok(token))
769
797
  console.log('[API]syncAndReplaceTabs/check user: invalid user')
770
- console.log(`token does not have permission`)
771
- return Promise.reject(`token does not have permission`)
798
+ return Promise.reject('errTokenNoPermission')
772
799
  }
773
800
 
774
801
  //userId
@@ -776,11 +803,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
776
803
 
777
804
  //check userId
778
805
  if (!isestr(userId)) {
779
- console.log('token', token)
806
+ console.log('token', maskTok(token))
780
807
  console.log('user', user)
781
808
  console.log('[API]syncAndReplaceTabs/check userId: invalid userId')
782
- console.log(`token does not have permission`)
783
- return Promise.reject(`token does not have permission`)
809
+ return Promise.reject('errTokenNoPermission')
784
810
  }
785
811
 
786
812
  //parsePayload
@@ -789,6 +815,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
789
815
  //syncAndReplaceTabs
790
816
  let r = await syncAndReplaceTabs(userId, inp, keyTable)
791
817
 
818
+ srLog.info({ event: 'api/syncAndReplaceTabs', userId, keyTable })
792
819
  return r
793
820
  }
794
821
 
@@ -816,7 +843,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
816
843
 
817
844
  //WServHapiServer
818
845
  instWServHapiServer = new WServHapiServer({
819
- port: opt.serverPort,
846
+ port: serverPort,
820
847
  pathStaticFiles,
821
848
  apiName: 'api',
822
849
  apis,
@@ -831,28 +858,28 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
831
858
  //check
832
859
  if (!isestr(token)) {
833
860
  console.log('apiType', apiType)
834
- console.log('authorization', authorization)
861
+ console.log('authorization', maskTok(authorization))
835
862
  console.log('invalid token')
836
863
  return false
837
864
  }
838
865
 
839
- //checkToken
866
+ //checkToken:套件層連線閘僅做「token 認證」(解析 user + 驗欄位齊備)。**授權**(如限管理員)屬
867
+ //套件使用者之責——由其提供之 getUserByToken(可對非授權者回 {})/ verifyClientUser / verifyAppUser,
868
+ //或 WServOrm 之 useCheckUser/useExcludeWhenNotAdmin 等鉤子決定;套件不對連線層強加特定授權政策(避免越界、
869
+ //保留使用者彈性)。詳見 spec/設計要點與取捨.md「套件授權責任」。
840
870
  let b = await p.checkToken(token)
841
- // console.log('b', b)
842
871
 
872
+ srLog.info({ event: 'verifyConn', apiType }) //連線之 token 認證通過(checkToken 失敗會 throw 不到此)
843
873
  return b
844
874
  },
845
875
  getUserIdByToken: async (token) => { //可使用async或sync函數
846
876
  // console.log('getUserIdByToken', token)
847
- return ''
848
- // let user = await getUserByToken(token) //api儲存時須使用
849
- // let userId = get(user, 'id', '')
850
- // if (!isestr(userId)) {
851
- // console.log('token', token)
852
- // console.log('userId', userId)
853
- // return Promise.reject(`can not find user.id`)
854
- // }
855
- // return userId
877
+ if (!isestr(token)) {
878
+ return ''
879
+ }
880
+ let user = await getUserByToken(token)
881
+ let userId = get(user, 'id', '')
882
+ return userId
856
883
  },
857
884
  useDbOrm: true,
858
885
  kpOrm: woItems,
@@ -860,9 +887,29 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
860
887
  tableNamesExec,
861
888
  methodsExec: ['select', 'insert', 'save', 'del'], //mix需於procOrm內註冊以提供
862
889
  tableNamesSync,
863
- kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數
864
-
865
- getWebInfor,
890
+ kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數(皆經 wrapErrLog:錯誤 srLog err-key 後 re-reject)
891
+
892
+ getWebInfor: wrapErrLog('getWebInfor', getWebInfor),
893
+
894
+ proxyRequest: wrapErrLog('proxyRequest', (userId, reqSpec) => {
895
+ return proxyRequest(reqSpec)
896
+ }),
897
+
898
+ getApisList: wrapErrLog('getApisList', (userId) => {
899
+ return getApisList(userId)
900
+ }),
901
+ saveApi: wrapErrLog('saveApi', (userId, row) => {
902
+ return saveApi(userId, row)
903
+ }),
904
+ deleteApi: wrapErrLog('deleteApi', (userId, id) => {
905
+ return deleteApi(userId, id)
906
+ }),
907
+
908
+ //統計資訊頁:回傳各 event 之時段發生頻率(讀 logFd 之 log)。連線之 token 認證由 verifyConn 把關;
909
+ //授權(限管理員)屬套件使用者責任(見 verifyConn 註解與設計要點與取捨「套件授權責任」)。timeLength 天數 / timeInterval 'hr'|'day'。
910
+ getStaEvent: wrapErrLog('getStaEvent', (userId, timeLength = 7, timeInterval = 'hr') => {
911
+ return staEvent(timeLength, timeInterval, { fdLog: logFd })
912
+ }),
866
913
 
867
914
  // getAPIsList: (userId, query = {}) => { //待提供api管理系統界面使用
868
915
  // return getAPIsList(query)
@@ -0,0 +1,62 @@
1
+ import iseobj from 'wsemi/src/iseobj.mjs'
2
+ import isestr from 'wsemi/src/isestr.mjs'
3
+
4
+
5
+ function procApis(deps = {}) {
6
+
7
+ //deps
8
+ let { woItems, procOrm, ds } = deps
9
+
10
+
11
+ let getApisList = async (userId) => {
12
+ return await woItems.apis.select({})
13
+ }
14
+
15
+
16
+ let saveApi = async (userId, row) => {
17
+
18
+ //check(reject err-key,由前端依 lang 反查顯示;邊界 kpFunExt 會 srLog 此 key)
19
+ if (!iseobj(row)) {
20
+ return Promise.reject('errApiRowInvalid')
21
+ }
22
+
23
+ //正規化:funNew 配 id/時間/預設並過濾欄位
24
+ let o = ds.apis.funNew(row)
25
+
26
+ //保留原 id 與創建時間(既有筆)
27
+ if (isestr(row.id)) {
28
+ o.id = row.id
29
+ if (isestr(row.timeCreate)) {
30
+ o.timeCreate = row.timeCreate
31
+ }
32
+ }
33
+
34
+ //save
35
+ let r = await procOrm(userId, 'apis', 'save', [o])
36
+
37
+ return r
38
+ }
39
+
40
+
41
+ let deleteApi = async (userId, id) => {
42
+
43
+ //check(reject err-key,由前端依 lang 反查顯示)
44
+ if (!isestr(id)) {
45
+ return Promise.reject('errApiIdInvalid')
46
+ }
47
+
48
+ let r = await procOrm(userId, 'apis', 'del', { id })
49
+
50
+ return r
51
+ }
52
+
53
+
54
+ return {
55
+ getApisList,
56
+ saveApi,
57
+ deleteApi,
58
+ }
59
+ }
60
+
61
+
62
+ export default procApis