w-web-sso 1.0.37 → 1.0.39

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 (102) hide show
  1. package/.github/workflows/ci-test.yml +2 -2
  2. package/_gh-pages-deploy/.nojekyll +0 -0
  3. package/_gh-pages-deploy/WWebSso.html +400 -0
  4. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  5. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  6. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  7. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  8. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  9. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  10. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  11. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  12. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  13. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  14. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  15. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  16. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  17. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  18. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  19. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  20. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  21. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  22. package/_gh-pages-deploy/index.html +84 -0
  23. package/_gh-pages-deploy/scripts/collapse.js +39 -0
  24. package/_gh-pages-deploy/scripts/commonNav.js +28 -0
  25. package/_gh-pages-deploy/scripts/linenumber.js +25 -0
  26. package/_gh-pages-deploy/scripts/nav.js +12 -0
  27. package/_gh-pages-deploy/scripts/polyfill.js +4 -0
  28. package/_gh-pages-deploy/scripts/prettify/Apache-License-2.0.txt +202 -0
  29. package/_gh-pages-deploy/scripts/prettify/lang-css.js +2 -0
  30. package/_gh-pages-deploy/scripts/prettify/prettify.js +28 -0
  31. package/_gh-pages-deploy/scripts/search.js +99 -0
  32. package/{docs/WWebSso.mjs.html → _gh-pages-deploy/server_WWebSso.mjs.html} +1333 -1149
  33. package/_gh-pages-deploy/src_components_Common_CheckYesNo.vue.html +195 -0
  34. package/_gh-pages-deploy/styles/jsdoc.css +776 -0
  35. package/_gh-pages-deploy/styles/prettify.css +80 -0
  36. package/dist/css/app.5f246189.css +1 -0
  37. package/dist/css/chunk-vendors.f831c81d.css +1 -0
  38. package/dist/index.tmp +2 -6
  39. package/dist/js/app-legacy.73f3eae0.js +1 -0
  40. package/dist/js/app.73f3eae0.js +1 -0
  41. package/dist/js/chunk-vendors-legacy.7c56bceb.js +21 -0
  42. package/dist/js/chunk-vendors.7c56bceb.js +21 -0
  43. package/dist/w-web-sso.umd.js +6 -4
  44. package/dist/w-web-sso.umd.js.map +1 -1
  45. package/docs/WWebSso.html +2 -2
  46. package/docs/index.html +1 -1
  47. package/docs/server_WWebSso.mjs.html +1402 -0
  48. package/docs/src_components_Common_CheckYesNo.vue.html +195 -0
  49. package/g.getSettings.mjs +49 -3
  50. package/g.initialData.mjs +103 -78
  51. package/package.json +17 -13
  52. package/public/index.html +3 -16
  53. package/server/WWebSso.mjs +1330 -1146
  54. package/server/genRandomPassword.mjs +120 -0
  55. package/server/procCore.mjs +700 -176
  56. package/server/procLang.mjs +1231 -1047
  57. package/server/procProtect.mjs +40 -12
  58. package/server/procStaInfor.mjs +46 -26
  59. package/server/template/changePasswordEmail-cht.html +1 -0
  60. package/server/template/changePasswordEmail-eng.html +1 -0
  61. package/server/template/regVerifyEmail-cht.html +1 -0
  62. package/server/template/regVerifyEmail-eng.html +1 -0
  63. package/server/template/resetPasswordEmail-cht.html +1 -0
  64. package/server/template/resetPasswordEmail-eng.html +1 -0
  65. package/server/template/verifyEmailResult.html +26 -0
  66. package/settings.json +49 -12
  67. package/src/App.vue +30 -13
  68. package/src/components/Common/CheckYes.vue +18 -1
  69. package/src/components/Common/CheckYesNo.vue +32 -0
  70. package/src/components/Layout.vue +19 -8
  71. package/src/components/LayoutContent.vue +23 -0
  72. package/src/components/LayoutContentIps.vue +119 -111
  73. package/src/components/LayoutContentStaInfor.vue +146 -43
  74. package/src/components/LayoutContentTokens.vue +174 -215
  75. package/src/components/LayoutContentUserInfor.vue +518 -1017
  76. package/src/components/LayoutContentUsers.vue +475 -395
  77. package/src/components/PageLogin.vue +467 -21
  78. package/src/components/PageUser.vue +109 -37
  79. package/src/main.js +1 -5
  80. package/src/plugins/mShare.mjs +0 -215
  81. package/src/plugins/mUI.mjs +188 -66
  82. package/src/schema/tables/users.mjs +12 -1
  83. package/src/store/mutations.mjs +4 -4
  84. package/src/store/types.mjs +1 -1
  85. package/srv.mjs +21 -2
  86. package/db/wsso/ips/data.mdb +0 -0
  87. package/db/wsso/ips/lock.mdb +0 -0
  88. package/db/wsso/tokens/data.mdb +0 -0
  89. package/db/wsso/tokens/lock.mdb +0 -0
  90. package/db/wsso/users/data.mdb +0 -0
  91. package/db/wsso/users/lock.mdb +0 -0
  92. package/dist/css/app.beea8385.css +0 -1
  93. package/dist/js/app-legacy.93c91f21.js +0 -1
  94. package/dist/js/app.93c91f21.js +0 -1
  95. package/dist/js/chunk-vendors-legacy.3ce45600.js +0 -14
  96. package/dist/js/chunk-vendors.3ce45600.js +0 -14
  97. package/g.provideUsers.mjs +0 -45
  98. package/server/provideTabs.mjs +0 -71
  99. package/src/components/Common/LabelItem.vue +0 -106
  100. package/src/components/ruleGroup.vue.txt +0 -644
  101. package/src/plugins/mDataSupport.mjs +0 -23
  102. package/test/all.test.mjs +0 -10
