w-web-perm 1.1.12 → 1.1.13
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/README.md +158 -123
- package/dist/css/app.f09c7433.css +1 -0
- package/dist/index.tmp +1 -1
- package/dist/js/app-legacy.8af87052.js +1 -0
- package/dist/js/app.8af87052.js +1 -0
- package/dist/js/{chunk-vendors.3e9e3ef1.js → chunk-vendors-legacy.ece5a361.js} +1 -1
- package/dist/js/{chunk-vendors-legacy.3e9e3ef1.js → chunk-vendors.ece5a361.js} +1 -1
- package/dist/w-web-perm.umd.js +2 -2
- package/dist/w-web-perm.umd.js.map +1 -1
- package/docs/WWebPerm.html +84 -4
- package/docs/global.html +23023 -1125
- package/docs/index.html +2 -2
- package/docs/server_WWebPerm.mjs.html +232 -32
- package/docs/server_cascadeWrite.mjs.html +225 -0
- package/docs/server_dataChannel.mjs.html +2 -2
- package/docs/server_keyCheck.mjs.html +353 -0
- package/docs/server_lockSave.mjs.html +2 -2
- package/docs/server_maskLog.mjs.html +2 -2
- package/docs/server_procCore.mjs.html +180 -41
- package/docs/server_staLogs_resolveShellWorker.mjs.html +2 -2
- package/docs/server_syncKeep.mjs.html +311 -0
- package/docs/server_tools_authRefsAudit.mjs.html +247 -0
- package/docs/server_tools_authRefsClean.mjs.html +335 -0
- package/docs/server_tools_fromTools.mjs.html +797 -0
- package/docs/server_tools_isMain.mjs.html +103 -0
- package/docs/server_tools_nameDupReport.mjs.html +280 -0
- package/docs/server_validateRows.mjs.html +2 -2
- package/docs/server_wrapInjected.mjs.html +3 -3
- package/docs/src_fetchJson.mjs.html +2 -2
- package/docs/src_js_cvKpToArr.mjs.html +2 -2
- package/docs/src_js_cvKpToObj.mjs.html +44 -33
- package/docs/src_js_draftSync.mjs.html +142 -0
- package/docs/src_js_eachOwn.mjs.html +3 -3
- package/docs/src_js_editorRefRows.mjs.html +356 -0
- package/docs/src_js_externalRows.mjs.html +338 -0
- package/docs/src_js_externalUi.mjs.html +230 -0
- package/docs/src_js_findRefRows.mjs.html +107 -0
- package/docs/src_js_findTouchedDup.mjs.html +150 -0
- package/docs/src_js_fmtLossyMsg.mjs.html +2 -2
- package/docs/src_js_fromAudit.mjs.html +489 -0
- package/docs/src_js_getAddImpact.mjs.html +269 -0
- package/docs/src_js_getAuthWarn.mjs.html +463 -0
- package/docs/src_js_getCascadePreview.mjs.html +258 -0
- package/docs/src_js_getDelRefCount.mjs.html +210 -0
- package/docs/src_js_getEffMode.mjs.html +92 -0
- package/docs/src_js_getKpLossy.mjs.html +47 -52
- package/docs/src_js_getNameErrs.mjs.html +266 -0
- package/docs/src_js_getOwn.mjs.html +3 -3
- package/docs/src_js_getPropKey.mjs.html +109 -0
- package/docs/src_js_getRuleEnable.mjs.html +2 -2
- package/docs/src_js_isAuthMode.mjs.html +4 -4
- package/docs/src_js_joinNames.mjs.html +2 -2
- package/docs/src_js_legendFit.mjs.html +2 -2
- package/docs/src_js_pairRowsToSnapshot.mjs.html +156 -0
- package/docs/src_js_refAudit.mjs.html +359 -0
- package/docs/src_js_refCascade.mjs.html +572 -0
- package/docs/src_js_relDialogSend.mjs.html +199 -0
- package/docs/src_js_rowDigest.mjs.html +265 -0
- package/docs/src_plugins_dataReloadGuard.mjs.html +109 -0
- package/docs/src_plugins_reuseDeletedIds.mjs.html +2 -2
- package/docs/src_plugins_submitGuard.mjs.html +2 -2
- package/g_authRefsClean.mjs +79 -0
- package/g_fixFromType.mjs +92 -0
- package/g_initialData.mjs +3 -3
- package/g_purgeFrom.mjs +127 -0
- package/package.json +1 -1
- package/server/WWebPerm.mjs +230 -30
- package/server/cascadeWrite.mjs +153 -0
- package/server/keyCheck.mjs +281 -0
- package/server/procCore.mjs +178 -39
- package/server/procLang.mjs +270 -3
- package/server/syncKeep.mjs +239 -0
- package/server/tools/authRefsAudit.mjs +175 -0
- package/server/tools/authRefsClean.mjs +263 -0
- package/server/tools/fromTools.mjs +725 -0
- package/server/tools/isMain.mjs +31 -0
- package/server/tools/nameDupReport.mjs +208 -0
- package/server/wrapInjected.mjs +1 -1
- package/src/components/LayoutContentGrups.vue +396 -75
- package/src/components/LayoutContentPemis.vue +395 -75
- package/src/components/LayoutContentTargets.vue +261 -25
- package/src/components/LayoutContentUsers.vue +334 -97
- package/src/components/VeCgrups.vue +88 -129
- package/src/components/VeCpemis.vue +86 -129
- package/src/components/VeCrules.vue +15 -5
- package/src/components/VeGrupBlngUsers.vue +202 -89
- package/src/components/VePemiBlngGrups.vue +209 -99
- package/src/js/cvKpToObj.mjs +42 -31
- package/src/js/draftSync.mjs +70 -0
- package/src/js/eachOwn.mjs +1 -1
- package/src/js/editorRefRows.mjs +284 -0
- package/src/js/externalRows.mjs +266 -0
- package/src/js/externalUi.mjs +158 -0
- package/src/js/findRefRows.mjs +35 -0
- package/src/js/findTouchedDup.mjs +78 -0
- package/src/js/fromAudit.mjs +417 -0
- package/src/js/getAddImpact.mjs +197 -0
- package/src/js/getAuthWarn.mjs +391 -0
- package/src/js/getCascadePreview.mjs +186 -0
- package/src/js/getDelRefCount.mjs +138 -0
- package/src/js/getEffMode.mjs +20 -0
- package/src/js/getKpLossy.mjs +44 -49
- package/src/js/getNameErrs.mjs +194 -0
- package/src/js/getOwn.mjs +1 -1
- package/src/js/getPropKey.mjs +37 -0
- package/src/js/isAuthMode.mjs +2 -2
- package/src/js/pairRowsToSnapshot.mjs +84 -0
- package/src/js/refAudit.mjs +287 -0
- package/src/js/refCascade.mjs +500 -0
- package/src/js/relDialogSend.mjs +127 -0
- package/src/js/rowDigest.mjs +193 -0
- package/src/plugins/dataReloadGuard.mjs +37 -0
- package/src/plugins/mShare.mjs +144 -140
- package/src/plugins/mUI.mjs +3 -8
- package/src/schema/tables/users.mjs +152 -152
- package/dist/css/app.6918ec45.css +0 -1
- package/dist/js/app-legacy.7cb7e394.js +0 -1
- package/dist/js/app.7cb7e394.js +0 -1
- package/docs/src_js_getKeyOrderLost.mjs.html +0 -121
- package/docs/src_js_getKpWriteLost.mjs.html +0 -100
- package/docs/src_js_keepKeyOrder.mjs.html +0 -139
- package/src/js/getKeyOrderLost.mjs +0 -49
- package/src/js/getKpWriteLost.mjs +0 -28
- package/src/js/keepKeyOrder.mjs +0 -67
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import JSON5 from 'json5'
|
|
2
|
+
import cvKpToArr from './cvKpToArr.mjs'
|
|
3
|
+
import findRefRows from './findRefRows.mjs'
|
|
4
|
+
import getEffMode from './getEffMode.mjs'
|
|
5
|
+
import getPropKey from './getPropKey.mjs'
|
|
6
|
+
import isAuthMode from './isAuthMode.mjs'
|
|
7
|
+
import { REF_OF, rewriteRefs } from './refCascade.mjs'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
//懸空引用稽核(升版一次性清理工具之核心; 規則帳本 R-REF-CASCADE-01 之配套, 適用表 n 上線前之舊資料可能已有懸空引用):
|
|
11
|
+
// users.cgrups 引用不存在之群組名、grups.cpemis 引用不存在之權限名、pemis.crules 引用不存在之管控對象 id.
|
|
12
|
+
// 清理=把懸空項目自授權字串移除(不論 isActive), 效果等同舊版「找不到即忽略」; 改寫一律經 refCascade.rewriteRefs(物件形式仍物件、陣列形式仍陣列、未命中者同一字串), 不另寫一套.
|
|
13
|
+
//本檔為純函數(不依賴 Vue/DOM/ORM), 供離線稽核(server/tools/authRefsAudit.mjs)、一次性清理(server/tools/authRefsClean.mjs/g_authRefsClean.mjs)與日後頁面共用.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
//EFFECT: 懸空項目對授權之影響說明(item.effect 之碼 → 文字; 依 src/plugins/mShare.mjs 之 mergeRules, R-AUTH-MERGE-00/R-PRINCIPLE-00 c)
|
|
17
|
+
const EFFECT = {
|
|
18
|
+
inactive: '停用項不參與授權合併, 移除不改變授權',
|
|
19
|
+
and: '啟用且有效模式為 AND(含 mode 缺/非法): 引用查無實體者內容全 n, 使該層合併結果為空(收嚴); 清理後此限制解除, 授權可能變多',
|
|
20
|
+
or: '啟用且為 OR: 引用查無實體者聯集貢獻 0; 惟若為同層唯一之 OR 項而同層另有合法 AND 項, 現況基底為空集(結果為空), 清理後基底改取 AND 項, 授權可能變多',
|
|
21
|
+
rule: 'crules 查無之管控對象 id: 授權輸出只列現存管控對象, 不影響授權',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
let isStr = (v) => typeof v === 'string'
|
|
26
|
+
let arr = (v) => (Array.isArray(v) ? v : [])
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
//mkIsDang: 建立「引用名稱查無實體」之判定函數(key → 是否懸空); grups/pemis 經 findRefRows(單一擁有者, 缺 name 視為 ''、===、歷史同名不是懸空, 同伺服端 getUserRules; 同一名稱只查一次,
|
|
30
|
+
//免使用者數 × 引用數 × 群組數之逐筆比對), targets 以 id 轉屬性鍵比對(同 mergeRules/getUserRules 之取值, 只收字串與數字之 id)
|
|
31
|
+
let mkIsDang = (rows, keyTable) => {
|
|
32
|
+
if (keyTable === 'targets') {
|
|
33
|
+
let s = new Set()
|
|
34
|
+
arr(rows).forEach((r) => {
|
|
35
|
+
if (r !== null && typeof r === 'object' && (isStr(r.id) || typeof r.id === 'number')) {
|
|
36
|
+
let k = getPropKey(r.id)
|
|
37
|
+
if (k !== null) {
|
|
38
|
+
s.add(k)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
return (k) => !s.has(k)
|
|
43
|
+
}
|
|
44
|
+
let memo = new Map()
|
|
45
|
+
return (k) => {
|
|
46
|
+
if (!memo.has(k)) {
|
|
47
|
+
memo.set(k, findRefRows(rows, k).length === 0)
|
|
48
|
+
}
|
|
49
|
+
return memo.get(k)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
//modeInfo: mode 之合法性(isAuthMode)與有效模式是否為 OR(getEffMode; mode 缺或非法者有效模式為 AND, 只作限制項, 見 mergeRules)
|
|
55
|
+
let modeInfo = (m) => ({ valid: isAuthMode(m), isOr: getEffMode(m) === 'OR' })
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
//decode: 授權字串 → { state, ents }; 'empty'(非字串或空白, 新增列之預設值, 非損壞)、'bad'(JSON5 解析失敗, 或解出非物件/陣列, 同 getAuthWarn.isBadData; reason 為 parse/notContainer/decode)、'ok'(ents 為 cvKpToArr 之解碼)
|
|
59
|
+
let decode = (str) => {
|
|
60
|
+
if (!isStr(str) || str.trim() === '') {
|
|
61
|
+
return { state: 'empty', ents: [] }
|
|
62
|
+
}
|
|
63
|
+
let kp = null
|
|
64
|
+
try {
|
|
65
|
+
kp = JSON5.parse(str)
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
return { state: 'bad', reason: 'parse', ents: [] }
|
|
69
|
+
}
|
|
70
|
+
if (kp === null || typeof kp !== 'object') {
|
|
71
|
+
return { state: 'bad', reason: 'notContainer', ents: [] }
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
return { state: 'ok', reason: '', ents: cvKpToArr(kp) }
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
return { state: 'bad', reason: 'decode', ents: [] }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
//maybeNonEmpty: 同層啟用項(es: [{ valid, isOr, zero }], 見 modeInfo)合併結果「可能非空」否, 依 mergeRules 之結構, 內容未知之實體項視為可能非空, zero 者(查無實體之懸空項, 或名稱非字串而不對應任何實體者)內容恆空:
|
|
83
|
+
// 沒有任何 mode 合法(OR/AND)之項 → 恆空; 任一 AND 有效項(含 mode 缺/非法, 只作限制)為 zero → 恆空(交集含空集); 有 OR 項時須至少一個 OR 項非 zero(聯集), 無 OR 項時以合法 AND 項為基底即可
|
|
84
|
+
let maybeNonEmpty = (es) => {
|
|
85
|
+
if (!es.some((e) => e.valid)) {
|
|
86
|
+
return false
|
|
87
|
+
}
|
|
88
|
+
if (es.some((e) => !e.isOr && e.zero)) {
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
if (es.some((e) => e.isOr)) {
|
|
92
|
+
return es.some((e) => e.isOr && !e.zero)
|
|
93
|
+
}
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 稽核引用端授權字串中查無實體(懸空)之引用, 並產生清理後之新字串(純函數, 不讀寫任何資料)
|
|
100
|
+
*
|
|
101
|
+
* 懸空判準同伺服端 findRefRows: cgrups/cpemis 以名稱 === 比對 grups/pemis 之 name(缺 name 視為 ''), 歷史同名(名稱對到多列)不是懸空;
|
|
102
|
+
* crules 之項目名稱以 getPropKey 轉屬性鍵後與 targets.id 比對. 解碼用 cvKpToArr(與伺服端 getUserRules 同一份); JSON5 解析失敗(或非物件/陣列)者列入 badJson, 不當作有引用、不動.
|
|
103
|
+
* 名稱非字串(陣列元素無 name、name 為數字或陣列等)之 cgrups/cpemis 項目不對應任何群組/權限名, 無法以名稱處置, 列入 unnamed(不清理, 須人工於後台處理; 編輯器對其亦拒存).
|
|
104
|
+
* 清理移除懸空項目不論 isActive; 不回顯 email/name 等個資(只列主鍵 id 與被引用之名稱).
|
|
105
|
+
*
|
|
106
|
+
* 清理後授權之變化(對照 mergeRules): 停用項、crules 項不影響授權; 啟用之 AND 項(含 mode 缺/非法)使該層結果為空, 清理後限制解除;
|
|
107
|
+
* 啟用之 OR 項聯集貢獻 0, 但若為同層唯一之 OR 項且同層另有合法 AND 項, 現況基底為空集, 清理後基底改取 AND 項. 以上皆只會放寬(授權變多), 不會收嚴.
|
|
108
|
+
* widen 以結構判定「可能變多」之引用端(實際是否變多取決於各實體內容, 為保守上界): users 含直接(自身 cgrups)與經群組傳導(啟用引用之群組其 cpemis 可能變多).
|
|
109
|
+
*
|
|
110
|
+
* @param {Object} d 輸入 { users, grups, pemis, targets }(各為列陣列, 缺者視為空)
|
|
111
|
+
* @returns {Object} 回傳 { items, counts, changes, badJson, unnamed, unsafe, noId, widen }:
|
|
112
|
+
* items 懸空項目 [{ table(users|grups|pemis), holderId, field, name, isActive, mode, effect }], effect 為 EFFECT 之碼(inactive|and|or|rule), mode 於 crules 為 null
|
|
113
|
+
* counts { nItems, nActive, nInactive, nAndActive, nOrActive, nBadJson, nUnnamed, nNoId, nChanges, nAndActiveHolders, nWidenUsers, nWidenGrups,
|
|
114
|
+
* byTable: { users|grups|pemis: { nItems, nHolders, nAndActive, nAndActiveHolders, nWidenHolders } } }; nAndActive 為啟用且有效模式為 AND 之懸空項數(ref 類), nAndActiveHolders 為擁有該類項目之使用者與群組列數
|
|
115
|
+
* changes [{ table, id, field, before, after, nDel }], after 為清理後新字串(經 rewriteRefs)
|
|
116
|
+
* badJson [{ table, id, field, reason }]; unnamed 為 [{ table, holderId, field, isActive, mode }]; unsafe 為含無法安全重新編碼之內容(如 JSON5 Infinity/NaN 數值, 重新編碼會變成 null 而改指別的規則名)故不清理之 [{ table, id, field }](須人工處理); noId 為缺字串主鍵而無從寫回之 [{ table, holderId, field, nItems }]
|
|
117
|
+
* widen [{ table(users|grups), holderId, field, via(direct|grups) }]
|
|
118
|
+
* @example
|
|
119
|
+
*
|
|
120
|
+
* let r = auditRefs({
|
|
121
|
+
* users: [{ id: 'u1', cgrups: '{"G":{"mode":"AND","isActive":"y"},"X":{"mode":"AND","isActive":"y"}}' }],
|
|
122
|
+
* grups: [{ id: 'g1', name: 'G', cpemis: '{}' }],
|
|
123
|
+
* pemis: [],
|
|
124
|
+
* targets: [],
|
|
125
|
+
* })
|
|
126
|
+
* console.log(r.items[0].name, r.changes[0].after)
|
|
127
|
+
* // => X {"G":{"mode":"AND","isActive":"y"}}
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
function auditRefs(d) {
|
|
131
|
+
let data = (d !== null && typeof d === 'object') ? d : {}
|
|
132
|
+
let items = []
|
|
133
|
+
let changes = []
|
|
134
|
+
let badJson = []
|
|
135
|
+
let unnamed = []
|
|
136
|
+
let unsafe = [] //含無法安全重新編碼之內容(如 JSON5 之 Infinity/NaN 數值)而不改寫之容器
|
|
137
|
+
let noId = []
|
|
138
|
+
let widen = []
|
|
139
|
+
let byTable = {}
|
|
140
|
+
|
|
141
|
+
//userRefs: 各使用者啟用引用之群組名(供經群組傳導之 widen); flagGrupNames: 有 widen 之群組列之名稱
|
|
142
|
+
let userRefs = []
|
|
143
|
+
let flagGrupNames = new Set()
|
|
144
|
+
let flagUsers = new Set()
|
|
145
|
+
|
|
146
|
+
for (let key of Object.keys(REF_OF)) {
|
|
147
|
+
let sp = REF_OF[key]
|
|
148
|
+
let t = sp.holder
|
|
149
|
+
let isRule = sp.kind === 'rule'
|
|
150
|
+
let isDangName = mkIsDang(data[key], key)
|
|
151
|
+
let tab = { nItems: 0, nHolders: 0, nAndActive: 0, nAndActiveHolders: 0, nWidenHolders: 0 }
|
|
152
|
+
byTable[t] = tab
|
|
153
|
+
|
|
154
|
+
for (let h of arr(data[t])) {
|
|
155
|
+
if (h === null || typeof h !== 'object') {
|
|
156
|
+
continue
|
|
157
|
+
}
|
|
158
|
+
let str = h[sp.field]
|
|
159
|
+
let dc = decode(str)
|
|
160
|
+
if (dc.state === 'bad') {
|
|
161
|
+
badJson.push({ table: t, id: h.id, field: sp.field, reason: dc.reason })
|
|
162
|
+
continue
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//逐項: 懸空(dang)、名稱非字串(unnamed, 仍參與合併而內容恆空)、其餘(實體存在)
|
|
166
|
+
let dang = []
|
|
167
|
+
let es = []
|
|
168
|
+
let activeNames = []
|
|
169
|
+
for (let e of dc.ents) {
|
|
170
|
+
let active = e.isActive === 'y'
|
|
171
|
+
let k = null
|
|
172
|
+
if (isRule) {
|
|
173
|
+
k = getPropKey(e.name)
|
|
174
|
+
if (k === null) {
|
|
175
|
+
continue //屬性鍵轉型必拋者, 伺服端 mergeRules 略過, 不對應任何標的
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
if (!isStr(e.name)) {
|
|
180
|
+
unnamed.push({ table: t, holderId: h.id, field: sp.field, isActive: e.isActive, mode: e.mode })
|
|
181
|
+
es.push({ ...modeInfo(e.mode), active, zero: true, dang: false })
|
|
182
|
+
continue
|
|
183
|
+
}
|
|
184
|
+
k = e.name
|
|
185
|
+
}
|
|
186
|
+
let isDang = isDangName(k)
|
|
187
|
+
if (!isRule) {
|
|
188
|
+
es.push({ ...modeInfo(e.mode), active, zero: isDang, dang: isDang })
|
|
189
|
+
if (active) {
|
|
190
|
+
activeNames.push(k)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (isDang) {
|
|
194
|
+
dang.push({ key: k, e, active })
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (t === 'users' && isStr(h.id)) {
|
|
198
|
+
userRefs.push({ id: h.id, names: activeNames })
|
|
199
|
+
}
|
|
200
|
+
if (dang.length === 0) {
|
|
201
|
+
continue
|
|
202
|
+
}
|
|
203
|
+
if (!isStr(h.id)) {
|
|
204
|
+
noId.push({ table: t, holderId: h.id, field: sp.field, nItems: dang.length })
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
//items
|
|
209
|
+
let nAnd = 0
|
|
210
|
+
for (let x of dang) {
|
|
211
|
+
let effect = 'rule'
|
|
212
|
+
if (!isRule) {
|
|
213
|
+
effect = !x.active ? 'inactive' : (modeInfo(x.e.mode).isOr ? 'or' : 'and')
|
|
214
|
+
}
|
|
215
|
+
if (effect === 'and') {
|
|
216
|
+
nAnd++
|
|
217
|
+
}
|
|
218
|
+
items.push({ table: t, holderId: h.id, field: sp.field, name: x.key, isActive: x.e.isActive, mode: isRule ? null : x.e.mode, effect })
|
|
219
|
+
}
|
|
220
|
+
tab.nItems += dang.length
|
|
221
|
+
tab.nHolders++
|
|
222
|
+
tab.nAndActive += nAnd
|
|
223
|
+
if (nAnd > 0) {
|
|
224
|
+
tab.nAndActiveHolders++
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
//changes: 以 refCascade.rewriteRefs 移除該容器內之懸空名稱(不論 isActive; 歷史同名非懸空不在集合內)
|
|
228
|
+
let r = rewriteRefs(str, { kind: sp.kind, del: new Set(dang.map((x) => x.key)) })
|
|
229
|
+
if (r.unsafe) {
|
|
230
|
+
unsafe.push({ table: t, id: h.id, field: sp.field })
|
|
231
|
+
}
|
|
232
|
+
else if (r.changed) {
|
|
233
|
+
changes.push({ table: t, id: h.id, field: sp.field, before: str, after: r.str, nDel: r.nDel })
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//widen: 同層啟用項, 現況合併結果必為空而清理後可能非空
|
|
237
|
+
if (!isRule) {
|
|
238
|
+
let A = es.filter((x) => x.active)
|
|
239
|
+
let R = A.filter((x) => !x.dang)
|
|
240
|
+
if (A.some((x) => x.dang) && !maybeNonEmpty(A) && maybeNonEmpty(R)) {
|
|
241
|
+
widen.push({ table: t, holderId: h.id, field: sp.field, via: 'direct' })
|
|
242
|
+
tab.nWidenHolders++
|
|
243
|
+
if (t === 'grups') {
|
|
244
|
+
flagGrupNames.add(h.name === undefined ? '' : h.name)
|
|
245
|
+
}
|
|
246
|
+
if (t === 'users') {
|
|
247
|
+
flagUsers.add(h.id)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//經群組傳導: 使用者啟用引用某群組名, 該名稱之群組列有 widen(其 cpemis 清理後授權可能變多)
|
|
255
|
+
if (flagGrupNames.size > 0) {
|
|
256
|
+
for (let u of userRefs) {
|
|
257
|
+
if (!flagUsers.has(u.id) && u.names.some((n) => flagGrupNames.has(n))) {
|
|
258
|
+
widen.push({ table: 'users', holderId: u.id, field: 'cgrups', via: 'grups' })
|
|
259
|
+
byTable.users.nWidenHolders++
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let refItems = items.filter((x) => x.effect !== 'rule')
|
|
265
|
+
let counts = {
|
|
266
|
+
nItems: items.length,
|
|
267
|
+
nActive: refItems.filter((x) => x.effect !== 'inactive').length,
|
|
268
|
+
nInactive: refItems.filter((x) => x.effect === 'inactive').length,
|
|
269
|
+
nAndActive: refItems.filter((x) => x.effect === 'and').length,
|
|
270
|
+
nOrActive: refItems.filter((x) => x.effect === 'or').length,
|
|
271
|
+
nBadJson: badJson.length,
|
|
272
|
+
nUnnamed: unnamed.length,
|
|
273
|
+
nUnsafe: unsafe.length,
|
|
274
|
+
nNoId: noId.length,
|
|
275
|
+
nChanges: changes.length,
|
|
276
|
+
nAndActiveHolders: byTable.users.nAndActiveHolders + byTable.grups.nAndActiveHolders,
|
|
277
|
+
nWidenUsers: byTable.users.nWidenHolders,
|
|
278
|
+
nWidenGrups: byTable.grups.nWidenHolders,
|
|
279
|
+
byTable,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return { items, counts, changes, badJson, unnamed, unsafe, noId, widen }
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
export { EFFECT, auditRefs }
|
|
287
|
+
export default auditRefs
|