connector: fix UserLogin lifecycle during provisioning
Bridge provisioning would crash because we wouldn't thread the necessary database models through.
This commit is contained in:
@@ -37,6 +37,7 @@ type DiscordClient struct {
|
||||
usersFromReady map[string]*discordgo.User
|
||||
UserLogin *bridgev2.UserLogin
|
||||
Session *discordgo.Session
|
||||
hasBegunSyncing bool
|
||||
}
|
||||
|
||||
func (d *DiscordConnector) LoadUserLogin(ctx context.Context, login *bridgev2.UserLogin) error {
|
||||
@@ -116,23 +117,6 @@ func (cl *DiscordClient) connect(ctx context.Context) error {
|
||||
user := cl.Session.State.User
|
||||
log.Info().Str("user_id", user.ID).Str("user_username", user.Username).Msg("Connected to Discord")
|
||||
|
||||
if cl.UserLogin != nil {
|
||||
// Feels a bit hacky to check for this here, but it should be true when
|
||||
// logging in initially. The UserLogin is only ever created if we know
|
||||
// that we connected successfully. We _do_ know that by now here, but we're
|
||||
// not tasked with creating the UserLogin; the login code is. Alas.
|
||||
|
||||
// FIXME(skip): Avatar.
|
||||
cl.UserLogin.RemoteProfile = status.RemoteProfile{
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
Name: user.String(),
|
||||
}
|
||||
if err := cl.UserLogin.Save(ctx); err != nil {
|
||||
log.Err(err).Msg("Couldn't save UserLogin after connecting")
|
||||
}
|
||||
}
|
||||
|
||||
// Stash all of the users we received in READY so we can perform quick lookups
|
||||
// keyed by user ID.
|
||||
cl.usersFromReady = make(map[string]*discordgo.User)
|
||||
@@ -140,7 +124,11 @@ func (cl *DiscordClient) connect(ctx context.Context) error {
|
||||
cl.usersFromReady[user.ID] = user
|
||||
}
|
||||
|
||||
go cl.syncChannels(ctx)
|
||||
// We won't have a UserLogin during provisioning, because the UserLogin can
|
||||
// only be properly constructed once we know what the Discord user ID is
|
||||
// (i.e. we have returned from this function). Thus, rely on the login
|
||||
// process calling this method manually.
|
||||
cl.BeginSyncingIfUserLoginPresent(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -160,6 +148,33 @@ func (d *DiscordClient) LogoutRemote(ctx context.Context) {
|
||||
d.Disconnect()
|
||||
}
|
||||
|
||||
func (cl *DiscordClient) BeginSyncingIfUserLoginPresent(ctx context.Context) {
|
||||
if cl.UserLogin == nil {
|
||||
cl.connector.bridge.Log.Warn().Msg("Not syncing just yet as we don't have a UserLogin")
|
||||
return
|
||||
}
|
||||
if cl.hasBegunSyncing {
|
||||
cl.connector.bridge.Log.Warn().Msg("Not beginning sync more than once")
|
||||
return
|
||||
}
|
||||
cl.hasBegunSyncing = true
|
||||
|
||||
log := cl.UserLogin.Log
|
||||
user := cl.Session.State.User
|
||||
|
||||
// FIXME(skip): Avatar.
|
||||
cl.UserLogin.RemoteProfile = status.RemoteProfile{
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
Name: user.String(),
|
||||
}
|
||||
if err := cl.UserLogin.Save(ctx); err != nil {
|
||||
log.Err(err).Msg("Couldn't save UserLogin after connecting")
|
||||
}
|
||||
|
||||
go cl.syncChannels(ctx)
|
||||
}
|
||||
|
||||
func (d *DiscordClient) syncChannels(ctx context.Context) {
|
||||
for _, dm := range d.Session.State.PrivateChannels {
|
||||
d.UserLogin.Log.Debug().Str("channel_id", dm.ID).Msg("Syncing private channel")
|
||||
|
||||
@@ -48,10 +48,11 @@ func (d *DiscordConnector) CreateLogin(ctx context.Context, user *bridgev2.User,
|
||||
return nil, fmt.Errorf("unknown login flow ID")
|
||||
}
|
||||
|
||||
return &DiscordLogin{User: user}, nil
|
||||
return &DiscordLogin{connector: d, User: user}, nil
|
||||
}
|
||||
|
||||
type DiscordLogin struct {
|
||||
connector *DiscordConnector
|
||||
User *bridgev2.User
|
||||
Token string
|
||||
Session *discordgo.Session
|
||||
@@ -104,6 +105,7 @@ func (dl *DiscordLogin) SubmitUserInput(ctx context.Context, input map[string]st
|
||||
}
|
||||
|
||||
client := DiscordClient{
|
||||
connector: dl.connector,
|
||||
Session: session,
|
||||
}
|
||||
err = client.connect(ctx)
|
||||
@@ -123,9 +125,14 @@ func (dl *DiscordLogin) SubmitUserInput(ctx context.Context, input map[string]st
|
||||
HeartbeatSession: session.HeartbeatSession,
|
||||
},
|
||||
}, &bridgev2.NewLoginParams{
|
||||
// We already have a Session; call this instead of the connector's main LoadUserLogin method and thread the Session through.
|
||||
// We already have a Session; let's call this instead of the connector's
|
||||
// main LoadUserLogin method, and thread the Session through.
|
||||
LoadUserLogin: func(ctx context.Context, login *bridgev2.UserLogin) error {
|
||||
login.Client = &client
|
||||
client.UserLogin = login
|
||||
|
||||
// Only now that we have a UserLogin can we begin syncing.
|
||||
client.BeginSyncingIfUserLoginPresent(ctx)
|
||||
return nil
|
||||
},
|
||||
DeleteOnConflict: true,
|
||||
|
||||
Reference in New Issue
Block a user