sumba 2.29.0 → 2.31.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 (38) hide show
  1. package/extend/bajo/hook.js +48 -51
  2. package/extend/bajo/intl/en-US.json +5 -5
  3. package/extend/bajo/intl/id.json +5 -5
  4. package/extend/dobo/feature/lat-lng.js +6 -1
  5. package/extend/dobo/feature/lat.js +1 -1
  6. package/extend/dobo/feature/lng.js +1 -1
  7. package/extend/dobo/feature/status.js +3 -1
  8. package/extend/dobo/fixture/site.json +1 -1
  9. package/extend/dobo/fixture/team-user.json +1 -1
  10. package/extend/dobo/fixture/team.json +2 -2
  11. package/extend/dobo/fixture/user.json +1 -1
  12. package/extend/dobo/model.js +82 -122
  13. package/extend/dobo/model.json +3 -9
  14. package/extend/sumba/route/anonymous.json +5 -0
  15. package/extend/sumba/route/secure.json +8 -0
  16. package/extend/waibuDb/schema/anonymous-guard.js +15 -0
  17. package/extend/waibuDb/schema/{route-guard.js → secure-guard.js} +2 -2
  18. package/extend/waibuDb/schema/team-user.js +2 -2
  19. package/extend/waibuDb/schema/team.json +1 -1
  20. package/extend/waibuMpa/extend/waibuAdmin/route/{x/model-guard → anonymous-guard}/@action.js +2 -3
  21. package/extend/waibuMpa/extend/waibuAdmin/route/{route-guard → secure-guard}/@action.js +2 -2
  22. package/extend/waibuMpa/route/access-token.js +3 -1
  23. package/extend/waibuRestApi/route/manage/anonymous-guard/model-builder.json +4 -0
  24. package/extend/waibuRestApi/route/manage/{route-guard → secure-guard}/model-builder.json +1 -1
  25. package/index.js +302 -98
  26. package/lib/get-site.js +1 -3
  27. package/lib/get-user.js +2 -6
  28. package/package.json +1 -1
  29. package/wiki/CHANGES.md +13 -0
  30. package/extend/dobo/fixture/x-route-guard.js +0 -24
  31. package/extend/waibuDb/schema/x-attrib-guard.js +0 -15
  32. package/extend/waibuDb/schema/x-model-guard.js +0 -15
  33. package/extend/waibuDb/schema/x-route-guard.js +0 -15
  34. package/extend/waibuMpa/extend/waibuAdmin/route/index.json +0 -3
  35. package/extend/waibuMpa/extend/waibuAdmin/route/x/attrib-guard/@action.js +0 -12
  36. package/extend/waibuMpa/extend/waibuAdmin/route/x/index.json +0 -3
  37. package/extend/waibuMpa/extend/waibuAdmin/route/x/route-guard/@action.js +0 -12
  38. package/lib/util.js +0 -201
