balanceofsatoshis 11.2.1 → 11.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Versions
2
2
 
3
+ ## Version 11.3.0
4
+
5
+ - `credentials`: Allow specifying specific methods to allow in a credential
6
+
3
7
  ## Version 11.2.1
4
8
 
5
9
  - Improve support for LND v0.13.3
package/bos CHANGED
@@ -420,6 +420,7 @@ prog
420
420
  .help('Output encrypted remote access credentials. Use with "nodes --add"')
421
421
  .option('--cleartext', 'Output remote access credentials without encryption')
422
422
  .option('--days <days>', 'Expiration days for credentials', INT, 365)
423
+ .option('--method <method_name>', 'White-list specific method', REPEATABLE)
423
424
  .option('--node <node_name>', 'Get credentials for a saved node')
424
425
  .option('--nospend', 'Credentials do not include spending privileges')
425
426
  .option('--readonly', 'Credentials only include read permissions')
@@ -432,6 +433,7 @@ prog
432
433
  is_cleartext: options.cleartext,
433
434
  is_nospend: options.nospend,
434
435
  is_readonly: options.readonly,
436
+ methods: flatten([options.method].filter(n => !!n)),
435
437
  node: options.node,
436
438
  },
437
439
  responses.returnObject({logger, reject, resolve}));
@@ -0,0 +1,41 @@
1
+ const {noSpendPerms} = require('./constants');
2
+ const {permissionEntities} = require('./constants');
3
+
4
+ const readPerms = permissionEntities.map(entity => `${entity}:read`);
5
+
6
+ /** Derive restrictions for macaroon
7
+
8
+ {
9
+ [is_nospend]: <Restrict Credentials To Non-Spending Permissions Bool>
10
+ [is_readonly]: <Restrict Credentials To Read-Only Permissions Bool>
11
+ [methods]: [<Allow Specific Method String>]
12
+ }
13
+
14
+ @returns
15
+ {
16
+ [allow]: {
17
+ methods: [<Allow Specific Method String>]
18
+ permissions: [<Entity:Action String>]
19
+ }
20
+ }
21
+ */
22
+ module.exports = args => {
23
+ const methods = args.methods || [];
24
+
25
+ // Exit early when specific credentials are not requested
26
+ if (!args.is_readonly && !args.is_nospend && !methods.length) {
27
+ return {};
28
+ }
29
+
30
+ const permissions = [];
31
+
32
+ if (!!args.is_readonly) {
33
+ readPerms.forEach(n => permissions.push(n));
34
+ }
35
+
36
+ if (!!args.is_nospend) {
37
+ noSpendPerms.forEach(n => permissions.push(n));
38
+ }
39
+
40
+ return {allow: {methods, permissions}};
41
+ };
@@ -16,6 +16,7 @@ const {pemAsDer} = require('./../encryption');
16
16
  is_nospend: <Restrict Credentials To Non-Spending Permissions Bool>
17
17
  is_readonly: <Restrict Credentials To Read-Only Permissions Bool>
18
18
  logger: <Winston Logger Object> ({info}) => ()
19
+ [methods]: [<Allow Specific Method String>]
19
20
  [node]: <Node Name String>
20
21
  }
21
22
 
@@ -81,6 +82,7 @@ module.exports = (args, cbk) => {
81
82
  is_nospend: args.is_nospend,
82
83
  is_readonly: args.is_readonly,
83
84
  logger: args.logger,
85
+ methods: args.methods,
84
86
  node: args.node,
85
87
  },
86
88
  cbk);
@@ -12,6 +12,7 @@ const {grantAccess} = require('ln-service');
12
12
  const {restrictMacaroon} = require('ln-service');
13
13
  const {returnResult} = require('asyncjs-util');
14
14
 
15
+ const credentialRestrictions = require('./credential_restrictions');
15
16
  const {decryptCiphertext} = require('./../encryption');
16
17
  const {derAsPem} = require('./../encryption');
17
18
  const getCert = require('./get_cert');
@@ -38,6 +39,7 @@ const socket = 'localhost:10009';
38
39
  [is_readonly]: <Restrict Credentials To Read-Only Permissions Bool>
39
40
  [key]: <Encrypt to Public Key DER Hex String>
40
41
  [logger]: <Winston Logger Object>
