diff --git a/packages/core/permissions/README.md b/packages/core/permissions/README.md index 80453ab8d8..918faa8051 100644 --- a/packages/core/permissions/README.md +++ b/packages/core/permissions/README.md @@ -79,12 +79,12 @@ const engine = permissions.engine } }) .on('post-format::validate.permission', ({ permission }) => { - if (permission.action === 'create') { + if (permission.action === 'update') { return false; } }) .on('format.permission', ({ permission }) => { - if (permission.action === 'create') { + if (permission.action === 'update') { return { ...permission, action: 'modify', @@ -99,11 +99,11 @@ const engine = permissions.engine return permission; }); -const ability = await engine.generateAbility([{ action: 'create' }, { action: 'delete' }]); +const ability = await engine.generateAbility([{ action: 'update' }, { action: 'delete' }]); -ability.can('create'); // false +ability.can('update'); // false ability.can('modify'); // true, because create was changed to 'modify' ability.can('delete'); // false, doesn't exist because it was changed by format.permission -ability.can('remove'); // true, pre-format::validate.permission runs before format.permission +ability.can('remove'); // true, pre-format::validate.permission validates before format.permission changed it ``` diff --git a/packages/core/permissions/lib/__tests__/permissions.engine.test.js b/packages/core/permissions/lib/__tests__/permissions.engine.test.js index f3462cbbc8..609c7f90fa 100644 --- a/packages/core/permissions/lib/__tests__/permissions.engine.test.js +++ b/packages/core/permissions/lib/__tests__/permissions.engine.test.js @@ -161,6 +161,56 @@ describe('Permissions Engine', () => { expect(ability.can('view', 'article')).toBeTruthy(); }); + it('validate hooks are called at the right time', async () => { + const { ability } = await buildEngineWithAbility({ + permissions: [{ action: 'update' }, { action: 'delete' }, { action: 'view' }], + engineHooks: [ + { + name: 'format.permission', + fn(permission) { + if (permission.action === 'update') { + return { + ...permission, + action: 'modify', + }; + } + if (permission.action === 'delete') { + return { + ...permission, + action: 'remove', + }; + } + if (permission.action === 'view') { + return { + ...permission, + action: 'read', + }; + } + return permission; + }, + }, + { + name: 'before-format::validate.permission', + fn: generateInvalidateActionHook('modify'), + }, + { + name: 'before-format::validate.permission', + fn: generateInvalidateActionHook('view'), + }, + { + name: 'post-format::validate.permission', + fn: generateInvalidateActionHook('update'), + }, + ], + }); + + expect(ability.can('update')).toBeFalsy(); + expect(ability.can('modify')).toBeTruthy(); + expect(ability.can('delete')).toBeFalsy(); + expect(ability.can('remove')).toBeTruthy(); + expect(ability.can('view')).toBeFalsy(); + }); + it('before-format::validate.permission can prevent action register', async () => { const { ability } = await buildEngineWithAbility({ permissions: [{ action: 'read', subject: 'article' }],