11package session
22
33import (
4+ "context"
5+ "fmt"
46 "testing"
57 "time"
68
79 "github.com/btcsuite/btcd/btcec/v2"
10+ "github.com/lightninglabs/lightning-terminal/accounts"
811 "github.com/lightningnetwork/lnd/clock"
12+ "github.com/lightningnetwork/lnd/fn"
13+ "github.com/lightningnetwork/lnd/macaroons"
914 "github.com/stretchr/testify/require"
15+ "gopkg.in/macaroon-bakery.v2/bakery/checkers"
16+ "gopkg.in/macaroon.v2"
1017)
1118
1219var testTime = time .Date (2020 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC )
@@ -324,9 +331,49 @@ func TestStateShift(t *testing.T) {
324331 require .ErrorContains (t , err , "illegal session state transition" )
325332}
326333
334+ // TestLinkedAccount tests that linking a session to an account works as
335+ // expected.
336+ func TestLinkedAccount (t * testing.T ) {
337+ t .Parallel ()
338+ ctx := context .Background ()
339+ clock := clock .NewTestClock (testTime )
340+
341+ accts := accounts .NewTestDB (t , clock )
342+ db := NewTestDBWithAccounts (t , clock , accts )
343+
344+ // Reserve a session. Link it to an account that does not yet exist.
345+ // This should fail.
346+ acctID := accounts.AccountID {1 , 2 , 3 , 4 }
347+ _ , err := reserveSession (db , "session 1" , withAccount (acctID ))
348+ require .ErrorIs (t , err , accounts .ErrAccNotFound )
349+
350+ // Now, add a new account
351+ acct , err := accts .NewAccount (ctx , 1234 , clock .Now ().Add (time .Hour ), "" )
352+ require .NoError (t , err )
353+
354+ // Reserve a session. Link it to the account that was just created.
355+ // This should succeed.
356+
357+ s1 , err := reserveSession (db , "session 1" , withAccount (acct .ID ))
358+ require .NoError (t , err )
359+ require .True (t , s1 .AccountID .IsSome ())
360+ s1 .AccountID .WhenSome (func (id accounts.AccountID ) {
361+ require .Equal (t , acct .ID , id )
362+ })
363+
364+ // Make sure that a fetched session includes the account ID.
365+ s1 , err = db .GetSessionByID (s1 .ID )
366+ require .NoError (t , err )
367+ require .True (t , s1 .AccountID .IsSome ())
368+ s1 .AccountID .WhenSome (func (id accounts.AccountID ) {
369+ require .Equal (t , acct .ID , id )
370+ })
371+ }
372+
327373type testSessionOpts struct {
328374 groupID * ID
329375 sessType Type
376+ account fn.Option [accounts.AccountID ]
330377}
331378
332379func defaultTestSessOpts () * testSessionOpts {
@@ -352,6 +399,12 @@ func withType(t Type) testSessionModifier {
352399 }
353400}
354401
402+ func withAccount (alias accounts.AccountID ) testSessionModifier {
403+ return func (s * testSessionOpts ) {
404+ s .account = fn .Some (alias )
405+ }
406+ }
407+
355408func reserveSession (db Store , label string ,
356409 mods ... testSessionModifier ) (* Session , error ) {
357410
@@ -360,12 +413,36 @@ func reserveSession(db Store, label string,
360413 mod (opts )
361414 }
362415
363- return db .NewSession (label , opts .sessType ,
364- time .Date (99999 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ),
365- "foo.bar.baz:1234" ,
416+ options := []Option {
366417 WithDevServer (),
367418 WithPrivacy (PrivacyFlags {ClearPubkeys }),
368419 WithLinkedGroupID (opts .groupID ),
420+ }
421+
422+ var caveats []macaroon.Caveat
423+ opts .account .WhenSome (func (id accounts.AccountID ) {
424+ // For now, we manually add the account caveat for bbolt
425+ // compatibility.
426+ accountCaveat := checkers .Condition (
427+ macaroons .CondLndCustom ,
428+ fmt .Sprintf ("%s %x" , accounts .CondAccount , id [:]),
429+ )
430+
431+ caveats = append (caveats , macaroon.Caveat {
432+ Id : []byte (accountCaveat ),
433+ })
434+
435+ options = append (
436+ options ,
437+ WithAccount (id ),
438+ WithMacaroonRecipe (caveats , nil ),
439+ )
440+ })
441+
442+ return db .NewSession (
443+ label , opts .sessType ,
444+ time .Date (99999 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ),
445+ "foo.bar.baz:1234" , options ... ,
369446 )
370447}
371448
0 commit comments