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.
Files changed (54) hide show
  1. package/extend/bajo/hook/bajo.extend@after-read-config.js +13 -0
  2. package/extend/bajo/hook/dobo.sumba-attrib-guard$dobo.sumba-x-attrib-guard@after-transaction.js +6 -0
  3. package/extend/bajo/hook/dobo.sumba-model-guard$dobo.sumba-x-model-guard@after-transaction.js +6 -0
  4. package/extend/bajo/hook/dobo.sumba-route-guard$dobo.sumba-x-route-guard@after-transaction.js +6 -0
  5. package/extend/bajo/hook/dobo.sumba-team$dobo.sumba-site@after-transaction.js +8 -0
  6. package/extend/bajo/hook/dobo@before-count-record.js +3 -3
  7. package/extend/bajo/hook/{dobo@before-create-record.js → dobo@before-driver-create-record.js} +6 -6
  8. package/extend/bajo/hook/dobo@before-driver-find-all-record.js +13 -0
  9. package/extend/bajo/hook/dobo@before-driver-find-record.js +114 -0
  10. package/extend/bajo/hook/dobo@before-driver-get-record.js +22 -0
  11. package/extend/bajo/hook/dobo@before-driver-remove-record.js +10 -0
  12. package/extend/bajo/hook/dobo@before-driver-update-record.js +10 -0
  13. package/extend/bajo/hook/waibu-mpa@pre-parsing.js +5 -4
  14. package/extend/bajo/hook/waibu-rest-api@pre-parsing.js +5 -4
  15. package/extend/bajo/hook/waibu-static@pre-parsing.js +5 -4
  16. package/extend/bajo/hook/waibu@after-app-boot.js +2 -0
  17. package/extend/bajo/intl/en-US.json +13 -2
  18. package/extend/bajo/intl/id.json +20 -2
  19. package/extend/dobo/feature/site-ids.js +19 -0
  20. package/extend/dobo/feature/team-ids.js +19 -0
  21. package/extend/dobo/fixture/{route-guard.js → x-route-guard.js} +2 -4
  22. package/extend/dobo/model/attrib-guard.js +32 -0
  23. package/extend/dobo/model/model-guard.js +48 -0
  24. package/extend/dobo/model/route-guard.js +42 -54
  25. package/extend/dobo/model/x-attrib-guard.js +14 -0
  26. package/extend/dobo/model/x-model-guard.js +13 -0
  27. package/extend/dobo/model/x-route-guard.js +13 -0
  28. package/extend/waibuDb/schema/attrib-guard.js +15 -0
  29. package/extend/waibuDb/schema/model-guard.js +15 -0
  30. package/extend/waibuDb/schema/route-guard.js +1 -1
  31. package/extend/waibuDb/schema/user.js +19 -26
  32. package/extend/waibuDb/schema/x-attrib-guard.js +15 -0
  33. package/extend/waibuDb/schema/x-model-guard.js +15 -0
  34. package/extend/waibuDb/schema/x-route-guard.js +15 -0
  35. package/extend/waibuMpa/extend/waibuAdmin/route/attrib-guard/@action.js +11 -0
  36. package/extend/waibuMpa/extend/waibuAdmin/route/model-guard/@action.js +11 -0
  37. package/extend/waibuMpa/extend/waibuAdmin/route/reset-user-password.js +2 -1
  38. package/extend/waibuMpa/extend/waibuAdmin/route/x/attrib-guard/@action.js +12 -0
  39. package/extend/waibuMpa/extend/waibuAdmin/route/{cache → x/cache}/@action.js +1 -1
  40. package/extend/waibuMpa/extend/waibuAdmin/route/x/model-guard/@action.js +12 -0
  41. package/extend/waibuMpa/extend/waibuAdmin/route/x/route-guard/@action.js +12 -0
  42. package/extend/waibuMpa/extend/waibuAdmin/route/{session → x/session}/@action.js +1 -1
  43. package/extend/waibuMpa/extend/waibuAdmin/route/{all-sites → x/site}/@action.js +1 -1
  44. package/index.js +114 -35
  45. package/lib/get-user.js +9 -8
  46. package/lib/util.js +58 -23
  47. package/package.json +1 -1
  48. package/wiki/CHANGES.md +13 -0
  49. package/extend/bajo/hook/dobo.sumba-team-guard@after-action.js +0 -6
  50. package/extend/bajo/hook/dobo.sumba-user-guard@after-action.js +0 -6
  51. package/extend/bajo/hook/dobo@before-find-record.js +0 -63
  52. package/extend/bajo/hook/dobo@before-get-record.js +0 -23
  53. package/extend/bajo/hook/dobo@before-remove-record.js +0 -10
  54. 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
@@ -0,0 +1,15 @@
1
+ async function attribGuard () {
2
+ return {
3
+ common: {
4
+ widget: {
5
+ teamIds: {
6
+ attr: {
7
+ refUrl: 'waibuAdmin:/{prefix}/team/details?id={id}'
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+
15
+ export default attribGuard
@@ -0,0 +1,15 @@
1
+ async function modelGuard () {
2
+ return {
3
+ common: {
4
+ widget: {
5
+ teamIds: {
6
+ attr: {
7
+ refUrl: 'waibuAdmin:/{prefix}/team/details?id={id}'
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+
15
+ export default modelGuard
@@ -2,7 +2,7 @@ async function routeGuard () {
2
2
  return {
3
3
  common: {
4
4
  widget: {
5
- teams: {
5
+ teamIds: {
6
6
  attr: {
7
7
  refUrl: 'waibuAdmin:/{prefix}/team/details?id={id}'
8
8
  }
@@ -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', 'apiKey:6'] },
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', 'apiKey'],
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,15 @@
1
+ async function xAttribGuard () {
2
+ return {
3
+ common: {
4
+ widget: {
5
+ siteIds: {
6
+ attr: {
7
+ refUrl: 'waibuAdmin:/{prefix}/site/details?id={id}'
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+
15
+ export default xAttribGuard
@@ -0,0 +1,15 @@
1
+ async function xModelGuard () {
2
+ return {
3
+ common: {
4
+ widget: {
5
+ siteIds: {
6
+ attr: {
7
+ refUrl: 'waibuAdmin:/{prefix}/site/details?id={id}'
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+
15
+ export default xModelGuard
@@ -0,0 +1,15 @@
1
+ async function xRouteGuard () {
2
+ return {
3
+ common: {
4
+ widget: {
5
+ siteIds: {
6
+ attr: {
7
+ refUrl: 'waibuAdmin:/{prefix}/site/details?id={id}'
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+
15
+ export default xRouteGuard
@@ -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 this.passwordRule(req)
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
@@ -1,7 +1,7 @@
1
1
  const action = {
2
2
  method: ['GET', 'POST'],
3
3
  title: 'cacheStorage',
4
- interSite: true,
4
+ xSite: true,
5
5
  handler: async function (req, reply) {
6
6
  if (!this.app.bajoCache) throw this.error('_notFound')
7
7
  const { importModule } = this.app.bajo
@@ -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
@@ -1,7 +1,7 @@
1
1
  const action = {
2
2
  method: ['GET', 'POST'],
3
3
  title: 'userSession',
4
- interSite: true,
4
+ xSite: true,
5
5
  handler: async function (req, reply) {
6
6
  const { importModule } = this.app.bajo
7
7
  const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
@@ -1,7 +1,7 @@
1
1
  const action = {
2
2
  method: ['GET', 'POST'],
3
3
  title: 'manageAllSite',
4
- interSite: true,
4
+ xSite: true,
5
5
  handler: async function (req, reply) {
6
6
  const { importModule } = this.app.bajo
7
7
  const crudSkel = await importModule('waibuAdmin:/lib/crud-skel.js')
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
- interSiteAdmins: [],
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.userGuards = []
156
- this.teamGuards = []
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.interSiteAdmins.length === 0) {
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.interSiteAdmins.push(user.id)
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/list` },
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/list` },
218
- { title: 'userSetting', href: `waibuAdmin:/${prefix}/user-setting/list` },
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/list` },
225
- { title: 'teamUser', href: `waibuAdmin:/${prefix}/team-user/list` },
226
- { title: 'teamSetting', href: `waibuAdmin:/${prefix}/team-setting/list` }
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/list` }
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/list` },
237
- { title: 'contactFormCat', href: `waibuAdmin:/${prefix}/contact-form-cat/list` },
238
- { title: 'ticket', href: `waibuAdmin:/${prefix}/ticket/list` },
239
- { title: 'ticketCat', href: `waibuAdmin:/${prefix}/ticket-cat/list` }
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/list` },
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 === 'misc')
250
- if (item) item.children.push({ title: 'cacheStorage', href: `waibuAdmin:/${prefix}/cache/list` })
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, req)
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 = [], method = 'GET', teams = [], guards = [] }) => {
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.methods.includes(method)) {
373
- if (teams.length === 0) return item
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
- getRouteGuards = async (reread) => {
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
- const model = getModel('SumbaRouteGuard')
538
- const results = await model.findAllRecord({ query: { status: 'ACTIVE' } }, { noMagic: true, dataOnly: true })
539
- this.routeGuards = orderBy(map(results, item => {
540
- item.path = routePath(item.path)
541
- return item
542
- }), ['weight', 'path'])
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
  }