Skip to content
This repository was archived by the owner on Jan 3, 2022. It is now read-only.

Commit 3888429

Browse files
authored
Add hasPermissions methods (#123)
* Add hasPermissions methods * Add tests, update coverage scripts
1 parent 5f7542e commit 3888429

14 files changed

+173
-22
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ dist/
55
.python-version
66
*.log
77
.nyc_output
8+
coverage

.nycrc

Lines changed: 0 additions & 4 deletions
This file was deleted.

index.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,12 @@ export class CapabilitiesController extends BaseController<any, any> implements
310310
return engine;
311311
}
312312

313+
/**
314+
* Checks the permissions for the given domain, or an empty array.
315+
*
316+
* @param domain - The domain whose permissions to retrieve.
317+
* @returns The permissions for the domain.
318+
*/
313319
getPermissionsForDomain (domain: string): IOcapLdCapability[] {
314320
const { domains = {} } = this.state;
315321
if (domains[domain]) {
@@ -324,19 +330,43 @@ export class CapabilitiesController extends BaseController<any, any> implements
324330
* Follows the delegation chain of the first matching permission found.
325331
*
326332
* @param {string} domain - The domain whose permission to retrieve.
327-
* @param {string} method - The method
333+
* @param {string} method - The method of the permission to retrieve.
328334
*/
329335
getPermission (domain: string, method: string): IOcapLdCapability | undefined {
330-
const permissions = this.getPermissionsForDomain(domain).filter(p => {
331-
return p.parentCapability === method;
332-
});
336+
const permissions = this.getPermissionsForDomain(domain)
337+
.filter(permission => {
338+
return permission.parentCapability === method;
339+
});
333340
if (permissions.length > 0) {
334341
return permissions.shift();
335342
}
336343

337344
return undefined;
338345
}
339346

347+
/**
348+
* Checks whether the given domain has permissions.
349+
*
350+
* @param domain - The domain to check.
351+
* @returns Whether the given domain has any permissions.
352+
*/
353+
hasPermissions (domain: string): boolean {
354+
return Boolean(this.state.domains?.[domain]);
355+
}
356+
357+
/**
358+
* Checks whether the given domain has the given permission.
359+
*
360+
* @param domain - The domain to check.
361+
* @param method - The method of the permission to check for.
362+
* @returns Whether the given domain has the given permission.
363+
*/
364+
hasPermission (domain: string, method: string): boolean {
365+
return this.getPermissionsForDomain(domain).some(permission => {
366+
return permission.parentCapability === method;
367+
});
368+
}
369+
340370
/**
341371
* Gets current permissions request objects.
342372
* Useful for displaying information for user consent.

nyc.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
extends: '@istanbuljs/nyc-config-typescript',
3+
};

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"lint:fix": "eslint --ext .ts,.js --fix .",
1414
"prepublishOnly": "yarn build",
1515
"test": "yarn build:typescript && node test",
16-
"test:coverage": "nyc node test"
16+
"coverage": "nyc node test",
17+
"coverage:html": "nyc --reporter=html node test"
1718
},
1819
"keywords": [],
1920
"author": "",
@@ -29,11 +30,12 @@
2930
"@types/uuid": "^3.4.4",
3031
"@typescript-eslint/eslint-plugin": "^2.17.0",
3132
"@typescript-eslint/parser": "^2.17.0",
33+
"clone": "^2.1.2",
3234
"eslint": "^6.8.0",
3335
"fast-deep-equal": "^2.0.1",
3436
"nyc": "^15.0.0",
3537
"tape": "^4.9.2",
36-
"typescript": "^4.0.3"
38+
"typescript": "^4.1.2"
3739
},
3840
"dependencies": {
3941
"@metamask/controllers": "^5.0.0",

test/caveats.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// / <reference path="../index.ts" />
22

33
const test = require('tape');
4-
const CapabilitiesController = require('../dist').CapabilitiesController;
5-
const sendRpcMethodWithResponse = require('./lib/utils').sendRpcMethodWithResponse;
4+
const { CapabilitiesController } = require('../dist');
5+
const { sendRpcMethodWithResponse } = require('./lib/utils');
66

77
const UNAUTHORIZED_CODE = require('eth-rpc-errors').ERROR_CODES.provider.unauthorized;
88

test/dependentPermissions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const test = require('tape');
2-
const CapabilitiesController = require('../dist').CapabilitiesController;
2+
const { CapabilitiesController } = require('../dist');
33
const JsonRpcEngine = require('json-rpc-engine');
44

55
test('restricted permission gets restricted provider', async (t) => {

test/forwarding.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const test = require('tape');
2-
const CapabilitiesController = require('../dist').CapabilitiesController;
2+
const { CapabilitiesController } = require('../dist');
33

44
const UNAUTHORIZED_CODE = require('eth-rpc-errors').ERROR_CODES.provider.unauthorized;
55
const METHOD_NOT_FOUND_CODE = require('eth-rpc-errors').ERROR_CODES.rpc.methodNotFound;

test/getPermissions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const test = require('tape');
2-
const CapabilitiesController = require('../dist').CapabilitiesController;
2+
const { CapabilitiesController } = require('../dist');
33
const equal = require('fast-deep-equal');
44

55
function noop () {}

test/hasPermissions.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
const test = require('tape');
2+
const { CapabilitiesController } = require('../dist');
3+
const clone = require('clone');
4+
5+
function noop () {}
6+
7+
const domain1 = 'foo.com';
8+
const domain2 = 'bar.io';
9+
10+
const method1 = 'restricted';
11+
const method2 = 'restricted2';
12+
13+
const domains = {
14+
[domain1]: {
15+
permissions: [
16+
{
17+
parentCapability: method1,
18+
id: 'abc',
19+
},
20+
],
21+
},
22+
[domain2]: {
23+
permissions: [
24+
{
25+
parentCapability: method2,
26+
id: 'xyz',
27+
},
28+
],
29+
},
30+
};
31+
32+
test('hasPermissions returns false if no permissions', (t) => {
33+
const ctrl = new CapabilitiesController({
34+
requestUserApproval: noop,
35+
});
36+
37+
t.equal(ctrl.hasPermissions(domain1), false, 'should return false');
38+
t.end();
39+
});
40+
41+
test('hasPermission returns false if no permissions', (t) => {
42+
const ctrl = new CapabilitiesController({
43+
requestUserApproval: noop,
44+
});
45+
46+
t.equal(ctrl.hasPermissions(domain1, method1), false, 'should return false');
47+
t.end();
48+
});
49+
50+
test('hasPermissions returns true with permissions', (t) => {
51+
const ctrl = new CapabilitiesController({
52+
requestUserApproval: noop,
53+
},
54+
{
55+
domains: clone(domains),
56+
});
57+
58+
t.equal(ctrl.hasPermissions(domain1), true, 'should return true for domain1');
59+
t.equal(ctrl.hasPermissions(domain2), true, 'should return true for domain2');
60+
t.end();
61+
});
62+
63+
test('hasPermission returns true with permissions and correct method', (t) => {
64+
const ctrl = new CapabilitiesController({
65+
requestUserApproval: noop,
66+
},
67+
{
68+
domains: clone(domains),
69+
});
70+
71+
t.equal(
72+
ctrl.hasPermission(domain1, method1),
73+
true,
74+
'should return true for domain1 and method1'
75+
);
76+
t.equal(
77+
ctrl.hasPermission(domain2, method2),
78+
true,
79+
'should return true for domain2 and method2'
80+
);
81+
t.end();
82+
});
83+
84+
test('hasPermissions returns with permissions but wrong domain', (t) => {
85+
const ctrl = new CapabilitiesController({
86+
requestUserApproval: noop,
87+
},
88+
{
89+
domains: {
90+
[domain1]: clone(domains[domain1]),
91+
},
92+
});
93+
94+
t.equal(ctrl.hasPermissions(domain1), true, 'should return true for domain1');
95+
t.equal(ctrl.hasPermissions(domain2), false, 'should return false for domain2');
96+
t.end();
97+
});
98+
99+
test('hasPermission returns false with permissions but wrong method', (t) => {
100+
const ctrl = new CapabilitiesController({
101+
requestUserApproval: noop,
102+
},
103+
{
104+
domains: clone(domains),
105+
});
106+
107+
t.equal(
108+
ctrl.hasPermission(domain1, method2),
109+
false,
110+
'should return false for domain1 and method2'
111+
);
112+
t.equal(
113+
ctrl.hasPermission(domain2, method1),
114+
false,
115+
'should return false for domain2 and method1'
116+
);
117+
t.end();
118+
});

0 commit comments

Comments
 (0)