@@ -2,12 +2,18 @@ package session
22
33import (
44 "context"
5+ "fmt"
56 "testing"
67 "time"
78
89 "github.com/btcsuite/btcd/btcec/v2"
10+ "github.com/lightninglabs/lightning-terminal/accounts"
911 "github.com/lightningnetwork/lnd/clock"
12+ "github.com/lightningnetwork/lnd/fn"
13+ "github.com/lightningnetwork/lnd/macaroons"
1014 "github.com/stretchr/testify/require"
15+ "gopkg.in/macaroon-bakery.v2/bakery/checkers"
16+ "gopkg.in/macaroon.v2"
1117)
1218
1319var testTime = time .Date (2020 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC )
@@ -335,9 +341,49 @@ func TestStateShift(t *testing.T) {
335341 require .ErrorContains (t , err , "illegal session state transition" )
336342}
337343
344+ // TestLinkedAccount tests that linking a session to an account works as
345+ // expected.
346+ func TestLinkedAccount (t * testing.T ) {
347+ t .Parallel ()
348+ ctx := context .Background ()
349+ clock := clock .NewTestClock (testTime )
350+
351+ accts := accounts .NewTestDB (t , clock )
352+ db := NewTestDBWithAccounts (t , clock , accts )
353+
354+ // Reserve a session. Link it to an account that does not yet exist.
355+ // This should fail.
356+ acctID := accounts.AccountID {1 , 2 , 3 , 4 }
357+ _ , err := reserveSession (db , "session 1" , withAccount (acctID ))
358+ require .ErrorIs (t , err , accounts .ErrAccNotFound )
359+
360+ // Now, add a new account
361+ acct , err := accts .NewAccount (ctx , 1234 , clock .Now ().Add (time .Hour ), "" )
362+ require .NoError (t , err )
363+
364+ // Reserve a session. Link it to the account that was just created.
365+ // This should succeed.
366+
367+ s1 , err := reserveSession (db , "session 1" , withAccount (acct .ID ))
368+ require .NoError (t , err )
369+ require .True (t , s1 .AccountID .IsSome ())
370+ s1 .AccountID .WhenSome (func (id accounts.AccountID ) {
371+ require .Equal (t , acct .ID , id )
372+ })
373+
374+ // Make sure that a fetched session includes the account ID.
375+ s1 , err = db .GetSessionByID (ctx , s1 .ID )
376+ require .NoError (t , err )
377+ require .True (t , s1 .AccountID .IsSome ())
378+ s1 .AccountID .WhenSome (func (id accounts.AccountID ) {
379+ require .Equal (t , acct .ID , id )
380+ })
381+ }
382+
338383type testSessionOpts struct {
339384 groupID * ID
340385 sessType Type
386+ account fn.Option [accounts.AccountID ]
341387}
342388
343389func defaultTestSessOpts () * testSessionOpts {
@@ -363,6 +409,12 @@ func withType(t Type) testSessionModifier {
363409 }
364410}
365411
412+ func withAccount (alias accounts.AccountID ) testSessionModifier {
413+ return func (s * testSessionOpts ) {
414+ s .account = fn .Some (alias )
415+ }
416+ }
417+
366418func reserveSession (db Store , label string ,
367419 mods ... testSessionModifier ) (* Session , error ) {
368420
@@ -371,13 +423,35 @@ func reserveSession(db Store, label string,
371423 mod (opts )
372424 }
373425
374- return db .NewSession (
375- context .Background (), label , opts .sessType ,
376- time .Date (99999 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ),
377- "foo.bar.baz:1234" ,
426+ options := []Option {
378427 WithDevServer (),
379428 WithPrivacy (PrivacyFlags {ClearPubkeys }),
380429 WithLinkedGroupID (opts .groupID ),
430+ }
431+
432+ opts .account .WhenSome (func (id accounts.AccountID ) {
433+ // For now, we manually add the account caveat for bbolt
434+ // compatibility.
435+ accountCaveat := checkers .Condition (
436+ macaroons .CondLndCustom ,
437+ fmt .Sprintf ("%s %x" , accounts .CondAccount , id [:]),
438+ )
439+
440+ caveats := append (caveats , macaroon.Caveat {
441+ Id : []byte (accountCaveat ),
442+ })
443+
444+ options = append (
445+ options ,
446+ WithAccount (id ),
447+ WithMacaroonRecipe (caveats , nil ),
448+ )
449+ })
450+
451+ return db .NewSession (
452+ context .Background (), label , opts .sessType ,
453+ time .Date (99999 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ),
454+ "foo.bar.baz:1234" , options ... ,
381455 )
382456}
383457
0 commit comments