@@ -1,4 +1,5 @@
1
1
  import Vue from 'vue'
2
+ import ot from 'dayjs'
2
3
  import min from 'lodash-es/min.js'
3
4
  import size from 'lodash-es/size.js'
4
5
  import take from 'lodash-es/take.js'
@@ -17,7 +18,6 @@ import dropRight from 'lodash-es/dropRight.js'
17
18
  import groupBy from 'lodash-es/groupBy.js'
18
19
  import sortBy from 'lodash-es/sortBy.js'
19
20
  import cloneDeep from 'lodash-es/cloneDeep.js'
20
- import cint from 'wsemi/src/cint.mjs'
21
21
  import delay from 'wsemi/src/delay.mjs'
22
22
  import isarr from 'wsemi/src/isarr.mjs'
23
23
  import isestr from 'wsemi/src/isestr.mjs'
@@ -25,6 +25,9 @@ import isfun from 'wsemi/src/isfun.mjs'
25
25
  import iseobj from 'wsemi/src/iseobj.mjs'
26
26
  import isearr from 'wsemi/src/isearr.mjs'
27
27
  import isEle from 'wsemi/src/isEle.mjs'
28
+ import istimemsTZ from 'wsemi/src/istimemsTZ.mjs'
29
+ import cstr from 'wsemi/src/cstr.mjs'
30
+ import cint from 'wsemi/src/cint.mjs'
28
31
  import strleft from 'wsemi/src/strleft.mjs'
29
32
  import strdelleft from 'wsemi/src/strdelleft.mjs'
30
33
  import sep from 'wsemi/src/sep.mjs'
@@ -34,27 +37,49 @@ import haskey from 'wsemi/src/haskey.mjs'
34
37
  import genPm from 'wsemi/src/genPm.mjs'
35
38
  import pmSeries from 'wsemi/src/pmSeries.mjs'
36
39
  import waitFun from 'wsemi/src/waitFun.mjs'
37
- import browserView from 'wsemi/src/browserView.mjs'
38
40
  import arrHas from 'wsemi/src/arrHas.mjs'
39
41
  import arrSort from 'wsemi/src/arrSort.mjs'
40
42
  import arrInsert from 'wsemi/src/arrInsert.mjs'
41
43
  import replace from 'wsemi/src/replace.mjs'
42
44
  import timemsTZ2past from 'wsemi/src/timemsTZ2past.mjs'
43
45
  import convertToTree from 'wsemi/src/convertToTree.mjs'
44
- // import WUiDwload from 'w-ui-dwload/src/WUiDwload.mjs'
45
46
 
46
47
 
47
48
  let vo = Vue.prototype
48
49
 
49
50
 
