Skip to content

Commit 54fe5ef

Browse files
authored
Merge pull request #969 from ellemouton/sql11Sessions3
[sql-11] sessions: interface massage
2 parents c0e85e0 + 6239428 commit 54fe5ef

File tree

7 files changed

+125
-42
lines changed

7 files changed

+125
-42
lines changed

session/interface.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ type Session struct {
7171
GroupID ID
7272
}
7373

74-
// NewSession creates a new session with the given user-defined parameters.
75-
func NewSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
76-
expiry time.Time, serverAddr string, devServer bool, perms []bakery.Op,
77-
caveats []macaroon.Caveat, featureConfig FeaturesConfig,
78-
privacy bool, linkedGroupID *ID, flags PrivacyFlags) (*Session, error) {
74+
// buildSession creates a new session with the given user-defined parameters.
75+
func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
76+
created, expiry time.Time, serverAddr string, devServer bool,
77+
perms []bakery.Op, caveats []macaroon.Caveat,
78+
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
79+
flags PrivacyFlags) (*Session, error) {
7980

8081
_, pairingSecret, err := mailbox.NewPassphraseEntropy()
8182
if err != nil {
@@ -98,8 +99,8 @@ func NewSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
9899
Label: label,
99100
State: StateCreated,
100101
Type: typ,
101-
Expiry: expiry,
102-
CreatedAt: time.Now(),
102+
Expiry: expiry.UTC(),
103+
CreatedAt: created.UTC(),
103104
ServerAddr: serverAddr,
104105
DevServer: devServer,
105106
MacaroonRootKey: macRootKey,
@@ -139,6 +140,18 @@ type IDToGroupIndex interface {
139140
// Store is the interface a persistent storage must implement for storing and
140141
// retrieving Terminal Connect sessions.
141142
type Store interface {
143+
// NewSession creates a new session with the given user-defined
144+
// parameters.
145+
//
146+
// NOTE: currently this purely a constructor of the Session type and
147+
// does not make any database calls. This will be changed in a future
148+
// commit.
149+
NewSession(id ID, localPrivKey *btcec.PrivateKey, label string,
150+
typ Type, expiry time.Time, serverAddr string, devServer bool,
151+
perms []bakery.Op, caveats []macaroon.Caveat,
152+
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
153+
flags PrivacyFlags) (*Session, error)
154+
142155
// CreateSession adds a new session to the store. If a session with the
143156
// same local public key already exists an error is returned. This
144157
// can only be called with a Session with an ID that the Store has

session/kvdb_store.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import (
1010
"time"
1111

1212
"github.com/btcsuite/btcd/btcec/v2"
13+
"github.com/lightningnetwork/lnd/clock"
1314
"go.etcd.io/bbolt"
15+
"gopkg.in/macaroon-bakery.v2/bakery"
16+
"gopkg.in/macaroon.v2"
1417
)
1518

1619
var (
@@ -77,13 +80,15 @@ const (
7780
// BoltStore is a bolt-backed persistent store.
7881
type BoltStore struct {
7982
*bbolt.DB
83+
84+
clock clock.Clock
8085
}
8186

8287
// A compile-time check to ensure that BoltStore implements the Store interface.
8388
var _ Store = (*BoltStore)(nil)
8489

8590
// NewDB creates a new bolt database that can be found at the given directory.
86-
func NewDB(dir, fileName string) (*BoltStore, error) {
91+
func NewDB(dir, fileName string, clock clock.Clock) (*BoltStore, error) {
8792
firstInit := false
8893
path := filepath.Join(dir, fileName)
8994

@@ -106,7 +111,10 @@ func NewDB(dir, fileName string) (*BoltStore, error) {
106111
return nil, err
107112
}
108113

109-
return &BoltStore{DB: db}, nil
114+
return &BoltStore{
115+
DB: db,
116+
clock: clock,
117+
}, nil
110118
}
111119

112120
// fileExists reports whether the named file or directory exists.
@@ -173,6 +181,25 @@ func getSessionKey(session *Session) []byte {
173181
return session.LocalPublicKey.SerializeCompressed()
174182
}
175183

184+
// NewSession creates a new session with the given user-defined parameters.
185+
//
186+
// NOTE: currently this purely a constructor of the Session type and does not
187+
// make any database calls. This will be changed in a future commit.
188+
//
189+
// NOTE: this is part of the Store interface.
190+
func (db *BoltStore) NewSession(id ID, localPrivKey *btcec.PrivateKey,
191+
label string, typ Type, expiry time.Time, serverAddr string,
192+
devServer bool, perms []bakery.Op, caveats []macaroon.Caveat,
193+
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
194+
flags PrivacyFlags) (*Session, error) {
195+
196+
return buildSession(
197+
id, localPrivKey, label, typ, db.clock.Now(), expiry,
198+
serverAddr, devServer, perms, caveats, featureConfig, privacy,
199+
linkedGroupID, flags,
200+
)
201+
}
202+
176203
// CreateSession adds a new session to the store. If a session with the same
177204
// local public key already exists an error is returned.
178205
//
@@ -398,7 +425,7 @@ func (db *BoltStore) RevokeSession(key *btcec.PublicKey) error {
398425
}
399426

400427
session.State = StateRevoked
401-
session.RevokedAt = time.Now()
428+
session.RevokedAt = db.clock.Now().UTC()
402429

403430
var buf bytes.Buffer
404431
if err := SerializeSession(&buf, session); err != nil {

session/store_test.go

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,28 @@ import (
66
"time"
77

88
"github.com/btcsuite/btcd/btcec/v2"
9+
"github.com/lightningnetwork/lnd/clock"
910
"github.com/stretchr/testify/require"
1011
)
1112

13+
var testTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
14+
1215
// TestBasicSessionStore tests the basic getters and setters of the session
1316
// store.
1417
func TestBasicSessionStore(t *testing.T) {
1518
// Set up a new DB.
16-
db, err := NewDB(t.TempDir(), "test.db")
19+
clock := clock.NewTestClock(testTime)
20+
db, err := NewDB(t.TempDir(), "test.db", clock)
1721
require.NoError(t, err)
1822
t.Cleanup(func() {
1923
_ = db.Close()
2024
})
2125

2226
// Create a few sessions.
23-
s1 := newSession(t, db, "session 1", nil)
24-
s2 := newSession(t, db, "session 2", nil)
25-
s3 := newSession(t, db, "session 3", nil)
26-
s4 := newSession(t, db, "session 4", nil)
27+
s1 := newSession(t, db, clock, "session 1", nil)
28+
s2 := newSession(t, db, clock, "session 2", nil)
29+
s3 := newSession(t, db, clock, "session 3", nil)
30+
s4 := newSession(t, db, clock, "session 4", nil)
2731

2832
// Persist session 1. This should now succeed.
2933
require.NoError(t, db.CreateSession(s1))
@@ -51,11 +55,11 @@ func TestBasicSessionStore(t *testing.T) {
5155
for _, s := range []*Session{s1, s2, s3} {
5256
session, err := db.GetSession(s.LocalPublicKey)
5357
require.NoError(t, err)
54-
require.Equal(t, s.Label, session.Label)
58+
assertEqualSessions(t, s, session)
5559

5660
session, err = db.GetSessionByID(s.ID)
5761
require.NoError(t, err)
58-
require.Equal(t, s.Label, session.Label)
62+
assertEqualSessions(t, s, session)
5963
}
6064

6165
// Fetch session 1 and assert that it currently has no remote pub key.
@@ -89,17 +93,18 @@ func TestBasicSessionStore(t *testing.T) {
8993
// TestLinkingSessions tests that session linking works as expected.
9094
func TestLinkingSessions(t *testing.T) {
9195
// Set up a new DB.
92-
db, err := NewDB(t.TempDir(), "test.db")
96+
clock := clock.NewTestClock(testTime)
97+
db, err := NewDB(t.TempDir(), "test.db", clock)
9398
require.NoError(t, err)
9499
t.Cleanup(func() {
95100
_ = db.Close()
96101
})
97102

98103
// Create a new session with no previous link.
99-
s1 := newSession(t, db, "session 1", nil)
104+
s1 := newSession(t, db, clock, "session 1", nil)
100105

101106
// Create another session and link it to the first.
102-
s2 := newSession(t, db, "session 2", &s1.GroupID)
107+
s2 := newSession(t, db, clock, "session 2", &s1.GroupID)
103108

104109
// Try to persist the second session and assert that it fails due to the
105110
// linked session not existing in the DB yet.
@@ -125,7 +130,8 @@ func TestLinkingSessions(t *testing.T) {
125130
// of the GetGroupID and GetSessionIDs methods.
126131
func TestLinkedSessions(t *testing.T) {
127132
// Set up a new DB.
128-
db, err := NewDB(t.TempDir(), "test.db")
133+
clock := clock.NewTestClock(testTime)
134+
db, err := NewDB(t.TempDir(), "test.db", clock)
129135
require.NoError(t, err)
130136
t.Cleanup(func() {
131137
_ = db.Close()
@@ -135,9 +141,9 @@ func TestLinkedSessions(t *testing.T) {
135141
// after are all linked to the prior one. All these sessions belong to
136142
// the same group. The group ID is equivalent to the session ID of the
137143
// first session.
138-
s1 := newSession(t, db, "session 1", nil)
139-
s2 := newSession(t, db, "session 2", &s1.GroupID)
140-
s3 := newSession(t, db, "session 3", &s2.GroupID)
144+
s1 := newSession(t, db, clock, "session 1", nil)
145+
s2 := newSession(t, db, clock, "session 2", &s1.GroupID)
146+
s3 := newSession(t, db, clock, "session 3", &s2.GroupID)
141147

142148
// Persist the sessions.
143149
require.NoError(t, db.CreateSession(s1))
@@ -163,8 +169,8 @@ func TestLinkedSessions(t *testing.T) {
163169

164170
// To ensure that different groups don't interfere with each other,
165171
// let's add another set of linked sessions not linked to the first.
166-
s4 := newSession(t, db, "session 4", nil)
167-
s5 := newSession(t, db, "session 5", &s4.GroupID)
172+
s4 := newSession(t, db, clock, "session 4", nil)
173+
s5 := newSession(t, db, clock, "session 5", &s4.GroupID)
168174

169175
require.NotEqual(t, s4.GroupID, s1.GroupID)
170176

@@ -192,7 +198,8 @@ func TestLinkedSessions(t *testing.T) {
192198
// method correctly checks if each session in a group passes a predicate.
193199
func TestCheckSessionGroupPredicate(t *testing.T) {
194200
// Set up a new DB.
195-
db, err := NewDB(t.TempDir(), "test.db")
201+
clock := clock.NewTestClock(testTime)
202+
db, err := NewDB(t.TempDir(), "test.db", clock)
196203
require.NoError(t, err)
197204
t.Cleanup(func() {
198205
_ = db.Close()
@@ -202,7 +209,7 @@ func TestCheckSessionGroupPredicate(t *testing.T) {
202209
// function is checked correctly.
203210

204211
// Add a new session to the DB.
205-
s1 := newSession(t, db, "label 1", nil)
212+
s1 := newSession(t, db, clock, "label 1", nil)
206213
require.NoError(t, db.CreateSession(s1))
207214

208215
// Check that the group passes against an appropriate predicate.
@@ -227,7 +234,7 @@ func TestCheckSessionGroupPredicate(t *testing.T) {
227234
require.NoError(t, db.RevokeSession(s1.LocalPublicKey))
228235

229236
// Add a new session to the same group as the first one.
230-
s2 := newSession(t, db, "label 2", &s1.GroupID)
237+
s2 := newSession(t, db, clock, "label 2", &s1.GroupID)
231238
require.NoError(t, db.CreateSession(s2))
232239

233240
// Check that the group passes against an appropriate predicate.
@@ -249,7 +256,7 @@ func TestCheckSessionGroupPredicate(t *testing.T) {
249256
require.False(t, ok)
250257

251258
// Add a new session that is not linked to the first one.
252-
s3 := newSession(t, db, "completely different", nil)
259+
s3 := newSession(t, db, clock, "completely different", nil)
253260
require.NoError(t, db.CreateSession(s3))
254261

255262
// Ensure that the first group is unaffected.
@@ -279,14 +286,15 @@ func TestCheckSessionGroupPredicate(t *testing.T) {
279286
require.True(t, ok)
280287
}
281288

282-
func newSession(t *testing.T, db Store, label string,
289+
func newSession(t *testing.T, db Store, clock clock.Clock, label string,
283290
linkedGroupID *ID) *Session {
284291

285292
id, priv, err := db.GetUnusedIDAndKeyPair()
286293
require.NoError(t, err)
287294

288-
session, err := NewSession(
295+
session, err := buildSession(
289296
id, priv, label, TypeMacaroonAdmin,
297+
clock.Now(),
290298
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
291299
"foo.bar.baz:1234", true, nil, nil, nil, true, linkedGroupID,
292300
[]PrivacyFlag{ClearPubkeys},
@@ -295,3 +303,32 @@ func newSession(t *testing.T, db Store, label string,
295303

296304
return session
297305
}
306+
307+
func assertEqualSessions(t *testing.T, expected, actual *Session) {
308+
expectedExpiry := expected.Expiry
309+
actualExpiry := actual.Expiry
310+
expectedRevoked := expected.RevokedAt
311+
actualRevoked := actual.RevokedAt
312+
expectedCreated := expected.CreatedAt
313+
actualCreated := actual.CreatedAt
314+
315+
expected.Expiry = time.Time{}
316+
expected.RevokedAt = time.Time{}
317+
expected.CreatedAt = time.Time{}
318+
actual.Expiry = time.Time{}
319+
actual.RevokedAt = time.Time{}
320+
actual.CreatedAt = time.Time{}
321+
322+
require.Equal(t, expected, actual)
323+
require.Equal(t, expectedExpiry.Unix(), actualExpiry.Unix())
324+
require.Equal(t, expectedRevoked.Unix(), actualRevoked.Unix())
325+
require.Equal(t, expectedCreated.Unix(), actualCreated.Unix())
326+
327+
// Restore the old values to not influence the tests.
328+
expected.Expiry = expectedExpiry
329+
expected.RevokedAt = expectedRevoked
330+
expected.CreatedAt = expectedCreated
331+
actual.Expiry = actualExpiry
332+
actual.RevokedAt = actualRevoked
333+
actual.CreatedAt = actualCreated
334+
}

session/tlv.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ func DeserializeSession(r io.Reader) (*Session, error) {
237237
session.Label = string(label)
238238
session.State = State(state)
239239
session.Type = Type(typ)
240-
session.Expiry = time.Unix(int64(expiry), 0)
241-
session.CreatedAt = time.Unix(int64(createdAt), 0)
240+
session.Expiry = time.Unix(int64(expiry), 0).UTC()
241+
session.CreatedAt = time.Unix(int64(createdAt), 0).UTC()
242242
session.ServerAddr = string(serverAddr)
243243
session.DevServer = devServer == 1
244244
session.WithPrivacyMapper = privacy == 1
@@ -248,7 +248,7 @@ func DeserializeSession(r io.Reader) (*Session, error) {
248248
}
249249

250250
if revokedAt != 0 {
251-
session.RevokedAt = time.Unix(int64(revokedAt), 0)
251+
session.RevokedAt = time.Unix(int64(revokedAt), 0).UTC()
252252
}
253253

254254
if t, ok := parsedTypes[typeMacaroonRecipe]; ok && t == nil {

session/tlv_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,9 @@ func TestSerializeDeserializeSession(t *testing.T) {
129129
priv, id, err := NewSessionPrivKeyAndID()
130130
require.NoError(t, err)
131131

132-
session, err := NewSession(
132+
session, err := buildSession(
133133
id, priv, test.name, test.sessType,
134+
time.Now(),
134135
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
135136
"foo.bar.baz:1234", true, test.perms,
136137
test.caveats, test.featureConfig, true,
@@ -183,8 +184,9 @@ func TestGroupIDForOlderSessions(t *testing.T) {
183184
priv, id, err := NewSessionPrivKeyAndID()
184185
require.NoError(t, err)
185186

186-
session, err := NewSession(
187+
session, err := buildSession(
187188
id, priv, "test-session", TypeMacaroonAdmin,
189+
time.Now(),
188190
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
189191
"foo.bar.baz:1234", true, nil, nil, nil, false, nil,
190192
PrivacyFlags{},
@@ -218,8 +220,9 @@ func TestGroupID(t *testing.T) {
218220
require.NoError(t, err)
219221

220222
// Create session 1 which is not linked to any previous session.
221-
session1, err := NewSession(
223+
session1, err := buildSession(
222224
id, priv, "test-session", TypeMacaroonAdmin,
225+
time.Now(),
223226
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
224227
"foo.bar.baz:1234", true, nil, nil, nil, false, nil,
225228
PrivacyFlags{},
@@ -232,8 +235,9 @@ func TestGroupID(t *testing.T) {
232235
// Create session 2 and link it to session 1.
233236
priv, id, err = NewSessionPrivKeyAndID()
234237
require.NoError(t, err)
235-
session2, err := NewSession(
238+
session2, err := buildSession(
236239
id, priv, "test-session", TypeMacaroonAdmin,
240+
time.Now(),
237241
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
238242
"foo.bar.baz:1234", true, nil, nil, nil, false,
239243
&session1.GroupID, PrivacyFlags{},

session_rpcserver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ func (s *sessionRpcServer) AddSession(ctx context.Context,
318318
return nil, err
319319
}
320320

321-
sess, err := session.NewSession(
321+
sess, err := s.cfg.db.NewSession(
322322
id, localPrivKey, req.Label, typ, expiry, req.MailboxServerAddr,
323323
req.DevServer, uniquePermissions, caveats, nil, false, nil,
324324
session.PrivacyFlags{},
@@ -1148,7 +1148,7 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
11481148
return nil, err
11491149
}
11501150

1151-
sess, err := session.NewSession(
1151+
sess, err := s.cfg.db.NewSession(
11521152
id, localPrivKey, req.Label, session.TypeAutopilot, expiry,
11531153
req.MailboxServerAddr, req.DevServer, perms, caveats,
11541154
clientConfig, privacy, linkedGroupID, privacyFlags,

0 commit comments

Comments
 (0)