w-web-perm 1.0.48 → 1.0.50

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 (111) hide show
  1. package/.github/workflows/ci-test.yml +2 -2
  2. package/README.md +5 -5
  3. package/dist/css/app.8781355a.css +1 -0
  4. package/dist/css/{chunk-vendors.f149e124.css → chunk-vendors.58917286.css} +1 -1
  5. package/dist/index.tmp +2 -2
  6. package/dist/js/app-legacy.b2754bb1.js +1 -0
  7. package/dist/js/app.b2754bb1.js +1 -0
  8. package/dist/js/chunk-vendors-legacy.c14a1ed1.js +21 -0
  9. package/dist/js/chunk-vendors.c14a1ed1.js +21 -0
  10. package/dist/w-web-perm.umd.js +2 -2
  11. package/dist/w-web-perm.umd.js.map +1 -1
  12. package/docs/WWebPerm.html +3 -3
  13. package/docs/WWebPerm.mjs.html +162 -210
  14. package/docs/index.html +1 -1
  15. package/logs/2026-06-19T16.log +191 -0
  16. package/logs/2026-06-19T23.log +0 -0
  17. package/logs/2026-06-20T00.log +207 -0
  18. package/logs/2026-06-20T11.log +221 -0
  19. package/logs/2026-06-20T12.log +146 -0
  20. package/logs/2026-06-20T13.log +134 -0
  21. package/logs/2026-06-20T14.log +296 -0
  22. package/logs/2026-06-20T15.log +225 -0
  23. package/logs/2026-06-20T16.log +174 -0
  24. package/logs/2026-06-21T16.log +110 -0
  25. package/logs/2026-06-21T17.log +301 -0
  26. package/logs/2026-06-21T18.log +238 -0
  27. package/logs/2026-06-21T19.log +141 -0
  28. package/logs/2026-06-21T20.log +99 -0
  29. package/logs/2026-06-21T21.log +143 -0
  30. package/logs/2026-06-21T23.log +26 -0
  31. package/logs/2026-06-22T00.log +33 -0
  32. package/logs/2026-06-22T08.log +235 -0
  33. package/logs/2026-06-22T09.log +246 -0
  34. package/logs/2026-06-22T10.log +301 -0
  35. package/logs/2026-06-22T11.log +140 -0
  36. package/logs/2026-06-22T12.log +22 -0
  37. package/logs/2026-06-22T14.log +44 -0
  38. package/logs/2026-06-22T23.log +951 -0
  39. package/logs/2026-06-23T00.log +263 -0
  40. package/logs/2026-06-23T08.log +611 -0
  41. package/logs/2026-06-30T21.log +3609 -0
  42. package/logs/2026-06-30T22.log +3682 -0
  43. package/logs/2026-06-30T23.log +592 -0
  44. package/logs/2026-07-01T12.log +0 -0
  45. package/logs/2026-07-09T22.log +2220 -0
  46. package/logs/2026-07-09T23.log +1140 -0
  47. package/logs/2026-07-10T12.log +6 -0
  48. package/logs/2026-07-10T13.log +351 -0
  49. package/logs/2026-07-10T16.log +1272 -0
  50. package/logs/2026-07-10T19.log +6 -0
  51. package/logs/2026-07-10T20.log +1883 -0
  52. package/logs/2026-07-10T21.log +3505 -0
  53. package/logs/2026-07-10T22.log +3395 -0
  54. package/logs/2026-07-11T00.log +1338 -0
  55. package/logs/2026-07-11T01.log +2492 -0
  56. package/logs/2026-07-11T17.log +19 -0
  57. package/package.json +23 -16
  58. package/public/index.html +2 -2
  59. package/server/WWebPerm.mjs +161 -209
  60. package/server/procCore.mjs +187 -0
  61. package/server/procLang.mjs +276 -60
  62. package/server/procStaInfor.mjs +128 -0
  63. package/server/provideTabs.mjs +1 -1
  64. package/server/srLog.mjs +30 -0
  65. package/server/staLogs/filterVpfsByWindow.mjs +27 -0
  66. package/server/staLogs/staEvent.callWorker.mjs +46 -0
  67. package/server/staLogs/staEvent.mjs +118 -0
  68. package/server/staLogs/staEvent.shellWorker.mjs +19 -0
  69. package/server/staLogs/staEventTable.mjs +102 -0
  70. package/settings.json +43 -0
  71. package/src/components/Common/CheckYes.vue +18 -1
  72. package/src/components/Layout.vue +1 -1
  73. package/src/components/LayoutContent.vue +13 -3
  74. package/src/components/LayoutContentGrups.vue +32 -25
  75. package/src/components/LayoutContentPemis.vue +32 -25
  76. package/src/components/LayoutContentStaInfor.vue +534 -0
  77. package/src/components/LayoutContentTargets.vue +35 -28
  78. package/src/components/LayoutContentUsers.vue +32 -25
  79. package/src/components/LayoutState.vue +5 -0
  80. package/src/components/VeCgrups.vue +19 -9
  81. package/src/components/VeCpemis.vue +19 -9
  82. package/src/components/VeCrules.vue +19 -9
  83. package/src/components/VeGrupBlngUsers.vue +35 -29
  84. package/src/components/VePemiBlngGrups.vue +35 -29
  85. package/src/getPerm.mjs +7 -17
  86. package/src/getPermUserInfor.mjs +8 -18
  87. package/src/main.js +4 -9
  88. package/src/perm.mjs +3 -4
  89. package/src/plugins/mShare.mjs +8 -13
  90. package/src/plugins/mUI.mjs +7 -44
  91. package/src/store/mutations.mjs +0 -10
  92. package/src/store/types.mjs +0 -2
  93. package/srv.mjs +76 -101
  94. package/tableTags.json +1 -1
  95. package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +450 -0
  96. package/db/wperm/grups/data.mdb +0 -0
  97. package/db/wperm/grups/lock.mdb +0 -0
  98. package/db/wperm/pemis/data.mdb +0 -0
  99. package/db/wperm/pemis/lock.mdb +0 -0
  100. package/db/wperm/targets/data.mdb +0 -0
  101. package/db/wperm/targets/lock.mdb +0 -0
  102. package/db/wperm/users/data.mdb +0 -0
  103. package/db/wperm/users/lock.mdb +0 -0
  104. package/dist/css/app.30e81bfe.css +0 -1
  105. package/dist/js/app-legacy.3324392e.js +0 -1
  106. package/dist/js/app.3324392e.js +0 -1
  107. package/dist/js/chunk-vendors-legacy.e8703728.js +0 -21
  108. package/dist/js/chunk-vendors.e8703728.js +0 -21
  109. package/src/plugins/mDataSelectorSchema.mjs +0 -30
  110. package/tableTags-web-perm.json +0 -1
  111. package/test/getUserRules.test.mjs +0 -899
