From ba9724e963c043dd2e65233bf486557d81dcec6c Mon Sep 17 00:00:00 2001 From: Garrett Date: Thu, 26 May 2022 22:59:32 +0000 Subject: [PATCH 1/3] fix: restore previous session on coder server --dev --- cli/server.go | 62 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/cli/server.go b/cli/server.go index ac6f49d5079a7..cfaade779fc42 100644 --- a/cli/server.go +++ b/cli/server.go @@ -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) + } + 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 + } + + // 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 From b9f2d96bf3b295775f644fdd547a94023c0d3232 Mon Sep 17 00:00:00 2001 From: Garrett Date: Thu, 26 May 2022 23:03:39 +0000 Subject: [PATCH 2/3] lint --- cli/server.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cli/server.go b/cli/server.go index cfaade779fc42..bd924b948406b 100644 --- a/cli/server.go +++ b/cli/server.go @@ -521,7 +521,7 @@ func server() *cobra.Command { // 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) { +func createFirstUser(logger slog.Logger, cmd *cobra.Command, client *codersdk.Client, cfg config.Root, email, password string) (func(), error) { if email == "" { return nil, xerrors.New("email is empty") } @@ -546,7 +546,7 @@ func createFirstUser(log slog.Logger, cmd *cobra.Command, client *codersdk.Clien } client.SessionToken = token.SessionToken - oldUrl, err := cfg.URL().Read() + oldURL, err := cfg.URL().Read() if err != nil { return nil, xerrors.Errorf("write local url: %w", err) } @@ -557,31 +557,31 @@ func createFirstUser(log slog.Logger, cmd *cobra.Command, client *codersdk.Clien // recover session data when server exits cleanup := func() { - currentUrl, err := cfg.URL().Read() + currentURL, err := cfg.URL().Read() if err != nil { - log.Error(cmd.Context(), "failed to read current session url", slog.Error(err)) + logger.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)) + logger.Error(cmd.Context(), "failed to read current session token", slog.Error(err)) return } // if it's changed since we wrote to it don't restore session - if currentUrl != client.URL.String() || + if currentURL != client.URL.String() || currentSession != token.SessionToken { return } - err = cfg.URL().Write(oldUrl) + err = cfg.URL().Write(oldURL) if err != nil { - log.Error(cmd.Context(), "failed to recover previous session url", slog.Error(err)) + logger.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)) + logger.Error(cmd.Context(), "failed to recover previous session token", slog.Error(err)) return } } From 71109e0d894f7592f13f4ece3deb829d8dc9dd13 Mon Sep 17 00:00:00 2001 From: Garrett Date: Fri, 27 May 2022 16:13:10 +0000 Subject: [PATCH 3/3] gracefully handle no session --- cli/server.go | 74 ++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/cli/server.go b/cli/server.go index bd924b948406b..48d7ee237a1ca 100644 --- a/cli/server.go +++ b/cli/server.go @@ -336,11 +336,11 @@ func server() *cobra.Command { return xerrors.Errorf("generate random admin password for dev: %w", err) } } - cleanupSession, err := createFirstUser(logger, cmd, client, config, devUserEmail, devUserPassword) + restorePreviousSession, err := createFirstUser(logger, cmd, client, config, devUserEmail, devUserPassword) if err != nil { return xerrors.Errorf("create first user: %w", err) } - defer cleanupSession() + defer restorePreviousSession() _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "email: %s\n", devUserEmail) _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "password: %s\n", devUserPassword) _, _ = fmt.Fprintln(cmd.ErrOrStderr()) @@ -520,7 +520,7 @@ func server() *cobra.Command { } // createFirstUser creates the first user and sets a valid session. -// Caller must call cleanup on server exit. +// Caller must call restorePreviousSession on server exit. func createFirstUser(logger slog.Logger, cmd *cobra.Command, client *codersdk.Client, cfg config.Root, email, password string) (func(), error) { if email == "" { return nil, xerrors.New("email is empty") @@ -546,43 +546,39 @@ func createFirstUser(logger slog.Logger, cmd *cobra.Command, client *codersdk.Cl } client.SessionToken = token.SessionToken - oldURL, err := cfg.URL().Read() - if err != nil { - return nil, xerrors.Errorf("write local url: %w", err) - } - 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 { - logger.Error(cmd.Context(), "failed to read current session url", slog.Error(err)) - return - } - currentSession, err := cfg.Session().Read() - if err != nil { - logger.Error(cmd.Context(), "failed to read current session token", slog.Error(err)) - return - } + // capture the current session and if exists recover session on server exit + restorePreviousSession := func() {} + oldURL, _ := cfg.URL().Read() + oldSession, _ := cfg.Session().Read() + if oldURL != "" && oldSession != "" { + restorePreviousSession = func() { + currentURL, err := cfg.URL().Read() + if err != nil { + logger.Error(cmd.Context(), "failed to read current session url", slog.Error(err)) + return + } + currentSession, err := cfg.Session().Read() + if err != nil { + logger.Error(cmd.Context(), "failed to read current session token", slog.Error(err)) + return + } - // if it's changed since we wrote to it don't restore session - if currentURL != client.URL.String() || - currentSession != token.SessionToken { - return - } + // 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 { - logger.Error(cmd.Context(), "failed to recover previous session url", slog.Error(err)) - return - } - err = cfg.Session().Write(oldSession) - if err != nil { - logger.Error(cmd.Context(), "failed to recover previous session token", slog.Error(err)) - return + err = cfg.URL().Write(oldURL) + if err != nil { + logger.Error(cmd.Context(), "failed to recover previous session url", slog.Error(err)) + return + } + err = cfg.Session().Write(oldSession) + if err != nil { + logger.Error(cmd.Context(), "failed to recover previous session token", slog.Error(err)) + return + } } } @@ -595,7 +591,7 @@ func createFirstUser(logger slog.Logger, cmd *cobra.Command, client *codersdk.Cl return nil, xerrors.Errorf("write session token: %w", err) } - return cleanup, nil + return restorePreviousSession, nil } // nolint:revive