51
+ let kpFallback = {
52
+ csIng: {
53
+ eng: 'Connecting...',
54
+ cht: '連線中...',
55
+ },
56
+ csLogin: {
57
+ eng: 'Logged in',
58
+ cht: '已登入',
59
+ },
60
+ csLogout: {
61
+ eng: 'Logged out',
62
+ cht: '已登出',
63
+ },
64
+ csErrConn: {
65
+ eng: 'Unable to connect',
66
+ cht: '無法連線',
67
+ },
68
+ csErrLogin: {
69
+ eng: 'Login denied',
70
+ cht: '拒絕登入',
71
+ },
72
+ }
73
+
74
+
50
75
  function setVo(vObj) {
51
76
  vo = vObj
52
77
  }
53
78
 
54
79
 
55
- // function updateConnState(connState) {
56
- // vo.$store.commit(vo.$store.types.UpdateConnState, connState)
57
- // }
80
+ function updateConnState(connState) {
81
+ vo.$store.commit(vo.$store.types.UpdateConnState, connState)
82
+ }
58
83
 
59
84
 
60
85
  function updateLoading(loading) {
@@ -108,16 +133,19 @@ function validLang(lang) {
108
133
  function getLang() {
109
134
  let lang = ''
110
135
 
111
- //from window
136
+ //from URL ?lang= (轉址攜帶語系時最優先,例如登入後 redirect 帶當前語系)
112
137
  if (!isestr(lang)) {
113
- let _lang = get(window, '___pmwsso___.language', '')
114
- // console.log('_lang(from window)', _lang)
115
- if (isestr(_lang)) {
116
- lang = validLang(_lang) //有可能取到未取代前模板符號
138
+ try {
139
+ let _lang = new URLSearchParams(window.location.search).get('lang') || ''
140
+ // console.log('_lang(from url)', _lang)
141
+ if (isestr(_lang)) {
142
+ lang = validLang(_lang)
143
+ }
117
144
  }
145
+ catch (err) {}
118
146
  }
119
147
 
120
- //from store
148
+ //from store (使用者當下選的,或 App.vue beforeMount 已設定)
121
149
  if (!isestr(lang)) {
122
150
  let _lang = get(vo, '$store.state.lang', '')
123
151
  // console.log('_lang(from store)', _lang)
@@ -126,10 +154,18 @@ function getLang() {
126
154
  }
127
155
  }
128
156
 
129
- //return
157
+ //from window (server 預設語系,fallback)
130
158
  if (!isestr(lang)) {
131
- return 'eng'
159
+ let _lang = get(window, '___pmwsso___.language', '')
160
+ // console.log('_lang(from window)', _lang)
161
+ if (isestr(_lang)) {
162
+ lang = validLang(_lang) //有可能取到未取代前模板符號
163
+ }
132
164
  }
165
+
166
+ //validLang
167
+ lang = validLang(lang) //有可能給予非預期lang
168
+
133
169
  return lang
134
170
  }
135
171
 
@@ -141,9 +177,7 @@ function setLang(lang = null, from = '') {
141
177
  if (!isestr(lang)) {
142
178
  lang = getLang()
143
179
  }
144
- else {
145
- lang = validLang(lang)
146
- }
180
+ lang = validLang(lang)
147
181
  // console.log('get lang', lang)
148
182
 
149
183
  //check, 若有變更才commit
@@ -181,6 +215,11 @@ function getKpText(key) {
181
215
 
182
216
  //t
183
217
  let t = get(kpText, key, '')
218
+ if (!isestr(t)) {
219
+ // fallback: 後端語系尚未載入時使用預設值
220
+ let lang = getLang()
221
+ t = get(kpFallback, `${key}.${lang}`, '')
222
+ }
184
223
  if (!isestr(t)) {
185
224
  t = key
186
225
  }
@@ -189,16 +228,20 @@ function getKpText(key) {
189
228
  }
190
229
 
191
230
 
192
- function gv(o, k, cv = null) {
193
- let r = get(o, k, '')
194
- if (!isestr(r)) {
195
- let def = getKpText('empty')
196
- return def
197
- }
198
- if (isfun(cv)) {
199
- r = cv(r)
231
+ //getKpTextErr: 錯誤訊息專用翻譯 — 先 getKpText(key) 取得模板, 再插值密碼政策值 (minLength / maxLength /
232
+ //consecutiveCharsMinMatch 來自 webInfor.passwordPolicyInfo, 即時反映 settings). 供「錯誤 reject key」顯示用:
233
+ //多數錯誤 key 無模板變數 (replace 為 no-op); 僅密碼政策 key (userPassword_keyLim*) 含 {minLength} 等需插值.
234
+ //設計: 後端一律 reject key 字串 (msg-key 契約), 前端統一以 $tErr(key) 翻譯+插值顯示.
235
+ function getKpTextErr(key) {
236
+ let t = getKpText(key)
237
+ if (!isestr(t)) {
238
+ return t
200
239
  }
201
- return r
240
+ let p = get(vo, '$store.state.webInfor.passwordPolicyInfo', {})
241
+ t = t.replace('{minLength}', get(p, 'minLength', ''))
242
+ t = t.replace('{maxLength}', get(p, 'maxLength', ''))
243
+ t = t.replace('{consecutiveCharsMinMatch}', get(p, 'consecutiveCharsMinMatch', ''))
244
+ return t
202
245
  }
203
246
 
204
247
 
@@ -287,21 +330,23 @@ function getUrlView() {
287
330
  }
288
331
 
289
332
 
290
- function goUrl(url, token) {
333
+ function goUrl(url, token, lang) {
291
334
 
292
- //replace
335
+ //replace {token}
293
336
  url = url.replaceAll('{token}', token)
294
337
 
338
+ //replace {lang} 佔位符(若 redir 模板顯式包含)
339
+ if (isestr(lang)) {
340
+ url = url.replaceAll('{lang}', lang)
341
+ }
342
+
343
+ //自動 append &lang= 給轉址後的系統作為依據(已含 lang 參數則不覆寫)
344
+ if (isestr(lang) && !/[?&]lang=/.test(url)) {
345
+ let sep = url.includes('?') ? '&' : '?'
346
+ url = `${url}${sep}lang=${encodeURIComponent(lang)}`
347
+ }
348
+
295
349
  //href
296
- // if (isDev()) {
297
- // console.log('10s後重導至:', url)
298
- // setTimeout(() => {
299
- // window.location.href = url
300
- // }, 10 * 1000)
301
- // }
302
- // else {
303
- // window.location.href = url
304
- // }
305
350
  window.location.href = url
306
351
 
307
352
  }
@@ -322,10 +367,10 @@ function login(account, password, opt = {}) {
322
367
  //pm
323
368
  let pm = genPm()
324
369
 
325
- async function core() {
370
+ //hideLoading, 結束預設隱藏loading, 只有當成功登入要轉址時不隱藏loading, 其他成功或失敗都要隱藏
371
+ let hideLoadingForEnd = true
326
372
 
327
- //show loading
328
- updateLoading(true)
373
+ let core = async() => {
329
374
 
330
375
  //delay
331
376
  await delay(1000)
@@ -342,11 +387,15 @@ function login(account, password, opt = {}) {
342
387
  //reject
343
388
  pm.reject('invalid $keyLS')
344
389
 
390
+ //結束後隱藏loading
391
+ hideLoadingForEnd = true
392
+
345
393
  return
346
394
  }
347
395
 
348
- //loginByAccountAndPassword
349
- let u = await vo.$fapi.loginByAccountAndPassword(account, password)
396
+ //loginByAccountAndPassword (帶 lang, 後端 reject { key, msg } 之 msg 依 lang 翻譯)
397
+ let langLogin = get(vo, '$store.state.lang', 'eng')
398
+ let u = await vo.$fapi.loginByAccountAndPassword(langLogin, account, password)
350
399
  // console.log('u', u)
351
400
 
352
401
  //key
@@ -363,6 +412,9 @@ function login(account, password, opt = {}) {
363
412
  //reject
364
413
  pm.reject('invalid user')
365
414
 
415
+ //結束後隱藏loading
416
+ hideLoadingForEnd = true
417
+
366
418
  return
367
419
  }
368
420
 
@@ -379,6 +431,9 @@ function login(account, password, opt = {}) {
379
431
  //reject
380
432
  pm.reject('invalid token')
381
433
 
434
+ //結束後隱藏loading
435
+ hideLoadingForEnd = true
436
+
382
437
  return
383
438
  }
384
439
 
@@ -389,6 +444,13 @@ function login(account, password, opt = {}) {
389
444
  updateUserToken(token)
390
445
  updateUserSelf(u)
391
446
 
447
+ //強制變更密碼模式: 不論原本是否要 useRedir, 一律不走 redir,
448
+ //並把 view 切到 'user' 確保 PageUser 進入強制變更模式 (見 PageUser.mounted)
449
+ if (get(u, 'isForceChangePw', '') === 'y') {
450
+ useRedir = false
451
+ updateViewState('user')
452
+ }
453
+
392
454
  //useRedir
393
455
  if (useRedir) {
394
456
 
@@ -405,43 +467,57 @@ function login(account, password, opt = {}) {
405
467
  //reject
406
468
  pm.reject('invalid redir')
407
469
 
470
+ //結束後隱藏loading
471
+ hideLoadingForEnd = true
472
+
408
473
  return
409
474
  }
410
475
 
411
- //goUrl
412
- goUrl(redir, token)
413
- // console.log('goUrl', redir, 'token', token)
476
+ //goUrl,帶上當前 lang 讓轉址後系統能讀 ?lang=
477
+ let lang = get(vo, '$store.state.lang', '')
478
+ goUrl(redir, token, lang)
479
+ // console.log('goUrl', redir, 'token', token, 'lang', lang)
414
480
 
415
481
  //resolve
416
482
  pm.resolve('redir')
417
483
 
418
- // //hide loading, 登入成功不能先隱藏loading, 開始轉址到轉跳會有一段時間, 持續顯示loading不隱藏, 避免使用者誤會登入失敗
419
- // updateLoading(false)
484
+ //結束後不隱藏loading, 因開始轉址到轉跳會有一段時間, 持續顯示loading不隱藏, 避免使用者誤會登入失敗
485
+ hideLoadingForEnd = false
420
486
 
421
487
  return
422
488
  }
423
489
 
424
- //hide loading, 登入成功後且非轉址時隱藏loading
425
- updateLoading(false)
490
+ //結束後隱藏loading, 登入成功後且非轉址時隱藏loading
491
+ hideLoadingForEnd = true
426
492
 
427
493
  //resolve
428
494
  pm.resolve('done')
429
495
 
430
496
  }
431
497
 
498
+ //show loading
499
+ updateLoading(true)
500
+
432
501
  //core
433
502
  core()
434
503
  .catch((err) => {
435
504
  // console.log('login', err)
436
505
 
437
- //alert
438
- vo.$alert(vo.$t('failedLoginForCatch'), { type: 'error' })
506
+ // //alert
507
+ // vo.$alert(vo.$t('failedLoginForCatch'), { type: 'error' })
439
508
 
440
509
  //reject
441
510
  pm.reject(err)
442
511
 
443
- //hide loading, 登入失敗後隱藏loading
444
- updateLoading(false)
512
+ })
513
+ .finally(() => {
514
+
515
+ if (hideLoadingForEnd) {
516
+
517
+ //hide loading, 登入失敗後隱藏loading
518
+ updateLoading(false)
519
+
520
+ }
445
521
 
446
522
  })
447
523
 
@@ -467,7 +543,7 @@ function autoLogin(opt = {}) {
467
543
  //pm
468
544
  let pm = genPm()
469
545
 
470
- async function core() {
546
+ let core = async () => {
471
547
  let errTemp = null
472
548
 
473
549
  //waitFun, 因須使用webKey故須等待syncState
@@ -504,29 +580,33 @@ function autoLogin(opt = {}) {
504
580
 
505
581
  //check
506
582
  if (!isestr(token)) {
507
- // console.log('invalid token')
583
+ // console.log('no token')
508
584
 
509
585
  //reject
510
- pm.reject('invalid token')
586
+ pm.reject('no token')
511
587
 
512
588
  return
513
589
  }
514
590
 
515
591
  //checkToken
516
- await vo.$fapi.checkToken(token) //斷線有重試機制, resolve僅回傳true, reject代表無效token或檢測token發生錯誤
592
+ let b = false
593
+ await vo.$fapi.checkToken(token) //斷線有重試機制; 後端 wrapper 在過期/無效時一律 reject, 僅在有效時 resolve(true), 不會 resolve(false)
594
+ .then((res) => {
595
+ b = res === true
596
+ })
517
597
  .catch((err) => {
518
598
  // console.log('checkToken catch', err)
519
599
  errTemp = err
520
600
  })
521
601
 
522
602
  //check
523
- if (errTemp) {
603
+ if (errTemp || !b) {
524
604
 
525
605
  //setItem, 清空token
526
606
  await localStorage.setItem(key, '')
527
607
 
528
608
  //reject
529
- pm.reject('token error')
609
+ pm.reject(errTemp ? 'token error' : 'token expired')
530
610
 
531
611
  return
532
612
  }
@@ -549,6 +629,13 @@ function autoLogin(opt = {}) {
549
629
  updateUserToken(token)
550
630
  updateUserSelf(u)
551
631
 
632
+ //強制變更密碼模式: 不論原本是否要 useRedir, 一律不走 redir,
633
+ //並把 view 切到 'user' 確保 PageUser 進入強制變更模式 (見 PageUser.mounted)
634
+ if (get(u, 'isForceChangePw', '') === 'y') {
635
+ useRedir = false
636
+ updateViewState('user')
637
+ }
638
+
552
639
  //useRedir
553
640
  if (useRedir) {
554
641
 
@@ -569,9 +656,10 @@ function autoLogin(opt = {}) {
569
656
  return
570
657
  }
571
658
 
572
- //goUrl
573
- goUrl(redir, token)
574
- // console.log('goUrl', redir, 'token', token)
659
+ //goUrl,帶上當前 lang 讓轉址後系統能讀 ?lang=
660
+ let lang = get(vo, '$store.state.lang', '')
661
+ goUrl(redir, token, lang)
662
+ // console.log('goUrl', redir, 'token', token, 'lang', lang)
575
663
 
576
664
  //resolve
577
665
  pm.resolve('redir')
@@ -589,8 +677,8 @@ function autoLogin(opt = {}) {
589
677
  .catch((err) => {
590
678
  // console.log('autoLogin', err)
591
679
 
592
- //alert
593
- vo.$alert(vo.$t('failedLoginForCatch'), { type: 'error' })
680
+ // //alert
681
+ // vo.$alert(vo.$t('failedLoginForCatch'), { type: 'error' })
594
682
 
595
683
  //reject
596
684
  pm.reject(err)
@@ -672,11 +760,40 @@ function getIcon(icon) {
672
760
  }
673
761
 
674
762
 
763
+ function gv(o, k, cv = null) {
764
+ let r = get(o, k, '')
765
+ if (!isestr(r)) {
766
+ let def = getKpText('empty')
767
+ return def
768
+ }
769
+ if (isfun(cv)) {
770
+ r = cv(r)
771
+ }
772
+ return r
773
+ }
774
+
775
+
776
+ function getTimemsTZ(v) {
777
+ if (istimemsTZ(v)) {
778
+ return ot(v).format('YYYY-MM-DDTHH:mm:ss.SSSZ')
779
+ }
780
+ return ''
781
+ }
782
+
783
+
784
+ function getTimeMin(v, def) {
785
+ if (istimemsTZ(v)) {
786
+ return ot(v).format('YYYY-MM-DD HH:mm')
787
+ }
788
+ return def
789
+ }
790
+
791
+
675
792
  let mUI = {
676
793
 
677
794
  setVo,
678
795
 
679
- // updateConnState,
796
+ updateConnState,
680
797
  updateLoading,
681
798
  updateViewState,
682
799
  updateUserToken,
@@ -685,8 +802,8 @@ let mUI = {
685
802
 
686
803
  setLang,
687
804
  getKpText,
805
+ getKpTextErr,
688
806
 
689
- gv,
690
807
  syncHeight,
691
808
 
692
809
  // waitData,
@@ -701,6 +818,11 @@ let mUI = {
701
818
 
702
819
  getIcon,
703
820
 
821
+ gv,
822
+ getTimemsTZ,
823
+ getTimeMin,
824
+ cstr,
825
+
704
826
  }
705
827
 
706
828
 
@@ -54,6 +54,10 @@ let settings = {
54
54
  name: '是否為系統管理員',
55
55
  type: 'STRING',
56
56
  },
57
+ tokenVerify: {
58
+ name: '註冊後驗證用token',
59
+ type: 'STRING',
60
+ },
57
61
  timeVerified: {
58
62
  name: '驗證時間',
59
63
  type: 'STRING',
@@ -66,6 +70,10 @@ let settings = {
66
70
  name: '封鎖時間',
67
71
  type: 'STRING',
68
72
  },
73
+ isForceChangePw: { //僅'y'或'n'
74
+ name: '是否須強制變更密碼',
75
+ type: 'STRING',
76
+ },
69
77
  userId: {
70
78
  name: '創建使用者主鍵',
71
79
  type: 'STRING',
@@ -82,7 +90,7 @@ let settings = {
82
90
  name: '更新時間',
83
91
  type: 'STRING',
84
92
  },
85
- isActive: {
93
+ isActive: { //僅'y'或'n'
86
94
  name: '是否有效',
87
95
  type: 'STRING',
88
96
  },
@@ -96,6 +104,9 @@ let funNew = (ndata = {}) => {
96
104
  o.userIdUpdate = o.userId
97
105
  o.timeUpdate = o.timeCreate
98
106
  o.isActive = 'y'
107
+ if (o.isForceChangePw !== 'y' && o.isForceChangePw !== 'n') {
108
+ o.isForceChangePw = 'n'
109
+ }
99
110
  return o
100
111
  }
101
112
 
@@ -26,7 +26,7 @@ let state = {
26
26
  userToken: '',
27
27
  userSelf: {},
28
28
 
29
- lang: 'cht', //'eng', 'cht'
29
+ lang: 'eng', //'eng', 'cht'
30
30
  kpText: {}, //一定要放在vuex內, 否則無法用broadcast驅動變更語系文字
31
31
 
32
32
  }
@@ -54,9 +54,9 @@ export let mutations = {
54
54
  state.kpText = kpText
55
55
  },
56
56
 
57
- // [types.UpdateConnState] (state, connState) {
58
- // state.connState = connState
59
- // },
57
+ [types.UpdateConnState] (state, connState) {
58
+ state.connState = connState
59
+ },
60
60
 
61
61
  [types.UpdateSyncState] (state, syncState) {
62
62
  state.syncState = syncState
@@ -1,7 +1,7 @@
1
1
  export const UpdateWebInfor = 'UpdateWebInfor'
2
2
  export const UpdateLang = 'UpdateLang'
3
3
  export const UpdateKpText = 'UpdateKpText'
4
- // export const UpdateConnState = 'UpdateConnState'
4
+ export const UpdateConnState = 'UpdateConnState'
5
5
  export const UpdateSyncState = 'UpdateSyncState'
6
6
  export const UpdateLoading = 'UpdateLoading'
7
7
  export const UpdateViewState = 'UpdateViewState'
package/srv.mjs CHANGED
@@ -8,10 +8,10 @@ let st = getSettings()
8
8
 
9
9
  let url = st.dbUrl
10
10
  let db = st.dbName
11
- let pathSettings = './settings.json'
11
+ let pathSettings = process.argv[2] || './settings.json'
12
12
 
13
13
  //WWebSso
14
- let instWWebSso = WWebSso(WOrm, url, db, pathSettings)
14
+ let instWWebSso = WWebSso(WOrm, url, db, pathSettings, st)
15
15
 
16
16
  instWWebSso.on('error', (err) => {
17
17
  console.log(err)
@@ -43,3 +43,22 @@ instWWebSso.on('error', (err) => {
43
43
  //http://localhost:11007/api/getSsoUserInfor?token=token-for-app&key=token&value=token-for-app => 無使用者id-for-app, 要能取得虛擬使用者資訊
44
44
 
45
45
  //node srv.mjs
46
+
47
+
48
+ let t=`
49
+
50
+ 密碼長度需在8~16碼,且須符合以下5項規則:
51
+
52
+ (1)有0~9的數字
53
+
54
+ (2)有英文字母(不限大小寫)
55
+
56
+ (3)有特殊字元(非大小寫字母及數字,例如以下字元: ! @ # $ ^ & * ( ) - + < > ? …等字元)
57
+
58
+ (4)不可和駭客最常猜測複雜密碼相同,例如1qaz@WSX、P@ssw0rd等
59
+
60
+ (5)不可包含與自己姓名代號相同之2個以上之連續字元(例如姓名代號123456,密碼不可包含12、23、34、45、56)
61
+
62
+ (6)不可包含「\」
63
+
64
+ `
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1 +0,0 @@
1
- .pgc-rotate[data-v-5b4e8bee]{width:100%;height:100%;margin:auto;position:absolute;top:0;bottom:0;left:0;right:0;z-index:1;-webkit-transition:all .6s ease-in-out;transition:all .6s ease-in-out;-webkit-animation:progress-circular-rotate-5b4e8bee 1.4s linear infinite;animation:progress-circular-rotate-5b4e8bee 1.4s linear infinite;-webkit-transform-origin:center center;transform-origin:center center}.pgc-dash[data-v-5b4e8bee]{-webkit-animation:progress-circular-dash-5b4e8bee 1.4s ease-in-out infinite;animation:progress-circular-dash-5b4e8bee 1.4s ease-in-out infinite;stroke-linecap:round;stroke-dasharray:80,200;stroke-dashoffset:0px}@-webkit-keyframes progress-circular-dash-5b4e8bee{0%{stroke-dasharray:1,200;stroke-dashoffset:0px}50%{stroke-dasharray:100,200;stroke-dashoffset:-15px}to{stroke-dasharray:100,200;stroke-dashoffset:-124px}}@keyframes progress-circular-dash-5b4e8bee{0%{stroke-dasharray:1,200;stroke-dashoffset:0px}50%{stroke-dasharray:100,200;stroke-dashoffset:-15px}to{stroke-dasharray:100,200;stroke-dashoffset:-124px}}@-webkit-keyframes progress-circular-rotate-5b4e8bee{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes progress-circular-rotate-5b4e8bee{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.WPopperFix[data-popper-reference-hidden][data-v-14d6bcb4]{visibility:hidden;pointer-events:none}.fade-enter-active[data-v-a0c94508],.fade-leave-active[data-v-a0c94508]{-webkit-transition:all .3s;transition:all .3s}.fade-enter[data-v-a0c94508],.fade-leave-to[data-v-a0c94508]{-webkit-transform:scaleX(0);transform:scaleX(0)}.fade-enter-to[data-v-a0c94508],.fade-leave[data-v-a0c94508]{-webkit-transform:scaleX(100%);transform:scaleX(100%)}.sb[data-v-6ce5bdb1]{-webkit-transition:opacity .3s;transition:opacity .3s;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.3) transparent}.sb[data-v-6ce5bdb1]::-webkit-scrollbar{width:8px;height:8px}.sb[data-v-6ce5bdb1]::-webkit-scrollbar-track{background:transparent}.sb[data-v-6ce5bdb1]::-webkit-scrollbar-thumb{background:rgba(0,0,0,.3);border-radius:20px;border:3px solid transparent}.ts[data-v-9a483320]{-webkit-transition:all .3s cubic-bezier(.25,.8,.5,1);transition:all .3s cubic-bezier(.25,.8,.5,1)}.bs[data-v-9a483320]{-webkit-box-shadow:0 8px 2px -8px rgba(0,0,0,.3),0 16px 24px 2px rgba(0,0,0,.3),0 6px 30px 5px rgba(0,0,0,.3);box-shadow:0 8px 2px -8px rgba(0,0,0,.3),0 16px 24px 2px rgba(0,0,0,.3),0 6px 30px 5px rgba(0,0,0,.3)}@media (min-width:640px){.sm\:grid-cols-2[data-v-99dfb112]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:grid-cols-1[data-v-99dfb112]{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:grid-cols-4[data-v-99dfb112]{grid-template-columns:repeat(4,minmax(0,1fr))}}.status-danger[data-v-0620fb52]{background-color:#fef2f2;color:#b91c1c;border:1px solid #fecaca}.status-warning[data-v-0620fb52]{background-color:#fffbeb;color:#b45309;border:1px solid #fde68a}.status-success[data-v-0620fb52]{background-color:#f0fdf4;color:#15803d;border:1px solid #bbf7d0}.status-info[data-v-0620fb52]{background-color:#f8fafc;color:#475569;border:1px solid #e2e8f0}.ts[data-v-b624c7f8]{-webkit-transition:all .3s;transition:all .3s}.bs[data-v-b624c7f8]{-webkit-box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12);box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}body,html{font-family:微軟正黑體,Microsoft JhengHei,MicrosoftJhengHeiRegular,Avenir,Helvetica,Arial,sans-serif;overflow-y:hidden}a,button,div,input,p,pre,span,textarea{font-family:inherit}