Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
import { ObservableStore } from '@metamask/obs-store';
|
|
|
|
import { CaveatTypes } from '../../../../shared/constants/permissions';
|
2020-01-27 23:42:03 +01:00
|
|
|
import {
|
|
|
|
LOG_IGNORE_METHODS,
|
2020-03-16 18:13:22 +01:00
|
|
|
LOG_LIMIT,
|
|
|
|
LOG_METHOD_TYPES,
|
2020-01-27 23:42:03 +01:00
|
|
|
WALLET_PREFIX,
|
2021-02-04 19:15:23 +01:00
|
|
|
} from './enums';
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Controller with middleware for logging requests and responses to restricted
|
|
|
|
* and permissions-related methods.
|
|
|
|
*/
|
2021-12-08 11:37:35 +01:00
|
|
|
export class PermissionLogController {
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
/**
|
|
|
|
* @param {{ restrictedMethods: Set<string>, initState: Record<string, unknown> }} options - Options bag.
|
|
|
|
*/
|
|
|
|
constructor({ restrictedMethods, initState }) {
|
2021-02-04 19:15:23 +01:00
|
|
|
this.restrictedMethods = restrictedMethods;
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
this.store = new ObservableStore({
|
|
|
|
permissionHistory: {},
|
|
|
|
permissionActivityLog: [],
|
|
|
|
...initState,
|
|
|
|
});
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
* Get the restricted method activity log.
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
2020-03-16 18:13:22 +01:00
|
|
|
* @returns {Array<Object>} The activity log.
|
2020-01-27 23:42:03 +01:00
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
getActivityLog() {
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
return this.store.getState().permissionActivityLog;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
* Update the restricted method activity log.
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
|
|
|
* @param {Array<Object>} logs - The new activity log array.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
updateActivityLog(logs) {
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
this.store.updateState({ permissionActivityLog: logs });
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
* Get the permission history log.
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
2020-03-16 18:13:22 +01:00
|
|
|
* @returns {Object} The permissions history log.
|
2020-01-27 23:42:03 +01:00
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
getHistory() {
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
return this.store.getState().permissionHistory;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
* Update the permission history log.
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
|
|
|
* @param {Object} history - The new permissions history log object.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
updateHistory(history) {
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
this.store.updateState({ permissionHistory: history });
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the exposed account history for the given origin.
|
|
|
|
* Sets the 'last seen' time to Date.now() for the given accounts.
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
* Does **not** update the 'lastApproved' time for the permission itself.
|
2020-12-08 20:48:47 +01:00
|
|
|
* Returns if the accounts array is empty.
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
|
|
|
* @param {string} origin - The origin that the accounts are exposed to.
|
|
|
|
* @param {Array<string>} accounts - The accounts.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
updateAccountsHistory(origin, accounts) {
|
2020-01-27 23:42:03 +01:00
|
|
|
if (accounts.length === 0) {
|
2021-02-04 19:15:23 +01:00
|
|
|
return;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
const accountToTimeMap = getAccountToTimeMap(accounts, Date.now());
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
this.commitNewHistory(origin, {
|
|
|
|
eth_accounts: {
|
|
|
|
accounts: accountToTimeMap,
|
|
|
|
},
|
2021-02-04 19:15:23 +01:00
|
|
|
});
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-03-16 18:13:22 +01:00
|
|
|
* Create a permissions log middleware. Records permissions activity and history:
|
|
|
|
*
|
|
|
|
* Activity: requests and responses for restricted and most wallet_ methods.
|
|
|
|
*
|
|
|
|
* History: for each origin, the last time a permission was granted, including
|
|
|
|
* which accounts were exposed, if any.
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
2020-03-16 18:13:22 +01:00
|
|
|
* @returns {JsonRpcEngineMiddleware} The permissions log middleware.
|
2020-01-27 23:42:03 +01:00
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
createMiddleware() {
|
2020-01-27 23:42:03 +01:00
|
|
|
return (req, res, next, _end) => {
|
2021-02-04 19:15:23 +01:00
|
|
|
let activityEntry, requestedMethods;
|
|
|
|
const { origin, method } = req;
|
|
|
|
const isInternal = method.startsWith(WALLET_PREFIX);
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
// we only log certain methods
|
|
|
|
if (
|
|
|
|
!LOG_IGNORE_METHODS.includes(method) &&
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
(isInternal || this.restrictedMethods.has(method))
|
2020-01-27 23:42:03 +01:00
|
|
|
) {
|
2021-02-04 19:15:23 +01:00
|
|
|
activityEntry = this.logRequest(req, isInternal);
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
if (method === `${WALLET_PREFIX}requestPermissions`) {
|
2020-03-16 18:13:22 +01:00
|
|
|
// get the corresponding methods from the requested permissions so
|
|
|
|
// that we can record permissions history
|
2021-02-04 19:15:23 +01:00
|
|
|
requestedMethods = this.getRequestedMethods(req);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
} else if (method === 'eth_requestAccounts') {
|
|
|
|
// eth_requestAccounts is a special case; we need to extract the accounts
|
|
|
|
// from it
|
2021-02-04 19:15:23 +01:00
|
|
|
activityEntry = this.logRequest(req, isInternal);
|
|
|
|
requestedMethods = ['eth_accounts'];
|
2020-01-27 23:42:03 +01:00
|
|
|
} else {
|
|
|
|
// no-op
|
2021-02-04 19:15:23 +01:00
|
|
|
next();
|
|
|
|
return;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// call next with a return handler for capturing the response
|
2020-02-15 21:34:12 +01:00
|
|
|
next((cb) => {
|
2021-02-04 19:15:23 +01:00
|
|
|
const time = Date.now();
|
|
|
|
this.logResponse(activityEntry, res, time);
|
2020-01-27 23:42:03 +01:00
|
|
|
|
2020-03-16 18:13:22 +01:00
|
|
|
if (requestedMethods && !res.error && res.result) {
|
2020-01-27 23:42:03 +01:00
|
|
|
// any permissions or accounts changes will be recorded on the response,
|
|
|
|
// so we only log permissions history here
|
|
|
|
this.logPermissionsHistory(
|
2020-11-03 00:41:28 +01:00
|
|
|
requestedMethods,
|
|
|
|
origin,
|
|
|
|
res.result,
|
|
|
|
time,
|
2020-01-27 23:42:03 +01:00
|
|
|
method === 'eth_requestAccounts',
|
2021-02-04 19:15:23 +01:00
|
|
|
);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
2021-02-04 19:15:23 +01:00
|
|
|
cb();
|
|
|
|
});
|
|
|
|
};
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates and commits an activity log entry, without response data.
|
|
|
|
*
|
|
|
|
* @param {Object} request - The request object.
|
|
|
|
* @param {boolean} isInternal - Whether the request is internal.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
logRequest(request, isInternal) {
|
2020-01-27 23:42:03 +01:00
|
|
|
const activityEntry = {
|
|
|
|
id: request.id,
|
|
|
|
method: request.method,
|
2020-11-03 00:41:28 +01:00
|
|
|
methodType: isInternal
|
|
|
|
? LOG_METHOD_TYPES.internal
|
|
|
|
: LOG_METHOD_TYPES.restricted,
|
2020-01-27 23:42:03 +01:00
|
|
|
origin: request.origin,
|
|
|
|
requestTime: Date.now(),
|
|
|
|
responseTime: null,
|
|
|
|
success: null,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
|
|
|
this.commitNewActivity(activityEntry);
|
|
|
|
return activityEntry;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-03-16 18:13:22 +01:00
|
|
|
* Adds response data to an existing activity log entry.
|
|
|
|
* Entry assumed already committed (i.e., in the log).
|
2020-01-27 23:42:03 +01:00
|
|
|
*
|
2020-03-16 18:13:22 +01:00
|
|
|
* @param {Object} entry - The entry to add a response to.
|
2020-01-27 23:42:03 +01:00
|
|
|
* @param {Object} response - The response object.
|
|
|
|
* @param {number} time - Output from Date.now()
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
logResponse(entry, response, time) {
|
2020-03-16 18:13:22 +01:00
|
|
|
if (!entry || !response) {
|
2021-02-04 19:15:23 +01:00
|
|
|
return;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
2022-04-21 17:44:15 +02:00
|
|
|
// The JSON-RPC 2.0 specification defines "success" by the presence of
|
|
|
|
// either the "result" or "error" property. The specification forbids
|
|
|
|
// both properties from being present simultaneously, and our JSON-RPC
|
|
|
|
// stack is spec-compliant at the time of writing.
|
|
|
|
entry.success = Object.hasOwnProperty.call(response, 'result');
|
2021-02-04 19:15:23 +01:00
|
|
|
entry.responseTime = time;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Commit a new entry to the activity log.
|
|
|
|
* Removes the oldest entry from the log if it exceeds the log limit.
|
|
|
|
*
|
|
|
|
* @param {Object} entry - The activity log entry.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
commitNewActivity(entry) {
|
2021-02-04 19:15:23 +01:00
|
|
|
const logs = this.getActivityLog();
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
// add new entry to end of log
|
2021-02-04 19:15:23 +01:00
|
|
|
logs.push(entry);
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
// remove oldest log if exceeding size limit
|
|
|
|
if (logs.length > LOG_LIMIT) {
|
2021-02-04 19:15:23 +01:00
|
|
|
logs.shift();
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
this.updateActivityLog(logs);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create new permissions history log entries, if any, and commit them.
|
|
|
|
*
|
|
|
|
* @param {Array<string>} requestedMethods - The method names corresponding to the requested permissions.
|
|
|
|
* @param {string} origin - The origin of the permissions request.
|
|
|
|
* @param {Array<IOcapLdCapability} result - The permissions request response.result.
|
|
|
|
* @param {string} time - The time of the request, i.e. Date.now().
|
|
|
|
* @param {boolean} isEthRequestAccounts - Whether the permissions request was 'eth_requestAccounts'.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
logPermissionsHistory(
|
|
|
|
requestedMethods,
|
|
|
|
origin,
|
|
|
|
result,
|
|
|
|
time,
|
|
|
|
isEthRequestAccounts,
|
2020-03-16 18:13:22 +01:00
|
|
|
) {
|
2021-02-04 19:15:23 +01:00
|
|
|
let accounts, newEntries;
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
if (isEthRequestAccounts) {
|
2021-02-04 19:15:23 +01:00
|
|
|
accounts = result;
|
|
|
|
const accountToTimeMap = getAccountToTimeMap(accounts, time);
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
newEntries = {
|
2020-11-03 00:41:28 +01:00
|
|
|
eth_accounts: {
|
2020-01-27 23:42:03 +01:00
|
|
|
accounts: accountToTimeMap,
|
|
|
|
lastApproved: time,
|
|
|
|
},
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2020-01-27 23:42:03 +01:00
|
|
|
} else {
|
|
|
|
// Records new "lastApproved" times for the granted permissions, if any.
|
|
|
|
// Special handling for eth_accounts, in order to record the time the
|
|
|
|
// accounts were last seen or approved by the origin.
|
|
|
|
newEntries = result
|
2020-03-16 18:13:22 +01:00
|
|
|
.map((perm) => {
|
|
|
|
if (perm.parentCapability === 'eth_accounts') {
|
2021-02-04 19:15:23 +01:00
|
|
|
accounts = this.getAccountsFromPermission(perm);
|
2020-03-16 18:13:22 +01:00
|
|
|
}
|
2020-01-27 23:42:03 +01:00
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
return perm.parentCapability;
|
2020-03-16 18:13:22 +01:00
|
|
|
})
|
|
|
|
.reduce((acc, method) => {
|
|
|
|
// all approved permissions will be included in the response,
|
|
|
|
// not just the newly requested ones
|
|
|
|
if (requestedMethods.includes(method)) {
|
|
|
|
if (method === 'eth_accounts') {
|
2021-02-04 19:15:23 +01:00
|
|
|
const accountToTimeMap = getAccountToTimeMap(accounts, time);
|
2020-01-27 23:42:03 +01:00
|
|
|
|
2020-03-16 18:13:22 +01:00
|
|
|
acc[method] = {
|
|
|
|
lastApproved: time,
|
|
|
|
accounts: accountToTimeMap,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2020-03-16 18:13:22 +01:00
|
|
|
} else {
|
2021-02-04 19:15:23 +01:00
|
|
|
acc[method] = { lastApproved: time };
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
2020-03-16 18:13:22 +01:00
|
|
|
}
|
2020-01-27 23:42:03 +01:00
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
return acc;
|
|
|
|
}, {});
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Object.keys(newEntries).length > 0) {
|
2021-02-04 19:15:23 +01:00
|
|
|
this.commitNewHistory(origin, newEntries);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Commit new entries to the permissions history log.
|
|
|
|
* Merges the history for the given origin, overwriting existing entries
|
|
|
|
* with the same key (permission name).
|
|
|
|
*
|
|
|
|
* @param {string} origin - The requesting origin.
|
|
|
|
* @param {Object} newEntries - The new entries to commit.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
commitNewHistory(origin, newEntries) {
|
2020-01-27 23:42:03 +01:00
|
|
|
// a simple merge updates most permissions
|
2021-02-04 19:15:23 +01:00
|
|
|
const history = this.getHistory();
|
2020-01-27 23:42:03 +01:00
|
|
|
const newOriginHistory = {
|
|
|
|
...history[origin],
|
|
|
|
...newEntries,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
// eth_accounts requires special handling, because of information
|
|
|
|
// we store about the accounts
|
2020-11-03 00:41:28 +01:00
|
|
|
const existingEthAccountsEntry =
|
2021-02-04 19:15:23 +01:00
|
|
|
history[origin] && history[origin].eth_accounts;
|
|
|
|
const newEthAccountsEntry = newEntries.eth_accounts;
|
2020-03-16 18:13:22 +01:00
|
|
|
|
2020-01-27 23:42:03 +01:00
|
|
|
if (existingEthAccountsEntry && newEthAccountsEntry) {
|
|
|
|
// we may intend to update just the accounts, not the permission
|
|
|
|
// itself
|
2020-11-03 00:41:28 +01:00
|
|
|
const lastApproved =
|
2020-01-27 23:42:03 +01:00
|
|
|
newEthAccountsEntry.lastApproved ||
|
2021-02-04 19:15:23 +01:00
|
|
|
existingEthAccountsEntry.lastApproved;
|
2020-01-27 23:42:03 +01:00
|
|
|
|
|
|
|
// merge old and new eth_accounts history entries
|
2020-08-19 18:27:05 +02:00
|
|
|
newOriginHistory.eth_accounts = {
|
2020-01-27 23:42:03 +01:00
|
|
|
lastApproved,
|
|
|
|
accounts: {
|
|
|
|
...existingEthAccountsEntry.accounts,
|
|
|
|
...newEthAccountsEntry.accounts,
|
|
|
|
},
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
history[origin] = newOriginHistory;
|
2020-01-27 23:42:03 +01:00
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
this.updateHistory(history);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all requested methods from a permissions request.
|
|
|
|
*
|
|
|
|
* @param {Object} request - The request object.
|
2020-03-16 18:13:22 +01:00
|
|
|
* @returns {Array<string>} The names of the requested permissions.
|
2020-01-27 23:42:03 +01:00
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
getRequestedMethods(request) {
|
2020-01-27 23:42:03 +01:00
|
|
|
if (
|
|
|
|
!request.params ||
|
2020-02-12 17:17:13 +01:00
|
|
|
!request.params[0] ||
|
2020-01-27 23:42:03 +01:00
|
|
|
typeof request.params[0] !== 'object' ||
|
|
|
|
Array.isArray(request.params[0])
|
|
|
|
) {
|
2021-02-04 19:15:23 +01:00
|
|
|
return null;
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
2021-02-04 19:15:23 +01:00
|
|
|
return Object.keys(request.params[0]);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the permitted accounts from an eth_accounts permissions object.
|
|
|
|
* Returns an empty array if the permission is not eth_accounts.
|
|
|
|
*
|
|
|
|
* @param {Object} perm - The permissions object.
|
2020-03-16 18:13:22 +01:00
|
|
|
* @returns {Array<string>} The permitted accounts.
|
2020-01-27 23:42:03 +01:00
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
getAccountsFromPermission(perm) {
|
2020-01-27 23:42:03 +01:00
|
|
|
if (perm.parentCapability !== 'eth_accounts' || !perm.caveats) {
|
2021-02-04 19:15:23 +01:00
|
|
|
return [];
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
const accounts = new Set();
|
2020-01-27 23:42:03 +01:00
|
|
|
for (const caveat of perm.caveats) {
|
|
|
|
if (
|
Permission System 2.0 (#12243)
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-12-07 04:16:49 +01:00
|
|
|
caveat.type === CaveatTypes.restrictReturnedAccounts &&
|
2020-01-27 23:42:03 +01:00
|
|
|
Array.isArray(caveat.value)
|
|
|
|
) {
|
|
|
|
for (const value of caveat.value) {
|
2021-02-04 19:15:23 +01:00
|
|
|
accounts.add(value);
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-04 19:15:23 +01:00
|
|
|
return [...accounts];
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// helper functions
|
|
|
|
|
2020-03-16 18:13:22 +01:00
|
|
|
/**
|
|
|
|
* Get a map from account addresses to the given time.
|
|
|
|
*
|
|
|
|
* @param {Array<string>} accounts - An array of addresses.
|
|
|
|
* @param {number} time - A time, e.g. Date.now().
|
|
|
|
* @returns {Object} A string:number map of addresses to time.
|
|
|
|
*/
|
2020-11-03 00:41:28 +01:00
|
|
|
function getAccountToTimeMap(accounts, time) {
|
2021-02-04 19:15:23 +01:00
|
|
|
return accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {});
|
2020-01-27 23:42:03 +01:00
|
|
|
}
|