w-web-perm 1.0.0 → 1.0.2
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 +58 -0
- package/dist/css/{chunk-vendors.65775501.css → chunk-vendors.1c6c57f9.css} +1 -1
- package/dist/index.tmp +1 -1
- package/dist/js/app-legacy.317de647.js +2 -0
- package/dist/js/app-legacy.317de647.js.map +1 -0
- package/dist/js/app.94cdbe9a.js +2 -0
- package/dist/js/app.94cdbe9a.js.map +1 -0
- package/dist/js/chunk-vendors-legacy.a074d0c0.js +13 -0
- package/dist/js/chunk-vendors-legacy.a074d0c0.js.map +1 -0
- package/dist/js/chunk-vendors.a074d0c0.js +13 -0
- package/dist/js/chunk-vendors.a074d0c0.js.map +1 -0
- package/dist/w-web-perm.umd.js +2 -2
- package/dist/w-web-perm.umd.js.map +1 -1
- package/docs/WWebPerm.html +1 -1
- package/docs/WWebPerm.mjs.html +61 -11
- package/docs/index.html +1 -1
- package/package.json +5 -4
- package/server/WWebPerm.mjs +60 -10
- package/src/components/LayoutContentGroups.vue +3 -2
- package/src/components/LayoutContentTargets.vue +9 -2
- package/src/components/VeUser.vue +5 -4
- package/src/components/ruleGroup.vue +6 -28
- package/src/perm.mjs +92 -44
- package/src/plugins/mShare.mjs +23 -155
- package/src/schema/tables/ruleGroups.mjs +2 -3
- package/src/schema/tables/targets.mjs +25 -32
- package/src/schema/tables/users.mjs +1 -1
- package/src/store/mutations.mjs +1 -1
- package/srv.mjs +24 -7
- package/tableTags-web-perm.json +1 -1
- package/dist/js/app-legacy.954e168c.js +0 -2
- package/dist/js/app-legacy.954e168c.js.map +0 -1
- package/dist/js/app.954e168c.js +0 -2
- package/dist/js/app.954e168c.js.map +0 -1
- package/dist/js/chunk-vendors-legacy.f5f1a231.js +0 -13
- package/dist/js/chunk-vendors-legacy.f5f1a231.js.map +0 -1
- package/dist/js/chunk-vendors.f5f1a231.js +0 -13
- package/dist/js/chunk-vendors.f5f1a231.js.map +0 -1
package/src/plugins/mShare.mjs
CHANGED
|
@@ -1,169 +1,22 @@
|
|
|
1
1
|
//前後端共用函數區
|
|
2
|
-
|
|
3
|
-
// import size from 'lodash/size'
|
|
4
|
-
// import take from 'lodash/take'
|
|
5
|
-
// import isEqual from 'lodash/isEqual'
|
|
6
|
-
import uniq from 'lodash/uniq'
|
|
7
|
-
// import set from 'lodash/set'
|
|
2
|
+
import JSON5 from 'json5'
|
|
8
3
|
import get from 'lodash/get'
|
|
9
4
|
import each from 'lodash/each'
|
|
10
5
|
import map from 'lodash/map'
|
|
11
6
|
import find from 'lodash/find'
|
|
12
|
-
import filter from 'lodash/filter'
|
|
13
|
-
// import last from 'lodash/last'
|
|
14
|
-
// import size from 'lodash/size'
|
|
15
|
-
import split from 'lodash/split'
|
|
16
7
|
import join from 'lodash/join'
|
|
17
8
|
import cloneDeep from 'lodash/cloneDeep'
|
|
18
9
|
import takeRight from 'lodash/takeRight'
|
|
19
10
|
import dropRight from 'lodash/dropRight'
|
|
20
11
|
import sortBy from 'lodash/sortBy'
|
|
21
12
|
import sep from 'wsemi/src/sep.mjs'
|
|
22
|
-
import isarr from 'wsemi/src/isarr.mjs'
|
|
23
|
-
import isstr from 'wsemi/src/isstr.mjs'
|
|
24
13
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
25
14
|
import haskey from 'wsemi/src/haskey.mjs'
|
|
26
15
|
import composeToTree from 'wsemi/src/composeToTree.mjs'
|
|
27
|
-
// import getFileAccept from 'wsemi/src/getFileAccept.mjs'
|
|
28
16
|
|
|
29
17
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
// //ts
|
|
33
|
-
// let ts = sep(attachmentsIds, ';')
|
|
34
|
-
|
|
35
|
-
// return ts
|
|
36
|
-
// }
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// function atJoin(ts) {
|
|
40
|
-
|
|
41
|
-
// //uniq
|
|
42
|
-
// ts = uniq(ts)
|
|
43
|
-
|
|
44
|
-
// //str
|
|
45
|
-
// let str = join(ts, ';')
|
|
46
|
-
|
|
47
|
-
// return str
|
|
48
|
-
// }
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// function atParse(attachmentsIds) {
|
|
52
|
-
|
|
53
|
-
// //ts
|
|
54
|
-
// let ts = atSep(attachmentsIds)
|
|
55
|
-
|
|
56
|
-
// //ids
|
|
57
|
-
// let ids = map(ts, (v) => {
|
|
58
|
-
// let s = sep(v, '@')
|
|
59
|
-
// let table = get(s, 0, '')
|
|
60
|
-
// let id = get(s, 1, '')
|
|
61
|
-
// if (table === '') {
|
|
62
|
-
// console.log('atParse: invalid table in attachmentsIds', attachmentsIds)
|
|
63
|
-
// }
|
|
64
|
-
// if (id === '') {
|
|
65
|
-
// console.log('atParse: invalid id in attachmentsIds', attachmentsIds)
|
|
66
|
-
// }
|
|
67
|
-
// return {
|
|
68
|
-
// table,
|
|
69
|
-
// id,
|
|
70
|
-
// }
|
|
71
|
-
// })
|
|
72
|
-
|
|
73
|
-
// return ids
|
|
74
|
-
// }
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// function atRemove(inp, removeId, opt = {}) {
|
|
78
|
-
|
|
79
|
-
// //removeId
|
|
80
|
-
// if (!isstr(removeId)) {
|
|
81
|
-
// removeId = ''
|
|
82
|
-
// }
|
|
83
|
-
// if (removeId.indexOf('@') >= 0) {
|
|
84
|
-
// removeId = split(removeId, '@')[1] //取後面id
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
// //ids
|
|
88
|
-
// let ids = []
|
|
89
|
-
// let returnTypeTemp = ''
|
|
90
|
-
// if (isarr(inp)) {
|
|
91
|
-
// ids = inp
|
|
92
|
-
// returnTypeTemp = 'array'
|
|
93
|
-
// }
|
|
94
|
-
// else if (isstr(inp)) {
|
|
95
|
-
// ids = atParse(inp)
|
|
96
|
-
// returnTypeTemp = 'string'
|
|
97
|
-
// }
|
|
98
|
-
|
|
99
|
-
// //returnType
|
|
100
|
-
// let returnType = get(opt, 'returnType', null)
|
|
101
|
-
// if (returnType !== 'array' && returnType !== 'string') {
|
|
102
|
-
// returnType = returnTypeTemp
|
|
103
|
-
// }
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// //filter
|
|
107
|
-
// ids = filter(ids, (v) => {
|
|
108
|
-
// return v.id !== removeId
|
|
109
|
-
// })
|
|
110
|
-
|
|
111
|
-
// if (returnType === 'array') {
|
|
112
|
-
// return ids
|
|
113
|
-
// }
|
|
114
|
-
// return atMerge(ids)
|
|
115
|
-
// }
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// function atMerge(ids) {
|
|
119
|
-
|
|
120
|
-
// //ts
|
|
121
|
-
// let ts = map(ids, (v) => {
|
|
122
|
-
// let table = get(v, 'table', '')
|
|
123
|
-
// let id = get(v, 'id', '')
|
|
124
|
-
// if (table === '') {
|
|
125
|
-
// console.log('atMerge: invalid table in ids', ids)
|
|
126
|
-
// }
|
|
127
|
-
// if (id === '') {
|
|
128
|
-
// console.log('atMerge: invalid id in ids', ids)
|
|
129
|
-
// }
|
|
130
|
-
// return `${table}@${id}`
|
|
131
|
-
// })
|
|
132
|
-
|
|
133
|
-
// return atJoin(ts)
|
|
134
|
-
// }
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// function isNumOrEng(str) {
|
|
138
|
-
// let regExp = /^[\d|a-zA-Z]+$/
|
|
139
|
-
// if (regExp.test(str)) {
|
|
140
|
-
// return true
|
|
141
|
-
// }
|
|
142
|
-
// else {
|
|
143
|
-
// return false
|
|
144
|
-
// }
|
|
145
|
-
// }
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// function extractFileType(fileName, fileType) {
|
|
149
|
-
// let r = ''
|
|
150
|
-
|
|
151
|
-
// //find
|
|
152
|
-
// let ar = getFileAccept()
|
|
153
|
-
// for (let i = 0; i < ar.length; i++) {
|
|
154
|
-
// if (ar[i].acp === fileType) {
|
|
155
|
-
// return ar[i].name
|
|
156
|
-
// }
|
|
157
|
-
// }
|
|
158
|
-
|
|
159
|
-
// //from name ext
|
|
160
|
-
// let s = split(fileName, '.')
|
|
161
|
-
// if (size(s) > 1) {
|
|
162
|
-
// return last(s)
|
|
163
|
-
// }
|
|
164
|
-
|
|
165
|
-
// return r
|
|
166
|
-
// }
|
|
18
|
+
//dlm
|
|
19
|
+
let dlm = '/'
|
|
167
20
|
|
|
168
21
|
|
|
169
22
|
function getAllBlocks(targets) {
|
|
@@ -172,10 +25,10 @@ function getAllBlocks(targets) {
|
|
|
172
25
|
let rs = map(targets, (v) => {
|
|
173
26
|
|
|
174
27
|
//text, parentId
|
|
175
|
-
let s = sep(v.id,
|
|
28
|
+
let s = sep(v.id, dlm) //[tag:dlm]
|
|
176
29
|
let text = get(takeRight(s), 0) //取最後節點
|
|
177
30
|
s = dropRight(s, 1)
|
|
178
|
-
let parentId = join(s,
|
|
31
|
+
let parentId = join(s, dlm) //[tag:dlm] 取父節點
|
|
179
32
|
|
|
180
33
|
return {
|
|
181
34
|
...v,
|
|
@@ -184,9 +37,11 @@ function getAllBlocks(targets) {
|
|
|
184
37
|
text,
|
|
185
38
|
}
|
|
186
39
|
})
|
|
40
|
+
// console.log('rs', rs)
|
|
187
41
|
|
|
188
42
|
//sortBy
|
|
189
43
|
rs = sortBy(rs, 'order')
|
|
44
|
+
// console.log('rs sortBy', rs)
|
|
190
45
|
|
|
191
46
|
return rs
|
|
192
47
|
}
|
|
@@ -196,6 +51,7 @@ function getTreeBlocks(targets) {
|
|
|
196
51
|
|
|
197
52
|
//getAllBlocks
|
|
198
53
|
let blocks = getAllBlocks(targets)
|
|
54
|
+
// console.log('blocks', blocks)
|
|
199
55
|
|
|
200
56
|
//opt
|
|
201
57
|
let opt = {
|
|
@@ -238,7 +94,7 @@ function getUserGroups(user, ruleGroups) {
|
|
|
238
94
|
|
|
239
95
|
//add rules
|
|
240
96
|
gs = map(gs, (g) => {
|
|
241
|
-
let rules =
|
|
97
|
+
let rules = JSON5.parse(g.crules)
|
|
242
98
|
g.rules = rules
|
|
243
99
|
return g
|
|
244
100
|
})
|
|
@@ -259,7 +115,7 @@ function getTargetsByGroup(targets, group) {
|
|
|
259
115
|
group = cloneDeep(group)
|
|
260
116
|
|
|
261
117
|
//rules
|
|
262
|
-
let rules =
|
|
118
|
+
let rules = JSON5.parse(group.crules)
|
|
263
119
|
|
|
264
120
|
//rulesDisplay
|
|
265
121
|
let rulesDisplay = {}
|
|
@@ -309,11 +165,19 @@ function getTargetsByGroup(targets, group) {
|
|
|
309
165
|
|
|
310
166
|
|
|
311
167
|
function getUserRules(user, ruleGroups, targets) {
|
|
168
|
+
//依照使用者所允許之ruleGroups轉出對全部targets權限
|
|
169
|
+
|
|
170
|
+
//ruleGroupsIds
|
|
171
|
+
let ruleGroupsIds = get(user, 'ruleGroupsIds', '')
|
|
312
172
|
|
|
313
173
|
//getUserGroups
|
|
314
174
|
let gs = getUserGroups(user, ruleGroups)
|
|
315
175
|
// console.log('gs', gs)
|
|
316
176
|
|
|
177
|
+
//ruleGroupsNames
|
|
178
|
+
let ruleGroupsNames = map(gs, 'name')
|
|
179
|
+
ruleGroupsNames = join(ruleGroupsNames, ';')
|
|
180
|
+
|
|
317
181
|
//getTargetsByGroup
|
|
318
182
|
let rulesDisplay = {}
|
|
319
183
|
each(gs, (g) => {
|
|
@@ -348,7 +212,11 @@ function getUserRules(user, ruleGroups, targets) {
|
|
|
348
212
|
})
|
|
349
213
|
// console.log('rulesDisplay', rulesDisplay)
|
|
350
214
|
|
|
351
|
-
return
|
|
215
|
+
return {
|
|
216
|
+
ruleGroupsIds,
|
|
217
|
+
ruleGroupsNames,
|
|
218
|
+
rules: rulesDisplay,
|
|
219
|
+
}
|
|
352
220
|
}
|
|
353
221
|
|
|
354
222
|
|
|
@@ -11,6 +11,7 @@ let keyTable = 'ruleGroups'
|
|
|
11
11
|
let tableNameCht = '權限群組'
|
|
12
12
|
let tableNameEng = 'Rule groups'
|
|
13
13
|
|
|
14
|
+
|
|
14
15
|
let settings = {
|
|
15
16
|
id: {
|
|
16
17
|
pk: true,
|
|
@@ -61,7 +62,7 @@ let funNew = (ndata = {}) => {
|
|
|
61
62
|
o.userIdUpdate = o.userId
|
|
62
63
|
o.timeCreate = nowms2str()
|
|
63
64
|
o.timeUpdate = o.timeCreate
|
|
64
|
-
o.isActive = 'y'
|
|
65
|
+
// o.isActive = 'y'
|
|
65
66
|
return o
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -70,8 +71,6 @@ let funTest = () => {
|
|
|
70
71
|
['權限群組1', `{ "___all___": { "show": "y", "active": "n" }, "專案A.頁A": { "show": "y", "active": "y" }, "專案A.頁B": { "show": "n", "active": "n" } }`],
|
|
71
72
|
['權限群組2', `{ "___all___": { "show": "y", "active": "n" } }`],
|
|
72
73
|
['權限群組3', `{ "___all___": { "show": "y", "active": "y" } }`],
|
|
73
|
-
// ['L0權限群組', `{ "___all___": { "show": "n", "active": "n" }, "主題列表": { "show": "y", "active": "n" } }`],
|
|
74
|
-
// ['L1權限群組', `{ "___all___": { "show": "y", "active": "y" } }`],
|
|
75
74
|
]
|
|
76
75
|
rs = map(rs, ([g, crules], k) => {
|
|
77
76
|
let v = funNew({ userId: 'id-for-admin', crules })
|
|
@@ -3,7 +3,7 @@ import keys from 'lodash/keys'
|
|
|
3
3
|
import genID from 'wsemi/src/genID.mjs'
|
|
4
4
|
import dtmapping from 'wsemi/src/dtmapping.mjs'
|
|
5
5
|
import dtpick from 'wsemi/src/dtpick.mjs'
|
|
6
|
-
import nowms2str from 'wsemi/src/nowms2str.mjs'
|
|
6
|
+
// import nowms2str from 'wsemi/src/nowms2str.mjs'
|
|
7
7
|
import now2strp from 'wsemi/src/now2strp.mjs'
|
|
8
8
|
|
|
9
9
|
|
|
@@ -11,6 +11,7 @@ let keyTable = 'targets'
|
|
|
11
11
|
let tableNameCht = '管控對象'
|
|
12
12
|
let tableNameEng = 'Targets'
|
|
13
13
|
|
|
14
|
+
|
|
14
15
|
let settings = {
|
|
15
16
|
id: {
|
|
16
17
|
pk: true,
|
|
@@ -38,46 +39,38 @@ let settings = {
|
|
|
38
39
|
let funNew = (ndata = {}) => {
|
|
39
40
|
let o = dtmapping(ndata, keys(settings))
|
|
40
41
|
o.id = `${now2strp()}-${genID()}`
|
|
41
|
-
o.timeCreate = nowms2str()
|
|
42
|
-
o.timeUpdate = o.timeCreate
|
|
43
|
-
o.isActive = 'y'
|
|
42
|
+
// o.timeCreate = nowms2str()
|
|
43
|
+
// o.timeUpdate = o.timeCreate
|
|
44
|
+
// o.isActive = 'y'
|
|
44
45
|
return o
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
let funTest = () => {
|
|
48
49
|
let rs = [
|
|
49
50
|
'專案A',
|
|
50
|
-
'專案A
|
|
51
|
-
'專案A
|
|
52
|
-
'專案A
|
|
53
|
-
'專案A
|
|
54
|
-
'專案A
|
|
55
|
-
'專案A
|
|
56
|
-
'專案A
|
|
57
|
-
'專案A
|
|
58
|
-
'專案A
|
|
59
|
-
'專案A
|
|
60
|
-
'專案A
|
|
51
|
+
'專案A/頁A',
|
|
52
|
+
'專案A/頁A/區塊A',
|
|
53
|
+
'專案A/頁A/區塊A/執行按鈕',
|
|
54
|
+
'專案A/頁A/區塊A/分析按鈕',
|
|
55
|
+
'專案A/頁B',
|
|
56
|
+
'專案A/頁B/區塊A',
|
|
57
|
+
'專案A/頁B/區塊A/執行按鈕',
|
|
58
|
+
'專案A/頁B/區塊A/分析按鈕',
|
|
59
|
+
'專案A/頁B/區塊B',
|
|
60
|
+
'專案A/頁B/區塊B/展開按鈕',
|
|
61
|
+
'專案A/頁B/區塊B/下載按鈕',
|
|
61
62
|
'專案B',
|
|
62
|
-
'專案B
|
|
63
|
-
'專案B
|
|
64
|
-
'專案B
|
|
65
|
-
'專案B
|
|
66
|
-
'專案B
|
|
67
|
-
'專案B
|
|
68
|
-
'專案B
|
|
69
|
-
'專案B
|
|
70
|
-
// '主題列表',
|
|
71
|
-
// '主題列表.隱藏已刪除',
|
|
72
|
-
// '主題列表.新增主題',
|
|
73
|
-
// '主題列表.主題排序',
|
|
74
|
-
// '主題列表.編輯主題',
|
|
75
|
-
// '主題列表.刪除主題',
|
|
76
|
-
// '後台管理',
|
|
77
|
-
// '權限管理',
|
|
63
|
+
'專案B/頁A',
|
|
64
|
+
'專案B/頁A/區塊A',
|
|
65
|
+
'專案B/頁A/區塊A/下載報表按鈕',
|
|
66
|
+
'專案B/頁A/區塊A/下載數據按鈕',
|
|
67
|
+
'專案B/頁B/區塊A',
|
|
68
|
+
'專案B/頁B/區塊B',
|
|
69
|
+
'專案B/頁B/區塊B/顯示後台按鈕',
|
|
70
|
+
'專案B/頁B/區塊B/轉跳主站按鈕',
|
|
78
71
|
]
|
|
79
72
|
rs = map(rs, (key, k) => {
|
|
80
|
-
let v = funNew({
|
|
73
|
+
let v = funNew({ description: key })
|
|
81
74
|
v.id = `id-for-${key}`
|
|
82
75
|
v = dtpick(v, keys(settings))
|
|
83
76
|
return v
|
|
@@ -104,7 +104,7 @@ let funTest = () => {
|
|
|
104
104
|
rs[3].from = 'teamB'
|
|
105
105
|
rs[4].from = 'teamB'
|
|
106
106
|
rs[4].isActive = 'n'
|
|
107
|
-
rs[5].ruleGroupsIds = `id-for
|
|
107
|
+
rs[5].ruleGroupsIds = `id-for-權限群組1`
|
|
108
108
|
rs[5].description = '測試系統管理員描述說明'
|
|
109
109
|
rs[5].isAdmin = 'y' //admin
|
|
110
110
|
console.log(`已產生: ${keyTable} 測試資料`, rs)
|
package/src/store/mutations.mjs
CHANGED
package/srv.mjs
CHANGED
|
@@ -30,15 +30,32 @@ let opt = {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
let getUserByToken = async (token) => {
|
|
33
|
-
if (token
|
|
34
|
-
|
|
33
|
+
// if (token === '{token-for-application}') { //提供外部應用系統作為存取使用者
|
|
34
|
+
// return {
|
|
35
|
+
// id: 'id-for-application',
|
|
36
|
+
// name: 'application',
|
|
37
|
+
// email: 'admin@example.com',
|
|
38
|
+
// isAdmin: 'y',
|
|
39
|
+
// }
|
|
40
|
+
// }
|
|
41
|
+
if (token === 'token-for-sys-application') { //將主系統視為外部應用系統, 依據指定token作為授權使用者
|
|
42
|
+
return {
|
|
43
|
+
id: 'id-for-application',
|
|
44
|
+
name: 'application',
|
|
45
|
+
email: 'admin@example.com',
|
|
46
|
+
isAdmin: 'y',
|
|
47
|
+
}
|
|
35
48
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
if (token === 'sys') { //開發階段w-ui-loginout自動給予browser使用者(且位於localhost)的token為sys
|
|
50
|
+
return {
|
|
51
|
+
id: 'id-for-admin',
|
|
52
|
+
name: 'tester',
|
|
53
|
+
email: 'admin@example.com',
|
|
54
|
+
isAdmin: 'y',
|
|
55
|
+
}
|
|
41
56
|
}
|
|
57
|
+
console.log('invalid token', token)
|
|
58
|
+
return {}
|
|
42
59
|
}
|
|
43
60
|
|
|
44
61
|
//WWebPerm
|
package/tableTags-web-perm.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"ruleGroups":"
|
|
1
|
+
{"ruleGroups":"lawH1q","targets":"ajtpXf","users":"t4rBhb"}
|