sumba 2.33.0 → 2.33.2
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
CHANGED
|
@@ -20,6 +20,22 @@ async function clearCacheUser (id, result) {
|
|
|
20
20
|
await clear({ key: `dobo|SumbaUser|getUserByToken|${token}` })
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
function filterModelFromSetting ({ model, field, options }) {
|
|
24
|
+
const { isEmpty, isArray, set } = this.app.lib._
|
|
25
|
+
const { req } = options
|
|
26
|
+
const opValue = req.getSetting(`sumba:modelGuard.${field}`, {})
|
|
27
|
+
const results = []
|
|
28
|
+
for (const op of ['in', 'nin', 'inOrNull']) {
|
|
29
|
+
if (isEmpty(opValue[op]) || !isArray(opValue[op])) continue
|
|
30
|
+
if (op === 'inOrNull') {
|
|
31
|
+
const val = set({}, field, set({}, '$in', opValue[op]))
|
|
32
|
+
const nl = set({}, field, { $eq: null })
|
|
33
|
+
results.push({ $or: [val, nl] })
|
|
34
|
+
} else results.push(set({}, field, set({}, '$' + op, opValue[op])))
|
|
35
|
+
}
|
|
36
|
+
return { results, opValue }
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
async function applyModelGuard ({ model, q, teamIds, options }) {
|
|
24
40
|
const { set, orderBy, isEmpty, isArray } = this.app.lib._
|
|
25
41
|
const { includes } = this.app.lib.aneka
|
|
@@ -39,15 +55,8 @@ async function applyModelGuard ({ model, q, teamIds, options }) {
|
|
|
39
55
|
const rules = orderBy(guards.filter(filterFn), ['field'])
|
|
40
56
|
for (const field of fields) {
|
|
41
57
|
if (!model.getNonVirtualProperties(true).includes(field)) continue // or, should it throws exception instead?
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
if (isEmpty(opValue[op]) || !isArray(opValue[op])) continue
|
|
45
|
-
if (op === 'inOrNull') {
|
|
46
|
-
const val = set({}, field, set({}, '$in', opValue[op]))
|
|
47
|
-
const nl = set({}, field, { $eq: null })
|
|
48
|
-
results.push({ $or: [val, nl] })
|
|
49
|
-
} else results.push(set({}, field, set({}, '$' + op, opValue[op])))
|
|
50
|
-
}
|
|
58
|
+
const inSetting = filterModelFromSetting.call(this, { model, field, options })
|
|
59
|
+
if (inSetting.results.length > 0) inSetting.results.push(...inSetting.results)
|
|
51
60
|
const prop = model.getProperty(field)
|
|
52
61
|
const items = rules.filter(item => item.field === field)
|
|
53
62
|
for (const item of items) {
|
|
@@ -55,7 +64,7 @@ async function applyModelGuard ({ model, q, teamIds, options }) {
|
|
|
55
64
|
return sanitizeByType(val, prop.type, { strict: true, inputFormat: 'string', model: model.name })
|
|
56
65
|
})
|
|
57
66
|
const op = item.condition.toLowerCase()
|
|
58
|
-
if (['in', 'nin'].includes(op) && !isEmpty(opValue[op]) && isArray(opValue[op])) values = values.filter(val => opValue[op].includes(val))
|
|
67
|
+
if (['in', 'nin'].includes(op) && !isEmpty(inSetting.opValue[op]) && isArray(inSetting.opValue[op])) values = values.filter(val => inSetting.opValue[op].includes(val))
|
|
59
68
|
if (isEmpty(values)) continue
|
|
60
69
|
let value
|
|
61
70
|
if (['in', 'nin'].includes(op)) value = set({}, '$' + op, values)
|
|
@@ -89,7 +98,7 @@ export async function applyAttribGuard ({ model, teamIds, options }) {
|
|
|
89
98
|
}
|
|
90
99
|
|
|
91
100
|
async function rebuildFilter (model, filter = {}, options = {}) {
|
|
92
|
-
const { isEmpty, get } = this.app.lib._
|
|
101
|
+
const { isEmpty, get, keys } = this.app.lib._
|
|
93
102
|
const { req } = options
|
|
94
103
|
const allowEmpty = !get(this, `app.${model.ns}.config.sumba.noEmptyQuery`, []).includes(model.name)
|
|
95
104
|
const hasSiteId = model.hasProperty('siteId')
|
|
@@ -97,7 +106,7 @@ async function rebuildFilter (model, filter = {}, options = {}) {
|
|
|
97
106
|
const hasTeamId = model.hasProperty('teamId')
|
|
98
107
|
const teams = get(req, 'user.teams', [])
|
|
99
108
|
const teamIds = teams.map(team => team.id + '')
|
|
100
|
-
|
|
109
|
+
const aliases = teams.map(team => team.alias)
|
|
101
110
|
const q = { $and: [] }
|
|
102
111
|
|
|
103
112
|
filter.query = filter.query ?? {}
|
|
@@ -110,12 +119,21 @@ async function rebuildFilter (model, filter = {}, options = {}) {
|
|
|
110
119
|
return
|
|
111
120
|
}
|
|
112
121
|
if (hasSiteId) q.$and.push({ siteId: req.site.id + '' })
|
|
113
|
-
/*
|
|
114
122
|
if (aliases.includes('administrator')) {
|
|
123
|
+
if (get(req, 'site.alias') === 'default') {
|
|
124
|
+
filter.query = q
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
const fields = keys(req.getSetting('sumba:modelGuard', {}))
|
|
128
|
+
const results = []
|
|
129
|
+
for (const field of fields) {
|
|
130
|
+
const inSetting = filterModelFromSetting.call(this, { model, field, options })
|
|
131
|
+
if (inSetting.results.length > 0) results.push(...inSetting.results)
|
|
132
|
+
}
|
|
133
|
+
if (results.length > 0) q.$and.push(...results)
|
|
115
134
|
filter.query = q
|
|
116
135
|
return
|
|
117
136
|
}
|
|
118
|
-
*/
|
|
119
137
|
if (isEmpty(req.user)) {
|
|
120
138
|
if (q.$and.length === 0 && !allowEmpty) throw this.error('_emptyColumnQuery')
|
|
121
139
|
filter.query = q
|
|
@@ -7,7 +7,7 @@ async function country (opts = {}) {
|
|
|
7
7
|
type: 'string',
|
|
8
8
|
maxLength: 2,
|
|
9
9
|
index: opts.index ?? true,
|
|
10
|
-
required: opts.required,
|
|
10
|
+
required: opts.required ?? true,
|
|
11
11
|
values: 'sumba:getCountriesValues',
|
|
12
12
|
rules: opts.enforceRule ? ['uppercase', { rule: 'length', params: 2 }] : [],
|
|
13
13
|
rulesMsg: opts.enforceRule ? { 'any.only': 'validCountryCodeRequired' } : undefined
|
|
@@ -29,7 +29,7 @@ const id = {
|
|
|
29
29
|
schema.view.format = {
|
|
30
30
|
createdAt: async function (val, rec) {
|
|
31
31
|
const message = this.app.bajoMarkdown ? this.app.bajoMarkdown.parseContent(rec.message) : rec.message
|
|
32
|
-
const isMe = rec.userId === req.user.id
|
|
32
|
+
const isMe = rec.userId === req.user.id + ''
|
|
33
33
|
const sentence = `<c:div margin="bottom-3"><c:badge background="color:${isMe ? 'primary' : 'secondary'}" t:content="${isMe ? 'you' : 'us'}" /> <small>${req.format(val, 'datetime')}</small></c:div>`
|
|
34
34
|
return (await this.component.buildSentence(sentence)) + message
|
|
35
35
|
}
|
package/index.js
CHANGED
|
@@ -745,7 +745,6 @@ async function factory (pkgName) {
|
|
|
745
745
|
const { merge, isEmpty, camelCase, get } = this.app.lib._
|
|
746
746
|
const { routePath } = this.app.waibu
|
|
747
747
|
const userId = get(req, 'session.userId')
|
|
748
|
-
|
|
749
748
|
const setUser = async () => {
|
|
750
749
|
if (!userId) return
|
|
751
750
|
try {
|
|
@@ -806,7 +805,8 @@ async function factory (pkgName) {
|
|
|
806
805
|
checkXSite = async (req, reply) => {
|
|
807
806
|
const { get } = this.app.lib._
|
|
808
807
|
if (!this.config.multiSite.enabled) return
|
|
809
|
-
|
|
808
|
+
const config = get(req, 'routeOptions.config')
|
|
809
|
+
if (!get(config, 'xSite') || ['/dashboard'].includes(config.pathSrc)) return
|
|
810
810
|
if (!get(req, 'user.isXSiteAdmin')) throw this.error('accessDenied', { statusCode: 403 })
|
|
811
811
|
}
|
|
812
812
|
|
package/lib/get-site.js
CHANGED
|
@@ -23,7 +23,7 @@ async function getSite (input, byId = false) {
|
|
|
23
23
|
}
|
|
24
24
|
site.setting = defaultsDeep({}, nsSetting, defSetting)
|
|
25
25
|
// additional fields
|
|
26
|
-
const country = await this.app.dobo.getModel('CdbCountry').getRecord(site.country, {
|
|
26
|
+
const country = await this.app.dobo.getModel('CdbCountry').getRecord(site.country, { noMagic: true })
|
|
27
27
|
site.countryName = (country ?? {}).name ?? site.country
|
|
28
28
|
}
|
|
29
29
|
|
package/lib/get-user.js
CHANGED
|
@@ -2,12 +2,14 @@ export async function mergeTeam (user, req) {
|
|
|
2
2
|
const { map, pick } = this.app.lib._
|
|
3
3
|
const { getModel } = this.app.dobo
|
|
4
4
|
user.teams = []
|
|
5
|
-
const query = { userId: user.id, siteId: user.siteId, status: 'ACTIVE' }
|
|
5
|
+
const query = { userId: user.id + '', siteId: user.siteId, status: 'ACTIVE' }
|
|
6
6
|
let mdl = getModel('SumbaTeamUser')
|
|
7
7
|
const userTeam = await mdl.findAllRecord({ query })
|
|
8
8
|
if (userTeam.length === 0) return
|
|
9
9
|
delete query.userId
|
|
10
|
-
|
|
10
|
+
const idProp = mdl.getProperty('id')
|
|
11
|
+
const $in = userTeam.map(item => ['integer', 'smallint'].includes(idProp.type) ? parseInt(item.teamId) : item.teamId)
|
|
12
|
+
query.id = { $in }
|
|
11
13
|
mdl = getModel('SumbaTeam')
|
|
12
14
|
const teams = await mdl.findAllRecord({ query })
|
|
13
15
|
if (teams.length > 0) {
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-06-18
|
|
4
|
+
|
|
5
|
+
- [2.33.2] Bug fix in ```hook.js```
|
|
6
|
+
|
|
3
7
|
## 2026-06-17
|
|
4
8
|
|
|
5
9
|
- [2.33.0] Add ```Site Setting``` in ```Cross-Site```
|
|
6
10
|
- [2.33.0] Bug fix in ```hook.js```
|
|
7
|
-
- [2.33.0] Bug fix in ```
|
|
11
|
+
- [2.33.0] Bug fix in ```sumba:siteId``` feature
|
|
12
|
+
- [2.33.1] Bug fix in ```checkUser()```, ```checkTeam()``` & ```checkXSite()```
|
|
13
|
+
- [2.33.1] Bug fix in ```sumba:country``` feature
|
|
8
14
|
|
|
9
15
|
## 2026-06-15
|
|
10
16
|
|