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.
- package/.github/workflows/ci-test.yml +2 -2
- package/_gh-pages-deploy/.nojekyll +0 -0
- package/_gh-pages-deploy/WWebSso.html +400 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/_gh-pages-deploy/index.html +84 -0
- package/_gh-pages-deploy/scripts/collapse.js +39 -0
- package/_gh-pages-deploy/scripts/commonNav.js +28 -0
- package/_gh-pages-deploy/scripts/linenumber.js +25 -0
- package/_gh-pages-deploy/scripts/nav.js +12 -0
- package/_gh-pages-deploy/scripts/polyfill.js +4 -0
- package/_gh-pages-deploy/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/_gh-pages-deploy/scripts/prettify/lang-css.js +2 -0
- package/_gh-pages-deploy/scripts/prettify/prettify.js +28 -0
- package/_gh-pages-deploy/scripts/search.js +99 -0
- package/{docs/WWebSso.mjs.html → _gh-pages-deploy/server_WWebSso.mjs.html} +1333 -1149
- package/_gh-pages-deploy/src_components_Common_CheckYesNo.vue.html +195 -0
- package/_gh-pages-deploy/styles/jsdoc.css +776 -0
- package/_gh-pages-deploy/styles/prettify.css +80 -0
- package/dist/css/app.5f246189.css +1 -0
- package/dist/css/chunk-vendors.f831c81d.css +1 -0
- package/dist/index.tmp +2 -6
- package/dist/js/app-legacy.73f3eae0.js +1 -0
- package/dist/js/app.73f3eae0.js +1 -0
- package/dist/js/chunk-vendors-legacy.7c56bceb.js +21 -0
- package/dist/js/chunk-vendors.7c56bceb.js +21 -0
- package/dist/w-web-sso.umd.js +6 -4
- package/dist/w-web-sso.umd.js.map +1 -1
- package/docs/WWebSso.html +2 -2
- package/docs/index.html +1 -1
- package/docs/server_WWebSso.mjs.html +1402 -0
- package/docs/src_components_Common_CheckYesNo.vue.html +195 -0
- package/g.getSettings.mjs +49 -3
- package/g.initialData.mjs +103 -78
- package/package.json +17 -13
- package/public/index.html +3 -16
- package/server/WWebSso.mjs +1330 -1146
- package/server/genRandomPassword.mjs +120 -0
- package/server/procCore.mjs +700 -176
- package/server/procLang.mjs +1231 -1047
- package/server/procProtect.mjs +40 -12
- package/server/procStaInfor.mjs +46 -26
- package/server/template/changePasswordEmail-cht.html +1 -0
- package/server/template/changePasswordEmail-eng.html +1 -0
- package/server/template/regVerifyEmail-cht.html +1 -0
- package/server/template/regVerifyEmail-eng.html +1 -0
- package/server/template/resetPasswordEmail-cht.html +1 -0
- package/server/template/resetPasswordEmail-eng.html +1 -0
- package/server/template/verifyEmailResult.html +26 -0
- package/settings.json +49 -12
- package/src/App.vue +30 -13
- package/src/components/Common/CheckYes.vue +18 -1
- package/src/components/Common/CheckYesNo.vue +32 -0
- package/src/components/Layout.vue +19 -8
- package/src/components/LayoutContent.vue +23 -0
- package/src/components/LayoutContentIps.vue +119 -111
- package/src/components/LayoutContentStaInfor.vue +146 -43
- package/src/components/LayoutContentTokens.vue +174 -215
- package/src/components/LayoutContentUserInfor.vue +518 -1017
- package/src/components/LayoutContentUsers.vue +475 -395
- package/src/components/PageLogin.vue +467 -21
- package/src/components/PageUser.vue +109 -37
- package/src/main.js +1 -5
- package/src/plugins/mShare.mjs +0 -215
- package/src/plugins/mUI.mjs +188 -66
- package/src/schema/tables/users.mjs +12 -1
- package/src/store/mutations.mjs +4 -4
- package/src/store/types.mjs +1 -1
- package/srv.mjs +21 -2
- package/db/wsso/ips/data.mdb +0 -0
- package/db/wsso/ips/lock.mdb +0 -0
- package/db/wsso/tokens/data.mdb +0 -0
- package/db/wsso/tokens/lock.mdb +0 -0
- package/db/wsso/users/data.mdb +0 -0
- package/db/wsso/users/lock.mdb +0 -0
- package/dist/css/app.beea8385.css +0 -1
- package/dist/js/app-legacy.93c91f21.js +0 -1
- package/dist/js/app.93c91f21.js +0 -1
- package/dist/js/chunk-vendors-legacy.3ce45600.js +0 -14
- package/dist/js/chunk-vendors.3ce45600.js +0 -14
- package/g.provideUsers.mjs +0 -45
- package/server/provideTabs.mjs +0 -71
- package/src/components/Common/LabelItem.vue +0 -106
- package/src/components/ruleGroup.vue.txt +0 -644
- package/src/plugins/mDataSupport.mjs +0 -23
- package/test/all.test.mjs +0 -10
package/src/plugins/mUI.mjs
CHANGED
|
@@ -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
|
-
|
|
56
|
-
|
|
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
|
|
136
|
+
//from URL ?lang= (轉址攜帶語系時最優先,例如登入後 redirect 帶當前語系)
|
|
112
137
|
if (!isestr(lang)) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
//
|
|
157
|
+
//from window (server 預設語系,fallback)
|
|
130
158
|
if (!isestr(lang)) {
|
|
131
|
-
|
|
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
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
|
|
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
|
-
|
|
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
|
-
|
|
370
|
+
//hideLoading, 結束預設隱藏loading, 只有當成功登入要轉址時不隱藏loading, 其他成功或失敗都要隱藏
|
|
371
|
+
let hideLoadingForEnd = true
|
|
326
372
|
|
|
327
|
-
|
|
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
|
|
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
|
-
|
|
413
|
-
|
|
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
|
-
|
|
419
|
-
|
|
484
|
+
//結束後不隱藏loading, 因開始轉址到轉跳會有一段時間, 持續顯示loading不隱藏, 避免使用者誤會登入失敗
|
|
485
|
+
hideLoadingForEnd = false
|
|
420
486
|
|
|
421
487
|
return
|
|
422
488
|
}
|
|
423
489
|
|
|
424
|
-
|
|
425
|
-
|
|
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
|
-
|
|
444
|
-
|
|
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
|
|
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('
|
|
583
|
+
// console.log('no token')
|
|
508
584
|
|
|
509
585
|
//reject
|
|
510
|
-
pm.reject('
|
|
586
|
+
pm.reject('no token')
|
|
511
587
|
|
|
512
588
|
return
|
|
513
589
|
}
|
|
514
590
|
|
|
515
591
|
//checkToken
|
|
516
|
-
|
|
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
|
-
|
|
574
|
-
|
|
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
|
-
|
|
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
|
|
package/src/store/mutations.mjs
CHANGED
|
@@ -26,7 +26,7 @@ let state = {
|
|
|
26
26
|
userToken: '',
|
|
27
27
|
userSelf: {},
|
|
28
28
|
|
|
29
|
-
lang: '
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
[types.UpdateConnState] (state, connState) {
|
|
58
|
+
state.connState = connState
|
|
59
|
+
},
|
|
60
60
|
|
|
61
61
|
[types.UpdateSyncState] (state, syncState) {
|
|
62
62
|
state.syncState = syncState
|
package/src/store/types.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const UpdateWebInfor = 'UpdateWebInfor'
|
|
2
2
|
export const UpdateLang = 'UpdateLang'
|
|
3
3
|
export const UpdateKpText = 'UpdateKpText'
|
|
4
|
-
|
|
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
|
+
`
|
package/db/wsso/ips/data.mdb
DELETED
|
Binary file
|
package/db/wsso/ips/lock.mdb
DELETED
|
Binary file
|
package/db/wsso/tokens/data.mdb
DELETED
|
Binary file
|
package/db/wsso/tokens/lock.mdb
DELETED
|
Binary file
|
package/db/wsso/users/data.mdb
DELETED
|
Binary file
|
package/db/wsso/users/lock.mdb
DELETED
|
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}
|