@@ -35,6 +35,7 @@ import (
3535 "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
3636 "github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"
3737 "github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
38+ "github.com/lightningnetwork/lnd/macaroons"
3839 "github.com/lightningnetwork/lnd/signal"
3940 "google.golang.org/grpc"
4041 "gopkg.in/macaroon-bakery.v2/bakery"
@@ -119,6 +120,7 @@ func main() {
119120 callbacks .Set ("wasmClientGetExpiry" , js .FuncOf (wc .GetExpiry ))
120121 callbacks .Set ("wasmClientHasPerms" , js .FuncOf (wc .HasPermissions ))
121122 callbacks .Set ("wasmClientIsReadOnly" , js .FuncOf (wc .IsReadOnly ))
123+ callbacks .Set ("wasmClientIsCustom" , js .FuncOf (wc .IsCustom ))
122124 js .Global ().Set (cfg .NameSpace , callbacks )
123125
124126 for _ , registration := range registrations {
@@ -353,6 +355,32 @@ func (w *wasmClient) IsReadOnly(_ js.Value, _ []js.Value) interface{} {
353355 return js .ValueOf (isReadOnly (macOps ))
354356}
355357
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+
356384func (w * wasmClient ) HasPermissions (_ js.Value , args []js.Value ) interface {} {
357385 if len (args ) != 1 {
358386 return js .ValueOf (false )
@@ -385,7 +413,7 @@ func (w *wasmClient) HasPermissions(_ js.Value, args []js.Value) interface{} {
385413
386414 // Check that the macaroon contains each of the required permissions
387415 // for the given URI.
388- return js .ValueOf (hasPermissions (macOps , ops ))
416+ return js .ValueOf (hasPermissions (uri , macOps , ops ))
389417}
390418
391419// extractMacaroonOps is a helper function that extracts operations from the
@@ -421,14 +449,27 @@ func isReadOnly(ops []*lnrpc.Op) bool {
421449
422450// hasPermissions returns true if all the operations in requiredOps can also be
423451// 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+
425455 // Create a lookup map of the macaroon operations.
426456 macOpsMap := make (map [string ]map [string ]bool )
427457 for _ , op := range macOps {
428458 macOpsMap [op .Entity ] = make (map [string ]bool )
429459
430460 for _ , action := range op .Actions {
431461 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+ }
432473 }
433474 }
434475
0 commit comments