UNPKG

@sap/cds

Version:

SAP Cloud Application Programming Model - CDS for Node.js

75 lines (62 loc) 2.63 kB
const cds = require('../../../cds') const { rewriteExpandAsterisk } = require('../../utils/rewriteAsterisks') const { ensureNoDraftsSuffix } = require('../../utils/draft') const _getTarget = (ref, target, definitions) => { if (cds.env.effective.odata.proxies) { const target_ = target.elements[ref[0]] if (ref.length === 1) return definitions[ensureNoDraftsSuffix(target_.target)] return _getTarget(ref.slice(1), target_, definitions) } const target_ = target.elements[ref.map(x => x.id || x).join('_')] return definitions[ensureNoDraftsSuffix(target_.target)] } const _getRestrictedExpand = (columns, target, definitions, depth = 0, maxLevels) => { if (!columns || !target || columns === '*') return const annotation = target['@Capabilities.ExpandRestrictions.NonExpandableProperties'] const restrictions = annotation?.map(element => element['=']) ?? [] let maxLevelsViolation rewriteExpandAsterisk(columns, target) for (const col of columns) { if (!col.expand) continue if (restrictions.length) { const ref = col.ref.join('_') const ref_ = restrictions.find(element => element.replace(/\./g, '_') === ref) if (ref_) return { type: 'nonExpandable', property: ref_ } } // expand: '**' or '*3' is only possible within custom handler, no check needed if (typeof col.expand[0] === 'string' && /^\*{1}[\d|*]+/.test(col.expand[0])) continue if (maxLevels != null && depth + 1 > maxLevels) { maxLevelsViolation ??= { type: 'maxLevels', maxLevels } continue } const restricted = _getRestrictedExpand( col.expand, _getTarget(col.ref, target, definitions), definitions, depth + 1, maxLevels ) if (restricted) { if (restricted.type === 'nonExpandable') return restricted maxLevelsViolation ??= restricted } } return maxLevelsViolation } function restrict_expand(req) { if (!req.query) return const columns = req.query.SELECT?.columns if (!columns) return const maxLevels = req.target['@Capabilities.ExpandRestrictions.Expandable'] === false ? 0 : (req.target['@Capabilities.ExpandRestrictions.MaxLevels'] ?? cds.env.query?.restrictions?.expand?.maxLevels) const restricted = _getRestrictedExpand(columns, req.target, this.model.definitions, 0, maxLevels) if (!restricted) return if (restricted.type === 'nonExpandable') { req.reject(400, 'EXPAND_IS_RESTRICTED', [restricted.property]) } else if (restricted.type === 'maxLevels') { req.reject(400, 'EXPAND_MAX_LEVELS_EXCEEDED', [restricted.maxLevels]) } } module.exports = restrict_expand