@@ -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