-
Notifications
You must be signed in to change notification settings - Fork 894
fix: restore previous session on coder server --dev #1821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -336,10 +336,11 @@ func server() *cobra.Command { | |
return xerrors.Errorf("generate random admin password for dev: %w", err) | ||
} | ||
} | ||
err = createFirstUser(cmd, client, config, devUserEmail, devUserPassword) | ||
cleanupSession, err := createFirstUser(logger, cmd, client, config, devUserEmail, devUserPassword) | ||
if err != nil { | ||
return xerrors.Errorf("create first user: %w", err) | ||
} | ||
defer cleanupSession() | ||
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "email: %s\n", devUserEmail) | ||
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "password: %s\n", devUserPassword) | ||
_, _ = fmt.Fprintln(cmd.ErrOrStderr()) | ||
|
@@ -518,12 +519,14 @@ func server() *cobra.Command { | |
return root | ||
} | ||
|
||
func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Root, email, password string) error { | ||
// createFirstUser creates the first user and sets a valid session. | ||
// Caller must call cleanup on server exit. | ||
func createFirstUser(log slog.Logger, cmd *cobra.Command, client *codersdk.Client, cfg config.Root, email, password string) (func(), error) { | ||
if email == "" { | ||
return xerrors.New("email is empty") | ||
return nil, xerrors.New("email is empty") | ||
} | ||
if password == "" { | ||
return xerrors.New("password is empty") | ||
return nil, xerrors.New("password is empty") | ||
} | ||
_, err := client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{ | ||
Email: email, | ||
|
@@ -532,26 +535,67 @@ func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Roo | |
OrganizationName: "acme-corp", | ||
}) | ||
if err != nil { | ||
return xerrors.Errorf("create first user: %w", err) | ||
return nil, xerrors.Errorf("create first user: %w", err) | ||
} | ||
token, err := client.LoginWithPassword(cmd.Context(), codersdk.LoginWithPasswordRequest{ | ||
Email: email, | ||
Password: password, | ||
}) | ||
if err != nil { | ||
return xerrors.Errorf("login with first user: %w", err) | ||
return nil, xerrors.Errorf("login with first user: %w", err) | ||
} | ||
client.SessionToken = token.SessionToken | ||
|
||
oldUrl, err := cfg.URL().Read() | ||
if err != nil { | ||
return nil, xerrors.Errorf("write local url: %w", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would fail if an old session didn't exist, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
} | ||
oldSession, err := cfg.Session().Read() | ||
if err != nil { | ||
return nil, xerrors.Errorf("write session token: %w", err) | ||
} | ||
|
||
// recover session data when server exits | ||
cleanup := func() { | ||
currentUrl, err := cfg.URL().Read() | ||
if err != nil { | ||
log.Error(cmd.Context(), "failed to read current session url", slog.Error(err)) | ||
return | ||
} | ||
currentSession, err := cfg.Session().Read() | ||
if err != nil { | ||
log.Error(cmd.Context(), "failed to read current session token", slog.Error(err)) | ||
return | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought: Do we need to consider cases where the user has tried the logout flow or ran Being able to restore on startup would also cover cases where the server is killed instead of graciously exited. I'm probably overthinking this though, this change alone should help alleviate the most common cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think as a first pass I'd rather not try to guess, because I could see devs spending quite a while trying to figure out what's wrong before they realize it's the session. Currently if it's different that we would expect we just choose "do nothing", and I'm down to add more logic here as we use it and run into cases. |
||
|
||
// if it's changed since we wrote to it don't restore session | ||
if currentUrl != client.URL.String() || | ||
currentSession != token.SessionToken { | ||
return | ||
} | ||
|
||
err = cfg.URL().Write(oldUrl) | ||
if err != nil { | ||
log.Error(cmd.Context(), "failed to recover previous session url", slog.Error(err)) | ||
return | ||
} | ||
err = cfg.Session().Write(oldSession) | ||
if err != nil { | ||
log.Error(cmd.Context(), "failed to recover previous session token", slog.Error(err)) | ||
return | ||
} | ||
} | ||
|
||
err = cfg.URL().Write(client.URL.String()) | ||
if err != nil { | ||
return xerrors.Errorf("write local url: %w", err) | ||
return nil, xerrors.Errorf("write local url: %w", err) | ||
} | ||
err = cfg.Session().Write(token.SessionToken) | ||
if err != nil { | ||
return xerrors.Errorf("write session token: %w", err) | ||
return nil, xerrors.Errorf("write session token: %w", err) | ||
} | ||
return nil | ||
|
||
return cleanup, nil | ||
} | ||
|
||
// nolint:revive | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Would
restore
/restorePreviousSession
be more descriptive here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done