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.
- package/extend/bajo/hook.js +48 -51
- package/extend/bajo/intl/en-US.json +5 -5
- package/extend/bajo/intl/id.json +5 -5
- package/extend/dobo/feature/lat-lng.js +6 -1
- package/extend/dobo/feature/lat.js +1 -1
- package/extend/dobo/feature/lng.js +1 -1
- package/extend/dobo/feature/status.js +3 -1
- package/extend/dobo/fixture/site.json +1 -1
- package/extend/dobo/fixture/team-user.json +1 -1
- package/extend/dobo/fixture/team.json +2 -2
- package/extend/dobo/fixture/user.json +1 -1
- package/extend/dobo/model.js +82 -122
- package/extend/dobo/model.json +3 -9
- package/extend/sumba/route/anonymous.json +5 -0
- package/extend/sumba/route/secure.json +8 -0
- package/extend/waibuDb/schema/anonymous-guard.js +15 -0
- package/extend/waibuDb/schema/{route-guard.js → secure-guard.js} +2 -2
- package/extend/waibuDb/schema/team-user.js +2 -2
- package/extend/waibuDb/schema/team.json +1 -1
- package/extend/waibuMpa/extend/waibuAdmin/route/{x/model-guard → anonymous-guard}/@action.js +2 -3
- package/extend/waibuMpa/extend/waibuAdmin/route/{route-guard → secure-guard}/@action.js +2 -2
- package/extend/waibuMpa/route/access-token.js +3 -1
- package/extend/waibuRestApi/route/manage/anonymous-guard/model-builder.json +4 -0
- package/extend/waibuRestApi/route/manage/{route-guard → secure-guard}/model-builder.json +1 -1
- package/index.js +302 -98
- package/lib/get-site.js +1 -3
- package/lib/get-user.js +2 -6
- package/package.json +1 -1
- package/wiki/CHANGES.md +13 -0
- package/extend/dobo/fixture/x-route-guard.js +0 -24
- package/extend/waibuDb/schema/x-attrib-guard.js +0 -15
- package/extend/waibuDb/schema/x-model-guard.js +0 -15
- package/extend/waibuDb/schema/x-route-guard.js +0 -15
- package/extend/waibuMpa/extend/waibuAdmin/route/index.json +0 -3
- package/extend/waibuMpa/extend/waibuAdmin/route/x/attrib-guard/@action.js +0 -12
- package/extend/waibuMpa/extend/waibuAdmin/route/x/index.json +0 -3
- package/extend/waibuMpa/extend/waibuAdmin/route/x/route-guard/@action.js +0 -12
- package/lib/util.js +0 -201
|
@@ -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,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
|
-
}
|