mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
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.
This commit is contained in:
parent
889cdfea71
commit
b81742fe9d
5 changed files with 147 additions and 45 deletions
|
|
@ -120,10 +120,13 @@ type Session struct {
|
|||
|
||||
// buildSession creates a new session with the given user-defined parameters.
|
||||
func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
|
||||
created, expiry time.Time, serverAddr string, devServer bool,
|
||||
perms []bakery.Op, caveats []macaroon.Caveat,
|
||||
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
|
||||
flags PrivacyFlags) (*Session, error) {
|
||||
created, expiry time.Time, serverAddr string,
|
||||
options ...Option) (*Session, error) {
|
||||
|
||||
opts := defaultSessionOptions()
|
||||
for _, o := range options {
|
||||
o(opts)
|
||||
}
|
||||
|
||||
_, pairingSecret, err := mailbox.NewPassphraseEntropy()
|
||||
if err != nil {
|
||||
|
|
@ -135,10 +138,10 @@ func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
|
|||
// The group ID will by default be the same as the Session ID
|
||||
// unless this session links to a previous session.
|
||||
groupID := id
|
||||
if linkedGroupID != nil {
|
||||
if opts.linkedGroupID != nil {
|
||||
// If this session is linked to a previous session, then the
|
||||
// group ID is the same as the linked session's group ID.
|
||||
groupID = *linkedGroupID
|
||||
groupID = *opts.linkedGroupID
|
||||
}
|
||||
|
||||
sess := &Session{
|
||||
|
|
@ -149,29 +152,109 @@ func buildSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
|
|||
Expiry: expiry.UTC(),
|
||||
CreatedAt: created.UTC(),
|
||||
ServerAddr: serverAddr,
|
||||
DevServer: devServer,
|
||||
DevServer: opts.devServer,
|
||||
MacaroonRootKey: macRootKey,
|
||||
PairingSecret: pairingSecret,
|
||||
LocalPrivateKey: localPrivKey,
|
||||
LocalPublicKey: localPrivKey.PubKey(),
|
||||
RemotePublicKey: nil,
|
||||
WithPrivacyMapper: privacy,
|
||||
PrivacyFlags: flags,
|
||||
WithPrivacyMapper: opts.privacy,
|
||||
PrivacyFlags: opts.privacyFlags,
|
||||
GroupID: groupID,
|
||||
MacaroonRecipe: opts.macaroonRecipe,
|
||||
}
|
||||
|
||||
if perms != nil || caveats != nil {
|
||||
sess.MacaroonRecipe = &MacaroonRecipe{
|
||||
if len(opts.featureConfig) != 0 {
|
||||
sess.FeatureConfig = &opts.featureConfig
|
||||
}
|
||||
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// sessionOptions defines various options that can be tweaked via functional
|
||||
// parameters for session creation.
|
||||
type sessionOptions struct {
|
||||
// privacy indicates if a privacy map should be used with this session.
|
||||
privacy bool
|
||||
|
||||
// privacyFlags to use in combination with the session's privacy mapper.
|
||||
privacyFlags PrivacyFlags
|
||||
|
||||
// featureConfig holds any feature configuration bytes to use for this
|
||||
// session.
|
||||
featureConfig FeaturesConfig
|
||||
|
||||
// linkedGroupID is the ID of the group that this session is linked
|
||||
// to. By default, a session is not linked to another group.
|
||||
linkedGroupID *ID
|
||||
|
||||
// devServer is true if TLS should be skipped when connecting to the
|
||||
// mailbox server.
|
||||
devServer bool
|
||||
|
||||
// macaroonRecipe holds the permissions and caveats that should be used
|
||||
// to bake the macaroon to be used with this session.
|
||||
macaroonRecipe *MacaroonRecipe
|
||||
}
|
||||
|
||||
// defaultSessionOptions returns a new sessionOptions struct with default
|
||||
// values set.
|
||||
func defaultSessionOptions() *sessionOptions {
|
||||
return &sessionOptions{
|
||||
privacy: false,
|
||||
privacyFlags: PrivacyFlags{},
|
||||
featureConfig: FeaturesConfig{},
|
||||
linkedGroupID: nil,
|
||||
devServer: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Option defines the signature of a functional option that can be used to
|
||||
// tweak various session creation options.
|
||||
type Option func(*sessionOptions)
|
||||
|
||||
// WithPrivacy can be used to enable the privacy mapper for this session.
|
||||
// An optional set of privacy flags can be provided to further customize the
|
||||
// privacy mapper.
|
||||
func WithPrivacy(flags PrivacyFlags) Option {
|
||||
return func(o *sessionOptions) {
|
||||
o.privacy = true
|
||||
o.privacyFlags = flags
|
||||
}
|
||||
}
|
||||
|
||||
// WithFeatureConfig can be used to set the feature configuration bytes for
|
||||
// this session.
|
||||
func WithFeatureConfig(config FeaturesConfig) Option {
|
||||
return func(o *sessionOptions) {
|
||||
o.featureConfig = config
|
||||
}
|
||||
}
|
||||
|
||||
// WithLinkedGroupID can be used to link this session to a previous session.
|
||||
func WithLinkedGroupID(groupID *ID) Option {
|
||||
return func(o *sessionOptions) {
|
||||
o.linkedGroupID = groupID
|
||||
}
|
||||
}
|
||||
|
||||
// WithDevServer can be used to set if TLS verification should be skipped when
|
||||
// connecting to the mailbox server.
|
||||
func WithDevServer() Option {
|
||||
return func(o *sessionOptions) {
|
||||
o.devServer = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithMacaroonRecipe can be used to set the permissions and caveats that
|
||||
// should be used to bake the macaroon for a session.
|
||||
func WithMacaroonRecipe(caveats []macaroon.Caveat, perms []bakery.Op) Option {
|
||||
return func(o *sessionOptions) {
|
||||
o.macaroonRecipe = &MacaroonRecipe{
|
||||
Permissions: perms,
|
||||
Caveats: caveats,
|
||||
}
|
||||
}
|
||||
|
||||
if len(featureConfig) != 0 {
|
||||
sess.FeatureConfig = &featureConfig
|
||||
}
|
||||
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// IDToGroupIndex defines an interface for the session ID to group ID index.
|
||||
|
|
@ -191,9 +274,7 @@ type Store interface {
|
|||
// parameters. The session will remain in the StateReserved state until
|
||||
// ShiftState is called to update the state.
|
||||
NewSession(label string, typ Type, expiry time.Time, serverAddr string,
|
||||
devServer bool, perms []bakery.Op, caveats []macaroon.Caveat,
|
||||
featureConfig FeaturesConfig, privacy bool, linkedGroupID *ID,
|
||||
flags PrivacyFlags) (*Session, error)
|
||||
opts ...Option) (*Session, error)
|
||||
|
||||
// GetSession fetches the session with the given key.
|
||||
GetSession(key *btcec.PublicKey) (*Session, error)
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ import (
|
|||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"go.etcd.io/bbolt"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -188,9 +186,7 @@ func getSessionKey(session *Session) []byte {
|
|||
//
|
||||
// NOTE: this is part of the Store interface.
|
||||
func (db *BoltStore) NewSession(label string, typ Type, expiry time.Time,
|
||||
serverAddr string, devServer bool, perms []bakery.Op,
|
||||
caveats []macaroon.Caveat, featureConfig FeaturesConfig, privacy bool,
|
||||
linkedGroupID *ID, flags PrivacyFlags) (*Session, error) {
|
||||
serverAddr string, opts ...Option) (*Session, error) {
|
||||
|
||||
var session *Session
|
||||
err := db.Update(func(tx *bbolt.Tx) error {
|
||||
|
|
@ -206,8 +202,7 @@ func (db *BoltStore) NewSession(label string, typ Type, expiry time.Time,
|
|||
|
||||
session, err = buildSession(
|
||||
id, localPrivKey, label, typ, db.clock.Now(), expiry,
|
||||
serverAddr, devServer, perms, caveats, featureConfig,
|
||||
privacy, linkedGroupID, flags,
|
||||
serverAddr, opts...,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -374,8 +374,10 @@ func reserveSession(db Store, label string,
|
|||
|
||||
return db.NewSession(label, opts.sessType,
|
||||
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
"foo.bar.baz:1234", true, nil, nil, nil, true, opts.groupID,
|
||||
[]PrivacyFlag{ClearPubkeys},
|
||||
"foo.bar.baz:1234",
|
||||
WithDevServer(),
|
||||
WithPrivacy(PrivacyFlags{ClearPubkeys}),
|
||||
WithLinkedGroupID(opts.groupID),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,10 +133,12 @@ func TestSerializeDeserializeSession(t *testing.T) {
|
|||
id, priv, test.name, test.sessType,
|
||||
time.Now(),
|
||||
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
"foo.bar.baz:1234", true, test.perms,
|
||||
test.caveats, test.featureConfig, true,
|
||||
test.linkedGroupID,
|
||||
[]PrivacyFlag{ClearPubkeys},
|
||||
"foo.bar.baz:1234",
|
||||
WithDevServer(),
|
||||
WithPrivacy(PrivacyFlags{ClearPubkeys}),
|
||||
WithMacaroonRecipe(test.caveats, test.perms),
|
||||
WithFeatureConfig(test.featureConfig),
|
||||
WithLinkedGroupID(test.linkedGroupID),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
@ -188,8 +190,8 @@ func TestGroupIDForOlderSessions(t *testing.T) {
|
|||
id, priv, "test-session", TypeMacaroonAdmin,
|
||||
time.Now(),
|
||||
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
"foo.bar.baz:1234", true, nil, nil, nil, false, nil,
|
||||
PrivacyFlags{},
|
||||
"foo.bar.baz:1234",
|
||||
WithDevServer(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
@ -224,8 +226,8 @@ func TestGroupID(t *testing.T) {
|
|||
id, priv, "test-session", TypeMacaroonAdmin,
|
||||
time.Now(),
|
||||
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
"foo.bar.baz:1234", true, nil, nil, nil, false, nil,
|
||||
PrivacyFlags{},
|
||||
"foo.bar.baz:1234",
|
||||
WithDevServer(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
@ -239,8 +241,9 @@ func TestGroupID(t *testing.T) {
|
|||
id, priv, "test-session", TypeMacaroonAdmin,
|
||||
time.Now(),
|
||||
time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
"foo.bar.baz:1234", true, nil, nil, nil, false,
|
||||
&session1.GroupID, PrivacyFlags{},
|
||||
"foo.bar.baz:1234",
|
||||
WithLinkedGroupID(&session1.ID),
|
||||
WithDevServer(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
|||
|
|
@ -308,10 +308,16 @@ func (s *sessionRpcServer) AddSession(ctx context.Context,
|
|||
}
|
||||
}
|
||||
|
||||
sessOpts := []session.Option{
|
||||
session.WithMacaroonRecipe(caveats, uniquePermissions),
|
||||
}
|
||||
|
||||
if req.DevServer {
|
||||
sessOpts = append(sessOpts, session.WithDevServer())
|
||||
}
|
||||
|
||||
sess, err := s.cfg.db.NewSession(
|
||||
req.Label, typ, expiry, req.MailboxServerAddr,
|
||||
req.DevServer, uniquePermissions, caveats, nil, false, nil,
|
||||
session.PrivacyFlags{},
|
||||
req.Label, typ, expiry, req.MailboxServerAddr, sessOpts...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating new session: %v", err)
|
||||
|
|
@ -1125,10 +1131,25 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
|
|||
caveats = append(caveats, firewall.MetaPrivacyCaveat)
|
||||
}
|
||||
|
||||
// Construct the functional options that will be used to create the
|
||||
// session.
|
||||
sessOpts := []session.Option{
|
||||
session.WithMacaroonRecipe(caveats, perms),
|
||||
session.WithFeatureConfig(clientConfig),
|
||||
session.WithLinkedGroupID(linkedGroupID),
|
||||
}
|
||||
|
||||
if req.DevServer {
|
||||
sessOpts = append(sessOpts, session.WithDevServer())
|
||||
}
|
||||
|
||||
if privacy {
|
||||
sessOpts = append(sessOpts, session.WithPrivacy(privacyFlags))
|
||||
}
|
||||
|
||||
sess, err := s.cfg.db.NewSession(
|
||||
req.Label, session.TypeAutopilot, expiry,
|
||||
req.MailboxServerAddr, req.DevServer, perms, caveats,
|
||||
clientConfig, privacy, linkedGroupID, privacyFlags,
|
||||
req.Label, session.TypeAutopilot, expiry, req.MailboxServerAddr,
|
||||
sessOpts...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating new session: %v", err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue