sumba 1.0.26 → 1.0.28

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.
@@ -1,6 +1,7 @@
1
1
  import checkUserId from '../../lib/check-user-id.js'
2
2
  import checkTheme from '../../lib/check-theme.js'
3
3
  import checkIconset from '../../lib/check-iconset.js'
4
+ import checkRole from '../../lib/check-role.js'
4
5
 
5
6
  const preParsing = {
6
7
  level: 10,
@@ -10,6 +11,7 @@ const preParsing = {
10
11
  await checkTheme.call(this, req, reply)
11
12
  await checkIconset.call(this, req, reply)
12
13
  await checkUserId.call(this, req, reply, 'waibuMpa')
14
+ await checkRole.call(this, req, reply, 'waibuMpa')
13
15
  req.menu = req.menu ?? {}
14
16
  if (req.user) {
15
17
  req.menu.user = [
@@ -1,9 +1,11 @@
1
1
  import checkUserId from '../../lib/check-user-id.js'
2
+ import checkRole from '../../lib/check-role.js'
2
3
 
3
4
  const onRequest = {
4
5
  level: 10,
5
6
  handler: async function (req, reply) {
6
7
  await checkUserId.call(this, req, reply, 'waibuRestApi')
8
+ await checkRole.call(this, req, reply, 'waibuRestApi')
7
9
  }
8
10
  }
9
11
 
@@ -1,9 +1,11 @@
1
1
  import checkUserId from '../../lib/check-user-id.js'
2
+ import checkRole from '../../lib/check-role.js'
2
3
 
3
4
  const onRequest = {
4
5
  level: 10,
5
6
  handler: async function (req, reply) {
6
7
  await checkUserId.call(this, req, reply, 'waibuStatic')
8
+ await checkRole.call(this, req, reply, 'waibuStatic')
7
9
  }
8
10
  }
9
11
 
@@ -1,13 +1,17 @@
1
1
  import collectRoutes from '../../lib/collect-routes.js'
2
+ import collectRoles from '../../lib/collect-roles.js'
2
3
 
3
4
  async function afterAppBoot () {
4
5
  this.log.trace('collectingRouteGuards')
5
6
  await collectRoutes.call(this, 'secure')
6
7
  await collectRoutes.call(this, 'anonymous')
7
8
  this.log.trace('secureRoutes%d', this.secureRoutes.length)
8
- this.log.trace('secureInvRoutes%d', this.secureInvRoutes.length)
9
+ this.log.trace('secureNegRoutes%d', this.secureNegRoutes.length)
9
10
  this.log.trace('anonRoutes%d', this.anonymousRoutes.length)
10
- this.log.trace('anonInvRoutes%d', this.anonymousInvRoutes.length)
11
+ this.log.trace('anonNegRoutes%d', this.anonymousNegRoutes.length)
12
+ this.log.trace('collectingRoleGuards')
13
+ await collectRoles.call(this)
14
+ this.log.trace('roles%d', this.roles.length)
11
15
  }
12
16
 
13
17
  export default afterAppBoot
@@ -61,9 +61,9 @@
61
61
  "warningMemberOnly%s": "Please authenticate yourself first, because the <a href=\"%s\">page<a> your're trying to access is a member only page",
62
62
  "collectingRouteGuards": "Collecting route guards:",
63
63
  "secureRoutes%d": "- Secure routes: %d",
64
- "secureInvRoutes%d": "- Secure, inverted routes: %d",
64
+ "secureNegRoutes%d": "- Secure, negated routes: %d",
65
65
  "anonRoutes%d": "- Anonymous routes: %d",
66
- "anonInvRoutes%d": "- Anonymous, inverted routes: %d",
66
+ "anonNegRoutes%d": "- Anonymous, negated routes: %d",
67
67
  "replies": "Replies",
68
68
  "compose": "Compose",
69
69
  "yourReply": "Your Reply",
@@ -74,6 +74,10 @@
74
74
  "emailSent": "An email has been sent to your address",
75
75
  "forgotPasswordLink": "Forgot Password Link",
76
76
  "forgotPasswordChanged": "Password Successfully Changed",
77
+ "collectingRoleGuards": "Collecting role guards:",
78
+ "roles%d": "- Roles: %d",
79
+ "negRoles%d": "- Negated Roles: %d",
80
+ "permissionDenied": "Permission Denied",
77
81
  "field": {
78
82
  "currentPassword": "Current Password",
79
83
  "newPassword": "New Password",
package/bajo/intl/id.json CHANGED
@@ -61,9 +61,9 @@
61
61
  "warningMemberOnly%s": "Silahkan melalukan otentikasi terlebih dahulu karena <a href=\"%s\">halaman<a> yang akan Anda akses adalah salah satu halaman khusus anggota saja",
62
62
  "collectingRouteGuards": "Mengoleksi pertahanan jalur:",
63
63
  "secureRoutes%d": "- Jalur aman: %d",
64
- "secureInvRoutes%d": "- Jalur aman, terbalik: %d",
64
+ "secureNegRoutes%d": "- Jalur aman, dinegasikan: %d",
65
65
  "anonRoutes%d": "- Jalur anonim: %d",
66
- "anonInvRoutes%d": "- Jalur anonim, terbalik: %d",
66
+ "anonNegRoutes%d": "- Jalur anonim, dinegasikan: %d",
67
67
  "conversation": "Percakapan",
68
68
  "replies": "Balas Berbalas",
69
69
  "compose": "Tulis",
@@ -75,6 +75,10 @@
75
75
  "emailSent": "Sebuah surel telah dikirim ke alamat Anda",
76
76
  "forgotPasswordLink": "Tautan Lupa Kata Sandi",
77
77
  "forgotPasswordChanged": "Kata Sandi Sukses Diubah",
78
+ "collectingRoleGuards": "Mengoleksi pertahanan peran:",
79
+ "roles%d": "- Peran: %d",
80
+ "negRoles%d": "- Peran, dinegasikan: %d",
81
+ "permissionDenied": "Permisi Ditolak",
78
82
  "field": {
79
83
  "currentPassword": "Kata Sandi Saat Ini",
80
84
  "newPassword": "Kata Sandi Baru",
@@ -0,0 +1,11 @@
1
+ function byGuard ({ guards, paths }) {
2
+ const { outmatch } = this.app.bajo.lib
3
+ const matcher = outmatch(guards)
4
+ let guarded
5
+ for (const path of paths) {
6
+ if (!guarded) guarded = matcher(path)
7
+ }
8
+ return guarded
9
+ }
10
+
11
+ export default byGuard
@@ -0,0 +1,19 @@
1
+ function byRole ({ paths = [], method = 'GET', roles = [], guards = [] }) {
2
+ const { includes } = this.app.bajo
3
+ const { outmatch } = this.app.bajo.lib
4
+
5
+ for (const item of guards) {
6
+ const matchPath = outmatch(item.path)
7
+ for (const path of paths) {
8
+ if (matchPath(path)) {
9
+ const matchMethods = outmatch(item.methods)
10
+ if (matchMethods(method)) {
11
+ if (item.values.length === 0) return item
12
+ if (includes(roles, item.values)) return item
13
+ }
14
+ }
15
+ }
16
+ }
17
+ }
18
+
19
+ export default byRole
@@ -0,0 +1,15 @@
1
+ function byRoutes ({ paths = [], method = 'GET', guards = [] }) {
2
+ const { outmatch } = this.app.bajo.lib
3
+
4
+ for (const item of guards) {
5
+ const matchPath = outmatch(item.path)
6
+ for (const path of paths) {
7
+ if (matchPath(path)) {
8
+ const matchMethods = outmatch(item.values)
9
+ if (matchMethods(method)) return item
10
+ }
11
+ }
12
+ }
13
+ }
14
+
15
+ export default byRoutes
@@ -1,5 +1,3 @@
1
- const unsafeFields = ['password']
2
-
3
1
  async function getUser (rec, safe = true) {
4
2
  const { recordGet } = this.app.dobo
5
3
  const { omit, isPlainObject } = this.app.bajo.lib._
@@ -7,7 +5,7 @@ async function getUser (rec, safe = true) {
7
5
  let user
8
6
  if (isPlainObject(rec)) user = rec
9
7
  else user = await recordGet('SumbaUser', rec, { noHook: true })
10
- return safe ? omit(user, unsafeFields) : user
8
+ return safe ? omit(user, this.unsafeUserFields) : user
11
9
  }
12
10
 
13
11
  export default getUser
@@ -0,0 +1 @@
1
+ export default ['password']
@@ -1,4 +1,4 @@
1
- <p>Welcome and thank your for joining us in <%= _get(_rel, 'site.title', 'our website') %>.
1
+ <p>Welcome and thank your for joining us in <%= _meta.site.title %>.
2
2
  Please click the following link to activate your account:</p>
3
3
 
4
4
  <p><% const url = _meta.hostHeader + _routePath("sumba:/user/activation") + "?key=" + token %>
@@ -1,4 +1,4 @@
1
- <p>Selamat datang dan telah bergabung di <%= _get(_rel, 'site.title', 'situs kami') %>. Selanjutnya,
1
+ <p>Selamat datang dan telah bergabung di <%= _meta.site.title %>. Selanjutnya,
2
2
  silahkan mengklik link dibawah ini untuk melakukan aktivasi akun anda:</p>
3
3
 
4
4
  <p><% const url = _meta.hostHeader + _routePath("sumba:/user/activation") + "?key=" + token %>
@@ -0,0 +1,19 @@
1
+ async function roleId (opts = {}) {
2
+ return {
3
+ properties: [{
4
+ name: 'roleId',
5
+ type: 'string',
6
+ maxLength: 50,
7
+ rel: {
8
+ site: {
9
+ schema: 'SumbaSite',
10
+ propName: 'id',
11
+ type: 'one-to-one'
12
+ }
13
+ },
14
+ index: true
15
+ }]
16
+ }
17
+ }
18
+
19
+ export default roleId
@@ -6,9 +6,9 @@ async function siteId (opts = {}) {
6
6
  maxLength: 50,
7
7
  rel: {
8
8
  site: {
9
- schema: 'SumbaSite',
9
+ schema: 'SumbaUser',
10
10
  propName: 'id',
11
- fields: 'all'
11
+ type: 'one-on-many'
12
12
  }
13
13
  },
14
14
  index: true
@@ -6,7 +6,11 @@ async function userId (opts = {}) {
6
6
  type: 'string',
7
7
  maxLength: 50,
8
8
  rel: {
9
- user: 'SumbaUser:id'
9
+ site: {
10
+ schema: 'SumbaSite',
11
+ propName: 'id',
12
+ type: 'one-on-one'
13
+ }
10
14
  },
11
15
  index: true
12
16
  }]
@@ -0,0 +1,5 @@
1
+ [{
2
+ "userId": "?:SumbaUser::username:admin",
3
+ "roleId": "?:SumbaRole::alias:administrator",
4
+ "siteId": "?:SumbaSite::alias:default"
5
+ }]
@@ -0,0 +1,6 @@
1
+ [{
2
+ "alias": "administrator",
3
+ "name": "Administrator",
4
+ "siteId": "?:SumbaSite::alias:default",
5
+ "status": "ENABLED"
6
+ }]
@@ -0,0 +1,15 @@
1
+ {
2
+ "properties": [
3
+ ],
4
+ "indexes": [{
5
+ "fields": ["userId", "siteId", "id"],
6
+ "unique": true
7
+ }],
8
+ "feature": {
9
+ "createdAt": true,
10
+ "updatedAt": true,
11
+ "sumba.siteId": true,
12
+ "sumba.userId": true,
13
+ "sumba.roleId": true
14
+ }
15
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "properties": [
3
+ "alias::20::true",
4
+ "name::50:true:true"
5
+ ],
6
+ "indexes": [{
7
+ "fields": ["alias", "siteId"],
8
+ "unique": true
9
+ }],
10
+ "feature": {
11
+ "createdAt": true,
12
+ "updatedAt": true,
13
+ "sumba.siteId": true,
14
+ "sumba.status": {
15
+ "default": "ENABLED",
16
+ "values": ["ENABLED", "DISABLED"]
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,32 @@
1
+ import { pathsToCheck } from './check-user-id.js'
2
+
3
+ async function mergeRoles (req) {
4
+ const { map } = this.app.bajo.lib._
5
+ const { recordFindAll } = this.app.dobo
6
+ req.user.roles = []
7
+ const query = { userId: req.user.id, siteId: req.site.id }
8
+ const userRoles = await recordFindAll('SumbaRoleUser', { query })
9
+ if (userRoles.length === 0) return
10
+ delete query.userId
11
+ query.id = { $in: map(userRoles, 'id'), status: 'ENABLED' }
12
+ const roles = await recordFindAll('SumbaRole', { query })
13
+ if (roles.length > 0) req.user.roles.push(...map(roles, 'alias'))
14
+ }
15
+
16
+ async function checkRole (req, reply, source) {
17
+ if (!req.user) return
18
+ const { map } = this.app.bajo.lib._
19
+ await mergeRoles.call(this, req)
20
+ const paths = pathsToCheck.call(this, req, true)
21
+ const match = this.checkPathsByRole({ paths, method: req.method, roles: req.user.roles, guards: this.roles })
22
+ if (match) return
23
+ const negMatch = this.checkPathsByRole({ paths, method: req.method, roles: req.user.roles, guards: this.negRoles })
24
+ if (negMatch) return
25
+ const guards = map(this.roles, r => r.path)
26
+ // fallback
27
+ const guarded = this.checkPathsByGuard({ paths, guards })
28
+ if (!guarded) return
29
+ throw this.error('permissionDenied')
30
+ }
31
+
32
+ export default checkRole
@@ -1,51 +1,26 @@
1
- async function checker (req, container) {
2
- const { outmatch } = this.app.bajo.lib
3
- const { get } = this.app.bajo.lib._
4
-
5
- let match
6
- for (const item of container) {
7
- let path = item.path
8
- const isI18n = get(this.app[item.source], 'config.i18n.detectors', []).includes('path')
9
- if (isI18n) path = `/${req.lang}${path}`
10
- const matchPath = outmatch(path, { separator: false })
11
- const checks = [req.routeOptions.url, req.url]
12
- for (const check of checks) {
13
- if (matchPath(check)) {
14
- const matchMethods = outmatch(item.methods)
15
- if (matchMethods(req.method)) {
16
- match = item
17
- break
18
- }
19
- }
20
- }
21
- if (match) break
22
- }
23
- return match
24
- }
25
-
26
- async function anonymous (req) {
27
- const { omit } = this.app.bajo.lib._
28
- const { getUser } = this
29
- const { routePath } = this.app.waibu
30
-
31
- if (!req.session) return
32
- if (req.session.user) {
33
- const match = await checker.call(this, req, this.anonymousRoutes)
34
- if (match) {
35
- const redir = routePath(this.config.redirect.signout, req)
36
- req.session.ref = req.url
37
- throw this.error('_redirect', { redirect: redir })
38
- }
39
- req.user = omit(await getUser(req.session.user.id), ['password', 'token'])
1
+ export function pathsToCheck (req, withHome) {
2
+ const { uniq, without } = this.app.bajo.lib._
3
+ const checks = uniq(without([req.routeOptions.url, req.url], undefined, null))
4
+ /*
5
+ if (withHome) {
6
+ const homePath = get(this, 'app.waibu.config.home.path')
7
+ const homeForward = get(this, 'app.waibu.config.home.forward')
8
+ if (homePath && homeForward) checks.unshift('/')
40
9
  }
10
+ */
11
+ return checks
41
12
  }
42
13
 
43
- async function misc (req) {
44
- const { omit } = this.app.bajo.lib._
45
- const { getUser } = this
46
- if (!req.session) return
47
- if (req.session.user) {
48
- req.user = omit(await getUser(req.session.user.id), ['password', 'token'])
14
+ async function setUser (req) {
15
+ const { get } = this.app.bajo.lib._
16
+ const id = get(req, 'session.user.id')
17
+ if (!id) return
18
+ try {
19
+ const user = await this.getUser(id)
20
+ if (user) req.user = user
21
+ else req.session.user = null
22
+ } catch (err) {
23
+ req.session.user = null
49
24
  }
50
25
  }
51
26
 
@@ -55,38 +30,56 @@ async function mergeSetting (req) {
55
30
 
56
31
  async function checkUserId (req, reply, source) {
57
32
  const { isEmpty, camelCase } = this.app.bajo.lib._
33
+ const { routePath } = this.app.waibu
58
34
 
59
35
  const ctx = this.app[source].instance
60
36
  if (!req.routeOptions.url) {
61
- await misc.call(this, req)
37
+ if (!req.session) return
38
+ await setUser.call(this, req)
62
39
  return
63
40
  }
64
- const match = await checker.call(this, req, this.secureRoutes)
65
- if (!match) {
66
- await anonymous.call(this, req)
67
- return
41
+
42
+ const paths = pathsToCheck.call(this, req)
43
+ let securePath = await this.checkPathsByRoutes({ paths, method: req.method, guards: this.secureRoutes })
44
+ if (securePath) {
45
+ const neg = await this.checkPathsByRoutes({ paths, method: req.method, guards: this.secureNegRoutes })
46
+ if (neg) securePath = undefined
68
47
  }
69
- // excluded ?
70
- const xmatch = await checker.call(this, req, this.secureInvRoutes)
71
- if (xmatch) {
72
- await anonymous.call(this, req)
48
+ let anonymousPath = await this.checkPathsByRoutes({ paths, method: req.method, guards: this.anonymousRoutes })
49
+ if (anonymousPath) {
50
+ const neg = await this.checkPathsByRoutes({ paths, method: req.method, guards: this.anonymousNegRoutes })
51
+ if (neg) anonymousPath = undefined
52
+ }
53
+ if (!securePath && !anonymousPath) {
54
+ if (req.session && req.session.user) await setUser.call(this, req)
73
55
  return
74
56
  }
75
- const authMethods = this.config.auth[match.source].methods ?? []
76
- if (isEmpty(authMethods)) throw this.error('noAuthMethod', { statusCode: 500 })
77
- let success
78
- for (const m of authMethods) {
79
- const handler = this[camelCase(`verify ${m}`)]
80
- if (!handler) throw this.error('invalidAuthMethod%s', m, { statusCode: 500 })
81
- const check = await handler(req, reply, source, ctx)
82
- if (check) {
83
- success = check
84
- break
57
+ if (anonymousPath) {
58
+ if (!req.session) return // can't check, so don't care
59
+ if (!req.session.user) return // not authenticated, why bother
60
+ req.session.ref = req.url
61
+ return reply.redirectTo(routePath(this.config.redirect.signout))
62
+ }
63
+ if (securePath) {
64
+ if (req.session && req.session.user) {
65
+ await setUser.call(this, req)
66
+ return
67
+ }
68
+ const authMethods = this.config.auth[securePath.source].methods ?? []
69
+ if (isEmpty(authMethods)) throw this.error('noAuthMethod', { statusCode: 500 })
70
+ let success
71
+ for (const m of authMethods) {
72
+ const handler = this[camelCase(`verify ${m}`)]
73
+ if (!handler) throw this.error('invalidAuthMethod%s', m, { statusCode: 500 })
74
+ const check = await handler(req, reply, source, ctx)
75
+ if (check) {
76
+ success = check
77
+ break
78
+ }
85
79
  }
80
+ if (!success) throw this.error('accessDenied', { statusCode: 401 })
81
+ await mergeSetting.call(this, req)
86
82
  }
87
- if (!success) throw this.error('accessDenied', { statusCode: 401 })
88
- await mergeSetting.call(this, req)
89
- return success
90
83
  }
91
84
 
92
85
  export default checkUserId
@@ -0,0 +1,44 @@
1
+ async function collect ({ file, ns, dir }) {
2
+ const { readConfig } = this.app.bajo
3
+ const { routePath } = this.app.waibu
4
+ const { camelCase, isString, find } = this.app.bajo.lib._
5
+
6
+ const roles = await readConfig(file, { ignoreError: true })
7
+ const [item] = file.replace(dir, '').split('@')
8
+ let [source, subNs] = item.split('.').map(s => camelCase(s))
9
+ subNs = subNs ? `.${subNs}` : ''
10
+ for (const k in roles) {
11
+ const values = isString(roles[k]) ? [roles[k]] : roles[k]
12
+ let [path, methods] = k.split(':')
13
+ const isNeg = path[0] === '!'
14
+ if (isNeg) path = path.slice(1)
15
+ path = routePath(`${ns}${subNs}:${path}`)
16
+ const item = {
17
+ source,
18
+ path,
19
+ methods: methods.split(','),
20
+ values
21
+ }
22
+ const guards = this[isNeg ? 'negRoles' : 'roles']
23
+ if (find(guards, { path })) continue
24
+ guards.push(item)
25
+ }
26
+ }
27
+
28
+ async function collectRoles () {
29
+ const { eachPlugins } = this.app.bajo
30
+
31
+ this.roles = this.roles ?? []
32
+ this.negRoles = this.negRoles ?? []
33
+ const items = []
34
+ if (this.app.waibuStatic) items.push('waibuStatic.asset', 'waibuStatic.virtual', 'waibu-static.asset', 'waibu-static.virtual')
35
+ if (this.app.waibuRestApi) items.push('waibuRestApi', 'waibu-rest-api')
36
+ if (this.app.waibuMpa) items.push('waibuMpa', 'waibu-mpa')
37
+ const pattern = `{${items.join(',')}}@roles.*`
38
+ const me = this
39
+ await eachPlugins(async function ({ file, ns, dir }) {
40
+ await collect.call(me, { file, ns, dir })
41
+ }, { glob: pattern, prefix: this.name })
42
+ }
43
+
44
+ export default collectRoles
@@ -1,45 +1,26 @@
1
- const indexes = []
2
- const invIndexes = []
3
-
4
1
  async function collect (type, { file, ns, dir }) {
5
2
  const { readConfig } = this.app.bajo
6
- const { routeDir } = this.app.waibu
7
- const { trim, camelCase } = this.app.bajo.lib._
8
- const { hash } = this.app.bajoExtra
3
+ const { routePath } = this.app.waibu
4
+ const { camelCase, isString, find } = this.app.bajo.lib._
9
5
 
10
6
  const routes = await readConfig(file, { ignoreError: true })
11
- let source = camelCase(trim(file.replace(dir, '').split('@')[0], '/'))
12
- let prefixHandler = routeDir
13
- if (this.app.waibuStatic && source.startsWith('waibuStatic')) {
14
- const { assetDir, virtualDir } = this.app.waibuStatic
15
- const parts = source.split('.')
16
- source = parts[0]
17
- prefixHandler = parts[1] === 'virtual' ? virtualDir : assetDir
18
- }
19
- for (let k in routes) {
20
- const v = routes[k]
21
- const prefix = prefixHandler(ns, source)
22
- const inverted = k[0] === '!'
23
- if (inverted) k = k.slice(1)
24
- if (k[0] !== '/') k = '/' + k
7
+ const [item] = file.replace(dir, '').split('@')
8
+ let [source, subNs] = item.split('.').map(s => camelCase(s))
9
+ subNs = subNs ? `.${subNs}` : ''
10
+
11
+ for (let path in routes) {
12
+ const values = isString(routes[path]) ? routes[path].split(',') : routes[path]
13
+ const isNeg = path[0] === '!'
14
+ if (isNeg) path = path.slice(1)
15
+ path = routePath(`${ns}${subNs}:${path}`)
25
16
  const item = {
26
- path: `${prefix}${k}`,
27
- methods: v,
28
- ns,
29
- source
30
- }
31
- const index = await hash(item)
32
- if (inverted && type === 'secure') {
33
- if (!invIndexes.includes(index)) {
34
- this[`${type}InvRoutes`].push(item)
35
- invIndexes.push(index)
36
- }
37
- } else {
38
- if (!indexes.includes(index)) {
39
- this[`${type}Routes`].push(item)
40
- indexes.push(index)
41
- }
17
+ source,
18
+ path,
19
+ values
42
20
  }
21
+ const guards = this[`${type}${isNeg ? 'Neg' : ''}Routes`]
22
+ if (find(guards, { path })) continue
23
+ guards.push(item)
43
24
  }
44
25
  }
45
26
 
@@ -47,7 +28,7 @@ async function collectRoutes (type) {
47
28
  const { eachPlugins } = this.app.bajo
48
29
 
49
30
  this[`${type}Routes`] = this[`${type}Routes`] ?? []
50
- this[`${type}InvRoutes`] = this[`${type}InvRoutes`] ?? []
31
+ this[`${type}NegRoutes`] = this[`${type}NegRoutes`] ?? []
51
32
  const items = []
52
33
  if (this.app.waibuStatic) items.push('waibuStatic.asset', 'waibuStatic.virtual', 'waibu-static.asset', 'waibu-static.virtual')
53
34
  if (this.app.waibuRestApi) items.push('waibuRestApi', 'waibu-rest-api')
@@ -57,8 +38,6 @@ async function collectRoutes (type) {
57
38
  await eachPlugins(async function ({ file, ns, dir }) {
58
39
  await collect.call(me, type, { file, ns, dir })
59
40
  }, { glob: pattern, prefix: this.name })
60
- indexes.splice(0)
61
- invIndexes.splice(0)
62
41
  }
63
42
 
64
43
  export default collectRoutes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sumba",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "description": "Bajo Framework's Biz Suite",
5
5
  "main": "index.js",
6
6
  "scripts": {