Skip to content

[base-controller] Enforce that RestrictedControllerMessenger is not initialized with internal actions/events in allow lists#2051

Merged
mcmire merged 13 commits intomainfrom
jongsun/do-not-require-allowing-own-actions-events
Nov 22, 2023
Merged

[base-controller] Enforce that RestrictedControllerMessenger is not initialized with internal actions/events in allow lists#2051
mcmire merged 13 commits intomainfrom
jongsun/do-not-require-allowing-own-actions-events

Conversation

@MajorLift
Copy link
Copy Markdown
Contributor

@MajorLift MajorLift commented Nov 16, 2023

Explanation

  • RestrictedControllerMessenger constructor and ControllerMessenger.getRestricted() method now raise a type error if an internal action is passed into allowedActions, or an internal event into allowedEvents.
    • Type 'string' is not assignable to type 'never'.
    • Type '"SomeController:internalAction"' is not assignable to type '"OtherController:externalAction1" | "OtherController:externalAction2"'.
  • Fixes breaking tests in downstream controllers in core repo.

Impact

  • The allowed{Actions,Events} arrays in ControllerMessenger.getRestricted() now align with the Allowed{Actions,Events} generic params of RestrictedControllerMessenger: Both only enumerate external actions/events.
  • This commit disallows allowed{Actions,Events} arrays that contain an incomplete list of internal actions/events.
    • A partial list doesn't provide any useful information as all internal actions/events will be available to the messenger regardless of whether any of them are allowlisted.
    • A partial list also gives the confusing impression that some internal actions/events can be disallowed through omission, which is not true as of feat(base-controller): Allow using internal events/actions #2050.

References

Changelog

@metamask/base-controller

  • BREAKING: The RestrictedControllerMessenger constructor and ControllerMessenger.getRestricted() method raise a type error if internal actions or events are passed into allowedActions or allowedEvents.

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@MajorLift MajorLift requested a review from a team as a code owner November 16, 2023 16:38
@MajorLift MajorLift self-assigned this Nov 16, 2023
@MajorLift MajorLift added the team-wallet-framework Deprecated: Please use `team-core-platform` instead. label Nov 16, 2023
mcmire
mcmire previously approved these changes Nov 16, 2023
@MajorLift MajorLift changed the title Apply #isInCurrentNamespace() method (for #2050) Fixes for #2050 Nov 16, 2023
@MajorLift MajorLift requested a review from a team as a code owner November 16, 2023 18:53
@MajorLift MajorLift force-pushed the jongsun/do-not-require-allowing-own-actions-events branch 3 times, most recently from 1ab6529 to 6fcaed0 Compare November 16, 2023 19:11
@MajorLift MajorLift changed the title Fixes for #2050 [base-controller] Enforce that RestrictedControllerMessenger is not initialized with internal actions/events in allow lists Nov 16, 2023
@Gudahtt Gudahtt force-pushed the do-not-require-allowing-own-actions-events branch from 4fd01b5 to 6542f62 Compare November 16, 2023 21:26
@MajorLift MajorLift marked this pull request as draft November 16, 2023 21:41
@MajorLift MajorLift marked this pull request as ready for review November 16, 2023 22:14
Base automatically changed from do-not-require-allowing-own-actions-events to main November 17, 2023 00:16
@Gudahtt Gudahtt dismissed mcmire’s stale review November 17, 2023 00:16

The base branch was changed.

@MajorLift MajorLift force-pushed the jongsun/do-not-require-allowing-own-actions-events branch 2 times, most recently from 86c09a7 to 1f64016 Compare November 17, 2023 17:02
Copy link
Copy Markdown
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any harm in allowlisting internal events/actions? What do you think about showing a warning instead?

@MajorLift MajorLift marked this pull request as draft November 17, 2023 19:37
@MajorLift
Copy link
Copy Markdown
Contributor Author

MajorLift commented Nov 17, 2023

