Skip to content

Commit

Permalink
Migrate PermissionController and SubjectMetadataController (#692)
Browse files Browse the repository at this point in the history
* Initial copy-paste

* Fix a bunch of imports etc

* Fix some typing issues

* Fix another type issue

* Fix linting issues + add missing doc strings

* Run Prettier on README

* Fix some test typing issues + ignore others

* Revert a recent change

* Remove unused function

* Remove remains of bold formatting

* Fix usage of messengers to improve test typing

* Fix some issues with JSDocs

* Add util function tests

* Use @metamask/types for a bunch of shared types

* Fix a few import issues

* Remove unnecessary ts-expect-error comments
  • Loading branch information
FrederikBolding authored and MajorLift committed Oct 11, 2023
1 parent fc8805d commit 93d9d1a
Show file tree
Hide file tree
Showing 29 changed files with 9,688 additions and 1 deletion.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@
"@ethereumjs/tx": "^3.2.1",
"@metamask/contract-metadata": "^1.31.0",
"@metamask/metamask-eth-abis": "3.0.0",
"@metamask/types": "^1.1.0",
"@types/uuid": "^8.3.0",
"abort-controller": "^3.0.0",
"async-mutex": "^0.2.6",
"babel-runtime": "^6.26.0",
"deep-freeze-strict": "^1.1.1",
"eth-ens-namehash": "^2.0.8",
"eth-json-rpc-infura": "^5.1.0",
"eth-keyring-controller": "^6.2.1",
Expand All @@ -55,8 +57,10 @@
"ethereumjs-wallet": "^1.0.1",
"ethers": "^5.4.1",
"ethjs-unit": "^0.1.6",
"fast-deep-equal": "^3.1.3",
"immer": "^9.0.6",
"isomorphic-fetch": "^3.0.0",
"json-rpc-engine": "^6.1.0",
"jsonschema": "^1.2.4",
"multiformats": "^9.5.2",
"nanoid": "^3.1.31",
Expand All @@ -73,6 +77,7 @@
"@metamask/eslint-config-jest": "^9.0.0",
"@metamask/eslint-config-nodejs": "^9.0.0",
"@metamask/eslint-config-typescript": "^9.0.1",
"@types/deep-freeze-strict": "^1.1.0",
"@types/jest": "^26.0.22",
"@types/jest-when": "^2.7.3",
"@types/node": "^14.14.31",
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ export * from './assets/TokensController';
export * from './assets/CollectiblesController';
export * from './assets/TokenDetectionController';
export * from './assets/CollectibleDetectionController';
export * from './permissions';
export * from './subject-metadata';
export { util };
136 changes: 136 additions & 0 deletions src/permissions/Caveat.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import * as errors from './errors';
import { decorateWithCaveats, PermissionConstraint } from '.';

describe('decorateWithCaveats', () => {
it('decorates a method with caveat', async () => {
const methodImplementation = () => [1, 2, 3];

const caveatSpecifications = {
reverse: {
type: 'reverse',
decorator: (method: any, _caveat: any) => async () => {
return (await method()).reverse();
},
},
};

const permission: PermissionConstraint = {
id: 'foo',
parentCapability: 'arbitraryMethod',
invoker: 'arbitraryInvoker',
date: Date.now(),
caveats: [{ type: 'reverse', value: null }],
};

const decorated = decorateWithCaveats(
methodImplementation,
permission,
caveatSpecifications,
);

expect(methodImplementation()).toStrictEqual([1, 2, 3]);
expect(
await decorated({
method: 'arbitraryMethod',
context: { origin: 'metamask.io' },
}),
).toStrictEqual([3, 2, 1]);
});

it('decorates a method with multiple caveats', async () => {
const methodImplementation = () => [1, 2, 3];

const caveatSpecifications = {
reverse: {
type: 'reverse',
decorator: (method: any, _caveat: any) => async () => {
return (await method()).reverse();
},
},
slice: {
type: 'slice',
decorator: (method: any, caveat: any) => async () => {
return (await method()).slice(0, caveat.value);
},
},
};

const permission: PermissionConstraint = {
id: 'foo',
parentCapability: 'arbitraryMethod',
invoker: 'arbitraryInvoker',
date: Date.now(),
caveats: [
{ type: 'reverse', value: null },
{ type: 'slice', value: 1 },
],
};

const decorated = decorateWithCaveats(
methodImplementation,
permission,
caveatSpecifications,
);

expect(methodImplementation()).toStrictEqual([1, 2, 3]);
expect(
await decorated({
method: 'arbitraryMethod',
context: { origin: 'metamask.io' },
}),
).toStrictEqual([3]);
});

it('returns the unmodified method implementation if there are no caveats', () => {
const methodImplementation = () => [1, 2, 3];

const permission: PermissionConstraint = {
id: 'foo',
parentCapability: 'arbitraryMethod',
invoker: 'arbitraryInvoker',
date: Date.now(),
caveats: null,
};

const decorated = decorateWithCaveats(methodImplementation, permission, {});
expect(methodImplementation()).toStrictEqual(
decorated({
method: 'arbitraryMethod',
context: { origin: 'metamask.io' },
}),
);
});

it('throws an error if the caveat type is unrecognized', () => {
const methodImplementation = () => [1, 2, 3];

const caveatSpecifications = {
reverse: {
type: 'reverse',
decorator: (method: any, _caveat: any) => async () => {
return (await method()).reverse();
},
},
};

const permission: PermissionConstraint = {
id: 'foo',
parentCapability: 'arbitraryMethod',
invoker: 'arbitraryInvoker',
date: Date.now(),
// This type doesn't exist
caveats: [{ type: 'kaplar', value: null }],
};

expect(() =>
decorateWithCaveats(
methodImplementation,
permission,
caveatSpecifications,
)({
method: 'arbitraryMethod',
context: { origin: 'metamask.io' },
}),
).toThrow(new errors.UnrecognizedCaveatTypeError('kaplar'));
});
});
Loading

0 comments on commit 93d9d1a

Please sign in to comment.