Skip to content

Commit b81742f

Browse files
committed
session: functional options for NewSession
For a cleaner interface, adjust the NewSession method of the Session store such that all optional arguments are functional options.
1 parent 889cdfe commit b81742f

File tree

5 files changed

+147
-45
lines changed

5 files changed

+147
-45
lines changed

session/interface.go

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,13 @@ type Session struct {
120120

121121
// buildSession creates a new session with the given user-defined parameters.
122122
func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
123-
created, expiry time.Time, serverAddr string, devServer bool,
124-
perms []bakery.Op, caveats []macaroon.Caveat,
125-
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
126-
flags PrivacyFlags) (*Session, error) {
123+
created, expiry time.Time, serverAddr string,
124+
options ...Option) (*Session, error) {
125+
126+
opts := defaultSessionOptions()
127+
for _, o := range options {
128+
o(opts)
129+
}
127130

128131
_, pairingSecret, err := mailbox.NewPassphraseEntropy()
129132
if err != nil {
@@ -135,10 +138,10 @@ func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
135138
// The group ID will by default be the same as the Session ID
136139
// unless this session links to a previous session.
137140
groupID := id
138-
if linkedGroupID != nil {
141+
if opts.linkedGroupID != nil {
139142
// If this session is linked to a previous session, then the
140143
// group ID is the same as the linked session's group ID.
141-
groupID = *linkedGroupID
144+
groupID = *opts.linkedGroupID
142145
}
143146

144147
sess := &Session{
@@ -149,29 +152,109 @@ func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
149152
Expiry: expiry.UTC(),
150153
CreatedAt: created.UTC(),
151154
ServerAddr: serverAddr,
152-
DevServer: devServer,
155+
DevServer: opts.devServer,
153156
MacaroonRootKey: macRootKey,
154157
PairingSecret: pairingSecret,
155158
LocalPrivateKey: localPrivKey,
156159
LocalPublicKey: localPrivKey.PubKey(),
157160
RemotePublicKey: nil,
158-
WithPrivacyMapper: privacy,
159-
PrivacyFlags: flags,
161+
WithPrivacyMapper: opts.privacy,
162+
PrivacyFlags: opts.privacyFlags,
160163
GroupID: groupID,
164+
MacaroonRecipe: opts.macaroonRecipe,
161165
}
162166

163-
if perms != nil || caveats != nil {
164-
sess.MacaroonRecipe = &MacaroonRecipe{
165-
Permissions: perms,
166-
Caveats: caveats,
167-
}
167+
if len(opts.featureConfig) != 0 {
168+
sess.FeatureConfig = &opts.featureConfig
168169
}
169170

170-
if len(featureConfig) != 0 {
171-
sess.FeatureConfig = &featureConfig
171+
return sess, nil
172+
}
173+
174+
// sessionOptions defines various options that can be tweaked via functional
175+
// parameters for session creation.
176+
type sessionOptions struct {
177+
// privacy indicates if a privacy map should be used with this session.
178+
privacy bool
179+
180+
// privacyFlags to use in combination with the session's privacy mapper.
181+
privacyFlags PrivacyFlags
182+
183+
// featureConfig holds any feature configuration bytes to use for this
184+
// session.
185+
featureConfig FeaturesConfig
186+
187+
// linkedGroupID is the ID of the group that this session is linked
188+
// to. By default, a session is not linked to another group.
189+
linkedGroupID *ID
190+
191+
// devServer is true if TLS should be skipped when connecting to the
192+
// mailbox server.
193+
devServer bool
194+
195+
// macaroonRecipe holds the permissions and caveats that should be used
196+
// to bake the macaroon to be used with this session.
197+
macaroonRecipe *MacaroonRecipe
198+
}
199+
200+
// defaultSessionOptions returns a new sessionOptions struct with default
201+
// values set.
202+
func defaultSessionOptions() *sessionOptions {
203+
return &sessionOptions{
204+
privacy: false,
205+
privacyFlags: PrivacyFlags{},
206+
featureConfig: FeaturesConfig{},
207+
linkedGroupID: nil,
208+
devServer: false,
172209
}
210+
}
173211

174-
return sess, nil
212+
// Option defines the signature of a functional option that can be used to
213+
// tweak various session creation options.
214+
type Option func(*sessionOptions)
215+
216+
// WithPrivacy can be used to enable the privacy mapper for this session.
217+
// An optional set of privacy flags can be provided to further customize the
218+
// privacy mapper.
219+
func WithPrivacy(flags PrivacyFlags) Option {
220+
return func(o *sessionOptions) {
221+
o.privacy = true
222+
o.privacyFlags = flags
223+
}
224+
}
225+
226+
// WithFeatureConfig can be used to set the feature configuration bytes for
227+
// this session.
228+
func WithFeatureConfig(config FeaturesConfig) Option {
229+
return func(o *sessionOptions) {
230+
o.featureConfig = config
231+
}
232+
}
233+
234+
// WithLinkedGroupID can be used to link this session to a previous session.
235+
func WithLinkedGroupID(groupID *ID) Option {
236+
return func(o *sessionOptions) {
237+
o.linkedGroupID = groupID
238+
}
239+
}
240+
241+
// WithDevServer can be used to set if TLS verification should be skipped when
242+
// connecting to the mailbox server.
243+
func WithDevServer() Option {
244+
return func(o *sessionOptions) {
245+
o.devServer = true
246+
}
247+
}
248+
249+
// WithMacaroonRecipe can be used to set the permissions and caveats that
250+
// should be used to bake the macaroon for a session.
251+
func WithMacaroonRecipe(caveats []macaroon.Caveat, perms []bakery.Op) Option {
252+
return func(o *sessionOptions) {
253+
o.macaroonRecipe = &MacaroonRecipe{
254+
Permissions: perms,
255+
Caveats: caveats,
256+
}
257+
}
175258
}
176259

177260
// IDToGroupIndex defines an interface for the session ID to group ID index.
@@ -191,9 +274,7 @@ type Store interface {
191274
// parameters. The session will remain in the StateReserved state until
192275
// ShiftState is called to update the state.
193276
NewSession(label string, typ Type, expiry time.Time, serverAddr string,
194-
devServer bool, perms []bakery.Op, caveats []macaroon.Caveat,
195-
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
196-
flags PrivacyFlags) (*Session, error)
277+
opts ...Option) (*Session, error)
197278

198279
// GetSession fetches the session with the given key.
199280
GetSession(key *btcec.PublicKey) (*Session, error)

session/kvdb_store.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ import (
1313
"github.com/btcsuite/btcd/btcec/v2"
1414
"github.com/lightningnetwork/lnd/clock"
1515
"go.etcd.io/bbolt"
16-
"gopkg.in/macaroon-bakery.v2/bakery"
17-
"gopkg.in/macaroon.v2"
1816
)
1917

2018
var (
@@ -188,9 +186,7 @@ func getSessionKey(session *Session) []byte {
188186
//
189187
// NOTE: this is part of the Store interface.
190188
func (db *BoltStore) NewSession(label string, typ Type, expiry time.Time,
191-
serverAddr string, devServer bool, perms []bakery.Op,
192-
caveats []macaroon.Caveat, featureConfig FeaturesConfig, privacy bool,
193-
linkedGroupID *ID, flags PrivacyFlags) (*Session, error) {
189+
serverAddr string, opts ...Option) (*Session, error) {
194190

195191
var session *Session
196192
err := db.Update(func(tx *bbolt.Tx) error {
@@ -206,8 +202,7 @@ func (db *BoltStore) NewSession(label string, typ Type, expiry time.Time,
206202

207203
session, err = buildSession(
208204
id, localPrivKey, label, typ, db.clock.Now(), expiry,
209-
serverAddr, devServer, perms, caveats, featureConfig,
210-
privacy, linkedGroupID, flags,
205+
serverAddr, opts...,
211206
)
212207
if err != nil {
213208
return err

session/store_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,10 @@ func reserveSession(db Store, label string,
374374

375375
return db.NewSession(label, opts.sessType,
376376
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
377-
"foo.bar.baz:1234", true, nil, nil, nil, true, opts.groupID,
378-
[]PrivacyFlag{ClearPubkeys},
377+
"foo.bar.baz:1234",
378+
WithDevServer(),
379+
WithPrivacy(PrivacyFlags{ClearPubkeys}),
380+
WithLinkedGroupID(opts.groupID),
379381
)
380382
}
381383

session/tlv_test.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,12 @@ func TestSerializeDeserializeSession(t *testing.T) {
133133
id, priv, test.name, test.sessType,
134134
time.Now(),
135135
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
136-
"foo.bar.baz:1234", true, test.perms,
137-
test.caveats, test.featureConfig, true,
138-
test.linkedGroupID,
139-
[]PrivacyFlag{ClearPubkeys},
136+
"foo.bar.baz:1234",
137+
WithDevServer(),
138+
WithPrivacy(PrivacyFlags{ClearPubkeys}),
139+
WithMacaroonRecipe(test.caveats, test.perms),
140+
WithFeatureConfig(test.featureConfig),
141+
WithLinkedGroupID(test.linkedGroupID),
140142
)
141143
require.NoError(t, err)
142144

@@ -188,8 +190,8 @@ func TestGroupIDForOlderSessions(t *testing.T) {
188190
id, priv, "test-session", TypeMacaroonAdmin,
189191
time.Now(),
190192
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
191-
"foo.bar.baz:1234", true, nil, nil, nil, false, nil,
192-
PrivacyFlags{},
193+
"foo.bar.baz:1234",
194+
WithDevServer(),
193195
)
194196
require.NoError(t, err)
195197

@@ -224,8 +226,8 @@ func TestGroupID(t *testing.T) {
224226
id, priv, "test-session", TypeMacaroonAdmin,
225227
time.Now(),
226228
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
227-
"foo.bar.baz:1234", true, nil, nil, nil, false, nil,
228-
PrivacyFlags{},
229+
"foo.bar.baz:1234",
230+
WithDevServer(),
229231
)
230232
require.NoError(t, err)
231233

@@ -239,8 +241,9 @@ func TestGroupID(t *testing.T) {
239241
id, priv, "test-session", TypeMacaroonAdmin,
240242
time.Now(),
241243
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
242-
"foo.bar.baz:1234", true, nil, nil, nil, false,
243-
&session1.GroupID, PrivacyFlags{},
244+
"foo.bar.baz:1234",
245+
WithLinkedGroupID(&session1.ID),
246+
WithDevServer(),
244247
)
245248
require.NoError(t, err)
246249

session_rpcserver.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,16 @@ func (s *sessionRpcServer) AddSession(ctx context.Context,
308308
}
309309
}
310310

311+
sessOpts := []session.Option{
312+
session.WithMacaroonRecipe(caveats, uniquePermissions),
313+
}
314+
315+
if req.DevServer {
316+
sessOpts = append(sessOpts, session.WithDevServer())
317+
}
318+
311319
sess, err := s.cfg.db.NewSession(
312-
req.Label, typ, expiry, req.MailboxServerAddr,
313-
req.DevServer, uniquePermissions, caveats, nil, false, nil,
314-
session.PrivacyFlags{},
320+
req.Label, typ, expiry, req.MailboxServerAddr, sessOpts...,
315321
)
316322
if err != nil {
317323
return nil, fmt.Errorf("error creating new session: %v", err)
@@ -1125,10 +1131,25 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
11251131
caveats = append(caveats, firewall.MetaPrivacyCaveat)
11261132
}
11271133

1134+
// Construct the functional options that will be used to create the
1135+
// session.
1136+
sessOpts := []session.Option{
1137+
session.WithMacaroonRecipe(caveats, perms),
1138+
session.WithFeatureConfig(clientConfig),
1139+
session.WithLinkedGroupID(linkedGroupID),
1140+
}
1141+
1142+
if req.DevServer {
1143+
sessOpts = append(sessOpts, session.WithDevServer())
1144+
}
1145+
1146+
if privacy {
1147+
sessOpts = append(sessOpts, session.WithPrivacy(privacyFlags))
1148+
}
1149+
11281150
sess, err := s.cfg.db.NewSession(
1129-
req.Label, session.TypeAutopilot, expiry,
1130-
req.MailboxServerAddr, req.DevServer, perms, caveats,
1131-
clientConfig, privacy, linkedGroupID, privacyFlags,
1151+
req.Label, session.TypeAutopilot, expiry, req.MailboxServerAddr,
1152+
sessOpts...,
11321153
)
11331154
if err != nil {
11341155
return nil, fmt.Errorf("error creating new session: %v", err)

0 commit comments

Comments
 (0)