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.
- package/README.md +1 -1
- package/dist/css/app.cad4a1ca.css +1 -0
- package/dist/index.tmp +4 -2
- package/dist/js/app-legacy.7687b23b.js +1 -0
- package/dist/js/app.7687b23b.js +1 -0
- package/dist/js/chunk-vendors-legacy.4c27cf51.js +15 -0
- package/dist/js/chunk-vendors.4c27cf51.js +15 -0
- package/dist/w-web-api.umd.js +2 -2
- package/dist/w-web-api.umd.js.map +1 -1
- package/docs/WWebApi.html +2 -2
- package/docs/index.html +1 -1
- package/docs/{WWebApi.mjs.html → server_WWebApi.mjs.html} +113 -66
- package/docs/src_components_Common_CheckYesNo.vue.html +187 -0
- package/g.getSettings.mjs +3 -0
- package/logs/2026-06-19T16.log +6 -0
- package/logs/2026-06-20T11.log +4 -0
- package/logs/2026-06-20T14.log +2 -0
- package/logs/2026-06-21T20.log +1 -0
- package/logs/2026-06-21T21.log +4 -0
- package/logs/2026-06-22T07.log +12 -0
- package/logs/2026-06-22T08.log +808 -0
- package/logs/2026-06-22T09.log +104 -0
- package/logs/2026-06-22T10.log +26 -0
- package/logs/2026-06-22T11.log +860 -0
- package/logs/2026-06-22T12.log +430 -0
- package/logs/2026-06-22T23.log +1547 -0
- package/logs/2026-06-23T00.log +473 -0
- package/logs/2026-06-23T08.log +231 -0
- package/logs/2026-06-23T09.log +179 -0
- package/logs/2026-07-01T11.log +488 -0
- package/logs/2026-07-09T22.log +370 -0
- package/logs/2026-07-09T23.log +370 -0
- package/logs/2026-07-10T12.log +284 -0
- package/logs/2026-07-10T13.log +777 -0
- package/logs/2026-07-11T17.log +2 -0
- package/package.json +20 -15
- package/public/index.html +9 -2
- package/server/WWebApi.mjs +110 -63
- package/server/procApis.mjs +62 -0
- package/server/procLang.mjs +372 -66
- package/server/procProxy.mjs +120 -0
- package/server/srLog.mjs +30 -0
- package/server/staLogs/filterVpfsByWindow.mjs +27 -0
- package/server/staLogs/staEvent.mjs +131 -0
- package/server/staLogs/test_staEvent.mjs +198 -0
- package/settings.json +18 -0
- package/src/App.vue +11 -7
- package/src/assets/scalar-ui.css +113 -0
- package/src/components/Common/CheckYes.vue +102 -0
- package/src/components/Common/CheckYesNo.vue +115 -0
- package/src/components/Common/LoadingWinBar.vue +114 -0
- package/src/components/Layout.vue +8 -26
- package/src/components/LayoutContent.vue +299 -350
- package/src/components/LayoutContentEdit.vue +577 -0
- package/src/components/LayoutContentStats.vue +485 -0
- package/src/components/LayoutContentTest.vue +781 -0
- package/src/components/MdPanel.vue +80 -58
- package/src/main.js +11 -8
- package/src/plugins/mUI.mjs +19 -39
- package/src/schema/tables/apis.mjs +30 -0
- package/src/store/mutations.mjs +0 -14
- package/src/store/types.mjs +0 -3
- package/srv.mjs +50 -20
- package/tableTags.json +1 -1
- package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +246 -0
- package/.github/workflows/ci-test.yml +0 -24
- package/.vscode/launch.json +0 -18
- package/db/wapis/apis/data.mdb +0 -0
- package/db/wapis/apis/lock.mdb +0 -0
- package/dist/css/app.b5cf2ef5.css +0 -1
- package/dist/js/app-legacy.927b5679.js +0 -1
- package/dist/js/app.927b5679.js +0 -1
- package/dist/js/chunk-vendors-legacy.ffb0c6c5.js +0 -13
- package/dist/js/chunk-vendors.ffb0c6c5.js +0 -13
- package/src/plugins/mDataSelectorSchema.mjs +0 -30
- package/src/plugins/mShare.mjs +0 -44
- package/tableTags-web-api.json +0 -1
- package/test/all.test.mjs +0 -10
package/docs/WWebApi.html
CHANGED
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
|
|
81
81
|
<dt class="tag-source">Source:</dt>
|
|
82
82
|
<dd class="tag-source"><ul class="dummy"><li>
|
|
83
|
-
<a href="
|
|
83
|
+
<a href="server_WWebApi.mjs.html">server/WWebApi.mjs</a>, <a href="server_WWebApi.mjs.html#line136">line 136</a>
|
|
84
84
|
</li></ul></dd>
|
|
85
85
|
|
|
86
86
|
|
|
@@ -885,7 +885,7 @@
|
|
|
885
885
|
<br class="clear">
|
|
886
886
|
|
|
887
887
|
<footer>
|
|
888
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.
|
|
888
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
889
889
|
</footer>
|
|
890
890
|
|
|
891
891
|
<script>prettyPrint();</script>
|
package/docs/index.html
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
<br class="clear">
|
|
72
72
|
|
|
73
73
|
<footer>
|
|
74
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.
|
|
74
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
75
75
|
</footer>
|
|
76
76
|
|
|
77
77
|
<script>prettyPrint();</script>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
|
|
5
5
|
<meta charset="utf-8">
|
|
6
|
-
<title>WWebApi.mjs - Documentation</title>
|
|
6
|
+
<title>server/WWebApi.mjs - Documentation</title>
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
<script src="scripts/prettify/prettify.js"></script>
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
<div id="main">
|
|
37
37
|
|
|
38
|
-
<h1 class="page-title">WWebApi.mjs</h1>
|
|
38
|
+
<h1 class="page-title">server/WWebApi.mjs</h1>
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
|
|
@@ -73,6 +73,10 @@ import replace from 'wsemi/src/replace.mjs'
|
|
|
73
73
|
import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs'
|
|
74
74
|
import WServOrm from 'w-serv-orm/src/WServOrm.mjs'
|
|
75
75
|
import procLang from './procLang.mjs'
|
|
76
|
+
import procProxy from './procProxy.mjs'
|
|
77
|
+
import procApis from './procApis.mjs'
|
|
78
|
+
import staEvent from './staLogs/staEvent.mjs'
|
|
79
|
+
import srLogInit from './srLog.mjs'
|
|
76
80
|
import ds from '../src/schema/index.mjs'
|
|
77
81
|
|
|
78
82
|
|
|
@@ -273,6 +277,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
273
277
|
//params
|
|
274
278
|
let showLanguage = get(opt, 'showLanguage', 'y')
|
|
275
279
|
let language = get(opt, 'language', 'eng')
|
|
280
|
+
let logFd = get(opt, 'logFd', './logs') //srLog 寫入 + staEvent 統計共用之 log 資料夾
|
|
276
281
|
|
|
277
282
|
|
|
278
283
|
//kpLangExt
|
|
@@ -294,11 +299,45 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
294
299
|
wp = WServOrm(ds, WOrm, url, db, optWServOrm)
|
|
295
300
|
}
|
|
296
301
|
catch (err) {
|
|
297
|
-
|
|
302
|
+
//ORM 為必要依賴:初始化失敗即 fail-fast,不以 wp={} 帶 undefined woItems/procOrm 殘缺啟動(與建構子其餘必要依賴一致)
|
|
303
|
+
console.log('WServOrm init failed', err)
|
|
304
|
+
throw err
|
|
298
305
|
}
|
|
299
306
|
let { woItems, procOrm } = wp
|
|
300
307
|
|
|
301
308
|
|
|
309
|
+
//srLog(後端 log;錯誤一律 log err-key 供識別,對齊 w-web-sso)
|
|
310
|
+
let srLog = srLogInit(opt)
|
|
311
|
+
|
|
312
|
+
//maskTok:debug console.log 不印完整 token/authorization(憑證),僅前 4 碼 + ***,避免憑證落入 stdout
|
|
313
|
+
let maskTok = (t) => isestr(t) ? (strleft(t, 4) + '***') : t
|
|
314
|
+
|
|
315
|
+
//kpFunExt 邊界統一處理:成功記 info(供 staEvent 統計呼叫頻率);catch 後端錯誤 → srLog 該 err-key →
|
|
316
|
+
//原樣 re-reject(前端依 key 查自己 lang 顯示)。event 統一加 'kpfun-' 前綴 → 專用事件、與 api/verifyConn 區分。
|
|
317
|
+
let wrapErrLog = (event, fn) => {
|
|
318
|
+
let ev = 'kpfun-' + event
|
|
319
|
+
return async (...args) => {
|
|
320
|
+
try {
|
|
321
|
+
let result = await fn(...args)
|
|
322
|
+
srLog.info({ event: ev }) //成功也記 info
|
|
323
|
+
return result
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
srLog.error({ event: ev, err })
|
|
327
|
+
return Promise.reject(err)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
//procProxy
|
|
334
|
+
let { proxyRequest } = procProxy({ srLog })
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
//procApis
|
|
338
|
+
let { getApisList, saveApi, deleteApi } = procApis({ woItems, procOrm, ds })
|
|
339
|
+
|
|
340
|
+
|
|
302
341
|
//getWebInfor
|
|
303
342
|
let getWebInfor = (userId) => {
|
|
304
343
|
return {
|
|
@@ -321,26 +360,26 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
321
360
|
if (!isestr(id)) {
|
|
322
361
|
console.log('user', user)
|
|
323
362
|
console.log('can not get the userId')
|
|
324
|
-
return Promise.reject(
|
|
363
|
+
return Promise.reject('errUserIdMissing')
|
|
325
364
|
}
|
|
326
365
|
let email = get(user, 'email', '')
|
|
327
366
|
if (!isestr(email)) {
|
|
328
367
|
console.log('user', user)
|
|
329
368
|
console.log('can not get the email of user')
|
|
330
|
-
return Promise.reject(
|
|
369
|
+
return Promise.reject('errUserEmailMissing')
|
|
331
370
|
}
|
|
332
371
|
let name = get(user, 'name', '')
|
|
333
372
|
if (!isestr(name)) {
|
|
334
373
|
console.log('user', user)
|
|
335
374
|
console.log('can not get userName')
|
|
336
|
-
return Promise.reject(
|
|
375
|
+
return Promise.reject('errUserNameMissing')
|
|
337
376
|
}
|
|
338
377
|
let isAdmin = get(user, 'isAdmin', '')
|
|
339
378
|
if (isAdmin !== 'y' && isAdmin !== 'n') {
|
|
340
379
|
console.log('user', user)
|
|
341
380
|
console.log('user.isAdmin is not y or n', user.isAdmin)
|
|
342
381
|
console.log('can not get the role of user')
|
|
343
|
-
return Promise.reject(
|
|
382
|
+
return Promise.reject('errUserRoleMissing')
|
|
344
383
|
}
|
|
345
384
|
return true
|
|
346
385
|
}
|
|
@@ -356,14 +395,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
356
395
|
}
|
|
357
396
|
|
|
358
397
|
//check
|
|
359
|
-
|
|
360
|
-
// if (!iseobj(userSelf)) {
|
|
361
|
-
// console.log(`token`, token)
|
|
362
|
-
// console.log(`can not find the user from token`)
|
|
363
|
-
// return Promise.reject(`can not find the user from token`)
|
|
364
|
-
// }
|
|
365
|
-
await checkUser(userSelf)
|
|
366
|
-
}
|
|
398
|
+
await checkUser(userSelf)
|
|
367
399
|
|
|
368
400
|
return userSelf
|
|
369
401
|
}
|
|
@@ -402,9 +434,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
402
434
|
if (!b) {
|
|
403
435
|
console.log('user', user)
|
|
404
436
|
console.log(`user does not have permission`)
|
|
405
|
-
return Promise.reject(
|
|
437
|
+
return Promise.reject('errUserNoPermission')
|
|
406
438
|
}
|
|
407
439
|
|
|
440
|
+
srLog.info({ event: 'verifyClientUser', from, userId: get(user, 'id', '') }) //瀏覽使用者驗證通過
|
|
408
441
|
return user
|
|
409
442
|
}
|
|
410
443
|
|
|
@@ -427,7 +460,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
427
460
|
if (!iseobj(user)) {
|
|
428
461
|
console.log(`token`, token)
|
|
429
462
|
console.log(`can not find the user from token`)
|
|
430
|
-
return Promise.reject(
|
|
463
|
+
return Promise.reject('errUserNotFound')
|
|
431
464
|
}
|
|
432
465
|
|
|
433
466
|
//verifyAppUser
|
|
@@ -440,9 +473,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
440
473
|
if (!b) {
|
|
441
474
|
console.log('user', user)
|
|
442
475
|
console.log(`user does not have permission`)
|
|
443
|
-
return Promise.reject(
|
|
476
|
+
return Promise.reject('errUserNoPermission')
|
|
444
477
|
}
|
|
445
478
|
|
|
479
|
+
srLog.info({ event: 'verifyAppUser', from, userId: get(user, 'id', '') }) //應用程式使用者驗證通過
|
|
446
480
|
return user
|
|
447
481
|
}
|
|
448
482
|
|
|
@@ -469,7 +503,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
469
503
|
if (!iseobj(payload)) {
|
|
470
504
|
console.log('payload', payload)
|
|
471
505
|
console.log(`invalid payload in req`)
|
|
472
|
-
return Promise.reject(
|
|
506
|
+
return Promise.reject('errPayloadInvalid')
|
|
473
507
|
}
|
|
474
508
|
|
|
475
509
|
//group
|
|
@@ -479,7 +513,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
479
513
|
if (!isestr(group)) {
|
|
480
514
|
console.log('payload', payload)
|
|
481
515
|
console.log(`invalid group in payload`)
|
|
482
|
-
return Promise.reject(
|
|
516
|
+
return Promise.reject('errGroupInvalid')
|
|
483
517
|
}
|
|
484
518
|
|
|
485
519
|
//rows
|
|
@@ -489,7 +523,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
489
523
|
if (!isearr(rows)) {
|
|
490
524
|
console.log('payload', payload)
|
|
491
525
|
console.log(`invalid rows in payload`)
|
|
492
|
-
return Promise.reject(
|
|
526
|
+
return Promise.reject('errRowsInvalid')
|
|
493
527
|
}
|
|
494
528
|
|
|
495
529
|
//r
|
|
@@ -529,7 +563,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
529
563
|
console.log('inp', inp)
|
|
530
564
|
console.log('group', group)
|
|
531
565
|
console.log(`invalid group`)
|
|
532
|
-
return Promise.reject(
|
|
566
|
+
return Promise.reject('errGroupInvalid')
|
|
533
567
|
}
|
|
534
568
|
|
|
535
569
|
//rows
|
|
@@ -540,7 +574,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
540
574
|
if (!isearr(rows)) {
|
|
541
575
|
console.log('inp', inp)
|
|
542
576
|
console.log('keyTable', keyTable)
|
|
543
|
-
return Promise.reject(
|
|
577
|
+
return Promise.reject('errRowsInvalid')
|
|
544
578
|
}
|
|
545
579
|
|
|
546
580
|
//save from
|
|
@@ -611,6 +645,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
611
645
|
c = replace(c, '/mapi/', '{sfd}/') //方法同genEntry
|
|
612
646
|
c = replace(c, '{sfd}', subfolder)
|
|
613
647
|
c = replace(c, '{urlRedirect}', urlRedirect)
|
|
648
|
+
c = replace(c, '{language}', language) //注入初始語系 → window.___pmwperm___.language(前端 getLang 之來源之一)
|
|
614
649
|
fs.writeFileSync(fpEntryOut, c, 'utf8')
|
|
615
650
|
}
|
|
616
651
|
catch (err) {
|
|
@@ -636,10 +671,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
636
671
|
//check
|
|
637
672
|
if (!isestr(token)) {
|
|
638
673
|
console.log('req.query', get(req, 'query'))
|
|
639
|
-
console.log('token', token)
|
|
674
|
+
console.log('token', maskTok(token))
|
|
640
675
|
console.log('[API]getUserByToken/check token: invalid token')
|
|
641
|
-
|
|
642
|
-
return Promise.reject(`token does not have permission`)
|
|
676
|
+
return Promise.reject('errTokenNoPermission')
|
|
643
677
|
}
|
|
644
678
|
|
|
645
679
|
//getAndVerifyClientUser
|
|
@@ -647,12 +681,12 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
647
681
|
|
|
648
682
|
//check
|
|
649
683
|
if (!iseobj(user)) {
|
|
650
|
-
console.log('token', token)
|
|
684
|
+
console.log('token', maskTok(token))
|
|
651
685
|
console.log('[API]getUserByToken/check user: invalid user')
|
|
652
|
-
|
|
653
|
-
return Promise.reject(`token does not have permission`)
|
|
686
|
+
return Promise.reject('errTokenNoPermission')
|
|
654
687
|
}
|
|
655
688
|
|
|
689
|
+
srLog.info({ event: 'api/getUserByToken', userId: get(user, 'id', '') })
|
|
656
690
|
return user
|
|
657
691
|
}
|
|
658
692
|
|
|
@@ -683,8 +717,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
683
717
|
// console.log('req.query', get(req, 'query'))
|
|
684
718
|
// console.log('token', token)
|
|
685
719
|
// console.log('[API]getAPIsList/check token: invalid token')
|
|
686
|
-
//
|
|
687
|
-
// return Promise.reject(`token does not have permission`)
|
|
720
|
+
// return Promise.reject('errTokenNoPermission')
|
|
688
721
|
// }
|
|
689
722
|
|
|
690
723
|
// //getAndVerifyClientUser
|
|
@@ -694,8 +727,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
694
727
|
// if (!iseobj(user)) {
|
|
695
728
|
// console.log('token', token)
|
|
696
729
|
// console.log('[API]getAPIsList/check user: invalid user')
|
|
697
|
-
//
|
|
698
|
-
// return Promise.reject(`token does not have permission`)
|
|
730
|
+
// return Promise.reject('errTokenNoPermission')
|
|
699
731
|
// }
|
|
700
732
|
|
|
701
733
|
// //getAPIsList
|
|
@@ -732,8 +764,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
732
764
|
// console.log('req.query', get(req, 'query'))
|
|
733
765
|
// console.log('token', token)
|
|
734
766
|
// console.log('[API]updateAPIs/check token: invalid token')
|
|
735
|
-
//
|
|
736
|
-
// return Promise.reject(`token does not have permission`)
|
|
767
|
+
// return Promise.reject('errTokenNoPermission')
|
|
737
768
|
// }
|
|
738
769
|
|
|
739
770
|
// //getAndVerifyClientUser
|
|
@@ -743,8 +774,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
743
774
|
// if (!iseobj(user)) {
|
|
744
775
|
// console.log('token', token)
|
|
745
776
|
// console.log('[API]updateAPIs/check user: invalid user')
|
|
746
|
-
//
|
|
747
|
-
// return Promise.reject(`token does not have permission`)
|
|
777
|
+
// return Promise.reject('errTokenNoPermission')
|
|
748
778
|
// }
|
|
749
779
|
|
|
750
780
|
// //parsePayload
|
|
@@ -782,10 +812,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
782
812
|
//check
|
|
783
813
|
if (!isestr(token)) {
|
|
784
814
|
console.log('req.query', get(req, 'query'))
|
|
785
|
-
console.log('token', token)
|
|
815
|
+
console.log('token', maskTok(token))
|
|
786
816
|
console.log('[API]syncAndReplaceTabs/check token: invalid token')
|
|
787
|
-
|
|
788
|
-
return Promise.reject(`token does not have permission`)
|
|
817
|
+
return Promise.reject('errTokenNoPermission')
|
|
789
818
|
}
|
|
790
819
|
|
|
791
820
|
//keyTable
|
|
@@ -796,15 +825,14 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
796
825
|
console.log('req.query', get(req, 'query'))
|
|
797
826
|
console.log('keyTable', keyTable)
|
|
798
827
|
console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable')
|
|
799
|
-
|
|
800
|
-
return Promise.reject(`token does not have permission`)
|
|
828
|
+
return Promise.reject('errKeyTableInvalid')
|
|
801
829
|
}
|
|
802
830
|
|
|
803
831
|
//check keyTable
|
|
804
832
|
let allowedTables = ['apis']
|
|
805
833
|
if (!allowedTables.includes(keyTable)) {
|
|
806
834
|
console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable)
|
|
807
|
-
return Promise.reject(
|
|
835
|
+
return Promise.reject('errKeyTableInvalid')
|
|
808
836
|
}
|
|
809
837
|
|
|
810
838
|
//getAndVerifyAppUser
|
|
@@ -812,10 +840,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
812
840
|
|
|
813
841
|
//check
|
|
814
842
|
if (!iseobj(user)) {
|
|
815
|
-
console.log('token', token)
|
|
843
|
+
console.log('token', maskTok(token))
|
|
816
844
|
console.log('[API]syncAndReplaceTabs/check user: invalid user')
|
|
817
|
-
|
|
818
|
-
return Promise.reject(`token does not have permission`)
|
|
845
|
+
return Promise.reject('errTokenNoPermission')
|
|
819
846
|
}
|
|
820
847
|
|
|
821
848
|
//userId
|
|
@@ -823,11 +850,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
823
850
|
|
|
824
851
|
//check userId
|
|
825
852
|
if (!isestr(userId)) {
|
|
826
|
-
console.log('token', token)
|
|
853
|
+
console.log('token', maskTok(token))
|
|
827
854
|
console.log('user', user)
|
|
828
855
|
console.log('[API]syncAndReplaceTabs/check userId: invalid userId')
|
|
829
|
-
|
|
830
|
-
return Promise.reject(`token does not have permission`)
|
|
856
|
+
return Promise.reject('errTokenNoPermission')
|
|
831
857
|
}
|
|
832
858
|
|
|
833
859
|
//parsePayload
|
|
@@ -836,6 +862,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
836
862
|
//syncAndReplaceTabs
|
|
837
863
|
let r = await syncAndReplaceTabs(userId, inp, keyTable)
|
|
838
864
|
|
|
865
|
+
srLog.info({ event: 'api/syncAndReplaceTabs', userId, keyTable })
|
|
839
866
|
return r
|
|
840
867
|
}
|
|
841
868
|
|
|
@@ -863,7 +890,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
863
890
|
|
|
864
891
|
//WServHapiServer
|
|
865
892
|
instWServHapiServer = new WServHapiServer({
|
|
866
|
-
port:
|
|
893
|
+
port: serverPort,
|
|
867
894
|
pathStaticFiles,
|
|
868
895
|
apiName: 'api',
|
|
869
896
|
apis,
|
|
@@ -878,28 +905,28 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
878
905
|
//check
|
|
879
906
|
if (!isestr(token)) {
|
|
880
907
|
console.log('apiType', apiType)
|
|
881
|
-
console.log('authorization', authorization)
|
|
908
|
+
console.log('authorization', maskTok(authorization))
|
|
882
909
|
console.log('invalid token')
|
|
883
910
|
return false
|
|
884
911
|
}
|
|
885
912
|
|
|
886
|
-
//checkToken
|
|
913
|
+
//checkToken:套件層連線閘僅做「token 認證」(解析 user + 驗欄位齊備)。**授權**(如限管理員)屬
|
|
914
|
+
//套件使用者之責——由其提供之 getUserByToken(可對非授權者回 {})/ verifyClientUser / verifyAppUser,
|
|
915
|
+
//或 WServOrm 之 useCheckUser/useExcludeWhenNotAdmin 等鉤子決定;套件不對連線層強加特定授權政策(避免越界、
|
|
916
|
+
//保留使用者彈性)。詳見 spec/設計要點與取捨.md「套件授權責任」。
|
|
887
917
|
let b = await p.checkToken(token)
|
|
888
|
-
// console.log('b', b)
|
|
889
918
|
|
|
919
|
+
srLog.info({ event: 'verifyConn', apiType }) //連線之 token 認證通過(checkToken 失敗會 throw 不到此)
|
|
890
920
|
return b
|
|
891
921
|
},
|
|
892
922
|
getUserIdByToken: async (token) => { //可使用async或sync函數
|
|
893
923
|
// console.log('getUserIdByToken', token)
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
// return Promise.reject(`can not find user.id`)
|
|
901
|
-
// }
|
|
902
|
-
// return userId
|
|
924
|
+
if (!isestr(token)) {
|
|
925
|
+
return ''
|
|
926
|
+
}
|
|
927
|
+
let user = await getUserByToken(token)
|
|
928
|
+
let userId = get(user, 'id', '')
|
|
929
|
+
return userId
|
|
903
930
|
},
|
|
904
931
|
useDbOrm: true,
|
|
905
932
|
kpOrm: woItems,
|
|
@@ -907,9 +934,29 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
|
|
|
907
934
|
tableNamesExec,
|
|
908
935
|
methodsExec: ['select', 'insert', 'save', 'del'], //mix需於procOrm內註冊以提供
|
|
909
936
|
tableNamesSync,
|
|
910
|
-
kpFunExt: { //接收參數第1個為userId,
|
|
911
|
-
|
|
912
|
-
getWebInfor,
|
|
937
|
+
kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數(皆經 wrapErrLog:錯誤 srLog err-key 後 re-reject)
|
|
938
|
+
|
|
939
|
+
getWebInfor: wrapErrLog('getWebInfor', getWebInfor),
|
|
940
|
+
|
|
941
|
+
proxyRequest: wrapErrLog('proxyRequest', (userId, reqSpec) => {
|
|
942
|
+
return proxyRequest(reqSpec)
|
|
943
|
+
}),
|
|
944
|
+
|
|
945
|
+
getApisList: wrapErrLog('getApisList', (userId) => {
|
|
946
|
+
return getApisList(userId)
|
|
947
|
+
}),
|
|
948
|
+
saveApi: wrapErrLog('saveApi', (userId, row) => {
|
|
949
|
+
return saveApi(userId, row)
|
|
950
|
+
}),
|
|
951
|
+
deleteApi: wrapErrLog('deleteApi', (userId, id) => {
|
|
952
|
+
return deleteApi(userId, id)
|
|
953
|
+
}),
|
|
954
|
+
|
|
955
|
+
//統計資訊頁:回傳各 event 之時段發生頻率(讀 logFd 之 log)。連線之 token 認證由 verifyConn 把關;
|
|
956
|
+
//授權(限管理員)屬套件使用者責任(見 verifyConn 註解與設計要點與取捨「套件授權責任」)。timeLength 天數 / timeInterval 'hr'|'day'。
|
|
957
|
+
getStaEvent: wrapErrLog('getStaEvent', (userId, timeLength = 7, timeInterval = 'hr') => {
|
|
958
|
+
return staEvent(timeLength, timeInterval, { fdLog: logFd })
|
|
959
|
+
}),
|
|
913
960
|
|
|
914
961
|
// getAPIsList: (userId, query = {}) => { //待提供api管理系統界面使用
|
|
915
962
|
// return getAPIsList(query)
|
|
@@ -942,7 +989,7 @@ export default WWebApi
|
|
|
942
989
|
<br class="clear">
|
|
943
990
|
|
|
944
991
|
<footer>
|
|
945
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.
|
|
992
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
946
993
|
</footer>
|
|
947
994
|
|
|
948
995
|
<script>prettyPrint();</script>
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>src/components/Common/CheckYesNo.vue - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebApi.html">WWebApi</a></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">src/components/Common/CheckYesNo.vue</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code><template>
|
|
49
|
+
<WConfirm
|
|
50
|
+
:show.sync="bShow"
|
|
51
|
+
:title="$t('systemMessage')"
|
|
52
|
+
:content="content"
|
|
53
|
+
:_contentColor="'white'"
|
|
54
|
+
:_contentIconColor="'white'"
|
|
55
|
+
:_contentBackgroundColor="'orange lighten-5'"
|
|
56
|
+
:_titleColor="'white'"
|
|
57
|
+
:headerBackgroundColor="'grey lighten-3'"
|
|
58
|
+
:noBtnText="$t('no')"
|
|
59
|
+
:yesBtnText="$t('yes')"
|
|
60
|
+
@click-no="clickBtn(false)"
|
|
61
|
+
@click-yes="clickBtn(true)"
|
|
62
|
+
></WConfirm>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script>
|
|
66
|
+
import Vue from 'vue'
|
|
67
|
+
import genPm from 'wsemi/src/genPm.mjs'
|
|
68
|
+
import WConfirm from 'w-component-vue/src/components/WConfirm.vue'
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
components: {
|
|
72
|
+
WConfirm,
|
|
73
|
+
},
|
|
74
|
+
props: {
|
|
75
|
+
},
|
|
76
|
+
data: function() {
|
|
77
|
+
return {
|
|
78
|
+
|
|
79
|
+
bShow: false,
|
|
80
|
+
pm: null,
|
|
81
|
+
|
|
82
|
+
content: '',
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
mounted: function() {
|
|
87
|
+
//console.log('mounted')
|
|
88
|
+
|
|
89
|
+
let vo = this
|
|
90
|
+
|
|
91
|
+
//set
|
|
92
|
+
Vue.prototype.$dg.showCheckYesNo = vo.show
|
|
93
|
+
|
|
94
|
+
},
|
|
95
|
+
computed: {
|
|
96
|
+
},
|
|
97
|
+
methods: {
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 顯示 Yes/No 確認對話框並回傳 Promise。
|
|
101
|
+
*
|
|
102
|
+
* **Contract** (caller 須遵守):
|
|
103
|
+
* - 使用者點 **Yes** → Promise `resolve()` (無值, 進 `.then()`)
|
|
104
|
+
* - 使用者點 **No** → Promise `reject('close')` (進 `.catch(err => err === 'close')`)
|
|
105
|
+
*
|
|
106
|
+
* 正確 caller pattern:
|
|
107
|
+
*
|
|
108
|
+
* vo.$dg.showCheckYesNo('確定要 X?')
|
|
109
|
+
* .then(() => {
|
|
110
|
+
* //使用者點 Yes
|
|
111
|
+
* doX()
|
|
112
|
+
* })
|
|
113
|
+
* .catch((err) => {
|
|
114
|
+
* //使用者點 No (err === 'close') 為正常路徑, 靜默處理
|
|
115
|
+
* if (err === 'close') return
|
|
116
|
+
* //非預期錯誤 (CheckYesNo 本身故障等)
|
|
117
|
+
* console.log('showCheckYesNo unexpected error', err)
|
|
118
|
+
* })
|
|
119
|
+
*
|
|
120
|
+
* @param {string} content - 顯示在 modal 中的訊息文字
|
|
121
|
+
* @returns {Promise<void>} Yes → resolve(); No → reject('close')
|
|
122
|
+
*/
|
|
123
|
+
show: function(content) {
|
|
124
|
+
//console.log('methods show', content)
|
|
125
|
+
|
|
126
|
+
let vo = this
|
|
127
|
+
|
|
128
|
+
//pm
|
|
129
|
+
vo.pm = genPm()
|
|
130
|
+
|
|
131
|
+
//save
|
|
132
|
+
vo.content = content
|
|
133
|
+
|
|
134
|
+
//show
|
|
135
|
+
vo.bShow = true
|
|
136
|
+
|
|
137
|
+
return vo.pm
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
clickBtn: function(mode) {
|
|
141
|
+
//console.log('methods clickBtn', mode)
|
|
142
|
+
|
|
143
|
+
let vo = this
|
|
144
|
+
|
|
145
|
+
if (mode) {
|
|
146
|
+
vo.pm.resolve()
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
vo.pm.reject('close')
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
//hide
|
|
153
|
+
vo.bShow = false
|
|
154
|
+
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<style scoped>
|
|
162
|
+
</style>
|
|
163
|
+
</code></pre>
|
|
164
|
+
</article>
|
|
165
|
+
</section>
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<br class="clear">
|
|
175
|
+
|
|
176
|
+
<footer>
|
|
177
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
178
|
+
</footer>
|
|
179
|
+
|
|
180
|
+
<script>prettyPrint();</script>
|
|
181
|
+
<script src="scripts/polyfill.js"></script>
|
|
182
|
+
<script src="scripts/linenumber.js"></script>
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
</body>
|
|
187
|
+
</html>
|
package/g.getSettings.mjs
CHANGED
|
@@ -12,6 +12,9 @@ function getSettings() {
|
|
|
12
12
|
// 'dbPort': 27017,
|
|
13
13
|
'dbUrl': './db',
|
|
14
14
|
'dbName': 'wapis',
|
|
15
|
+
'ssoBaseUrl': 'http://localhost:11007',
|
|
16
|
+
'ssoAppToken': '', //部署時填入SSO tokens表中isApp=y的app token
|
|
17
|
+
'ssoLoginUrl': 'http://localhost:11007/', //未登入時導向之SSO登入頁
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{"level":50,"time":1781856410899,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
|
|
2
|
+
{"level":50,"time":1781856420503,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
|
|
3
|
+
{"level":50,"time":1781856490388,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
|
|
4
|
+
{"level":50,"time":1781856524374,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
|
|
5
|
+
{"level":50,"time":1781856931047,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
|
|
6
|
+
{"level":50,"time":1781856965662,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
|