sumba 2.23.0 → 2.25.0
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/extend/bajo/hook/bajo.extend@after-read-config.js +13 -0
- package/extend/bajo/hook/dobo.sumba-attrib-guard$dobo.sumba-x-attrib-guard@after-transaction.js +6 -0
- package/extend/bajo/hook/dobo.sumba-model-guard$dobo.sumba-x-model-guard@after-transaction.js +6 -0
- package/extend/bajo/hook/dobo.sumba-route-guard$dobo.sumba-x-route-guard@after-transaction.js +6 -0
- package/extend/bajo/hook/dobo.sumba-team$dobo.sumba-site@after-transaction.js +8 -0
- package/extend/bajo/hook/dobo@before-count-record.js +3 -3
- package/extend/bajo/hook/{dobo@before-create-record.js → dobo@before-driver-create-record.js} +6 -6
- package/extend/bajo/hook/dobo@before-driver-find-all-record.js +13 -0
- package/extend/bajo/hook/dobo@before-driver-find-record.js +114 -0
- package/extend/bajo/hook/dobo@before-driver-get-record.js +22 -0
- package/extend/bajo/hook/dobo@before-driver-remove-record.js +10 -0
- package/extend/bajo/hook/dobo@before-driver-update-record.js +10 -0
- package/extend/bajo/hook/waibu-mpa@pre-parsing.js +5 -4
- package/extend/bajo/hook/waibu-rest-api@pre-parsing.js +5 -4
- package/extend/bajo/hook/waibu-static@pre-parsing.js +5 -4
- package/extend/bajo/hook/waibu@after-app-boot.js +2 -0
- package/extend/bajo/intl/en-US.json +13 -2
- package/extend/bajo/intl/id.json +20 -2
- package/extend/dobo/feature/site-ids.js +19 -0
- package/extend/dobo/feature/team-ids.js +19 -0
- package/extend/dobo/fixture/{route-guard.js → x-route-guard.js} +2 -4
- package/extend/dobo/model/attrib-guard.js +32 -0
- package/extend/dobo/model/model-guard.js +48 -0
- package/extend/dobo/model/route-guard.js +42 -54
- package/extend/dobo/model/x-attrib-guard.js +14 -0
- package/extend/dobo/model/x-model-guard.js +13 -0
- package/extend/dobo/model/x-route-guard.js +13 -0
- package/extend/waibuDb/schema/attrib-guard.js +15 -0
- package/extend/waibuDb/schema/model-guard.js +15 -0
- package/extend/waibuDb/schema/route-guard.js +1 -1
- package/extend/waibuDb/schema/user.js +19 -26
- package/extend/waibuDb/schema/x-attrib-guard.js +15 -0
- package/extend/waibuDb/schema/x-model-guard.js +15 -0
- package/extend/waibuDb/schema/x-route-guard.js +15 -0
- package/extend/waibuMpa/extend/waibuAdmin/route/attrib-guard/@action.js +11 -0
- package/extend/waibuMpa/extend/waibuAdmin/route/model-guard/@action.js +11 -0
- package/extend/waibuMpa/extend/waibuAdmin/route/reset-user-password.js +2 -1
- package/extend/waibuMpa/extend/waibuAdmin/route/x/attrib-guard/@action.js +12 -0
- package/extend/waibuMpa/extend/waibuAdmin/route/{cache → x/cache}/@action.js +1 -1
- package/extend/waibuMpa/extend/waibuAdmin/route/x/model-guard/@action.js +12 -0
- package/extend/waibuMpa/extend/waibuAdmin/route/x/route-guard/@action.js +12 -0
- package/extend/waibuMpa/extend/waibuAdmin/route/{session → x/session}/@action.js +1 -1
- package/extend/waibuMpa/extend/waibuAdmin/route/{all-sites → x/site}/@action.js +1 -1
- package/index.js +114 -35
- package/lib/get-user.js +9 -8
- package/lib/util.js +58 -23
- package/package.json +1 -1
- package/wiki/CHANGES.md +13 -0
- package/extend/bajo/hook/dobo.sumba-team-guard@after-action.js +0 -6
- package/extend/bajo/hook/dobo.sumba-user-guard@after-action.js +0 -6
- package/extend/bajo/hook/dobo@before-find-record.js +0 -63
- package/extend/bajo/hook/dobo@before-get-record.js +0 -23
- package/extend/bajo/hook/dobo@before-remove-record.js +0 -10
- package/extend/bajo/hook/dobo@before-update-record.js +0 -10
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { properties, features } from './route-guard.js'
|
|
2
|
+
import { options } from './model-guard.js'
|
|
3
|
+
|
|
4
|
+
async function xRouteGuard () {
|
|
5
|
+
const { isString } = this.app.lib._
|
|
6
|
+
return {
|
|
7
|
+
properties: properties.filter(prop => !isString(prop) || (isString(prop) && !prop.startsWith('teamIds'))),
|
|
8
|
+
features: features.filter(feat => !isString(feat) || (isString(feat) && !['sumba:siteId', 'dobo:updatedAt'].includes(feat))).concat('sumba:siteIds', 'dobo:updatedAt'),
|
|
9
|
+
options
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default xRouteGuard
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
async function user ({ req } = {}) {
|
|
2
|
+
const { merge } = this.app.lib._
|
|
3
|
+
const details = {
|
|
4
|
+
forceVisible: ['password', 'token'],
|
|
5
|
+
format: {
|
|
6
|
+
password: function (val, rec) {
|
|
7
|
+
return `<a href="waibuAdmin:/site/reset-user-password?username=${rec.username}">${req.t('resetPassword')}</a>`
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
widget: {
|
|
11
|
+
password: {
|
|
12
|
+
component: 'form-plaintext'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
2
16
|
return {
|
|
3
17
|
common: {
|
|
4
18
|
layout: [
|
|
5
19
|
{ name: 'meta', fields: ['id:3', 'createdAt:3', 'updatedAt:3', 'status:3'] },
|
|
6
|
-
{ name: 'account', fields: ['username:3', 'email:3', 'provider:3', 'password:3', 'firstName:3', 'lastName:3'
|
|
20
|
+
{ name: 'account', fields: ['username:3', 'email:3', 'provider:3', 'password:3', 'firstName:3', 'lastName:3'] },
|
|
7
21
|
{ name: 'address', fields: ['address1:12', 'address2:12', 'city:6-md 8-sm', 'zipCode:2-md 4-sm', 'provinceState:4-md', 'country:6-md', 'phone:6-md', 'website:12'] },
|
|
8
22
|
{ name: 'socialMedia', fields: ['socX:3-md 6-sm', 'socInstagram:3-md 6-sm', 'socFacebook:3-md 6-sm', 'socLinkedIn:3-md 6-sm'] }
|
|
9
23
|
],
|
|
@@ -19,7 +33,7 @@ async function user ({ req } = {}) {
|
|
|
19
33
|
sort: 'username:1',
|
|
20
34
|
limit: 10
|
|
21
35
|
},
|
|
22
|
-
fields: ['createdAt', 'status', 'username', 'provider', 'email', 'firstName', 'lastName', 'city', 'zipCode', 'provinceState', 'country', 'phone'
|
|
36
|
+
fields: ['createdAt', 'status', 'username', 'provider', 'email', 'firstName', 'lastName', 'city', 'zipCode', 'provinceState', 'country', 'phone'],
|
|
23
37
|
stat: {
|
|
24
38
|
aggregate: [
|
|
25
39
|
{ fields: ['status'], group: 'status', aggregate: ['count'] },
|
|
@@ -28,35 +42,14 @@ async function user ({ req } = {}) {
|
|
|
28
42
|
]
|
|
29
43
|
}
|
|
30
44
|
},
|
|
31
|
-
details
|
|
32
|
-
forceVisible: ['password', 'token'],
|
|
33
|
-
widget: {
|
|
34
|
-
password: {
|
|
35
|
-
component: 'form-plaintext',
|
|
36
|
-
attr: {
|
|
37
|
-
href: 'waibuAdmin:/site/reset-user-password?username={username}',
|
|
38
|
-
value: req.t('resetPassword')
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
},
|
|
45
|
+
details,
|
|
43
46
|
add: {
|
|
44
47
|
forceVisible: ['password'],
|
|
45
48
|
hidden: ['id', 'createdAt', 'updatedAt', 'provider']
|
|
46
49
|
},
|
|
47
|
-
edit: {
|
|
48
|
-
forceVisible: ['password', 'token'],
|
|
49
|
-
widget: {
|
|
50
|
-
password: {
|
|
51
|
-
component: 'form-plaintext',
|
|
52
|
-
attr: {
|
|
53
|
-
href: 'waibuAdmin:/site/reset-user-password?username={username}',
|
|
54
|
-
value: req.t('resetPassword')
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
},
|
|
50
|
+
edit: merge({}, details, {
|
|
58
51
|
readonly: ['id', 'createdAt', 'updatedAt', 'username', 'provider']
|
|
59
|
-
}
|
|
52
|
+
})
|
|
60
53
|
}
|
|
61
54
|
}
|
|
62
55
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const action = {
|
|
2
|
+
method: ['GET', 'POST'],
|
|
3
|
+
title: 'attribGuard',
|
|
4
|
+
handler: async function (req, reply) {
|
|
5
|
+
const { importModule } = this.app.bajo
|
|
6
|
+
const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
|
|
7
|
+
return await crudSkel.call(this, 'SumbaAttribGuard', req, reply)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default action
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const action = {
|
|
2
|
+
method: ['GET', 'POST'],
|
|
3
|
+
title: 'modelGuard',
|
|
4
|
+
handler: async function (req, reply) {
|
|
5
|
+
const { importModule } = this.app.bajo
|
|
6
|
+
const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
|
|
7
|
+
return await crudSkel.call(this, 'SumbaModelGuard', req, reply)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default action
|
|
@@ -4,13 +4,14 @@ const resetUserPassword = {
|
|
|
4
4
|
handler: async function (req, reply) {
|
|
5
5
|
const { importPkg } = this.app.bajo
|
|
6
6
|
const { defaultsDeep } = this.app.lib.aneka
|
|
7
|
+
const { passwordRule } = this.app.sumba
|
|
7
8
|
const Joi = await importPkg('dobo:joi')
|
|
8
9
|
const model = this.app.dobo.getModel('SumbaUser')
|
|
9
10
|
const form = defaultsDeep(req.body, { username: req.query.username })
|
|
10
11
|
let error
|
|
11
12
|
if (req.method === 'POST') {
|
|
12
13
|
try {
|
|
13
|
-
const password = await
|
|
14
|
+
const password = await passwordRule(req)
|
|
14
15
|
const schema = Joi.object({
|
|
15
16
|
username: Joi.string().max(50).required(),
|
|
16
17
|
password,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const action = {
|
|
2
|
+
method: ['GET', 'POST'],
|
|
3
|
+
title: 'xAttribGuard',
|
|
4
|
+
xSite: true,
|
|
5
|
+
handler: async function (req, reply) {
|
|
6
|
+
const { importModule } = this.app.bajo
|
|
7
|
+
const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
|
|
8
|
+
return await crudSkel.call(this, 'SumbaXAttribGuard', req, reply)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default action
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const action = {
|
|
2
|
+
method: ['GET', 'POST'],
|
|
3
|
+
title: 'xModelGuard',
|
|
4
|
+
xSite: true,
|
|
5
|
+
handler: async function (req, reply) {
|
|
6
|
+
const { importModule } = this.app.bajo
|
|
7
|
+
const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
|
|
8
|
+
return await crudSkel.call(this, 'SumbaXModelGuard', req, reply)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default action
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const action = {
|
|
2
|
+
method: ['GET', 'POST'],
|
|
3
|
+
title: 'xRouteGuard',
|
|
4
|
+
xSite: true,
|
|
5
|
+
handler: async function (req, reply) {
|
|
6
|
+
const { importModule } = this.app.bajo
|
|
7
|
+
const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
|
|
8
|
+
return await crudSkel.call(this, 'SumbaXRouteGuard', req, reply)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default action
|
package/index.js
CHANGED
|
@@ -20,7 +20,7 @@ const defMultiSite = {
|
|
|
20
20
|
async function factory (pkgName) {
|
|
21
21
|
const me = this
|
|
22
22
|
const { getModel } = this.app.dobo
|
|
23
|
-
const { cloneDeep } = this.app.lib._
|
|
23
|
+
const { cloneDeep, uniq, isEmpty } = this.app.lib._
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Sumba class
|
|
@@ -32,11 +32,14 @@ async function factory (pkgName) {
|
|
|
32
32
|
super(pkgName, me.app)
|
|
33
33
|
this.config = {
|
|
34
34
|
multiSite: cloneDeep(defMultiSite),
|
|
35
|
-
|
|
35
|
+
crossSiteAdmins: [], // format: "<siteAlias>:<username>"
|
|
36
36
|
waibu: {
|
|
37
37
|
title: 'site',
|
|
38
38
|
prefix: 'site'
|
|
39
39
|
},
|
|
40
|
+
dobo: {
|
|
41
|
+
model: {}
|
|
42
|
+
},
|
|
40
43
|
waibuMpa: {
|
|
41
44
|
home: 'sumba:/your-stuff/profile',
|
|
42
45
|
icon: 'globe',
|
|
@@ -152,8 +155,10 @@ async function factory (pkgName) {
|
|
|
152
155
|
getUserByTokenDur: '1m'
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
|
-
this.
|
|
156
|
-
this.
|
|
158
|
+
this.routeGuards = { local: [], global: [] }
|
|
159
|
+
this.modelGuards = { local: [], global: [] }
|
|
160
|
+
this.attribGuards = { local: [], global: [] }
|
|
161
|
+
|
|
157
162
|
this.unsafeUserFields = ['password']
|
|
158
163
|
this.selfBind(['createNewSite', 'removeSite', 'getSite', 'getUserById', 'getUserByToken', 'getUserByUsernamePassword'])
|
|
159
164
|
}
|
|
@@ -170,10 +175,10 @@ async function factory (pkgName) {
|
|
|
170
175
|
|
|
171
176
|
start = async () => {
|
|
172
177
|
const { getModel } = this.app.dobo
|
|
173
|
-
if (this.config.
|
|
178
|
+
if (this.config.crossSiteAdmins.length === 0) {
|
|
174
179
|
const site = await getModel('SumbaSite').findOneRecord({ query: { alias: 'default' } }, { noMagic: true })
|
|
175
180
|
const user = await getModel('SumbaUser').findOneRecord({ query: { username: 'admin', siteId: site.id } }, { noMagic: true })
|
|
176
|
-
this.config.
|
|
181
|
+
this.config.crossSiteAdmins.push(`${site.alias}:${user.username}`)
|
|
177
182
|
}
|
|
178
183
|
}
|
|
179
184
|
|
|
@@ -204,50 +209,60 @@ async function factory (pkgName) {
|
|
|
204
209
|
if (!this.app.waibuAdmin) return
|
|
205
210
|
const { getPluginPrefix } = this.app.waibu
|
|
206
211
|
const prefix = getPluginPrefix(this.ns)
|
|
212
|
+
const params = { action: 'list' }
|
|
207
213
|
const items = [{
|
|
214
|
+
title: 'xSite',
|
|
215
|
+
children: [
|
|
216
|
+
{ title: 'allSites', href: `waibuAdmin:/${prefix}/x/site/:action`, params },
|
|
217
|
+
{ title: 'xRouteGuard', href: `waibuAdmin:/${prefix}/x/route-guard/:action`, params },
|
|
218
|
+
{ title: 'xModelGuard', href: `waibuAdmin:/${prefix}/x/model-guard/:action`, params },
|
|
219
|
+
{ title: 'xAttribGuard', href: `waibuAdmin:/${prefix}/x/attrib-guard/:action`, params },
|
|
220
|
+
{ title: 'userSession', href: `waibuAdmin:/${prefix}/x/session/:action`, params }
|
|
221
|
+
]
|
|
222
|
+
}, {
|
|
208
223
|
title: 'manageSite',
|
|
209
224
|
children: [
|
|
210
225
|
{ title: 'siteProfile', href: `waibuAdmin:/${prefix}/site` },
|
|
211
|
-
{ title: 'siteSetting', href: `waibuAdmin:/${prefix}/site-setting
|
|
212
|
-
{ title: 'allSites', href: `waibuAdmin:/${prefix}/all-sites/list` }
|
|
226
|
+
{ title: 'siteSetting', href: `waibuAdmin:/${prefix}/site-setting/:action`, params }
|
|
213
227
|
]
|
|
214
228
|
}, {
|
|
215
229
|
title: 'manageUser',
|
|
216
230
|
children: [
|
|
217
|
-
{ title: 'userProfile', href: `waibuAdmin:/${prefix}/user
|
|
218
|
-
{ title: 'userSetting', href: `waibuAdmin:/${prefix}/user-setting
|
|
231
|
+
{ title: 'userProfile', href: `waibuAdmin:/${prefix}/user/:action`, params },
|
|
232
|
+
{ title: 'userSetting', href: `waibuAdmin:/${prefix}/user-setting/:action`, params },
|
|
219
233
|
{ title: 'resetUserPassword', href: `waibuAdmin:/${prefix}/reset-user-password` }
|
|
220
234
|
]
|
|
221
235
|
}, {
|
|
222
236
|
title: 'manageTeam',
|
|
223
237
|
children: [
|
|
224
|
-
{ title: 'teamProfile', href: `waibuAdmin:/${prefix}/team
|
|
225
|
-
{ title: 'teamUser', href: `waibuAdmin:/${prefix}/team-user
|
|
226
|
-
{ title: 'teamSetting', href: `waibuAdmin:/${prefix}/team-setting
|
|
238
|
+
{ title: 'teamProfile', href: `waibuAdmin:/${prefix}/team/:action`, params },
|
|
239
|
+
{ title: 'teamUser', href: `waibuAdmin:/${prefix}/team-user/:action`, params },
|
|
240
|
+
{ title: 'teamSetting', href: `waibuAdmin:/${prefix}/team-setting/:action`, params }
|
|
227
241
|
]
|
|
228
242
|
}, {
|
|
229
243
|
title: 'permission',
|
|
230
244
|
children: [
|
|
231
|
-
{ title: 'routeGuard', href: `waibuAdmin:/${prefix}/route-guard
|
|
245
|
+
{ title: 'routeGuard', href: `waibuAdmin:/${prefix}/route-guard/:action`, params },
|
|
246
|
+
{ title: 'modelGuard', href: `waibuAdmin:/${prefix}/model-guard/:action`, params },
|
|
247
|
+
{ title: 'attribGuard', href: `waibuAdmin:/${prefix}/attrib-guard/:action`, params }
|
|
232
248
|
]
|
|
233
249
|
}, {
|
|
234
250
|
title: 'supportSystem',
|
|
235
251
|
children: [
|
|
236
|
-
{ title: 'contactForm', href: `waibuAdmin:/${prefix}/contact-form
|
|
237
|
-
{ title: 'contactFormCat', href: `waibuAdmin:/${prefix}/contact-form-cat
|
|
238
|
-
{ title: 'ticket', href: `waibuAdmin:/${prefix}/ticket
|
|
239
|
-
{ title: 'ticketCat', href: `waibuAdmin:/${prefix}/ticket-cat
|
|
252
|
+
{ title: 'contactForm', href: `waibuAdmin:/${prefix}/contact-form/:action`, params },
|
|
253
|
+
{ title: 'contactFormCat', href: `waibuAdmin:/${prefix}/contact-form-cat/:action`, params },
|
|
254
|
+
{ title: 'ticket', href: `waibuAdmin:/${prefix}/ticket/:action`, params },
|
|
255
|
+
{ title: 'ticketCat', href: `waibuAdmin:/${prefix}/ticket-cat/:action`, params }
|
|
240
256
|
]
|
|
241
257
|
}, {
|
|
242
258
|
title: 'misc',
|
|
243
259
|
children: [
|
|
244
|
-
{ title: 'manageDownload', href: `waibuAdmin:/${prefix}/download
|
|
245
|
-
{ title: 'userSession', href: `waibuAdmin:/${prefix}/session/list` }
|
|
260
|
+
{ title: 'manageDownload', href: `waibuAdmin:/${prefix}/download/:action`, params }
|
|
246
261
|
]
|
|
247
262
|
}]
|
|
248
263
|
if (this.app.bajoCache) {
|
|
249
|
-
const item = items.find(i => i.title === '
|
|
250
|
-
|
|
264
|
+
const item = items.find(i => i.title === 'xSite')
|
|
265
|
+
item.children.push({ title: 'cacheStorage', href: `waibuAdmin:/${prefix}/x/cache/:action`, params })
|
|
251
266
|
}
|
|
252
267
|
return items
|
|
253
268
|
}
|
|
@@ -272,13 +287,14 @@ async function factory (pkgName) {
|
|
|
272
287
|
|
|
273
288
|
verifySession = async (req, reply, source, payload) => {
|
|
274
289
|
const { routePath } = this.app.waibu
|
|
290
|
+
const { query, params } = req
|
|
275
291
|
|
|
276
292
|
if (!req.session) return false
|
|
277
293
|
if (req.session.userId) {
|
|
278
294
|
req.user = await this.getUserById(req.session.userId, req)
|
|
279
295
|
return true
|
|
280
296
|
}
|
|
281
|
-
const redir = routePath(this.config.redirect.signin,
|
|
297
|
+
const redir = routePath(this.config.redirect.signin, { query, params })
|
|
282
298
|
req.session.ref = req.url
|
|
283
299
|
throw this.error('_redirect', { redirect: redir })
|
|
284
300
|
}
|
|
@@ -361,7 +377,7 @@ async function factory (pkgName) {
|
|
|
361
377
|
return true
|
|
362
378
|
}
|
|
363
379
|
|
|
364
|
-
checkPathsByRoute = ({ paths = [],
|
|
380
|
+
checkPathsByRoute = ({ paths = [], teamIds = [], guards = [] }) => {
|
|
365
381
|
const { includes } = this.app.lib.aneka
|
|
366
382
|
const { outmatch } = this.app.lib
|
|
367
383
|
|
|
@@ -369,10 +385,8 @@ async function factory (pkgName) {
|
|
|
369
385
|
const matchPath = outmatch(item.path)
|
|
370
386
|
for (const path of paths) {
|
|
371
387
|
if (matchPath(path)) {
|
|
372
|
-
if (item.
|
|
373
|
-
|
|
374
|
-
if (includes(teams, item.teams)) return item
|
|
375
|
-
}
|
|
388
|
+
if (includes(teamIds, item.teamIds)) return item
|
|
389
|
+
if (teamIds.length === 0) return item
|
|
376
390
|
}
|
|
377
391
|
}
|
|
378
392
|
}
|
|
@@ -529,20 +543,85 @@ async function factory (pkgName) {
|
|
|
529
543
|
return await hash(item, this.config.auth.common.apiKey.algo)
|
|
530
544
|
}
|
|
531
545
|
|
|
532
|
-
|
|
546
|
+
_fetchGuards = async (type = 'Route') => {
|
|
533
547
|
const { getModel } = this.app.dobo
|
|
548
|
+
const options = { noMagic: true, noCache: true, noDriverHook: true, dataOnly: true }
|
|
549
|
+
const filter = { query: { status: 'ACTIVE' } }
|
|
550
|
+
return {
|
|
551
|
+
global: await getModel(`SumbaX${type}Guard`).findAllRecord(filter, options),
|
|
552
|
+
local: await getModel(`Sumba${type}Guard`).findAllRecord(filter, options),
|
|
553
|
+
siteIds: (await getModel('SumbaSite').findAllRecord(filter.options)).map(item => item.id + '')
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
getRouteGuards = async (reread) => {
|
|
534
558
|
const { routePath } = this.app.waibu
|
|
535
559
|
const { map, orderBy } = this.app.lib._
|
|
560
|
+
const { isSet } = this.app.lib.aneka
|
|
536
561
|
if (!reread) return this.routeGuards
|
|
537
|
-
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
562
|
+
|
|
563
|
+
const result = await this._fetchGuards('Route')
|
|
564
|
+
for (const type of ['global', 'local']) {
|
|
565
|
+
result[type] = result[type].map(item => {
|
|
566
|
+
item.siteIds = item.siteIds ?? []
|
|
567
|
+
if (item.siteIds.length === 0) item.siteIds = [...result.siteIds]
|
|
568
|
+
if (item.siteId) item.siteIds = uniq([...item.siteIds, item.siteId].filter(i => isSet(i)).map(i => i + ''))
|
|
569
|
+
item.teamIds = (item.teamIds ?? []).filter(i => isSet(i)).map(i => i + '')
|
|
570
|
+
item.methods = item.methods ?? []
|
|
571
|
+
delete item.siteId
|
|
572
|
+
return item
|
|
573
|
+
})
|
|
574
|
+
this.routeGuards[type] = orderBy(map(result[type], item => {
|
|
575
|
+
item.path = routePath(item.path)
|
|
576
|
+
return item
|
|
577
|
+
}), ['weight', 'path'], ['desc', 'asc'])
|
|
578
|
+
}
|
|
543
579
|
return this.routeGuards
|
|
544
580
|
}
|
|
545
581
|
|
|
582
|
+
getModelGuards = async (reread) => {
|
|
583
|
+
const { isSet } = this.app.lib.aneka
|
|
584
|
+
if (!reread) return this.modelGuards
|
|
585
|
+
|
|
586
|
+
const result = await this._fetchGuards('Model')
|
|
587
|
+
for (const type of ['global', 'local']) {
|
|
588
|
+
this.modelGuards[type] = result[type].filter(item => (!isEmpty(item.value)) && (!isEmpty(item.models))).map(item => {
|
|
589
|
+
item.siteIds = item.siteIds ?? []
|
|
590
|
+
if (item.siteIds.length === 0) item.siteIds = [...result.siteIds]
|
|
591
|
+
if (item.siteId) item.siteIds = uniq([...item.siteIds, item.siteId].filter(i => isSet(i)).map(i => i + ''))
|
|
592
|
+
item.teamIds = (item.teamIds ?? []).filter(i => isSet(i)).map(i => i + '')
|
|
593
|
+
delete item.siteId
|
|
594
|
+
return item
|
|
595
|
+
})
|
|
596
|
+
}
|
|
597
|
+
return this.modelGuards
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
getAttribGuards = async (reread) => {
|
|
601
|
+
const { isSet } = this.app.lib.aneka
|
|
602
|
+
if (!reread) return this.attribGuards
|
|
603
|
+
|
|
604
|
+
const result = await this._fetchGuards('Attrib')
|
|
605
|
+
for (const type of ['global', 'local']) {
|
|
606
|
+
this.attribGuards[type] = result[type].map(item => {
|
|
607
|
+
item.siteIds = item.siteIds ?? []
|
|
608
|
+
if (item.siteIds.length === 0) item.siteIds = [...result.siteIds]
|
|
609
|
+
if (item.siteId) item.siteIds = uniq([...item.siteIds, item.siteId].filter(i => isSet(i)).map(i => i + ''))
|
|
610
|
+
item.teamIds = (item.teamIds ?? []).filter(i => isSet(i)).map(i => i + '')
|
|
611
|
+
item.models = item.models ?? []
|
|
612
|
+
item.hiddenCols = item.hiddenCols ?? []
|
|
613
|
+
delete item.siteId
|
|
614
|
+
return item
|
|
615
|
+
})
|
|
616
|
+
}
|
|
617
|
+
return this.attribGuards
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
getModelNames = (asValue) => {
|
|
621
|
+
const values = this.app.dobo.models.map(item => item.name).sort()
|
|
622
|
+
return asValue ? values.map(item => ({ value: item, text: item })) : values
|
|
623
|
+
}
|
|
624
|
+
|
|
546
625
|
createNewSite = createNewSite
|
|
547
626
|
removeSite = removeSite
|
|
548
627
|
getSite = getSite
|
package/lib/get-user.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { parseNsSettings } from './util.js'
|
|
2
2
|
|
|
3
|
-
export async function mergeTeam (user) {
|
|
3
|
+
export async function mergeTeam (user, req) {
|
|
4
4
|
const { map, pick } = this.app.lib._
|
|
5
5
|
const { getModel } = this.app.dobo
|
|
6
|
-
user.interSiteAdmin = this.config.interSiteAdmins.includes(user.id)
|
|
7
6
|
user.teams = []
|
|
8
7
|
const query = { userId: user.id, siteId: user.siteId }
|
|
9
8
|
let mdl = getModel('SumbaTeamUser')
|
|
@@ -31,6 +30,8 @@ export async function mergeTeam (user) {
|
|
|
31
30
|
user.teams.push(item)
|
|
32
31
|
}
|
|
33
32
|
}
|
|
33
|
+
user.isXSiteAdmin = this.config.crossSiteAdmins.includes(`${req.site.alias}:${user.username}`)
|
|
34
|
+
user.isAdmin = user.teams.some(t => t.alias === 'administrator')
|
|
34
35
|
for (const field of this.unsafeUserFields) {
|
|
35
36
|
delete user[field]
|
|
36
37
|
}
|
|
@@ -45,9 +46,9 @@ export async function getUserById (id, req) {
|
|
|
45
46
|
user = await getCache({ key })
|
|
46
47
|
if (user) return JSON.parse(user)
|
|
47
48
|
}
|
|
48
|
-
user = await getModel('SumbaUser').getRecord(id, { noHook: true, throwNotFound: false, req })
|
|
49
|
+
user = await getModel('SumbaUser').getRecord(id, { noHook: true, noDriverHook: true, throwNotFound: false, req })
|
|
49
50
|
if (!user) return
|
|
50
|
-
await mergeTeam.call(this, user)
|
|
51
|
+
await mergeTeam.call(this, user, req)
|
|
51
52
|
if (setCache) {
|
|
52
53
|
await setCache({ key, value: JSON.stringify(user), ttl: this.config.cacheTtl.getUserByIdDur })
|
|
53
54
|
}
|
|
@@ -63,9 +64,9 @@ export async function getUserByToken (token, req) {
|
|
|
63
64
|
user = await getCache({ key })
|
|
64
65
|
if (user) return JSON.parse(user)
|
|
65
66
|
}
|
|
66
|
-
user = await getModel('SumbaUser').findOneRecord({ query: { token } }, { noHook: true, throwNotFound: false, req })
|
|
67
|
+
user = await getModel('SumbaUser').findOneRecord({ query: { token } }, { noHook: true, noDriverHook: true, throwNotFound: false, req })
|
|
67
68
|
if (!user) return
|
|
68
|
-
await mergeTeam.call(this, user)
|
|
69
|
+
await mergeTeam.call(this, user, req)
|
|
69
70
|
if (setCache) {
|
|
70
71
|
await setCache({ key, value: JSON.stringify(user), ttl: this.config.cacheTtl.getUserByTokenDur })
|
|
71
72
|
}
|
|
@@ -80,11 +81,11 @@ export async function getUserByUsernamePassword (username = '', password = '', r
|
|
|
80
81
|
const bcrypt = await importPkg('bajoExtra:bcrypt')
|
|
81
82
|
|
|
82
83
|
const query = { username, provider: 'local', siteId: req.site.id }
|
|
83
|
-
const user = await model.findOneRecord({ query }, { req, forceNoHidden: true, noHook: true })
|
|
84
|
+
const user = await model.findOneRecord({ query }, { req, forceNoHidden: true, noHook: true, noDriverHook: true })
|
|
84
85
|
if (!user) throw this.error('validationError', { details: [{ field: 'username', error: 'Unknown username' }], statusCode: 401 })
|
|
85
86
|
if (user.status !== 'ACTIVE') throw this.error('validationError', { details: ['User is inactive or temporarily disabled'], statusCode: 401 })
|
|
86
87
|
const verified = await bcrypt.compare(password, user.password)
|
|
87
88
|
if (!verified) throw this.error('validationError', { details: [{ field: 'password', error: 'invalidPassword' }], statusCode: 401 })
|
|
88
|
-
await mergeTeam.call(this, user)
|
|
89
|
+
await mergeTeam.call(this, user, req)
|
|
89
90
|
return user
|
|
90
91
|
}
|