Skip to content

**BREAKING** Add PermissionTree class & introduce children to Permission specifications #1513

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

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

hmalik88
Copy link
Contributor

@hmalik88 hmalik88 commented Jul 15, 2023

Closes #1459

What:

With the addition of the children property to a specification, the PermissionTree class was created to analyze the relationships between the permissions we pass into the PermissionController. This class can determine the root permissions and properly walk a permission chain to populate permission requests and also determine if they are invalid.

Why:

This gives developers the ability to make their permission requests less verbose and makes it easier for the end user to accept permission requests when they have permission groups to simplify what the origin is asking for. This change in the short term is intended for breaking up the snap_manageState method into child permissions and for the upcoming custom UI work.

How:

Permission requests won't change, the snap developer can keep the manifest the same, only specifying child permissions IF they need to specify a caveat.

Note: Currently, I've allowed the implementation to be flexible enough to just enforce parent permissions being called, but In the future, this class can be used to enforce strict permission chains starting from root permissions if we so wish OR even a hybrid approach for certain permission chains.

@hmalik88 hmalik88 requested a review from a team as a code owner July 15, 2023 17:01
@hmalik88 hmalik88 requested a review from GuillaumeRx July 31, 2023 15:09
Copy link
Contributor

@GuillaumeRx GuillaumeRx left a comment

Choose a reason for hiding this comment

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

Looks good to me, don't forget to mark this as breaking since you're changing the return type of grantPermissions

@hmalik88 hmalik88 changed the title Add PermissionTree class & introduce children to Permission specifications **BREAKING** Add PermissionTree class & introduce children to Permission specifications Aug 16, 2023
@Gudahtt
Copy link
Member

Gudahtt commented Sep 5, 2023

Could you update the architecture document to explain the purpose of permission trees? https://github.com/MetaMask/core/blob/main/packages/permission-controller/ARCHITECTURE.md

It would be great especially to have a sentence or two at least on what problem this solves, e.g. when adding permissions, when should you consider using a permission tree/group?

Copy link
Member

@Mrtenz Mrtenz left a comment

Choose a reason for hiding this comment

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

Would like to see some more tests in the permission controller, like:

  • Granting endowment permissions.
  • Permissions with caveats.
  • Requesting grouped and non-grouped permissions.

Comment on lines +2543 to +2554
let error;
try {
await controller.grantPermissions({
subject: { origin: '' },
approvedPermissions: {
wallet_getSecretArray: {},
},
}),
).toThrow(new errors.InvalidSubjectIdentifierError(''));
});
} catch (err) {
error = err;
}
expect(error).toStrictEqual(new errors.InvalidSubjectIdentifierError(''));
Copy link
Member

Choose a reason for hiding this comment

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

await expect(() => ...).rejects.toThrow(...)?

* Controller passing in permissions specifications for the tree to analyze.
*/
export class PermissionTree {
private readonly _permissionSpecifications: Readonly<
Copy link
Member

Choose a reason for hiding this comment

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

Hash private? This applies to all private variables and methods in this class.

* An array of associated permission names that fall under this "parent" permission. Target names would be limited to the
* array of child permissions associated with this particular permission.
*/
children?: Readonly<TargetName[]>;
Copy link
Member

Choose a reason for hiding this comment

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

Should we enforce that only a special type of permission can have children?

I am thinking it might be useful to define a PermissionGroup similarly to how we have endowments and RPC methods currently and only allow permissions of type "permission group" to actually function as a group.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Re-doing this PR based on a convo w/ @rekmarks to keep a concept of groups as well, minus the need for an extraneous permission in state.

const populatedRequest =
this.permissionTree.getPopulatedRequest(approvedPermissions);

const sideEffects = this.getSideEffects(populatedRequest);
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I understand the reasoning behind this. Side-effects were intentionally previously only executed for requested permissions 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The side-effect is defined in the permission spec, the child permission is requested implicitly, I'm not sure what's the issue?

@@ -1573,8 +1581,26 @@ export class PermissionController<
>
>;

const populatedRequest =
Copy link
Member

Choose a reason for hiding this comment

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

With the current permission tree approach if we change a permission group after its creation a user might be able to get in a weird state where they don't have all the permissions they expect

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, hmm...maybe that's something that should be taken care of in the migration?

Copy link
Member

Choose a reason for hiding this comment

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

We need to be explicit with this at least, whether we expect migrations to be written when permission groups change or whether permission groups are dynamic and will automatically change when we update specifications

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll mention it in the docs, maybe even leave a code snippet for a migration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Introduce concept of PermissionGroups to the PermissionController
5 participants