w-web-task 1.0.32 → 1.0.33
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/dist/index.tmp +1 -1
- package/dist/js/app-legacy.c161c06f.js +1 -0
- package/dist/js/app.c161c06f.js +1 -0
- package/dist/js/{chunk-vendors-legacy.03f6ffe7.js → chunk-vendors-legacy.59fd6af8.js} +3 -3
- package/dist/js/{chunk-vendors.03f6ffe7.js → chunk-vendors.59fd6af8.js} +3 -3
- package/dist/w-web-task.umd.js +2 -2
- package/dist/w-web-task.umd.js.map +1 -1
- package/docs/WWebTask.html +447 -6
- package/docs/global.html +240 -2
- package/docs/index.html +2 -2
- package/docs/server_WWebTask.mjs.html +61 -46
- package/docs/server_authorizeExec.mjs.html +129 -0
- package/docs/server_lockSave.mjs.html +2 -2
- package/docs/server_maskLog.mjs.html +2 -2
- package/docs/server_wrapInjected.mjs.html +2 -2
- package/docs/src_plugins_submitGuard.mjs.html +2 -2
- package/g.mOrm.mjs +2 -7
- package/package.json +10 -10
- package/server/WWebTask.mjs +59 -44
- package/server/authorizeExec.mjs +57 -0
- package/srv.mjs +11 -8
- package/dist/js/app-legacy.1c14647d.js +0 -1
- package/dist/js/app.1c14647d.js +0 -1
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<nav >
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebTask.html">WWebTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li></ul>
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebTask.html">WWebTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createAuthorizeExec">createAuthorizeExec</a></li><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li></ul>
|
|
33
33
|
|
|
34
34
|
</nav>
|
|
35
35
|
|
|
@@ -169,7 +169,7 @@ export { maskTok, maskQuery, maskUrl }
|
|
|
169
169
|
<br class="clear">
|
|
170
170
|
|
|
171
171
|
<footer>
|
|
172
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
172
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Oct 14 2026 08:01:17 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
173
173
|
</footer>
|
|
174
174
|
|
|
175
175
|
<script>prettyPrint();</script>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<nav >
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebTask.html">WWebTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li></ul>
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebTask.html">WWebTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createAuthorizeExec">createAuthorizeExec</a></li><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li></ul>
|
|
33
33
|
|
|
34
34
|
</nav>
|
|
35
35
|
|
|
@@ -170,7 +170,7 @@ export { wrapInjected, describeUpstream }
|
|
|
170
170
|
<br class="clear">
|
|
171
171
|
|
|
172
172
|
<footer>
|
|
173
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
173
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Oct 14 2026 08:01:17 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
174
174
|
</footer>
|
|
175
175
|
|
|
176
176
|
<script>prettyPrint();</script>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<nav >
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebTask.html">WWebTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li></ul>
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebTask.html">WWebTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createAuthorizeExec">createAuthorizeExec</a></li><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li></ul>
|
|
33
33
|
|
|
34
34
|
</nav>
|
|
35
35
|
|
|
@@ -150,7 +150,7 @@ export default submitGuard
|
|
|
150
150
|
<br class="clear">
|
|
151
151
|
|
|
152
152
|
<footer>
|
|
153
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
153
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Oct 14 2026 08:01:17 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
154
154
|
</footer>
|
|
155
155
|
|
|
156
156
|
<script>prettyPrint();</script>
|
package/g.mOrm.mjs
CHANGED
|
@@ -11,13 +11,8 @@ let st = getSettings()
|
|
|
11
11
|
let url = st.dbUrl
|
|
12
12
|
let db = st.dbName
|
|
13
13
|
|
|
14
|
-
//WServOrm
|
|
15
|
-
let
|
|
16
|
-
getUserById: null,
|
|
17
|
-
useCheckUser: false,
|
|
18
|
-
useExcludeWhenNotAdmin: false,
|
|
19
|
-
}
|
|
20
|
-
let r = WServOrm(ds, WOrm, url, db, opt)
|
|
14
|
+
//WServOrm(w-serv-orm 已移除之 useCheckUser / getUserById / useExcludeWhenNotAdmin 不再傳入, spec D17)
|
|
15
|
+
let r = WServOrm(ds, WOrm, url, db)
|
|
21
16
|
let { woItems, procOrm } = r
|
|
22
17
|
|
|
23
18
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w-web-task",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"main": "dist/w-web-task.umd.js",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"axios": "^1.18.1",
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"json5": "^2.2.3",
|
|
9
9
|
"showdown": "^2.1.0",
|
|
10
10
|
"w-aggrid-vue": "^2.1.8",
|
|
11
|
-
"w-component-vue": "^2.5.
|
|
12
|
-
"w-data-collector": "^1.0.
|
|
13
|
-
"w-serv-hapi": "^1.1.
|
|
14
|
-
"w-serv-orm": "^1.1.
|
|
15
|
-
"w-syslog": "^1.0.
|
|
16
|
-
"w-ui-loginout": "^1.0.
|
|
17
|
-
"wsemi": "^1.9.
|
|
11
|
+
"w-component-vue": "^2.5.29",
|
|
12
|
+
"w-data-collector": "^1.0.46",
|
|
13
|
+
"w-serv-hapi": "^1.1.6",
|
|
14
|
+
"w-serv-orm": "^1.1.10",
|
|
15
|
+
"w-syslog": "^1.0.33",
|
|
16
|
+
"w-ui-loginout": "^1.0.32",
|
|
17
|
+
"wsemi": "^1.9.16"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@vue/cli-plugin-babel": "^5.0.8",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"eslint-plugin-vue": "^9.10.0",
|
|
30
30
|
"vue": "^2.7.16",
|
|
31
31
|
"vuex": "^3.6.2",
|
|
32
|
-
"w-orm-lmdb": "^1.0.
|
|
33
|
-
"w-package-tools": "^1.1.
|
|
32
|
+
"w-orm-lmdb": "^1.0.39",
|
|
33
|
+
"w-package-tools": "^1.1.18",
|
|
34
34
|
"w-package-tools-e2e": "^1.0.6",
|
|
35
35
|
"w-screenctl": "^1.0.25"
|
|
36
36
|
},
|
package/server/WWebTask.mjs
CHANGED
|
@@ -22,9 +22,11 @@ import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
|
22
22
|
import replace from 'wsemi/src/replace.mjs'
|
|
23
23
|
import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs'
|
|
24
24
|
import WServOrm from 'w-serv-orm/src/WServOrm.mjs'
|
|
25
|
+
import checkOptRemoved from 'w-serv-orm/src/checkOptRemoved.mjs'
|
|
25
26
|
import procLang from './procLang.mjs'
|
|
26
27
|
import procCore from './procCore.mjs'
|
|
27
28
|
import createLockSave from './lockSave.mjs'
|
|
29
|
+
import createAuthorizeExec from './authorizeExec.mjs'
|
|
28
30
|
import srLogInit from './srLog.mjs'
|
|
29
31
|
import { maskTok, maskQuery } from './maskLog.mjs'
|
|
30
32
|
import { wrapInjected } from './wrapInjected.mjs'
|
|
@@ -39,11 +41,23 @@ import ds from '../src/schema/index.mjs'
|
|
|
39
41
|
* @param {String} url 輸入資料庫連線字串,例如w-orm-lmdb為'./db'
|
|
40
42
|
* @param {String} db 輸入資料庫名稱字串
|
|
41
43
|
* @param {Function} getUserByToken 輸入處理函數,函數會傳入使用者token,通過此函數處理後並回傳使用者資訊物件,並至少須提供'id'、'email'、'name'、'isAdmin'欄位,且'isAdmin'限輸入'y'或'n'
|
|
42
|
-
* @param {Function} verifyClientUser
|
|
43
|
-
* @param {Function} verifyAppUser
|
|
44
|
+
* @param {Function} verifyClientUser 輸入驗證瀏覽使用者身份之處理函數,函數會傳入使用者資訊物件與來源字串(from),通過此函數識別後回傳布林值,允許使用者回傳true,反之回傳false。作用於登入檢查(/api/getUserByToken,from為'getUserByToken')與前端資料通道之每次請求(連線閘,from為w-converhp之apiType如'main'),兩者同一判定;拋錯或reject視同不允許
|
|
45
|
+
* @param {Function} verifyAppUser 輸入驗證應用程序使用者身份之處理函數,函數會傳入使用者資訊物件與來源字串(from,為API名稱),通過此函數識別後回傳布林值,允許使用者回傳true,反之回傳false。作用於對外HTTP REST API(agent面);拋錯或reject視同不允許
|
|
44
46
|
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
45
47
|
* @param {Integer} [opt.serverPort=11008] 輸入伺服器通訊port,預設11008
|
|
46
|
-
* @
|
|
48
|
+
* @param {String} [opt.subfolder=''] 輸入網站子目錄字串,例如'mtask',預設''
|
|
49
|
+
* @param {String} [opt.urlRedirect=''] 輸入未登入時導向之網址字串(例如SSO登入頁),預設''
|
|
50
|
+
* @param {String} [opt.showLanguage='y'] 輸入是否顯示語系選單字串,可選'y'、'n',預設'y'
|
|
51
|
+
* @param {String} [opt.language='eng'] 輸入初始語系字串,可選'eng'、'cht',預設'eng'
|
|
52
|
+
* @param {Object} [opt.webName={}] 輸入網站名稱物件,key為語系而值為字串,預設{}
|
|
53
|
+
* @param {Object} [opt.webDescription={}] 輸入網站說明物件,key為語系而值為字串,預設{}
|
|
54
|
+
* @param {String} [opt.webLogo=''] 輸入網站logo字串,預設''
|
|
55
|
+
* @param {Object} [opt.kpLangExt={}] 輸入擴充語系物件,預設{}
|
|
56
|
+
* @param {String} [opt.logFd='./logs'] 輸入後端log資料夾字串,相對路徑以建構時之工作目錄解析,資料夾不可建立時(例如上層為檔案)於建構時拋錯(w-syslog 1.0.33起;於資料庫建立之前),預設'./logs'
|
|
57
|
+
* @param {String} [opt.logInterval='hr'] 輸入後端log分檔模式字串,可選'day'、'hr',預設'hr'
|
|
58
|
+
* @param {Integer} [opt.archiveAfterDays=30] 輸入終態任務與舊訊息逾此天數搬至冷表之天數,小於等於0為停用,預設30
|
|
59
|
+
* 已移除之設定:useCheckUser、getUserById、useExcludeWhenNotAdmin(w-serv-orm已移除),給予undefined、null、false以外之值即於建構時拋錯(於任何副作用之前)
|
|
60
|
+
* @returns {Object} 回傳w-serv-hapi之伺服器事件物件,可監聽error事件;w-serv-hapi 1.1.6起另帶ready與stop,惟stop只停止伺服器與其下游,不釋放本套件之計時器(封存掃描、雙擊防護占位)與資料庫連線,本套件以結束行程收尾
|
|
47
61
|
*/
|
|
48
62
|
function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser, opt = {}) {
|
|
49
63
|
let instWServHapiServer = null
|
|
@@ -91,6 +105,11 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
91
105
|
}
|
|
92
106
|
|
|
93
107
|
|
|
108
|
+
//checkOptRemoved: w-serv-orm 已移除之 useCheckUser / getUserById / useExcludeWhenNotAdmin(spec D17), 本套件不讀不轉交;
|
|
109
|
+
//給予 undefined / null / false 以外之值即同步拋 w-serv-orm 之原文訊息. 置於任何副作用(srLog 之 log 目錄、資料庫)之前; 規則與訊息由 w-serv-orm 單一擁有
|
|
110
|
+
checkOptRemoved(opt)
|
|
111
|
+
|
|
112
|
+
|
|
94
113
|
//serverPort
|
|
95
114
|
let serverPort = get(opt, 'serverPort')
|
|
96
115
|
if (!ispint(serverPort)) {
|
|
@@ -99,18 +118,6 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
99
118
|
serverPort = cint(serverPort)
|
|
100
119
|
|
|
101
120
|
|
|
102
|
-
//useCheckUser
|
|
103
|
-
let useCheckUser = get(opt, 'useCheckUser', false)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
//getUserById
|
|
107
|
-
let getUserById = get(opt, 'getUserById', null)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
//useExcludeWhenNotAdmin
|
|
111
|
-
let useExcludeWhenNotAdmin = get(opt, 'useExcludeWhenNotAdmin', false)
|
|
112
|
-
|
|
113
|
-
|
|
114
121
|
//webName
|
|
115
122
|
let webName = get(opt, 'webName', {})
|
|
116
123
|
|
|
@@ -153,14 +160,13 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
153
160
|
let kpLang = procLang({ kpLangExt, webName, webDescription })
|
|
154
161
|
|
|
155
162
|
|
|
156
|
-
//srLog(後端 log;錯誤一律 log err-key
|
|
163
|
+
//srLog(後端 log;錯誤一律 log err-key 供識別)
|
|
157
164
|
let srLog = srLogInit(opt)
|
|
158
165
|
|
|
159
166
|
//注入函數一律經 wrapInjected 包裝後使用(W 契約,spec/設計要點與取捨.md D15):
|
|
160
|
-
//部署方注入之 getUserByToken / verifyClientUser / verifyAppUser
|
|
167
|
+
//部署方注入之 getUserByToken / verifyClientUser / verifyAppUser 同步拋錯或 reject 時,視同否定結果(查無 → null、無權限 → false),
|
|
161
168
|
//走各呼叫點既有分支回自家 key;失敗原文(舊版 sso helper 為已代入權杖之完整網址)不上拋、不入 log,只記 describeUpstream 之 key 或型別。
|
|
162
169
|
//以包裝版取代參數本身 → 其後所有呼叫點(含日後新增者)結構上只可能用到包裝版;包裝處記 warn(因),呼叫點記 error(果)。
|
|
163
|
-
//getUserById 選填(useCheckUser=true 時由 WServOrm 呼叫;原 reject 原文經 execute 之 pm2resolve 回前端),有給才包裝,查無由 WServOrm 既有分支拒絕。
|
|
164
170
|
let onInjectFail = (name) => {
|
|
165
171
|
return (d) => {
|
|
166
172
|
srLog.warn({ event: `inject-${name}-fail`, ...d })
|
|
@@ -169,20 +175,12 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
169
175
|
getUserByToken = wrapInjected(getUserByToken, { failValue: null, onFail: onInjectFail('getUserByToken') })
|
|
170
176
|
verifyClientUser = wrapInjected(verifyClientUser, { failValue: false, onFail: onInjectFail('verifyClientUser') })
|
|
171
177
|
verifyAppUser = wrapInjected(verifyAppUser, { failValue: false, onFail: onInjectFail('verifyAppUser') })
|
|
172
|
-
if (isfun(getUserById)) {
|
|
173
|
-
getUserById = wrapInjected(getUserById, { failValue: null, onFail: onInjectFail('getUserById') })
|
|
174
|
-
}
|
|
175
178
|
|
|
176
179
|
|
|
177
180
|
//WServOrm
|
|
178
|
-
let optWServOrm = {
|
|
179
|
-
useCheckUser,
|
|
180
|
-
getUserById,
|
|
181
|
-
useExcludeWhenNotAdmin,
|
|
182
|
-
}
|
|
183
181
|
let wp = {}
|
|
184
182
|
try {
|
|
185
|
-
wp = WServOrm(ds, WOrm, url, db
|
|
183
|
+
wp = WServOrm(ds, WOrm, url, db)
|
|
186
184
|
}
|
|
187
185
|
catch (err) {
|
|
188
186
|
//ORM 為必要依賴:初始化失敗即 fail-fast,不以 wp={} 帶 undefined woItems/procOrm 殘缺啟動
|
|
@@ -345,12 +343,21 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
345
343
|
|
|
346
344
|
//p
|
|
347
345
|
let p = {
|
|
348
|
-
checkToken
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
346
|
+
//checkToken:資料通道之連線閘(verifyConn 用),回傳是否放行(spec D17 決策 3)。
|
|
347
|
+
//認證:getTokenUser,與 HTTP 路徑同一出口(S8);失敗 reject 自家 key(w-converhp 回 permission denied、不寫 srLog,D15)。
|
|
348
|
+
//授權:已包裝之 verifyClientUser(拋錯或 reject 視同 false 並記 inject warn),與登入檢查 getAndVerifyClientUser 同一判定;from 為 w-converhp 之 apiType。
|
|
349
|
+
checkToken: async(token, from = '') => {
|
|
350
|
+
|
|
351
|
+
//getTokenUser
|
|
352
|
+
let user = await getTokenUser(token)
|
|
353
|
+
|
|
354
|
+
//verifyClientUser
|
|
355
|
+
let b = verifyClientUser(user, from)
|
|
356
|
+
if (ispm(b)) {
|
|
357
|
+
b = await b
|
|
358
|
+
}
|
|
352
359
|
|
|
353
|
-
return
|
|
360
|
+
return !!b
|
|
354
361
|
},
|
|
355
362
|
}
|
|
356
363
|
|
|
@@ -950,15 +957,16 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
950
957
|
]
|
|
951
958
|
|
|
952
959
|
|
|
953
|
-
//tableNamesExec, tableNamesSync
|
|
954
|
-
|
|
955
|
-
//(
|
|
956
|
-
//
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
+
//tableNamesExec, tableNamesSync, methodsExec
|
|
961
|
+
//資料通道之表操作只開 select, 供前端同步 channels/channelMembers (spec D17 決策 2); 寫入一律走 kpFunExt 業務函式
|
|
962
|
+
//(D16 lockSave、確保成員列 kmx、D7 游標身分皆在其內), 避免前端或直打 /api/main 之 ORM 直寫繞過之 (2026-10-14 前曾開 insert/save/del).
|
|
963
|
+
//tasks/messages 之生命週期/原子寫入亦一律走 kpFunExt (對應 spec 設計總覽 §6.2 註 與 設計要點與取捨 D2).
|
|
964
|
+
//tableNamesSync 須與 tableNamesExec 對齊且 methodsExec 須含 select: 同步引擎收到某表 tag 變更時會呼叫 kpExec[table].select() 去重抓
|
|
965
|
+
//(w-serv-webdata 1.1.12 於建構時檢核). messages/tasks 前端一律走 $fapi getMessages/getTasks 按需拉取 (非 ORM change 推送), 故不放進 sync.
|
|
966
|
+
//methodsExec 為單一定義: 同時交 w-serv-hapi 綁定與 authorizeExec 判斷
|
|
960
967
|
let tableNamesExec = ['channels', 'channelMembers']
|
|
961
968
|
let tableNamesSync = tableNamesExec
|
|
969
|
+
let methodsExec = ['select']
|
|
962
970
|
|
|
963
971
|
|
|
964
972
|
//WServHapiServer
|
|
@@ -982,11 +990,17 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
982
990
|
return false
|
|
983
991
|
}
|
|
984
992
|
|
|
985
|
-
//checkToken
|
|
986
|
-
let b = await p.checkToken(token)
|
|
993
|
+
//checkToken:token 認證(解析 user + 驗欄位齊備; 失敗 reject 自家 key)+ 瀏覽使用者授權(部署方之 verifyClientUser, 與登入檢查同一強度; spec D17 決策 3)
|
|
994
|
+
let b = await p.checkToken(token, apiType)
|
|
987
995
|
|
|
988
|
-
|
|
989
|
-
|
|
996
|
+
//check
|
|
997
|
+
if (!b) {
|
|
998
|
+
srLog.error({ event: 'verifyConn', err: 'errUserNoPermission', apiType }) //授權不通過須入 log 供稽核/統計; 只記 key 與 apiType, 不記權杖與使用者物件
|
|
999
|
+
return false
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
srLog.info({ event: 'verifyConn', apiType }) //連線之認證與授權通過
|
|
1003
|
+
return true
|
|
990
1004
|
},
|
|
991
1005
|
getUserIdByToken: async (token) => { //可使用async或sync函數
|
|
992
1006
|
//fail-closed(S9,對齊 perm):token 非字串或查無 userId(含上游失敗經 wrapInjected 視同查無)一律 reject,
|
|
@@ -1008,7 +1022,8 @@ function WWebTask(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1008
1022
|
kpOrm: woItems,
|
|
1009
1023
|
operOrm: procOrm, //procOrm的輸入為: userId, tableName, methodName, input
|
|
1010
1024
|
tableNamesExec,
|
|
1011
|
-
methodsExec
|
|
1025
|
+
methodsExec,
|
|
1026
|
+
authorizeExec: createAuthorizeExec({ methodsExec, srLog }), //w-serv-webdata 1.1.7 起 useDbOrm=true 時必填; 只放行已識別使用者之 select, 拒絕記 srLog (spec D17)
|
|
1012
1027
|
tableNamesSync,
|
|
1013
1028
|
kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數 (皆經 wrapErrLog)
|
|
1014
1029
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import get from 'lodash-es/get.js'
|
|
2
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
3
|
+
import isearr from 'wsemi/src/isearr.mjs'
|
|
4
|
+
import isfun from 'wsemi/src/isfun.mjs'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 資料通道表操作之授權函數(交 w-serv-hapi / w-serv-webdata 之 opt.authorizeExec; spec D17 決策 2)
|
|
9
|
+
*
|
|
10
|
+
* w-serv-webdata 1.1.7 起 useDbOrm=true 時必填, 前端呼叫表操作(如同步之 channels.select)時於 operOrm 之前呼叫,
|
|
11
|
+
* 回傳嚴格等於 true 才放行, 其他值一律回應 'permission denied' 且不呼叫 operOrm.
|
|
12
|
+
* 本套件之資料通道只開放 methodsExec 所列方法(['select'], 供前端同步); 寫入一律經 kpFunExt(D16 lockSave、確保成員列 kmx、D7 游標身分皆在其內).
|
|
13
|
+
* 放行: userId 為非空字串, 且 methodName 屬 methodsExec; 回傳一律為布林.
|
|
14
|
+
* 拒絕: 回 false 並記 srLog.error({ event: 'authorizeExec', err, tableName, methodName }), userId 缺為 'errUserIdMissing', 方法不在清單為 'errUserNoPermission'.
|
|
15
|
+
* getUserIdByToken 已 fail-closed 且 w-serv-webdata 只綁定 methodsExec 之方法, 故兩個拒絕分支於正常呼叫不會發生, 屬縱深防護.
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} opt 輸入設定物件
|
|
18
|
+
* @param {Array} opt.methodsExec 輸入允許之表操作方法陣列(須與交 w-serv-hapi 之 methodsExec 為同一陣列), 須為非空陣列
|
|
19
|
+
* @param {Object} opt.srLog 輸入後端 log 物件, 須具 error 函數
|
|
20
|
+
* @returns {Function} 回傳 ({ userId, tableName, methodName }) => Boolean
|
|
21
|
+
*/
|
|
22
|
+
function createAuthorizeExec(opt = {}) {
|
|
23
|
+
|
|
24
|
+
//methodsExec
|
|
25
|
+
let methodsExec = get(opt, 'methodsExec')
|
|
26
|
+
if (!isearr(methodsExec)) {
|
|
27
|
+
throw new Error('invalid opt.methodsExec')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//srLog
|
|
31
|
+
let srLog = get(opt, 'srLog')
|
|
32
|
+
if (!isfun(get(srLog, 'error'))) {
|
|
33
|
+
throw new Error('invalid opt.srLog')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let authorizeExec = ({ userId, tableName, methodName } = {}) => {
|
|
37
|
+
|
|
38
|
+
//check userId
|
|
39
|
+
if (!isestr(userId)) {
|
|
40
|
+
srLog.error({ event: 'authorizeExec', err: 'errUserIdMissing', tableName, methodName })
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//check methodName
|
|
45
|
+
if (!methodsExec.includes(methodName)) {
|
|
46
|
+
srLog.error({ event: 'authorizeExec', err: 'errUserNoPermission', tableName, methodName })
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return authorizeExec
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
export default createAuthorizeExec
|
package/srv.mjs
CHANGED
|
@@ -23,10 +23,6 @@ let ssoAppToken = st.ssoAppToken
|
|
|
23
23
|
let ssoLoginUrl = st.ssoLoginUrl
|
|
24
24
|
let opt = {
|
|
25
25
|
|
|
26
|
-
useCheckUser: false,
|
|
27
|
-
getUserById: null,
|
|
28
|
-
useExcludeWhenNotAdmin: false,
|
|
29
|
-
|
|
30
26
|
serverPort: get(stApp, 'serverPort', 11008),
|
|
31
27
|
subfolder: '', //mtask
|
|
32
28
|
urlRedirect: ssoLoginUrl, //未登入時導向SSO登入頁, 本機測試時得先編譯, 再瀏覽: http://localhost:11008/
|
|
@@ -82,6 +78,11 @@ let getUserByToken = async (token) => {
|
|
|
82
78
|
if (token === '{token-for-verify-throw}' && process.env.NODE_ENV !== 'production') {
|
|
83
79
|
return { id: 'id-for-verify-throw', name: 'verify-throw', email: 'verify-throw@example.com', isAdmin: 'y' }
|
|
84
80
|
}
|
|
81
|
+
//'{token-for-nonadmin}' 為測試用權杖 (test/api-dataChannel), 同樣受 NODE_ENV 守門: 解析為有效但非系統管理者之使用者 (isAdmin='n'),
|
|
82
|
+
//下方 verifyClientUser 拒絕之, 供驗證資料通道之連線閘與登入檢查同一授權強度 (spec D17).
|
|
83
|
+
if (token === '{token-for-nonadmin}' && process.env.NODE_ENV !== 'production') {
|
|
84
|
+
return { id: 'id-for-nonadmin', name: 'nonadmin', email: 'nonadmin@example.com', isAdmin: 'n' }
|
|
85
|
+
}
|
|
85
86
|
//未設定 SSO app token 時(本機開發未接SSO), 不打SSO直接拒絕
|
|
86
87
|
if (!ssoAppToken) {
|
|
87
88
|
console.log('ssoAppToken 未設定, 略過 SSO 驗證')
|
|
@@ -108,8 +109,9 @@ let getUserByToken = async (token) => {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
let verifyClientUser = (user, from) => {
|
|
111
|
-
|
|
112
|
-
console.log('
|
|
112
|
+
//不於每次呼叫印出使用者物件: 登入檢查與資料通道之連線閘(前端每 2 秒輪詢)皆經此函數 (spec D17; 同 w-web-perm srv.mjs)
|
|
113
|
+
// console.log('verifyClientUser/user', user)
|
|
114
|
+
//於生產環境時得加入限制瀏覽器使用者身份機制 (from 為 'getUserByToken' 或資料通道之 apiType, 如 'main')
|
|
113
115
|
//測試用 (受 NODE_ENV 守門): 合成使用者 id-for-verify-throw (見 getUserByToken 之 '{token-for-verify-throw}') 一律拋出夾合成秘密之 Error
|
|
114
116
|
if (get(user, 'id', '') === 'id-for-verify-throw' && process.env.NODE_ENV !== 'production') {
|
|
115
117
|
throw new Error('SYNTH-VERIFY-SECRET-FOR-TEST')
|
|
@@ -119,8 +121,9 @@ let verifyClientUser = (user, from) => {
|
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
let verifyAppUser = (user, from) => {
|
|
122
|
-
|
|
123
|
-
console.log('
|
|
124
|
+
//不於每次呼叫印出使用者物件: agent 之每次 HTTP REST 請求皆經此函數 (與 verifyClientUser 對稱; 同 w-web-perm srv.mjs)
|
|
125
|
+
// console.log('verifyAppUser/user', user)
|
|
126
|
+
//於生產環境時得加入限制應用程式使用者身份機制
|
|
124
127
|
//測試用 (受 NODE_ENV 守門): 合成使用者 id-for-verify-throw (見 getUserByToken 之 '{token-for-verify-throw}') 一律拋出夾合成秘密之 Error
|
|
125
128
|
if (get(user, 'id', '') === 'id-for-verify-throw' && process.env.NODE_ENV !== 'production') {
|
|
126
129
|
throw new Error('SYNTH-VERIFY-SECRET-FOR-TEST')
|