UNPKG

@sap/eslint-plugin-cds

Version:

ESLint plugin including recommended SAP Cloud Application Programming model and environment rules

86 lines (78 loc) 2.63 kB
'use strict' const VALID_PSEUDO_ROLES = new Set(['authenticated-user', 'system-user', 'internal-user', 'any']) module.exports = { meta: { schema: [{/* to avoid deprecation warning for ESLint 9 */}], docs: { description: '`@restrict.to` must have valid values.', category: 'Model Validation', recommended: true, url: 'https://cap.cloud.sap/docs/tools/cds-lint/rules/auth-valid-restrict-to', }, messages: { invalidType: 'Invalid type for value of `@restrict.to`. Must either be string or array of strings.', pseudoRoleTypo: "Did you mean pseudo-role '{{valid}}' instead of '{{role}}'?", any: 'Role \'any\' overrides all other roles. Replace by \'any\' only.' }, type: 'problem', model: 'inferred' }, create (context) { return { entity: checkRestrictTo, service: checkRestrictTo, action: checkRestrictTo, function: checkRestrictTo, } function checkRestrictTo(def) { // TODO: This check also applies to `@requires`. Test that. if (!Array.isArray(def?.['@restrict'])) return const node = context.getNode(def) const file = def.$location.file def['@restrict'].forEach(checkRestrictEntry) function checkRestrictEntry(entry) { if (entry?.to !== undefined) { const roles = getUserRoles(entry) if (roles.every(checkRole)) { // all roles are valid if (roles.length > 1 && roles.includes('any')) context.report({ messageId: 'any', node, file }) } } } function getUserRoles(entry) { if (typeof entry.to === 'string') { return [ entry.to ] } else if (Array.isArray(entry.to)) { return entry.to } else { // neither string nor array: report invalid type context.report({ messageId: 'invalidType', node, file }) return [] } } function checkRole(role) { if (typeof role !== 'string') { context.report({ messageId: 'invalidType', node, file }) return false } else if (role !== '') { // empty roles handled by auth-no-empty-restrictions const roleLowercase = role.toLowerCase() if (roleLowercase !== role && VALID_PSEUDO_ROLES.has(roleLowercase)) { context.report({ messageId: 'pseudoRoleTypo', data: { role, valid: roleLowercase }, node, file, }) return false } return true } } } } }