@sap/cds
Version:
SAP Cloud Application Programming Model - CDS for Node.js
85 lines (75 loc) • 3.12 kB
JavaScript
const cds = require('../../../cds')
const serviceHandler = require('./service')
const requiresHandler = require('./requires')
const readOnlyHandler = require('./readOnly')
const insertOnlyHandler = require('./insertOnly')
const capabilitiesHandler = require('./capabilities')
const autoexposeHandler = require('./autoexpose')
const restrictHandler = require('./restrict')
const restrictExpandHandler = require('./expand')
module.exports = function () {
// REVISIT: general approach to dependent auth:
// add restrictions to auth-dependent entities as if modeled to allow static access during request processing
// // TODO: where to do?
// // add restrictions to auth-dependent entities
// const defs = this.model.definitions
// const deps = []
// for (const each of this.entities) {
// for (const k in each.compositions) {
// const c = each.compositions[k]
// const ct = defs[c.target]
// if (defs[ct?.elements.up_?.target] === each && !ct['@requires'] && !ct['@restrict']) {
// deps.push(c.target)
// }
// }
// }
// for (const each of deps) {
// const e = defs[each]
// let rstr
// let cur = defs[e.elements.up_.target]
// while (cur && !rstr) {
// rstr = cur['@requires'] || cur['@restrict']
// cur = defs[cur.elements.up_?.target]
// }
// if (rstr) {
// // TODO: normalize restriction to @restrict syntax
// // TODO: add rewrite paths in instance-based auth
// e['@restrict'] = rstr
// }
// }
// mark entities that depend on ancestor for auth with that ancestor
const defs = this.model?.definitions
for (const each of this.entities) {
for (const k in each.compositions) {
const c = each.compositions[k]
const ct = defs[c.target]
if (defs[ct?.elements.up_?.target] === each && !ct['@requires'] && !ct['@restrict']) {
let rstr
let cur = defs[ct.elements.up_.target]
while (!rstr && cur) {
if (cur['@requires'] || cur['@restrict']) rstr = cur
cur = defs[cur.elements.up_?.target]
}
if (rstr) Object.defineProperty(ct, '_auth_depends_on', { value: rstr })
}
}
}
// service-level restrictions (not all requests are dispatched by protocol adapter with its early access check)
// REVISIT cds^11: remove opt-out
const roles = cds.env.features.service_level_restrictions !== false && this.definition && serviceHandler.roles4(this)
return async function handle_authorization(req) {
// check service-level restrictions on local calls //> REVISIT: does that mean we check the same twice below?
if (roles) serviceHandler.check(roles, req, this.definition)
// @requires
requiresHandler.call(this, req)
// access control (cheaper than @restrict -> do first)
readOnlyHandler.call(this, req)
insertOnlyHandler.call(this, req)
capabilitiesHandler.call(this, req)
autoexposeHandler.call(this, req)
// @restrict
await restrictHandler.call(this, req)
// expand restrictions
if (req.event === 'READ') restrictExpandHandler.call(this, req)
}
}