42
+ [methods]: [<Allow Specific Method String>]
41
43
  [node]: <Node Name String> // Defaults to default local mainnet node creds
42
44
  }
43
45
 
@@ -199,8 +201,14 @@ module.exports = (args, cbk) => {
199
201
  'macaroon',
200
202
  ({credentials, macaroon}, cbk) =>
201
203
  {
204
+ const {allow} = credentialRestrictions({
205
+ is_nospend: args.is_nospend,
206
+ is_readonly: args.is_readonly,
207
+ methods: args.methods,
208
+ });
209
+
202
210
  // Exit early when readonly credentials are not requested
203
- if (!args.is_readonly && !args.is_nospend) {
211
+ if (!allow) {
204
212
  return cbk(null, {macaroon});
205
213
  }
206
214
 
@@ -210,9 +218,12 @@ module.exports = (args, cbk) => {
210
218
  socket: credentials.socket,
211
219
  });
212
220
 
213
- const permissions = !!args.is_readonly ? readPerms : noSpendPerms;
214
-
215
- return grantAccess({lnd, permissions}, cbk);
221
+ return grantAccess({
222
+ lnd,
223
+ methods: allow.methods,
224
+ permissions: allow.permissions,
225
+ },
226
+ cbk);
216
227
  }],
217
228
 
218
229
  // Final credentials with encryption applied
package/package.json CHANGED
@@ -35,7 +35,7 @@
35
35
  "inquirer": "8.1.5",
36
36
  "invoices": "2.0.0",
37
37
  "ln-accounting": "5.0.3",
38
- "ln-service": "52.10.1",
38
+ "ln-service": "52.10.2",
39
39
  "ln-sync": "2.0.2",
40
40
  "ln-telegram": "3.3.0",
41
41
  "moment": "2.29.1",
@@ -80,5 +80,5 @@
80
80
  "postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis --push .",
81
81
  "test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 test/arrays/*.js test/balances/*.js test/chain/*.js test/display/*.js test/encryption/*.js test/fiat/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/peers/*.js test/responses/*.js test/routing/*.js test/services/*.js test/swaps/*.js test/tags/*.js test/wallets/*.js"
82
82
  },
83
- "version": "11.2.1"
83
+ "version": "11.3.0"
84
84
  }
@@ -0,0 +1,74 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const method = require('./../../lnd/credential_restrictions');
4
+
5
+ const tests = [
6
+ {
7
+ args: {},
8
+ description: 'No restrictions results in no allow elements',
9
+ expected: {},
10
+ },
11
+ {
12
+ args: {is_nospend: true},
13
+ description: 'No spend results in nospend permissions',
14
+ expected: {
15
+ allow: {
16
+ methods: [],
17
+ permissions: [
18
+ 'address:read',
19
+ 'address:write',
20
+ 'info:read',
21
+ 'info:write',
22
+ 'invoices:read',
23
+ 'invoices:write',
24
+ 'macaroon:read',
25
+ 'message:read',
26
+ 'offchain:read',
27
+ 'onchain:read',
28
+ 'peers:read',
29
+ 'peers:write',
30
+ 'signer:read',
31
+ ],
32
+ },
33
+ },
34
+ },
35
+ {
36
+ args: {is_readonly: true},
37
+ description: 'Readonly results in read permissions',
38
+ expected: {
39
+ allow: {
40
+ methods: [],
41
+ permissions: [
42
+ 'address:read',
43
+ 'info:read',
44
+ 'invoices:read',
45
+ 'macaroon:read',
46
+ 'message:read',
47
+ 'offchain:read',
48
+ 'onchain:read',
49
+ 'peers:read',
50
+ 'signer:read',
51
+ ],
52
+ },
53
+ },
54
+ },
55
+ {
56
+ args: {methods: ['getWalletInfo']},
57
+ description: 'Readonly results in read permissions',
58
+ expected: {allow: {methods: ['getWalletInfo'], permissions: []}},
59
+ },
60
+ ];
61
+
62
+ tests.forEach(({args, description, error, expected}) => {
63
+ return test(description, async ({end, strictSame, throws}) => {
64
+ if (!!error) {
65
+ throws(() => method(args), new Error(error), 'Got expected error');
66
+ } else {
67
+ const res = method(args);
68
+
69
+ strictSame(res, expected, 'Got expected result');
70
+ }
71
+
72
+ return end();
73
+ });
74
+ });