@sap/cds-mtxs
Version:
SAP Cloud Application Programming Model - Multitenancy library
98 lines (81 loc) • 2.91 kB
JavaScript
const EXTENSION_ALLOWLIST = 'extension-allowlist'
const PROTECTED_NAMESPACES = ['cds.xt']
const BUILT_IN_NAMESPACES = ['cds.core', 'cds.outbox'] //> cds.outbox for legacy apps
module.exports.isBuiltIn = (name) => {
for (const namespace of BUILT_IN_NAMESPACES) {
if (name?.startsWith(`${namespace}.`)) return true
}
return false
}
module.exports.Allowlist = class Allowlist {
constructor(mtxConfig, fullCsn) {
this.allowlist = Allowlist._setupPermissionList(mtxConfig, fullCsn)
}
get all() {
return this.allowlist.all
}
get entity() {
return this.allowlist.entity
}
get service() {
return this.allowlist.service
}
getList(kind) {
return this.allowlist[kind]
}
getPermission(kind, name) {
function findInList(list, name) {
if (list) {
const splitName = name.split('.')
while (splitName.length > 0) {
const nameOrPrefix = splitName.join('.')
if (list[nameOrPrefix]) {
return list[nameOrPrefix]
}
splitName.pop()
}
return list['*'] ? list['*'] : null
}
return null
}
// no fallback for namespace to not break existing behavior -> return no restriction
return findInList(this.allowlist[kind], name) || (kind !== 'namespace' ? findInList(this.allowlist['all'], name) : {})
}
isAllowed(kind, name) {
// check protected internal namespaces
if (PROTECTED_NAMESPACES.some( namespace => name.startsWith(`${namespace}.`))) return false
return this.getPermission(kind, name)
}
static _setupPermissionList(mtxConfig, fullCsn) {
// internal structure:
// result[kind][name] = { kind, new-fields | new-entities | annotations }
const result = {}
// create from new lists
const allowlistNewFormat = mtxConfig[EXTENSION_ALLOWLIST]
if (allowlistNewFormat) {
// separate into single entities /services for better processing
for (const permission of allowlistNewFormat) {
if (permission.for) {
for (const name of permission.for) {
if (permission.kind) {
// kind is specified
result[permission.kind] = result[permission.kind] || {}
result[permission.kind][name] = permission
} else {
// check kind
if (fullCsn.definitions[name]) {
result[fullCsn.definitions[name].kind] = result[fullCsn.definitions[name].kind] || {}
result[fullCsn.definitions[name].kind][name] = permission
} else {
// allow all
result.all = result.all || {}
result.all[name] = permission
}
}
}
}
}
}
return result
}
}