@@ -1,15 +0,0 @@
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
@@ -1,15 +0,0 @@
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
@@ -1,3 +0,0 @@
1
- {
2
- "redirect": "waibuAdmin:/site/site"
3
- }
@@ -1,12 +0,0 @@
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,3 +0,0 @@
1
- {
2
- "redirect": "waibuAdmin:/site/x/site/list"
3
- }
@@ -1,12 +0,0 @@
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/lib/util.js DELETED
@@ -1,201 +0,0 @@
1
- export function parseNsSettings (ns, setting, items) {
2
- const { trim, set, isPlainObject, isArray, isEmpty, find } = this.app.lib._
3
- const { parseObject, dayjs } = this.app.lib
4
-
5
- for (const item of items) {
6
- if (item.ns === '_var' || ns === '_var') continue
7
- let value = trim([item.value] ?? '')
8
- if (value[0] === '#' && value[value.length - 1] === '#') {
9
- const val = value.slice(1, -1)
10
- const newValue = find(items, { ns: '_var', key: val })
11
- if (newValue) value = newValue.value
12
- }
13
- if (['[', '{'].includes(value[0]) && [']', '}'].includes(value[value.length - 1])) {
14
- try {
15
- value = parseObject(JSON.parse(value))
16
- } catch (err) {}
17
- } else if (Number(value)) value = Number(value)
18
- else if (['true', 'false'].includes(value)) value = value === 'true'
19
- else if (item.key.endsWith('$in')) value = value.split('\n').map(v => v.trim())
20
- else {
21
- const dt = dayjs(value)
22
- if (dt.isValid()) value = dt.toDate()
23
- }
24
- if ((isPlainObject(value) || isArray(value)) && isEmpty(value)) continue
25
- set(setting, `${ns}.${item.key}`, value)
26
- }
27
- }
28
-
29
- export function pathsToCheck (req, withHome) {
30
- const { uniq, without } = this.app.lib._
31
- const items = [req.routeOptions.url, req.url].map(url => url.split('?')[0].split('#')[0])
32
- return uniq(without(items, undefined, null))
33
- }
34
-
35
- export async function checkIconset (req, reply) {
36
- const { get, isString } = this.app.lib._
37
- const mpa = this.app.waibuMpa
38
-
39
- if (!req.site) return
40
- const siteIconset = get(req, 'site.setting.waibuMpa.iconset')
41
- req.iconset = siteIconset ?? get(mpa, 'config.iconset.set', 'default')
42
- const hiconset = req.headers['x-iconset']
43
- if (isString(hiconset) && mpa.getIconset(hiconset)) req.iconset = hiconset
44
- req.iconset = req.iconset ?? 'default'
45
- }
46
-
47
- export async function checkTheme (req, reply) {
48
- const { get, isString } = this.app.lib._
49
- const mpa = this.app.waibuMpa
50
-
51
- if (!req.site) return
52
- const siteTheme = get(req, 'site.setting.waibuMpa.theme')
53
- req.theme = siteTheme ?? get(mpa, 'config.theme.set', 'default')
54
- const htheme = req.headers['x-theme']
55
- if (isString(htheme) && mpa.getTheme(htheme)) req.theme = htheme
56
- req.theme = req.theme ?? 'default'
57
- }
58
-
59
- export async function checkTeam (req, reply, route) {
60
- const { map } = this.app.lib._
61
- const { outmatch } = this.app.lib
62
- route.teamIds = route.teamIds ?? []
63
- if (route.teamIds.length === 0) return
64
-
65
- const teamIds = map(req.user.teams, 'id')
66
- const teamAliases = map(req.user.teams, 'alias')
67
- if (req.user.isAdmin) return
68
- const matchXSite = outmatch(route.path)
69
- if (req.routeOptions.config.xSite && matchXSite(req.url) && req.user.isXSiteAdmin) return
70
- if (teamAliases.length === 0) throw this.error('accessDenied', { statusCode: 403 })
71
-
72
- const paths = pathsToCheck.call(this, req, true)
73
- const guards = await this.getRouteGuards()
74
- const globalGuards = guards.global.filter(item => item.siteIds.includes(req.site.id + '') && item.teamIds.length > 0)
75
- const localGuards = guards.local.filter(item => item.siteIds.includes(req.site.id + '') && item.teamIds.length > 0)
76
- let match = this.checkPathsByRoute({ paths, teamIds, guards: localGuards.filter(item => !item.negation) })
77
- if (match) {
78
- const neg = this.checkPathsByRoute({ paths, teamIds, guards: localGuards.filter(item => item.negation) })
79
- if (neg) match = undefined
80
- }
81
- if (!match) {
82
- match = this.checkPathsByRoute({ paths, teamIds, guards: globalGuards.filter(item => !item.negation) })
83
- if (match) {
84
- const neg = this.checkPathsByRoute({ paths, teamIds, guards: globalGuards.filter(item => item.negation) })
85
- if (neg) match = undefined
86
- }
87
- }
88
- if (!match) throw this.error('accessDenied', { statusCode: 403 })
89
- // passed
90
- }
91
-
92
- export async function checkUserId (req, reply, source) {
93
- const { merge, isEmpty, camelCase, get } = this.app.lib._
94
- const { routePath } = this.app.waibu
95
- const userId = get(req, 'session.userId')
96
-
97
- const setUser = async () => {
98
- if (!userId) return
99
- try {
100
- const user = await this.getUserById(userId, req)
101
- if (user) req.user = user
102
- else req.session.userId = null
103
- } catch (err) {
104
- console.log(err)
105
- req.session.userId = null
106
- }
107
- }
108
-
109
- if (req.session) req.session.siteId = req.site.id
110
-
111
- const webApp = get(req, 'routeOptions.config.webApp', 'waibu')
112
- if (!req.routeOptions.url) {
113
- if (!req.session) return
114
- await setUser()
115
- return
116
- }
117
-
118
- const paths = pathsToCheck.call(this, req)
119
- const guards = await this.getRouteGuards()
120
- let securePath
121
- let anonymousPath
122
- const globalGuards = guards.global.filter(item => item.siteIds.includes(req.site.id + ''))
123
- const localGuards = guards.local.filter(item => item.siteIds.includes(req.site.id + ''))
124
- // find anonymousPath
125
- anonymousPath = await this.checkPathsByRoute({ req, paths, guards: localGuards.filter(item => item.anonymous && !item.negation) })
126
- if (anonymousPath) {
127
- const neg = await this.checkPathsByRoute({ req, paths, guards: localGuards.filter(item => item.anonymous && item.negation) })
128
- if (neg) anonymousPath = undefined
129
- }
130
- if (!anonymousPath) {
131
- anonymousPath = await this.checkPathsByRoute({ req, paths, guards: globalGuards.filter(item => item.anonymous && !item.negation) })
132
- if (anonymousPath) {
133
- const neg = await this.checkPathsByRoute({ req, paths, guards: globalGuards.filter(item => item.anonymous && item.negation) })
134
- if (neg) anonymousPath = undefined
135
- }
136
- }
137
- // find securePath
138
- securePath = await this.checkPathsByRoute({ req, paths, guards: localGuards.filter(item => !item.anonymous && !item.negation) })
139
- if (securePath) {
140
- const neg = await this.checkPathsByRoute({ req, paths, guards: localGuards.filter(item => !item.anonymous && item.negation) })
141
- if (neg) securePath = undefined
142
- }
143
- if (!securePath) {
144
- securePath = await this.checkPathsByRoute({ req, paths, guards: globalGuards.filter(item => !item.anonymous && !item.negation) })
145
- if (securePath) {
146
- const neg = await this.checkPathsByRoute({ req, paths, guards: globalGuards.filter(item => !item.anonymous && item.negation) })
147
- if (neg) securePath = undefined
148
- }
149
- }
150
- // checking...
151
- if (!securePath && !anonymousPath) {
152
- if (userId) await setUser()
153
- return false // regular, unguarded path. Not secure & not anonymous path
154
- }
155
- if (anonymousPath) {
156
- if (!userId) return false
157
- req.session.ref = req.url
158
- return reply.redirectTo(routePath(this.config.redirect.signout))
159
- }
160
- if (!(securePath.methods ?? []).includes(req.method)) throw this.error('accessDenied', { statusCode: 403 })
161
- if (userId) {
162
- await setUser()
163
- return securePath
164
- }
165
- const silentOnError = this.config.auth[webApp].silentOnError ?? this.config.auth.common.silentOnError
166
- const payload = silentOnError ? { noContent: true } : undefined
167
- const authMethods = this.config.auth[webApp].methods ?? []
168
- if (isEmpty(authMethods)) throw this.error('noAuthMethod', merge({ statusCode: 500 }, payload))
169
- let success
170
- for (const m of authMethods) {
171
- const handler = this[camelCase(`verify ${m}`)]
172
- if (!handler) throw this.error('invalidAuthMethod%s', m, merge({ statusCode: 500 }, payload))
173
- const check = await handler(req, reply, source, payload)
174
- if (check) {
175
- success = check
176
- break
177
- }
178
- }
179
- if (!success) throw this.error('accessDeniedNoAuth', merge({ statusCode: 403 }, payload))
180
- return securePath
181
- }
182
-
183
- export async function latLngHook (body, options) {
184
- const { isSet } = this.app.lib.aneka
185
- const { round } = this.app.lib.aneka
186
- if (!isSet(body[options.field])) return
187
- body[options.field] = round(body[options.field], options.scale)
188
- }
189
-
190
- /**
191
- * If current route is an inter site route user is an inter site admin, then let it passed
192
- *
193
- * @param {Object} req - Request object
194
- * @param {Object} reply - Reply object
195
- * @returns
196
- */
197
- export async function checkXSite (req, reply) {
198
- const { get } = this.app.lib._
199
- if (!get(req, 'routeOptions.config.xSite')) return
200
- if (!get(req, 'user.isXSiteAdmin')) throw this.error('accessDenied', { statusCode: 403 })
201
- }