@@ -35,6 +35,7 @@ import (
35
35
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
36
36
"github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"
37
37
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
38
+ "github.com/lightningnetwork/lnd/macaroons"
38
39
"github.com/lightningnetwork/lnd/signal"
39
40
"google.golang.org/grpc"
40
41
"gopkg.in/macaroon-bakery.v2/bakery"
@@ -119,6 +120,7 @@ func main() {
119
120
callbacks .Set ("wasmClientGetExpiry" , js .FuncOf (wc .GetExpiry ))
120
121
callbacks .Set ("wasmClientHasPerms" , js .FuncOf (wc .HasPermissions ))
121
122
callbacks .Set ("wasmClientIsReadOnly" , js .FuncOf (wc .IsReadOnly ))
123
+ callbacks .Set ("wasmClientIsCustom" , js .FuncOf (wc .IsCustom ))
122
124
js .Global ().Set (cfg .NameSpace , callbacks )
123
125
124
126
for _ , registration := range registrations {
@@ -353,6 +355,32 @@ func (w *wasmClient) IsReadOnly(_ js.Value, _ []js.Value) interface{} {
353
355
return js .ValueOf (isReadOnly (macOps ))
354
356
}
355
357
358
+ func (w * wasmClient ) IsCustom (_ js.Value , _ []js.Value ) interface {} {
359
+ if w .mac == nil {
360
+ log .Errorf ("macaroon not obtained yet. IsCustom should " +
361
+ "only be called once the connection is complete" )
362
+ return js .ValueOf (false )
363
+ }
364
+
365
+ macOps , err := extractMacaroonOps (w .mac )
366
+ if err != nil {
367
+ log .Errorf ("could not extract macaroon ops: %v" , err )
368
+ return js .ValueOf (false )
369
+ }
370
+
371
+ // We consider a session type to be "custom" if it has any permissions
372
+ // with the "uri" entity.
373
+ var isCustom bool
374
+ for _ , op := range macOps {
375
+ if op .Entity == macaroons .PermissionEntityCustomURI {
376
+ isCustom = true
377
+ break
378
+ }
379
+ }
380
+
381
+ return js .ValueOf (isCustom )
382
+ }
383
+
356
384
func (w * wasmClient ) HasPermissions (_ js.Value , args []js.Value ) interface {} {
357
385
if len (args ) != 1 {
358
386
return js .ValueOf (false )
@@ -385,7 +413,7 @@ func (w *wasmClient) HasPermissions(_ js.Value, args []js.Value) interface{} {
385
413
386
414
// Check that the macaroon contains each of the required permissions
387
415
// for the given URI.
388
- return js .ValueOf (hasPermissions (macOps , ops ))
416
+ return js .ValueOf (hasPermissions (uri , macOps , ops ))
389
417
}
390
418
391
419
// extractMacaroonOps is a helper function that extracts operations from the
@@ -421,14 +449,27 @@ func isReadOnly(ops []*lnrpc.Op) bool {
421
449
422
450
// hasPermissions returns true if all the operations in requiredOps can also be
423
451
// found in macOps.
424
- func hasPermissions (macOps []* lnrpc.Op , requiredOps []bakery.Op ) bool {
452
+ func hasPermissions (uri string , macOps []* lnrpc.Op ,
453
+ requiredOps []bakery.Op ) bool {
454
+
425
455
// Create a lookup map of the macaroon operations.
426
456
macOpsMap := make (map [string ]map [string ]bool )
427
457
for _ , op := range macOps {
428
458
macOpsMap [op .Entity ] = make (map [string ]bool )
429
459
430
460
for _ , action := range op .Actions {
431
461
macOpsMap [op.Entity ][action ] = true
462
+
463
+ // We account here for the special case where the
464
+ // operation gives access to an entire URI. This is the
465
+ // case when the Entity is equal to the "uri" keyword
466
+ // and when the Action is equal to the URI that access
467
+ // is being granted to.
468
+ if op .Entity == macaroons .PermissionEntityCustomURI &&
469
+ action == uri {
470
+
471
+ return true
472
+ }
432
473
}
433
474
}
434
475
0 commit comments