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.
- package/.github/workflows/ci-test.yml +2 -2
- package/README.md +5 -5
- package/dist/css/app.8781355a.css +1 -0
- package/dist/css/{chunk-vendors.f149e124.css → chunk-vendors.58917286.css} +1 -1
- package/dist/index.tmp +2 -2
- package/dist/js/app-legacy.b2754bb1.js +1 -0
- package/dist/js/app.b2754bb1.js +1 -0
- package/dist/js/chunk-vendors-legacy.c14a1ed1.js +21 -0
- package/dist/js/chunk-vendors.c14a1ed1.js +21 -0
- package/dist/w-web-perm.umd.js +2 -2
- package/dist/w-web-perm.umd.js.map +1 -1
- package/docs/WWebPerm.html +3 -3
- package/docs/WWebPerm.mjs.html +162 -210
- package/docs/index.html +1 -1
- package/logs/2026-06-19T16.log +191 -0
- package/logs/2026-06-19T23.log +0 -0
- package/logs/2026-06-20T00.log +207 -0
- package/logs/2026-06-20T11.log +221 -0
- package/logs/2026-06-20T12.log +146 -0
- package/logs/2026-06-20T13.log +134 -0
- package/logs/2026-06-20T14.log +296 -0
- package/logs/2026-06-20T15.log +225 -0
- package/logs/2026-06-20T16.log +174 -0
- package/logs/2026-06-21T16.log +110 -0
- package/logs/2026-06-21T17.log +301 -0
- package/logs/2026-06-21T18.log +238 -0
- package/logs/2026-06-21T19.log +141 -0
- package/logs/2026-06-21T20.log +99 -0
- package/logs/2026-06-21T21.log +143 -0
- package/logs/2026-06-21T23.log +26 -0
- package/logs/2026-06-22T00.log +33 -0
- package/logs/2026-06-22T08.log +235 -0
- package/logs/2026-06-22T09.log +246 -0
- package/logs/2026-06-22T10.log +301 -0
- package/logs/2026-06-22T11.log +140 -0
- package/logs/2026-06-22T12.log +22 -0
- package/logs/2026-06-22T14.log +44 -0
- package/logs/2026-06-22T23.log +951 -0
- package/logs/2026-06-23T00.log +263 -0
- package/logs/2026-06-23T08.log +611 -0
- package/logs/2026-06-30T21.log +3609 -0
- package/logs/2026-06-30T22.log +3682 -0
- package/logs/2026-06-30T23.log +592 -0
- package/logs/2026-07-01T12.log +0 -0
- package/logs/2026-07-09T22.log +2220 -0
- package/logs/2026-07-09T23.log +1140 -0
- package/logs/2026-07-10T12.log +6 -0
- package/logs/2026-07-10T13.log +351 -0
- package/logs/2026-07-10T16.log +1272 -0
- package/logs/2026-07-10T19.log +6 -0
- package/logs/2026-07-10T20.log +1883 -0
- package/logs/2026-07-10T21.log +3505 -0
- package/logs/2026-07-10T22.log +3395 -0
- package/logs/2026-07-11T00.log +1338 -0
- package/logs/2026-07-11T01.log +2492 -0
- package/logs/2026-07-11T17.log +19 -0
- package/package.json +23 -16
- package/public/index.html +2 -2
- package/server/WWebPerm.mjs +161 -209
- package/server/procCore.mjs +187 -0
- package/server/procLang.mjs +276 -60
- package/server/procStaInfor.mjs +128 -0
- package/server/provideTabs.mjs +1 -1
- package/server/srLog.mjs +30 -0
- package/server/staLogs/filterVpfsByWindow.mjs +27 -0
- package/server/staLogs/staEvent.callWorker.mjs +46 -0
- package/server/staLogs/staEvent.mjs +118 -0
- package/server/staLogs/staEvent.shellWorker.mjs +19 -0
- package/server/staLogs/staEventTable.mjs +102 -0
- package/settings.json +43 -0
- package/src/components/Common/CheckYes.vue +18 -1
- package/src/components/Layout.vue +1 -1
- package/src/components/LayoutContent.vue +13 -3
- package/src/components/LayoutContentGrups.vue +32 -25
- package/src/components/LayoutContentPemis.vue +32 -25
- package/src/components/LayoutContentStaInfor.vue +534 -0
- package/src/components/LayoutContentTargets.vue +35 -28
- package/src/components/LayoutContentUsers.vue +32 -25
- package/src/components/LayoutState.vue +5 -0
- package/src/components/VeCgrups.vue +19 -9
- package/src/components/VeCpemis.vue +19 -9
- package/src/components/VeCrules.vue +19 -9
- package/src/components/VeGrupBlngUsers.vue +35 -29
- package/src/components/VePemiBlngGrups.vue +35 -29
- package/src/getPerm.mjs +7 -17
- package/src/getPermUserInfor.mjs +8 -18
- package/src/main.js +4 -9
- package/src/perm.mjs +3 -4
- package/src/plugins/mShare.mjs +8 -13
- package/src/plugins/mUI.mjs +7 -44
- package/src/store/mutations.mjs +0 -10
- package/src/store/types.mjs +0 -2
- package/srv.mjs +76 -101
- package/tableTags.json +1 -1
- package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +450 -0
- package/db/wperm/grups/data.mdb +0 -0
- package/db/wperm/grups/lock.mdb +0 -0
- package/db/wperm/pemis/data.mdb +0 -0
- package/db/wperm/pemis/lock.mdb +0 -0
- package/db/wperm/targets/data.mdb +0 -0
- package/db/wperm/targets/lock.mdb +0 -0
- package/db/wperm/users/data.mdb +0 -0
- package/db/wperm/users/lock.mdb +0 -0
- package/dist/css/app.30e81bfe.css +0 -1
- package/dist/js/app-legacy.3324392e.js +0 -1
- package/dist/js/app.3324392e.js +0 -1
- package/dist/js/chunk-vendors-legacy.e8703728.js +0 -21
- package/dist/js/chunk-vendors.e8703728.js +0 -21
- package/src/plugins/mDataSelectorSchema.mjs +0 -30
- package/tableTags-web-perm.json +0 -1
- package/test/getUserRules.test.mjs +0 -899
package/server/WWebPerm.mjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import fs from 'fs'
|
|
3
3
|
import get from 'lodash-es/get.js'
|
|
4
|
-
import each from 'lodash-es/each.js'
|
|
5
4
|
import map from 'lodash-es/map.js'
|
|
6
5
|
import keys from 'lodash-es/keys.js'
|
|
7
|
-
import size from 'lodash-es/size.js'
|
|
8
6
|
import join from 'lodash-es/join.js'
|
|
9
7
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
10
8
|
import isestr from 'wsemi/src/isestr.mjs'
|
|
@@ -23,15 +21,16 @@ import fsIsFolder from 'wsemi/src/fsIsFolder.mjs'
|
|
|
23
21
|
import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
24
22
|
import replace from 'wsemi/src/replace.mjs'
|
|
25
23
|
import strdelleft from 'wsemi/src/strdelleft.mjs'
|
|
26
|
-
import haskey from 'wsemi/src/haskey.mjs'
|
|
27
|
-
import arrHas from 'wsemi/src/arrHas.mjs'
|
|
28
|
-
import ltdtDiffByKey from 'wsemi/src/ltdtDiffByKey.mjs'
|
|
29
24
|
import ltdtmapping from 'wsemi/src/ltdtmapping.mjs'
|
|
25
|
+
import pmKeyMutex from 'wsemi/src/pmKeyMutex.mjs'
|
|
30
26
|
import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs'
|
|
31
27
|
import WServOrm from 'w-serv-orm/src/WServOrm.mjs'
|
|
32
28
|
import ds from '../src/schema/index.mjs'
|
|
33
29
|
import { getUserRules } from '../src/plugins/mShare.mjs'
|
|
30
|
+
import procCore from './procCore.mjs'
|
|
34
31
|
import procLang from './procLang.mjs'
|
|
32
|
+
import srLogInit from './srLog.mjs'
|
|
33
|
+
import procStaInfor from './procStaInfor.mjs'
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
/**
|
|
@@ -41,7 +40,7 @@ import procLang from './procLang.mjs'
|
|
|
41
40
|
* @param {Function} WOrm 輸入資料庫ORM函數
|
|
42
41
|
* @param {String} url 輸入資料庫連線字串,例如w-orm-lmdb為'./db',或w-orm-mongodb為'mongodb://username:password@$127.0.0.1:27017'
|
|
43
42
|
* @param {String} db 輸入資料庫名稱字串
|
|
44
|
-
* @param {Function} getUserByToken 輸入處理函數,函數會傳入使用者token,通過此函數處理後並回傳使用者資訊物件,並至少須提供'id'、'email'、'name'、'isAdmin'欄位,且'isAdmin'限輸入'y'或'n'
|
|
43
|
+
* @param {Function} getUserByToken 輸入處理函數,函數會傳入使用者token,通過此函數處理後並回傳使用者資訊物件,並至少須提供'id'、'email'、'name'、'isAdmin'欄位,且'isAdmin'限輸入'y'或'n'。注意: token 回傳之'isAdmin'僅供識別,權限系統一律以自身users表該使用者之'isAdmin'欄位值為權威,不會被 token 宣稱之值複寫
|
|
45
44
|
* @param {Function} verifyClientUser 輸入驗證瀏覽使用者身份之處理函數,函數會傳入使用者資訊物件,通過此函數識別後回傳布林值,允許使用者回傳true,反之回傳false
|
|
46
45
|
* @param {Function} verifyAppUser 輸入驗證應用程序使用者身份之處理函數,函數會傳入使用者資訊物件,通過此函數識別後回傳布林值,允許使用者回傳true,反之回傳false
|
|
47
46
|
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
@@ -268,6 +267,10 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
268
267
|
let kpLang = procLang({ kpLangExt, webName, webDescription })
|
|
269
268
|
|
|
270
269
|
|
|
270
|
+
//srLog
|
|
271
|
+
let srLog = srLogInit(opt)
|
|
272
|
+
|
|
273
|
+
|
|
271
274
|
//WServOrm
|
|
272
275
|
let optWServOrm = {
|
|
273
276
|
useCheckUser,
|
|
@@ -280,12 +283,35 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
280
283
|
}
|
|
281
284
|
catch (err) {
|
|
282
285
|
console.log(err)
|
|
286
|
+
srLog.error({ event: 'WServOrm-init-error', msg: (err && err.message) || 'WServOrmInitFailed' })
|
|
287
|
+
throw err //fail-fast: ORM 初始化失敗直接終止啟動, 不以 wp={} 繼續組裝出「port 起得來但 woItems/procOrm 為 undefined、CRUD 全 crash」的半死伺服器
|
|
283
288
|
}
|
|
284
289
|
let { woItems, procOrm } = wp
|
|
285
290
|
|
|
286
291
|
|
|
292
|
+
//pmKeyMutex: per-key in-memory mutex, 同 key 序列化、不同 key 並行.
|
|
293
|
+
//perm 為「整表批次 diff」寫入, key 粒度為 {op}:{keyTable}, 防同表並行 race (lost update).
|
|
294
|
+
let kmx = pmKeyMutex()
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
//procCore: 整表批次 diff 寫入邏輯 (updateTabItems + updateTargets/Pemis/Grups/Users)
|
|
298
|
+
let pc = procCore(woItems, procOrm, { srLog, kmx })
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
//procStaInfor: 統計資訊, fdLog 對齊 srLog 使用同一目錄(讀 settings.logFd, fallback 邏輯同 srLog.mjs); mock 由 settings.staEventMock 注入(e2e 統計圖穩定用)
|
|
302
|
+
let logFd = get(opt, 'logFd', '')
|
|
303
|
+
if (!isestr(logFd)) {
|
|
304
|
+
logFd = './_logs'
|
|
305
|
+
}
|
|
306
|
+
let psi = procStaInfor({ fdLog: logFd, mock: get(opt, 'staEventMock', false) })
|
|
307
|
+
|
|
308
|
+
|
|
287
309
|
//getWebInfor
|
|
288
310
|
let getWebInfor = (userId) => {
|
|
311
|
+
|
|
312
|
+
//info
|
|
313
|
+
srLog.info({ event: 'getWebInfor-success', userId })
|
|
314
|
+
|
|
289
315
|
return {
|
|
290
316
|
|
|
291
317
|
// webName, //已併入kpLang
|
|
@@ -348,162 +374,32 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
348
374
|
// }
|
|
349
375
|
|
|
350
376
|
|
|
351
|
-
//updateTabItems
|
|
352
|
-
let updateTabItems = async (keyTable, userId, rows, keyDetect) => {
|
|
353
|
-
// console.log('updateTabItems', keyTable, userId, rows.length, keyDetect)
|
|
354
|
-
|
|
355
|
-
//ltdtmapping
|
|
356
|
-
rows = ltdtmapping(rows, ds[keyTable].keys)
|
|
357
|
-
// console.log('ltdtmapping rows', rows)
|
|
358
|
-
|
|
359
|
-
//重給order
|
|
360
|
-
rows = map(rows, (r, k) => {
|
|
361
|
-
r.order = k + 1
|
|
362
|
-
return r
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
//ckKey
|
|
366
|
-
let ckKey = (rows, key) => {
|
|
367
|
-
let err = null
|
|
368
|
-
|
|
369
|
-
//check
|
|
370
|
-
let kp = {}
|
|
371
|
-
each(rows, (v, k) => {
|
|
372
|
-
|
|
373
|
-
//value
|
|
374
|
-
let value = get(v, key, '')
|
|
375
|
-
|
|
376
|
-
//check
|
|
377
|
-
if (!isestr(value)) {
|
|
378
|
-
err = `rows[${k}].${key} is not an effective string`
|
|
379
|
-
return false //跳出
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
//check
|
|
383
|
-
if (haskey(kp, value)) {
|
|
384
|
-
err = `rows[${k}].${key}[${value}] is duplicate`
|
|
385
|
-
return false //跳出
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
//kp
|
|
389
|
-
kp[value] = true
|
|
390
|
-
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
return err
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
//偵測未給予或重複
|
|
397
|
-
let err = null
|
|
398
|
-
if (true) {
|
|
399
|
-
if (arrHas(keyTable, ['targets'])) {
|
|
400
|
-
err = ckKey(rows, 'id')
|
|
401
|
-
if (err !== null) {
|
|
402
|
-
return Promise.reject(err)
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
if (arrHas(keyTable, ['pemis', 'grups'])) { //users可重複name故不列入
|
|
406
|
-
err = ckKey(rows, 'name')
|
|
407
|
-
if (err !== null) {
|
|
408
|
-
return Promise.reject(err)
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
if (arrHas(keyTable, ['users'])) {
|
|
412
|
-
err = ckKey(rows, 'email')
|
|
413
|
-
if (err !== null) {
|
|
414
|
-
return Promise.reject(err)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
//ltdtDiffByKey
|
|
420
|
-
let ltdtOld = await woItems[keyTable].select()
|
|
421
|
-
let ltdtNew = rows
|
|
422
|
-
let r = ltdtDiffByKey(ltdtOld, ltdtNew, keyDetect)
|
|
423
|
-
// console.log('ltdtDiffByKey r', r)
|
|
424
|
-
|
|
425
|
-
//del
|
|
426
|
-
if (size(r.del) > 0) {
|
|
427
|
-
await procOrm(userId, keyTable, 'del', r.del) //須使用procOrm才有辦法自動給予相關欄位
|
|
428
|
-
// .catch((err) => {
|
|
429
|
-
// console.log('woItems[keyTable].del err', err)
|
|
430
|
-
// })
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
//add
|
|
434
|
-
if (size(r.add) > 0) {
|
|
435
|
-
await procOrm(userId, keyTable, 'insert', r.add) //須使用procOrm才有辦法自動給予相關欄位
|
|
436
|
-
// .catch((err) => {
|
|
437
|
-
// console.log('woItems[keyTable].insert err', err)
|
|
438
|
-
// })
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
//diff
|
|
442
|
-
if (size(r.diff) > 0) {
|
|
443
|
-
await procOrm(userId, keyTable, 'save', r.diff) //須使用procOrm才有辦法自動給予相關欄位
|
|
444
|
-
// .catch((err) => {
|
|
445
|
-
// console.log('woItems[keyTable].save err', err)
|
|
446
|
-
// })
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
return ltdtNew
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
//updateTargets
|
|
454
|
-
let updateTargets = async (userId, rows) => {
|
|
455
|
-
rows = await updateTabItems('targets', userId, rows, 'id')
|
|
456
|
-
return rows
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
//updatePemis
|
|
461
|
-
let updatePemis = async (userId, rows) => {
|
|
462
|
-
rows = await updateTabItems('pemis', userId, rows, 'name')
|
|
463
|
-
return rows
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
//updateGrups
|
|
468
|
-
let updateGrups = async (userId, rows) => {
|
|
469
|
-
rows = await updateTabItems('grups', userId, rows, 'name')
|
|
470
|
-
return rows
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
//updateUsers
|
|
475
|
-
let updateUsers = async (userId, rows) => {
|
|
476
|
-
rows = await updateTabItems('users', userId, rows, 'id')
|
|
477
|
-
return rows
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
|
|
481
377
|
//checkUser
|
|
482
378
|
let checkUser = async(user) => {
|
|
483
379
|
let id = get(user, 'id', '')
|
|
484
380
|
if (!isestr(id)) {
|
|
485
381
|
console.log('user', user)
|
|
486
|
-
|
|
487
|
-
return Promise.reject(`
|
|
382
|
+
srLog.error({ event: 'checkUser-error', msg: 'cannotGetUserId' })
|
|
383
|
+
return Promise.reject(`cannotGetUserId`)
|
|
488
384
|
}
|
|
489
385
|
let email = get(user, 'email', '')
|
|
490
386
|
if (!isestr(email)) {
|
|
491
387
|
console.log('user', user)
|
|
492
|
-
|
|
493
|
-
return Promise.reject(`
|
|
388
|
+
srLog.error({ event: 'checkUser-error', msg: 'cannotGetUserEmail' })
|
|
389
|
+
return Promise.reject(`cannotGetUserEmail`)
|
|
494
390
|
}
|
|
495
391
|
let name = get(user, 'name', '')
|
|
496
392
|
if (!isestr(name)) {
|
|
497
393
|
console.log('user', user)
|
|
498
|
-
|
|
499
|
-
return Promise.reject(`
|
|
394
|
+
srLog.error({ event: 'checkUser-error', msg: 'cannotGetUserName' })
|
|
395
|
+
return Promise.reject(`cannotGetUserName`)
|
|
500
396
|
}
|
|
501
397
|
let isAdmin = get(user, 'isAdmin', '')
|
|
502
398
|
if (isAdmin !== 'y' && isAdmin !== 'n') {
|
|
503
399
|
console.log('user', user)
|
|
504
400
|
console.log('user.isAdmin is not y or n', user.isAdmin)
|
|
505
|
-
|
|
506
|
-
return Promise.reject(`
|
|
401
|
+
srLog.error({ event: 'checkUser-error', msg: 'cannotGetUserRole' })
|
|
402
|
+
return Promise.reject(`cannotGetUserRole`)
|
|
507
403
|
}
|
|
508
404
|
return true
|
|
509
405
|
}
|
|
@@ -526,8 +422,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
526
422
|
//check
|
|
527
423
|
if (!iseobj(userSelf)) {
|
|
528
424
|
console.log(`token`, token)
|
|
529
|
-
|
|
530
|
-
return Promise.reject(`
|
|
425
|
+
srLog.error({ event: 'getTokenUser-error', msg: 'cannotFindUserFromToken' })
|
|
426
|
+
return Promise.reject(`cannotFindUserFromToken`)
|
|
531
427
|
}
|
|
532
428
|
|
|
533
429
|
//check userSelf
|
|
@@ -541,8 +437,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
541
437
|
if (!isestr(vSelf)) {
|
|
542
438
|
console.log('userSelf', userSelf)
|
|
543
439
|
console.log('mappingBy', mappingBy)
|
|
544
|
-
|
|
545
|
-
return Promise.reject(`
|
|
440
|
+
srLog.error({ event: 'getTokenUser-error', msg: 'cannotGetUserProp', mappingBy })
|
|
441
|
+
return Promise.reject(`cannotGetUserProp`)
|
|
546
442
|
}
|
|
547
443
|
|
|
548
444
|
//userFind
|
|
@@ -554,17 +450,14 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
554
450
|
if (!iseobj(userFind)) {
|
|
555
451
|
console.log('userSelf', userSelf)
|
|
556
452
|
console.log('mappingBy', mappingBy)
|
|
557
|
-
|
|
558
|
-
return Promise.reject(`
|
|
453
|
+
srLog.error({ event: 'getTokenUser-error', msg: 'cannotGetUserFromPerm', mappingBy })
|
|
454
|
+
return Promise.reject(`cannotGetUserFromPerm`)
|
|
559
455
|
}
|
|
560
456
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
userFind.isAdmin = isAdminSelf
|
|
566
|
-
}
|
|
567
|
-
// console.log('userFind(isAdmin)', userFind)
|
|
457
|
+
//isAdmin 權威為 perm users 表之欄位值, 不以 token(getUserByToken)宣稱之 isAdmin 複寫。
|
|
458
|
+
//(2026-07-11 稽核 A-C1 裁決(b): 原此處有一段恆為 no-op 之「複寫isAdmin」死碼
|
|
459
|
+
// (userFind.isAdmin = isAdminSelf, 把自己指派給自己), 與 JSDoc 舊文「輸入'y'時會複寫」互斥;
|
|
460
|
+
// 依業主裁決採保守解: 刪除死碼、文件對齊實際行為, 不啟用 token→admin 提權路徑。)
|
|
568
461
|
|
|
569
462
|
return userFind
|
|
570
463
|
}
|
|
@@ -602,8 +495,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
602
495
|
//check
|
|
603
496
|
if (!b) {
|
|
604
497
|
console.log('user', user)
|
|
605
|
-
|
|
606
|
-
return Promise.reject(`
|
|
498
|
+
srLog.error({ event: 'getAndVerifyClientUser-error', msg: 'userNoPermission', from })
|
|
499
|
+
return Promise.reject(`userNoPermission`)
|
|
607
500
|
}
|
|
608
501
|
|
|
609
502
|
return user
|
|
@@ -627,8 +520,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
627
520
|
//check
|
|
628
521
|
if (!iseobj(user)) {
|
|
629
522
|
console.log(`token`, token)
|
|
630
|
-
|
|
631
|
-
return Promise.reject(`
|
|
523
|
+
srLog.error({ event: 'getAndVerifyAppUser-error', msg: 'cannotFindUserFromToken' })
|
|
524
|
+
return Promise.reject(`cannotFindUserFromToken`)
|
|
632
525
|
}
|
|
633
526
|
|
|
634
527
|
//verifyAppUser
|
|
@@ -640,8 +533,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
640
533
|
//check
|
|
641
534
|
if (!b) {
|
|
642
535
|
console.log('user', user)
|
|
643
|
-
|
|
644
|
-
return Promise.reject(`
|
|
536
|
+
srLog.error({ event: 'getAndVerifyAppUser-error', msg: 'userNoPermission', from })
|
|
537
|
+
return Promise.reject(`userNoPermission`)
|
|
645
538
|
}
|
|
646
539
|
|
|
647
540
|
return user
|
|
@@ -662,8 +555,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
662
555
|
//check
|
|
663
556
|
if (!iseobj(payload)) {
|
|
664
557
|
console.log('payload', payload)
|
|
665
|
-
|
|
666
|
-
return Promise.reject(`
|
|
558
|
+
srLog.error({ event: 'parsePayload-error', msg: 'invalidPayload' })
|
|
559
|
+
return Promise.reject(`invalidPayload`)
|
|
667
560
|
}
|
|
668
561
|
|
|
669
562
|
//from
|
|
@@ -672,8 +565,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
672
565
|
//check
|
|
673
566
|
if (!isestr(from)) {
|
|
674
567
|
console.log('payload', payload)
|
|
675
|
-
|
|
676
|
-
return Promise.reject(`
|
|
568
|
+
srLog.error({ event: 'parsePayload-error', msg: 'invalidFromInPayload' })
|
|
569
|
+
return Promise.reject(`invalidFromInPayload`)
|
|
677
570
|
}
|
|
678
571
|
|
|
679
572
|
//rows
|
|
@@ -682,8 +575,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
682
575
|
//check
|
|
683
576
|
if (!isearr(rows)) {
|
|
684
577
|
console.log('payload', payload)
|
|
685
|
-
|
|
686
|
-
return Promise.reject(`
|
|
578
|
+
srLog.error({ event: 'parsePayload-error', msg: 'invalidRowsInPayload' })
|
|
579
|
+
return Promise.reject(`invalidRowsInPayload`)
|
|
687
580
|
}
|
|
688
581
|
|
|
689
582
|
//inp
|
|
@@ -699,6 +592,9 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
699
592
|
//syncAndReplaceTabs
|
|
700
593
|
let syncAndReplaceTabs = async (userId, inp, keyTable) => {
|
|
701
594
|
|
|
595
|
+
//序列化同表之並行整表 delAll+insert: 防 lost update (同 keyTable 序列化, 不同表並行)
|
|
596
|
+
return await kmx('syncAndReplaceTabs:' + keyTable, async () => {
|
|
597
|
+
|
|
702
598
|
//from
|
|
703
599
|
let from = get(inp, 'from', '')
|
|
704
600
|
// console.log('from', from)
|
|
@@ -706,8 +602,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
706
602
|
//check
|
|
707
603
|
if (!isestr(from)) {
|
|
708
604
|
console.log('inp', inp)
|
|
709
|
-
|
|
710
|
-
return Promise.reject(`
|
|
605
|
+
srLog.error({ event: 'syncAndReplaceTabs-error', msg: 'invalidFrom', keyTable })
|
|
606
|
+
return Promise.reject(`invalidFrom`)
|
|
711
607
|
}
|
|
712
608
|
|
|
713
609
|
//rows
|
|
@@ -718,7 +614,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
718
614
|
if (!isearr(rows)) {
|
|
719
615
|
console.log('inp', inp)
|
|
720
616
|
console.log('keyTable', keyTable)
|
|
721
|
-
|
|
617
|
+
srLog.error({ event: 'syncAndReplaceTabs-error', msg: 'invalidRows', keyTable })
|
|
618
|
+
return Promise.reject(`invalidRows`)
|
|
722
619
|
}
|
|
723
620
|
|
|
724
621
|
//save from
|
|
@@ -741,6 +638,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
741
638
|
// console.log('r', r)
|
|
742
639
|
|
|
743
640
|
return r
|
|
641
|
+
|
|
642
|
+
})
|
|
744
643
|
}
|
|
745
644
|
|
|
746
645
|
|
|
@@ -801,8 +700,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
801
700
|
//check
|
|
802
701
|
if (!iseobj(kur)) {
|
|
803
702
|
console.log('userId', userId)
|
|
804
|
-
|
|
805
|
-
return Promise.reject(`
|
|
703
|
+
srLog.error({ event: 'getGenUserAndRulesByUserId-error', msg: 'cannotGetUserRules', userId })
|
|
704
|
+
return Promise.reject(`cannotGetUserRules`)
|
|
806
705
|
}
|
|
807
706
|
|
|
808
707
|
//grupsNames
|
|
@@ -876,8 +775,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
876
775
|
console.log('req.query', get(req, 'query'))
|
|
877
776
|
console.log('token', token)
|
|
878
777
|
console.log('[API]getUserByToken/check token: invalid token')
|
|
879
|
-
|
|
880
|
-
return Promise.reject(`
|
|
778
|
+
srLog.error({ event: 'api/getUserByToken-error', msg: 'tokenNoPermission' })
|
|
779
|
+
return Promise.reject(`tokenNoPermission`)
|
|
881
780
|
}
|
|
882
781
|
|
|
883
782
|
//getAndVerifyClientUser
|
|
@@ -888,10 +787,13 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
888
787
|
if (!iseobj(user)) {
|
|
889
788
|
console.log('token', token)
|
|
890
789
|
console.log('[API]getUserByToken/check user: invalid user')
|
|
891
|
-
|
|
892
|
-
return Promise.reject(`
|
|
790
|
+
srLog.error({ event: 'api/getUserByToken-error', msg: 'tokenNoPermission' })
|
|
791
|
+
return Promise.reject(`tokenNoPermission`)
|
|
893
792
|
}
|
|
894
793
|
|
|
794
|
+
//info
|
|
795
|
+
srLog.info({ event: 'api/getUserByToken-success', userId: get(user, 'id', '') })
|
|
796
|
+
|
|
895
797
|
return user
|
|
896
798
|
}
|
|
897
799
|
|
|
@@ -923,8 +825,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
923
825
|
console.log('req.query', get(req, 'query'))
|
|
924
826
|
console.log('token', token)
|
|
925
827
|
console.log('[API]getPerm/check token: invalid token')
|
|
926
|
-
|
|
927
|
-
return Promise.reject(`
|
|
828
|
+
srLog.error({ event: 'api/getPerm-error', msg: 'tokenNoPermission' })
|
|
829
|
+
return Promise.reject(`tokenNoPermission`)
|
|
928
830
|
}
|
|
929
831
|
|
|
930
832
|
//getAndVerifyClientUser, 發起token的所屬使用者, 驗證僅對client使用者, 不得使用app使用者
|
|
@@ -935,8 +837,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
935
837
|
if (!iseobj(userSelf)) {
|
|
936
838
|
console.log('token', token)
|
|
937
839
|
console.log('[API]getPerm/check userSelf: invalid userSelf')
|
|
938
|
-
|
|
939
|
-
return Promise.reject(`
|
|
840
|
+
srLog.error({ event: 'api/getPerm-error', msg: 'tokenNoPermission' })
|
|
841
|
+
return Promise.reject(`tokenNoPermission`)
|
|
940
842
|
}
|
|
941
843
|
|
|
942
844
|
//userIdSelf, client使用者的userId
|
|
@@ -948,8 +850,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
948
850
|
console.log('token', token)
|
|
949
851
|
console.log('userSelf', userSelf)
|
|
950
852
|
console.log('[API]getPerm/check userIdSelf: invalid userIdSelf')
|
|
951
|
-
|
|
952
|
-
return Promise.reject(`
|
|
853
|
+
srLog.error({ event: 'api/getPerm-error', msg: 'tokenNoPermission' })
|
|
854
|
+
return Promise.reject(`tokenNoPermission`)
|
|
953
855
|
}
|
|
954
856
|
|
|
955
857
|
//getGenUserAndRulesByUserId, 查找到的client使用者與權限
|
|
@@ -962,10 +864,13 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
962
864
|
console.log('userSelf', userSelf)
|
|
963
865
|
console.log('userIdSelf', userIdSelf)
|
|
964
866
|
console.log('[API]getPerm/check userWithRulesSelf: invalid userWithRulesSelf')
|
|
965
|
-
|
|
966
|
-
return Promise.reject(`
|
|
867
|
+
srLog.error({ event: 'api/getPerm-error', msg: 'tokenNoPermission' })
|
|
868
|
+
return Promise.reject(`tokenNoPermission`)
|
|
967
869
|
}
|
|
968
870
|
|
|
871
|
+
//info
|
|
872
|
+
srLog.info({ event: 'api/getPerm-success', userId: userIdSelf })
|
|
873
|
+
|
|
969
874
|
return userWithRulesSelf
|
|
970
875
|
}
|
|
971
876
|
|
|
@@ -996,8 +901,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
996
901
|
if (!isestr(tokenSelf)) {
|
|
997
902
|
console.log('req.query', get(req, 'query'))
|
|
998
903
|
console.log('[API]getPermUserInfor/check tokenSelf: invalid tokenSelf')
|
|
999
|
-
|
|
1000
|
-
return Promise.reject(`
|
|
904
|
+
srLog.error({ event: 'api/getPermUserInfor-error', msg: 'tokenNoPermission' })
|
|
905
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1001
906
|
}
|
|
1002
907
|
|
|
1003
908
|
//getAndVerifyAppUser, 發起token的所屬使用者, 驗證須為app使用者
|
|
@@ -1009,8 +914,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1009
914
|
console.log('req.query', get(req, 'query'))
|
|
1010
915
|
console.log('tokenSelf', tokenSelf)
|
|
1011
916
|
console.log('[API]getPermUserInfor/check userSelf: invalid userSelf')
|
|
1012
|
-
|
|
1013
|
-
return Promise.reject(`
|
|
917
|
+
srLog.error({ event: 'api/getPermUserInfor-error', msg: 'tokenNoPermission' })
|
|
918
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1014
919
|
}
|
|
1015
920
|
|
|
1016
921
|
//userIdFind, 欲查找使用者的userId
|
|
@@ -1022,8 +927,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1022
927
|
console.log('req.query', get(req, 'query'))
|
|
1023
928
|
console.log('tokenSelf', tokenSelf)
|
|
1024
929
|
console.log('[API]getPermUserInfor/check userIdFind: invalid userIdFind')
|
|
1025
|
-
|
|
1026
|
-
return Promise.reject(`
|
|
930
|
+
srLog.error({ event: 'api/getPermUserInfor-error', msg: 'tokenNoPermission' })
|
|
931
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1027
932
|
}
|
|
1028
933
|
|
|
1029
934
|
//getGenUserAndRulesByUserId, 查找到的使用者與權限
|
|
@@ -1034,10 +939,13 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1034
939
|
if (!iseobj(userWithRulesFind)) {
|
|
1035
940
|
console.log('userIdFind', userIdFind)
|
|
1036
941
|
console.log('[API]getPermUserInfor/check userWithRulesFind: invalid userWithRulesFind')
|
|
1037
|
-
|
|
1038
|
-
return Promise.reject(`
|
|
942
|
+
srLog.error({ event: 'api/getPermUserInfor-error', msg: 'userIdNoPermrules' })
|
|
943
|
+
return Promise.reject(`userIdNoPermrules`)
|
|
1039
944
|
}
|
|
1040
945
|
|
|
946
|
+
//info
|
|
947
|
+
srLog.info({ event: 'api/getPermUserInfor-success', userId: userIdFind })
|
|
948
|
+
|
|
1041
949
|
return userWithRulesFind
|
|
1042
950
|
}
|
|
1043
951
|
|
|
@@ -1069,8 +977,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1069
977
|
console.log('req.query', get(req, 'query'))
|
|
1070
978
|
console.log('token', token)
|
|
1071
979
|
console.log('[API]syncAndReplaceTabs/check token: invalid token')
|
|
1072
|
-
|
|
1073
|
-
return Promise.reject(`
|
|
980
|
+
srLog.error({ event: 'api/syncAndReplaceTabs-error', msg: 'tokenNoPermission' })
|
|
981
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1074
982
|
}
|
|
1075
983
|
|
|
1076
984
|
//keyTable
|
|
@@ -1081,15 +989,16 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1081
989
|
console.log('req.query', get(req, 'query'))
|
|
1082
990
|
console.log('keyTable', keyTable)
|
|
1083
991
|
console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable')
|
|
1084
|
-
|
|
1085
|
-
return Promise.reject(`
|
|
992
|
+
srLog.error({ event: 'api/syncAndReplaceTabs-error', msg: 'tokenNoPermission' })
|
|
993
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1086
994
|
}
|
|
1087
995
|
|
|
1088
996
|
//check keyTable
|
|
1089
997
|
let allowedTables = ['targets', 'pemis', 'grups', 'users']
|
|
1090
998
|
if (!allowedTables.includes(keyTable)) {
|
|
1091
999
|
console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable)
|
|
1092
|
-
|
|
1000
|
+
srLog.error({ event: 'api/syncAndReplaceTabs-error', msg: 'invalidKeyTable', keyTable })
|
|
1001
|
+
return Promise.reject(`invalidKeyTable`)
|
|
1093
1002
|
}
|
|
1094
1003
|
|
|
1095
1004
|
//getAndVerifyAppUser
|
|
@@ -1099,8 +1008,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1099
1008
|
if (!iseobj(user)) {
|
|
1100
1009
|
console.log('token', token)
|
|
1101
1010
|
console.log('[API]syncAndReplaceTabs/check user: invalid user')
|
|
1102
|
-
|
|
1103
|
-
return Promise.reject(`
|
|
1011
|
+
srLog.error({ event: 'api/syncAndReplaceTabs-error', msg: 'tokenNoPermission' })
|
|
1012
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1104
1013
|
}
|
|
1105
1014
|
|
|
1106
1015
|
//userId
|
|
@@ -1111,8 +1020,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1111
1020
|
console.log('token', token)
|
|
1112
1021
|
console.log('user', user)
|
|
1113
1022
|
console.log('[API]syncAndReplaceTabs/check userId: invalid userId')
|
|
1114
|
-
|
|
1115
|
-
return Promise.reject(`
|
|
1023
|
+
srLog.error({ event: 'api/syncAndReplaceTabs-error', msg: 'tokenNoPermission' })
|
|
1024
|
+
return Promise.reject(`tokenNoPermission`)
|
|
1116
1025
|
}
|
|
1117
1026
|
|
|
1118
1027
|
//parsePayload
|
|
@@ -1121,6 +1030,9 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1121
1030
|
//syncAndReplaceTabs
|
|
1122
1031
|
let r = await syncAndReplaceTabs(userId, inp, keyTable)
|
|
1123
1032
|
|
|
1033
|
+
//info
|
|
1034
|
+
srLog.info({ event: 'api/syncAndReplaceTabs-success', userId, keyTable })
|
|
1035
|
+
|
|
1124
1036
|
return r
|
|
1125
1037
|
}
|
|
1126
1038
|
|
|
@@ -1147,7 +1059,7 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1147
1059
|
|
|
1148
1060
|
//WServHapiServer
|
|
1149
1061
|
instWServHapiServer = new WServHapiServer({
|
|
1150
|
-
port:
|
|
1062
|
+
port: serverPort,
|
|
1151
1063
|
pathStaticFiles,
|
|
1152
1064
|
apiName: 'api',
|
|
1153
1065
|
apis,
|
|
@@ -1171,6 +1083,21 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1171
1083
|
let b = await p.checkToken(token)
|
|
1172
1084
|
// console.log('b', b)
|
|
1173
1085
|
|
|
1086
|
+
//ip, 對齊sso慣例x-forwarded-for取第1個, fallback到req remoteAddress, 取不到則略過
|
|
1087
|
+
let ip = get(headers, 'x-forwarded-for', '').split(',')[0].trim()
|
|
1088
|
+
if (!isestr(ip)) {
|
|
1089
|
+
ip = get(req, 'info.remoteAddress', '') || get(req, 'socket.remoteAddress', '') || get(req, 'connection.remoteAddress', '')
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
//origin
|
|
1093
|
+
let origin = get(headers, 'origin', '')
|
|
1094
|
+
|
|
1095
|
+
//referer
|
|
1096
|
+
let referer = get(headers, 'referer', '')
|
|
1097
|
+
|
|
1098
|
+
//info
|
|
1099
|
+
srLog.info({ event: 'verifyConn', ok: b, apiType, ip, origin, referer })
|
|
1100
|
+
|
|
1174
1101
|
return b
|
|
1175
1102
|
},
|
|
1176
1103
|
getUserIdByToken: async (token) => { //可使用async或sync函數
|
|
@@ -1180,7 +1107,8 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1180
1107
|
if (!isestr(userId)) {
|
|
1181
1108
|
console.log('token', token)
|
|
1182
1109
|
console.log('userId', userId)
|
|
1183
|
-
|
|
1110
|
+
srLog.error({ event: 'getUserIdByToken-error', msg: 'cannotFindUserId' })
|
|
1111
|
+
return Promise.reject(`cannotFindUserId`)
|
|
1184
1112
|
}
|
|
1185
1113
|
return userId
|
|
1186
1114
|
},
|
|
@@ -1200,10 +1128,34 @@ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser
|
|
|
1200
1128
|
// getGrupsList,
|
|
1201
1129
|
// getUsersList,
|
|
1202
1130
|
|
|
1203
|
-
updateTargets,
|
|
1204
|
-
updatePemis,
|
|
1205
|
-
updateGrups,
|
|
1206
|
-
updateUsers,
|
|
1131
|
+
updateTargets: pc.updateTargets,
|
|
1132
|
+
updatePemis: pc.updatePemis,
|
|
1133
|
+
updateGrups: pc.updateGrups,
|
|
1134
|
+
updateUsers: pc.updateUsers,
|
|
1135
|
+
|
|
1136
|
+
getStaEvent: async (userId, timeLength, timeInterval) => {
|
|
1137
|
+
try {
|
|
1138
|
+
let rs = await psi.getStaEvent(userId, timeLength, timeInterval)
|
|
1139
|
+
srLog.info({ event: 'getStaEvent-success', userId })
|
|
1140
|
+
return rs
|
|
1141
|
+
}
|
|
1142
|
+
catch (err) {
|
|
1143
|
+
srLog.error({ event: 'getStaEvent-error', userId, msg: (typeof err === 'string') ? err : ((err && err.message) || 'cannotGetStaEvent') })
|
|
1144
|
+
throw err
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
|
|
1148
|
+
getStaEventTable: async (userId) => {
|
|
1149
|
+
try {
|
|
1150
|
+
let rs = await psi.getStaEventTable(userId)
|
|
1151
|
+
srLog.info({ event: 'getStaEventTable-success', userId })
|
|
1152
|
+
return rs
|
|
1153
|
+
}
|
|
1154
|
+
catch (err) {
|
|
1155
|
+
srLog.error({ event: 'getStaEventTable-error', userId, msg: (typeof err === 'string') ? err : ((err && err.message) || 'cannotGetStaEventTable') })
|
|
1156
|
+
throw err
|
|
1157
|
+
}
|
|
1158
|
+
},
|
|
1207
1159
|
|
|
1208
1160
|
},
|
|
1209
1161
|
fnTableTags: 'tableTags-web-perm.json',
|