diff --git a/src/permissions/PermissionController.test.ts b/src/permissions/PermissionController.test.ts index 6d0530c25a3..a80bda6635c 100644 --- a/src/permissions/PermissionController.test.ts +++ b/src/permissions/PermissionController.test.ts @@ -4452,6 +4452,46 @@ describe('PermissionController', () => { expect(revokeAllPermissionsSpy).toHaveBeenNthCalledWith(1, 'foo'); }); + it('action: PermissionController:revokePermissionForAllSubjects', () => { + const messenger = getUnrestrictedMessenger(); + const options = getPermissionControllerOptions({ + messenger: getPermissionControllerMessenger(messenger), + }); + const controller = new PermissionController< + DefaultPermissionSpecifications, + DefaultCaveatSpecifications + >(options); + + controller.grantPermissions({ + subject: { origin: 'foo' }, + approvedPermissions: { + wallet_getSecretArray: {}, + }, + }); + const revokePermissionForAllSubjectsSpy = jest.spyOn( + controller, + 'revokePermissionForAllSubjects', + ); + + expect( + controller.hasPermission('foo', 'wallet_getSecretArray'), + ).toStrictEqual(true); + + messenger.call( + 'PermissionController:revokePermissionForAllSubjects', + 'wallet_getSecretArray', + ); + + expect( + controller.hasPermission('foo', 'wallet_getSecretArray'), + ).toStrictEqual(false); + expect(revokePermissionForAllSubjectsSpy).toHaveBeenCalledTimes(1); + expect(revokePermissionForAllSubjectsSpy).toHaveBeenNthCalledWith( + 1, + 'wallet_getSecretArray', + ); + }); + it('action: PermissionsController:requestPermissions', async () => { const messenger = getUnrestrictedMessenger(); const options = getPermissionControllerOptions({ diff --git a/src/permissions/PermissionController.ts b/src/permissions/PermissionController.ts index ec41d04eb4c..ec107becafe 100644 --- a/src/permissions/PermissionController.ts +++ b/src/permissions/PermissionController.ts @@ -236,6 +236,15 @@ export type RevokeAllPermissions = { handler: GenericPermissionController['revokeAllPermissions']; }; +/** + * Revokes all permissions corresponding to the specified target for all subjects. + * Does nothing if no subjects or no such permission exists. + */ +export type RevokePermissionForAllSubjects = { + type: `${typeof controllerName}:revokePermissionForAllSubjects`; + handler: GenericPermissionController['revokePermissionForAllSubjects']; +}; + /** * Clears all permissions from the {@link PermissionController}. */ @@ -263,9 +272,10 @@ export type PermissionControllerActions = | GetPermissions | HasPermission | HasPermissions - | RevokePermissions + | RequestPermissions | RevokeAllPermissions - | RequestPermissions; + | RevokePermissionForAllSubjects + | RevokePermissions; /** * The generic state change event of the {@link PermissionController}. @@ -681,8 +691,9 @@ export class PermissionController< ); this.messagingSystem.registerActionHandler( - `${controllerName}:revokePermissions` as const, - this.revokePermissions.bind(this), + `${controllerName}:requestPermissions` as const, + (subject: PermissionSubjectMetadata, permissions: RequestedPermissions) => + this.requestPermissions(subject, permissions), ); this.messagingSystem.registerActionHandler( @@ -691,9 +702,18 @@ export class PermissionController< ); this.messagingSystem.registerActionHandler( - `${controllerName}:requestPermissions` as const, - (subject: PermissionSubjectMetadata, permissions: RequestedPermissions) => - this.requestPermissions(subject, permissions), + `${controllerName}:revokePermissionForAllSubjects` as const, + ( + target: ExtractPermission< + ControllerPermissionSpecification, + ControllerCaveatSpecification + >['parentCapability'], + ) => this.revokePermissionForAllSubjects(target), + ); + + this.messagingSystem.registerActionHandler( + `${controllerName}:revokePermissions` as const, + this.revokePermissions.bind(this), ); }