@@ -12,13 +12,13 @@ async function getPermUserInfor(url, tokenSelf, userIdTar, opt = {}) {
12
12
 
13
13
  //check
14
14
  if (!isestr(url)) {
15
- return Promise.reject('invalid url')
15
+ return Promise.reject('invalidUrl')
16
16
  }
17
17
  if (!isestr(tokenSelf)) {
18
- return Promise.reject('invalid tokenSelf')
18
+ return Promise.reject('invalidTokenSelf')
19
19
  }
20
20
  if (!isestr(userIdTar)) {
21
- return Promise.reject('invalid userIdTar')
21
+ return Promise.reject('invalidUserIdTar')
22
22
  }
23
23
 
24
24
  //funConvertPerm
@@ -26,7 +26,7 @@ async function getPermUserInfor(url, tokenSelf, userIdTar, opt = {}) {
26
26
 
27
27
  //url
28
28
  if (url.indexOf('token={sysToken}') < 0 && url.indexOf('userId={userId}') < 0) {
29
- return Promise.reject(`no 'token={sysToken}', 'userId={userId}' in url`)
29
+ return Promise.reject('noTokenUserIdInUrl')
30
30
  }
31
31
  url = url.replaceAll('{sysToken}', tokenSelf) //系統介接用permToken
32
32
  url = url.replaceAll('{userId}', userIdTar)
@@ -40,10 +40,7 @@ async function getPermUserInfor(url, tokenSelf, userIdTar, opt = {}) {
40
40
 
41
41
  //check
42
42
  if (errTemp !== null) {
43
- console.log('res', res)
44
- console.log('errTemp', errTemp)
45
- console.log(`can not get user by url[${url}]`)
46
- return Promise.reject(`can not get user by url[${url}]`) //由SSO取得使用者資訊錯誤
43
+ return Promise.reject('cannotGetUserByUrl') //由SSO取得使用者資訊錯誤
47
44
  }
48
45
 
49
46
  //data
@@ -57,12 +54,7 @@ async function getPermUserInfor(url, tokenSelf, userIdTar, opt = {}) {
57
54
 
58
55
  //check
59
56
  if (state !== 'success') {
60
- console.log('res', res)
61
- console.log('data', data)
62
- console.log('state', state)
63
- console.log('errTemp', msg)
64
- console.log(`can not get user data by url[${url}]`)
65
- return Promise.reject(`can not get user data by url[${url}]`) //取得使用者資訊失敗
57
+ return Promise.reject('cannotGetUserDataByUrl') //取得使用者資訊失敗
66
58
  }
67
59
 
68
60
  //ur
@@ -71,8 +63,7 @@ async function getPermUserInfor(url, tokenSelf, userIdTar, opt = {}) {
71
63
 
72
64
  //check
73
65
  if (!iseobj(ur)) {
74
- console.log(`no user data by url[${url}]`)
75
- return Promise.reject(`no user data by url[${url}]`)
66
+ return Promise.reject('noUserDataByUrl')
76
67
  }
77
68
 
78
69
  //check
@@ -87,8 +78,7 @@ async function getPermUserInfor(url, tokenSelf, userIdTar, opt = {}) {
87
78
 
88
79
  //check
89
80
  if (!iseobj(ur)) {
90
- console.log(`no user data after funConvertPerm`)
91
- return Promise.reject(`no user data after funConvertPerm`)
81
+ return Promise.reject('noUserDataAfterConvert')
92
82
  }
93
83
 
94
84
  }
package/src/main.js CHANGED
@@ -2,13 +2,10 @@ import Vue from 'vue'
2
2
  import get from 'lodash-es/get.js'
3
3
  import WServHapiClient from 'w-serv-hapi/src/WServHapiClient.mjs'
4
4
  import WAlert from 'w-component-vue/src/components/WAlert.mjs'
5
- import domMutation from 'w-component-vue/src/js/domMutation.mjs'
6
5
  import domResize from 'w-component-vue/src/js/domResize.mjs'
7
- import domDragDrop from 'w-component-vue/src/js/domDragDrop.mjs'
8
6
  import App from './App.vue'
9
7
  import store from './store/index.mjs'
10
8
  import ui from './plugins/mUI.mjs'
11
- import mDataSelectorSchema from './plugins/mDataSelectorSchema.mjs'
12
9
  import * as s from './plugins/mShare.mjs'
13
10
  import ds from './schema/index.mjs'
14
11
  // console.log('ds', ds)
@@ -26,21 +23,16 @@ Vue.prototype.$alert = function() {
26
23
  }
27
24
  }
28
25
 
29
- //dssm
30
- let dssm = mDataSelectorSchema(ds)
31
-
32
26
  //prototype
33
27
  Vue.prototype.$ui = ui
34
28
  Vue.prototype.$t = ui.getKpText
29
+ Vue.prototype.$tErr = ui.tErr
35
30
  Vue.prototype.$s = s
36
- Vue.prototype.$dssm = dssm
37
31
  Vue.prototype.$ds = ds
38
32
  Vue.prototype.$dg = {}
39
33
 
40
34
  //directive
41
35
  Vue.directive('domresize', domResize())
42
- Vue.directive('dommutation', domMutation())
43
- Vue.directive('domdragdrop', domDragDrop())
44
36
 
45
37
  //WServHapiClient
46
38
  // let bFirstSync = false //不需要bFirstSync, 由getWebInfor結束代表第1次完成同步
@@ -75,6 +67,9 @@ WServHapiClient({
75
67
  })
76
68
  .catch((err) => {
77
69
  console.log(err)
70
+ //getWebInfor 失敗時, connState 已為 csLogin 但 webInfor 為空 → ready 永遠為 false 會永久卡「已登入」轉圈畫面.
71
+ //改落到 csErrConn, 讓 LayoutState 顯示「無法連線」狀態畫面 (使用者可見錯誤而非靜默卡死).
72
+ ui.updateConnState('csErrConn')
78
73
  })
79
74
 
80
75
  },
package/src/perm.mjs CHANGED
@@ -23,12 +23,11 @@ function perm() {
23
23
  if (!isestr(url)) {
24
24
  throw new Error(`invalid url`)
25
25
  }
26
- if (url.indexOf('token=') === 0) {
26
+ if (url.indexOf('token=') < 0) {
27
27
  throw new Error(`url does not include 'token='`)
28
28
  }
29
- if (url.indexOf('userId=') === 0) {
30
- throw new Error(`url does not include 'userId='`)
31
- }
29
+ //註: conn() 為通用連線, getPerm 之 url 僅含 token=、getPermUserInfor 才含 userId=,
30
+ //故此處不強制 userId=(端點專屬之 userId 驗證由後端對應 handler 負責)。
32
31
 
33
32
  //permSuccess
34
33
  let permSuccess = get(opt, 'permSuccess')
@@ -479,25 +479,20 @@ function getUserRules(user, grups, pemis, targets) {
479
479
  }
480
480
  // console.log('merge _rules', cloneDeep(_rules))
481
481
 
482
- //expand _rules
482
+ //expand _rules:以「當前 targets」為輸出主軸——逐 target 取其解析後 isActive(取自合併 crules 的 kp、預設 'n')。
483
+ //如此只列現存管控對象;crules 仍引用但已從 targets 刪除的「孤兒 target」自然被濾掉,不再殘留於權限樹。
484
+ //(修正前:輸出 kp 全部 keys = crules keys ∪ targets,導致已刪 target 因 crules 殘留引用而仍出現在權限樹。)
483
485
  if (true) {
484
486
  let kp = {}
485
487
  each(_rules, (v) => {
486
488
  kp[v.name] = v.isActive
487
489
  })
488
- each(targets, (t) => {
489
- // console.log('t', t)
490
- if (!haskey(kp, t.id)) {
491
- kp[t.id] = 'n'
492
- }
493
- })
494
490
  let rs = []
495
- each(kp, (v, k) => {
496
- let r = {
497
- name: k,
498
- isActive: v,
499
- }
500
- rs.push(r)
491
+ each(targets, (t) => {
492
+ rs.push({
493
+ name: t.id,
494
+ isActive: get(kp, t.id, 'n'),
495
+ })
501
496
  })
502
497
  _rules = rs
503
498
  }
@@ -1,45 +1,11 @@
1
1
  import Vue from 'vue'
2
- import min from 'lodash-es/min.js'
3
- import size from 'lodash-es/size.js'
4
- import take from 'lodash-es/take.js'
5
- import isEqual from 'lodash-es/isEqual.js'
6
- import uniq from 'lodash-es/uniq.js'
7
- import set from 'lodash-es/set.js'
8
2
  import get from 'lodash-es/get.js'
9
3
  import each from 'lodash-es/each.js'
10
- import map from 'lodash-es/map.js'
11
- import filter from 'lodash-es/filter.js'
12
- import last from 'lodash-es/last.js'
13
- import split from 'lodash-es/split.js'
14
- import join from 'lodash-es/join.js'
15
- import drop from 'lodash-es/drop.js'
16
- import dropRight from 'lodash-es/dropRight.js'
17
- import groupBy from 'lodash-es/groupBy.js'
18
- import sortBy from 'lodash-es/sortBy.js'
19
4
  import cloneDeep from 'lodash-es/cloneDeep.js'
20
- import cint from 'wsemi/src/cint.mjs'
21
5
  import delay from 'wsemi/src/delay.mjs'
22
- import isarr from 'wsemi/src/isarr.mjs'
23
6
  import isestr from 'wsemi/src/isestr.mjs'
24
7
  import isfun from 'wsemi/src/isfun.mjs'
25
- import isearr from 'wsemi/src/isearr.mjs'
26
- import isEle from 'wsemi/src/isEle.mjs'
27
- import strleft from 'wsemi/src/strleft.mjs'
28
- import strdelleft from 'wsemi/src/strdelleft.mjs'
29
- import sep from 'wsemi/src/sep.mjs'
30
- import aes2str from 'wsemi/src/aes2str.mjs'
31
- import str2aes from 'wsemi/src/str2aes.mjs'
32
- import haskey from 'wsemi/src/haskey.mjs'
33
- import genPm from 'wsemi/src/genPm.mjs'
34
- import pmSeries from 'wsemi/src/pmSeries.mjs'
35
8
  import waitFun from 'wsemi/src/waitFun.mjs'
36
- import browserView from 'wsemi/src/browserView.mjs'
37
- import arrHas from 'wsemi/src/arrHas.mjs'
38
- import arrSort from 'wsemi/src/arrSort.mjs'
39
- import arrInsert from 'wsemi/src/arrInsert.mjs'
40
- import replace from 'wsemi/src/replace.mjs'
41
- import timemsTZ2past from 'wsemi/src/timemsTZ2past.mjs'
42
- import convertToTree from 'wsemi/src/convertToTree.mjs'
43
9
  // import WUiDwload from 'w-ui-dwload/src/WUiDwload.mjs'
44
10
 
45
11
 
@@ -215,16 +181,13 @@ function getKpText(key) {
215
181
  }
216
182
 
217
183
 
218
- function gv(o, k, cv = null) {
219
- let r = get(o, k, '')
220
- if (!isestr(r)) {
221
- let def = getKpText('empty')
222
- return def
184
+ function tErr(err) {
185
+ let key = isestr(err) ? err : 'anUnexpectedErrorOccurred'
186
+ let msg = getKpText(key) //後端 err key → 翻譯
187
+ if (msg === key) { //getKpText 查無 → 回傳 key 本身 → 非 procLang key (連線層 raw 等)
188
+ msg = getKpText('cannotConnectServer')
223
189
  }
224
- if (isfun(cv)) {
225
- r = cv(r)
226
- }
227
- return r
190
+ return msg
228
191
  }
229
192
 
230
193
 
@@ -290,8 +253,8 @@ let mUI = {
290
253
 
291
254
  setLang,
292
255
  getKpText,
256
+ tErr,
293
257
 
294
- gv,
295
258
  syncHeight,
296
259
 
297
260
  // waitData,
@@ -74,12 +74,6 @@ export let mutations = {
74
74
  state[msg.tableName] = msg.data
75
75
  },
76
76
 
77
- [types.UpdateData] (state, msg) {
78
- //msg.path內為存取路徑, 需使用set處理
79
- // console.log('UpdateData msg', msg)
80
- set(state, msg.path, msg.data)
81
- },
82
-
83
77
  [types.UpdateHeightApp] (state, heightApp) {
84
78
  state.heightApp = heightApp
85
79
  },
@@ -92,10 +86,6 @@ export let mutations = {
92
86
  state.heightToolbar = heightToolbar
93
87
  },
94
88
 
95
- [types.UpdateMenu] (state, menu) {
96
- state.menu = menu
97
- },
98
-
99
89
  [types.UpdateUserToken] (state, userToken) {
100
90
  state.userToken = userToken
101
91
  },
@@ -6,10 +6,8 @@ export const UpdateSyncState = 'UpdateSyncState'
6
6
  export const UpdateLoading = 'UpdateLoading'
7
7
  // export const UpdateViewState = 'UpdateViewState'
8
8
  export const UpdateTableData = 'UpdateTableData'
9
- export const UpdateData = 'UpdateData'
10
9
  export const UpdateHeightApp = 'UpdateHeightApp'
11
10
  export const UpdateHeightAppEff = 'UpdateHeightAppEff'
12
11
  export const UpdateHeightToolbar = 'UpdateHeightToolbar'
13
- export const UpdateMenu = 'UpdateMenu'
14
12
  export const UpdateUserToken = 'UpdateUserToken'
15
13
  export const UpdateUserSelf = 'UpdateUserSelf'
package/srv.mjs CHANGED
@@ -1,101 +1,76 @@
1
- import WOrm from 'w-orm-lmdb/src/WOrmLmdb.mjs'
2
- import WWebPerm from './server/WWebPerm.mjs'
3
- import getSettings from './g.getSettings.mjs'
4
-
5
-
6
- //st
7
- let st = getSettings()
8
-
9
- let url = st.dbUrl
10
- let db = st.dbName
11
- let opt = {
12
-
13
- useCheckUser: false,
14
- getUserById: null,
15
- useExcludeWhenNotAdmin: false,
16
-
17
- serverPort: 11006,
18
- subfolder: '', //mperm
19
- urlRedirect: 'https://www.google.com/', //本機測試時得先編譯, 再瀏覽: http://localhost:11006/
20
-
21
- showLanguage: 'y', //'n',
22
- language: 'eng', //'eng', 'cht'
23
-
24
- showModeEditTargets: 'y', //'n',
25
- showModeEditPemis: 'y',
26
- showModeEditGrups: 'y',
27
- showModeEditUsers: 'y',
28
- modeEditTargets: 'y', //'n',
29
- modeEditPemis: 'y',
30
- modeEditGrups: 'y',
31
- modeEditUsers: 'y',
32
-
33
- webName: {
34
- 'eng': 'Permission Service',
35
- 'cht': '權限管理系統',
36
- },
37
- webDescription: {
38
- 'eng': 'A web service package for user permissions and management targets.',
39
- 'cht': '基於簡易分層架構來給予與設定使用者所需之權限及群組管理功能',
40
- },
41
- webLogo: 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjQ4IiB3aWR0aD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTQ4IDBIMHY0OGg0OFYwWiIgZmlsbD0iI2ZmZiIgZmlsbC1vcGFjaXR5PSIuMDEiLz48cGF0aCBkPSJNMzcuODU2IDIwdjhNMjcuNDY0IDM4bDMuNDY0LTIgMy40NjQtMk0yMC41MzYgMzhsLTMuNDY1LTItMy40NjQtMk0xMC4xNDQgMjB2OE0xMy42MDcgMTRsMy40NjUtMiAzLjQ2NC0yTTI3LjQ2NCAxMGwzLjQ2NCAyIDMuNDY0IDIiIHN0cm9rZT0iI0ZGOTgwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiLz48cGF0aCBkPSJNMjQgNDRhNCA0IDAgMSAwIDAtOCA0IDQgMCAwIDAgMCA4Wk0yNCAxMmE0IDQgMCAxIDAgMC04IDQgNCAwIDAgMCAwIDhaTTI0IDI4YTQgNCAwIDEgMCAwLTggNCA0IDAgMCAwIDAgOFpNMzggMjBhNCA0IDAgMSAwIDAtOCA0IDQgMCAwIDAgMCA4Wk0zOCAzNmE0IDQgMCAxIDAgMC04IDQgNCAwIDAgMCAwIDhaTTEwIDIwYTQgNCAwIDEgMCAwLTggNCA0IDAgMCAwIDAgOFpNMTAgMzZhNCA0IDAgMSAwIDAtOCA0IDQgMCAwIDAgMCA4WiIgZmlsbD0iI0ZGRTBCMiIgc3Ryb2tlPSIjRkY5ODAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==',
42
-
43
- // kpLangExt: {
44
- // mmTargets: {
45
- // eng: `Current features list`,
46
- // cht: `現有功能清單`,
47
- // },
48
- // mmTargetsMsg: {
49
- // eng: `Features generally refer to entities such as pages, data, etc., and can also include features or services.`,
50
- // cht: `現有功能泛指實體的頁面、數據等,亦可為的功能或服務。`,
51
- // },
52
- // },
53
-
54
- }
55
-
56
- let getUserByToken = async (token) => {
57
- // console.log('getUserByToken/token', token)
58
- // console.log('於生產環境時得加入SSO等驗證token機制')
59
- // return {} //測試無法登入
60
- if (token === '{token-for-application}') { //提供外部應用系統作為存取使用者
61
- return {
62
- id: 'id-for-application',
63
- name: 'application',
64
- email: 'application@example.com',
65
- isAdmin: 'y',
66
- }
67
- }
68
- if (token === 'sys') { //開發階段w-ui-loginout自動給予browser使用者(且位於localhost)的token為sys
69
- return {
70
- id: 'id-for-admin',
71
- name: 'admin',
72
- email: 'admin@example.com', //mappingBy為email, 開發階段時會使用email找到所建置之使用者資料
73
- isAdmin: 'y',
74
- }
75
- }
76
- console.log('invalid token', token)
77
- return {}
78
- }
79
-
80
- let verifyClientUser = (user, from) => {
81
- // console.log('verifyClientUser/user', user)
82
- // console.log('於生產環境時得加入限制瀏覽器使用者身份機制')
83
- // return false //測試無法登入
84
- return user.isAdmin === 'y' //測試僅系統管理者使用
85
- }
86
-
87
- let verifyAppUser = (user, from) => {
88
- // console.log('verifyAppUser/user', user)
89
- // console.log('於生產環境時得加入限制應用程式使用者身份機制')
90
- // return false //測試無法登入
91
- return user.isAdmin === 'y' //測試僅系統管理者使用
92
- }
93
-
94
- //WWebPerm
95
- let instWWebPerm = WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser, opt)
96
-
97
- instWWebPerm.on('error', (err) => {
98
- console.log(err)
99
- })
100
-
101
- //node srv.mjs
1
+ import fs from 'fs'
2
+ import JSON5 from 'json5'
3
+ import WOrm from 'w-orm-lmdb/src/WOrmLmdb.mjs'
4
+ import WWebPerm from './server/WWebPerm.mjs'
5
+ import getSettings from './g.getSettings.mjs'
6
+
7
+
8
+ //st(DB 設定)
9
+ let st = getSettings()
10
+
11
+ let url = st.dbUrl
12
+ let db = st.dbName
13
+
14
+ //app 設定來源: argv[2] 指定之 settings 檔(供 e2e restartBackend 注入不同語系等), 預設 ./settings.json.(對齊 SSO srv.mjs)
15
+ //JSON5 格式(無引號鍵 / 單引號 / 註解 / 尾逗號); language / webName / modeEdit* / webLogo 等資料設定皆在此檔.
16
+ let pathSettings = process.argv[2] || './settings.json'
17
+ let appSt = JSON5.parse(fs.readFileSync(pathSettings, 'utf8'))
18
+
19
+ let opt = {
20
+
21
+ useCheckUser: false,
22
+ getUserById: null,
23
+ useExcludeWhenNotAdmin: false,
24
+
25
+ //serverPort / subfolder / urlRedirect / showLanguage / language / showModeEdit* / modeEdit* / webName / webDescription / webLogo / kpLangExt 皆由 settings.json 提供
26
+ ...appSt,
27
+
28
+ }
29
+
30
+ let getUserByToken = async (token) => {
31
+ // console.log('getUserByToken/token', token)
32
+ // console.log('於生產環境時得加入SSO等驗證token機制')
33
+ // return {} //測試無法登入
34
+ if (token === '{token-for-application}') { //提供外部應用系統作為存取使用者
35
+ return {
36
+ id: 'id-for-application',
37
+ name: 'application',
38
+ email: 'application@example.com',
39
+ isAdmin: 'y',
40
+ }
41
+ }
42
+ if (token === 'sys') { //開發階段w-ui-loginout自動給予browser使用者(且位於localhost)的token為sys
43
+ return {
44
+ id: 'id-for-admin',
45
+ name: 'admin',
46
+ email: 'admin@example.com', //mappingBy為email, 開發階段時會使用email找到所建置之使用者資料
47
+ isAdmin: 'y',
48
+ }
49
+ }
50
+ console.log('invalid token', token)
51
+ return {}
52
+ }
53
+
54
+ let verifyClientUser = (user, from) => {
55
+ // console.log('verifyClientUser/user', user)
56
+ // console.log('於生產環境時得加入限制瀏覽器使用者身份機制')
57
+ // return false //測試無法登入
58
+ return user.isAdmin === 'y' //測試僅系統管理者使用
59
+ }
60
+
61
+ let verifyAppUser = (user, from) => {
62
+ // console.log('verifyAppUser/user', user)
63
+ // console.log('於生產環境時得加入限制應用程式使用者身份機制')
64
+ // return false //測試無法登入
65
+ return user.isAdmin === 'y' //測試僅系統管理者使用
66
+ }
67
+
68
+ //WWebPerm
69
+ let instWWebPerm = WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser, opt)
70
+
71
+ instWWebPerm.on('error', (err) => {
72
+ console.log(err)
73
+ })
74
+
75
+ //node srv.mjs
76
+ //node srv.mjs <pathSettings> //指定 settings 檔(e2e 注入語系用)
package/tableTags.json CHANGED
@@ -1 +1 @@
1
- {"grups":"2026-03-29T21:41:46+08:00|yI6vlG","pemis":"2026-03-29T21:41:46+08:00|eXQml3","targets":"2026-03-29T21:41:46+08:00|CdW12e","users":"2026-03-29T22:01:58+08:00|dDEKFJ"}
1
+ {"grups":"2026-07-11T17:38:16+08:00|oibw7P","pemis":"2026-07-11T17:38:16+08:00|cnWe25","targets":"2026-07-11T17:38:16+08:00|OChCfm","users":"2026-07-11T17:38:16+08:00|7oyfiw"}