@mcmire I agree that this should probably be done at the type level rather than throwing an error at runtime. Will update with new approach.

MajorLift added a commit that referenced this pull request Nov 17, 2023
…time error handling (#2058)

## Explanation

- Previously, error handling branches for
`RestrictedControllerMessenger` methods were not being tested on the
basis of compile-time checks: "Branches unreachable with valid types".
- However, given that these methods are being called by our JavaScript
clients, we also need assurances on runtime error-handling behavior.
- This PR adds jest tests for the previously ignored error handling
branches: coverage is brought up to 100%.
- `@ts-expect-error` is used to suppress the compile-time type errors to
simulate a JavaScript environment.

## References

- Closes #2059
- See #2051 (comment)

## Changelog

### `@metamask/base-controller`

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've highlighted breaking changes using the "BREAKING" category
above as appropriate

---------

Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
@Mrtenz
Copy link
Copy Markdown
Member

Mrtenz commented Nov 19, 2023

What is considered "internal action/event"? In the Snap Controller, we subscribe to events fired from the Snap Controller. Would this no longer be allowed?

@MajorLift
Copy link
Copy Markdown
Contributor Author

@Mrtenz No worries, this PR won't affect the snap controller event subscriptions you linked to. It doesn't restrict any event subscriptions or action handler registrations in general.

Internal actions/events for a controller are those with type names that are in the controller's namespace (e.g. SnapController:snapUpdated is internal to SnapController).

These internal actions/events should always be allowed for usage by its controller, but previously they needed to be explicitly specified in RestrictedControllerMessenger allowlists (allowedActions, allowedEvents). This was fixed recently in #2050.

This PR is a follow-up to that enforcing that internal actions/events are not redundantly included in the allowlists at all. So it only affects how RestrictedControllerMessenger is initialized (by its constructor, or with ControllerMessenger.getRestricted()), not which actions/events it can use.

@MajorLift MajorLift force-pushed the jongsun/do-not-require-allowing-own-actions-events branch 2 times, most recently from 2101516 to 65b6827 Compare November 20, 2023 17:56
@Mrtenz
Copy link
Copy Markdown
Member

Mrtenz commented Nov 20, 2023

@Mrtenz No worries, this PR won't affect the snap controller event subscriptions you linked to. It doesn't restrict any event subscriptions or action handler registrations in general.

Internal actions/events for a controller are those with type names that are in the controller's namespace (e.g. SnapController:snapUpdated is internal to SnapController).

These internal actions/events should always be allowed for usage by its controller, but previously they needed to be explicitly specified in RestrictedControllerMessenger allowlists (allowedActions, allowedEvents). This was fixed recently in #2050.

This PR is a follow-up to that enforcing that internal actions/events are not redundantly included in the allowlists at all. So it only affects how RestrictedControllerMessenger is initialized (by its constructor, or with ControllerMessenger.getRestricted()), not which actions/events it can use.

Thanks for the clarification!

@MajorLift MajorLift force-pushed the jongsun/do-not-require-allowing-own-actions-events branch from 65b6827 to 54aab73 Compare November 21, 2023 14:07
@MajorLift MajorLift marked this pull request as ready for review November 21, 2023 14:14
…arameters in the `ControllerMessenger.getRestricted()` method and the `RestrictedControllerMessenger` constructor do not include actions/events that are in the messenger's namespace
@MajorLift MajorLift force-pushed the jongsun/do-not-require-allowing-own-actions-events branch from 54aab73 to 8343b17 Compare November 21, 2023 17:05
@mcmire mcmire mentioned this pull request Nov 21, 2023
@MajorLift MajorLift force-pushed the jongsun/do-not-require-allowing-own-actions-events branch from 8343b17 to c96a214 Compare November 21, 2023 17:11
Copy link
Copy Markdown
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this took so long to review. I realized that all I really needed to do was look at the changes here and see if they made sense on their own, which they do. I still think that the types in RestrictedControllerMessenger are super confusing, but this PR doesn't make them more confusing, it just narrows what's already there.

@mcmire mcmire merged commit fda4269 into main Nov 22, 2023
@mcmire mcmire deleted the jongsun/do-not-require-allowing-own-actions-events branch November 22, 2023 15:17
mcmire added a commit that referenced this pull request Nov 22, 2023
…ot initialized with internal actions/events in allow lists (#2051)

## Explanation

- `RestrictedControllerMessenger` constructor and
`ControllerMessenger.getRestricted()` method now raise a type error if
an internal action is passed into `allowedActions`, or an internal event
into `allowedEvents`.
	- ` Type 'string' is not assignable to type 'never'.`
- `Type '"SomeController:internalAction"' is not assignable to type
'"OtherController:externalAction1" |
"OtherController:externalAction2"'.`
- Fixes breaking tests in downstream controllers in core repo.

## Impact

- The `allowed{Actions,Events}` arrays in
`ControllerMessenger.getRestricted()` now align with the
`Allowed{Actions,Events}` generic params of
`RestrictedControllerMessenger`: Both only enumerate external
actions/events.
- This commit disallows `allowed{Actions,Events}` arrays that contain an
incomplete list of internal actions/events.
- A partial list doesn't provide any useful information as all internal
actions/events will be available to the messenger regardless of whether
any of them are allowlisted.
- A partial list also gives the confusing impression that some internal
actions/events can be *disallowed* through omission, which is not true
as of #2050.

---------

Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
MajorLift added a commit that referenced this pull request Nov 29, 2023
…wareMessenger` pattern, fix `any` (#1970)

## Explanation

### Apply controller-messenger pattern
- Defines `QueuedRequestMiddlewareMessenger`,
`SelectedNetworkMiddlewareMessenger` types to represent external
controller messengers in the middleware chain.
  - Reserved for internal use and not exported at package level.
- Defines separate allow lists for
`QueuedRequest{Controller,Middleware}Messenger` and
`SelectedNetwork{Controller,Middleware}Messenger`.

### Type fixes
- Defines and exports `QueuedRequestMiddlewareJsonRpcRequest`,
`SelectedNetworkMiddlewareJsonRpcRequest` types.
- Fix `any` usage in `createSelectedNetworkMiddleware`

### Tests
- Fixes `any`, `as any` usage in `QueuedRequestController`,
`QueuedRequestMiddleware` tests.
- Moves util functions for building test messengers into individual test
files.
- For context:
#1970 (comment)

## References

- Follow-up from #1806
- Builds on #2051
- Closes #2038

## Changelog

### `@metamask/queued-request-controller`

- **ADDED**: Add `QueuedRequestMiddlewareJsonRpcRequest` typee
- **BREAKING:** `QueuedRequestControllerMessenger` can no longer be
defined with any allowed actions or events.
- **CHANGED**: Move `@metamask/approval-controller` from devDeps to
deps.

### `@metamask/selected-network-controller`

- **ADDED**: Add `SelectedNetworkMiddlewareJsonRpcRequest` type
- **BREAKING:** Rename `SelectedNetworkControllerAction` to
`SelectedNetworkControllerActions` and `SelectedNetworkControllerEvent`
to `SelectedNetworkControllerEvents` for consistency with corresponding
type exports from other controllers.
- **BREAKING:** `createSelectedNetworkMiddleware` return type is
constrained to satisfy `JsonRpcMiddleware<JsonRpcParams, Json>`, and the
`req` parameter needs to satisfy
`SelectedNetworkMiddlewareJsonRpcRequest`.

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've highlighted breaking changes using the "BREAKING" category
above as appropriate

---------

Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

team-wallet-framework Deprecated: Please use `team-core-platform` instead.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[base-controller] Enforce that RestrictedControllerMessenger is not initialized with internal actions/events in allow lists

4 participants