Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 13 commits into from
Nov 22, 2023

Conversation

MajorLift
Copy link
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

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
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
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 <[email protected]>
@Mrtenz
Copy link
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
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
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
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
128 checks passed
@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 <[email protected]>
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 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants