Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/localstack/lstk/internal/auth"
"github.com/localstack/lstk/internal/env"
"github.com/localstack/lstk/internal/log"
"github.com/localstack/lstk/internal/output"
"github.com/localstack/lstk/internal/telemetry"
"github.com/localstack/lstk/internal/ui"
"github.com/localstack/lstk/internal/version"
Expand All @@ -23,14 +24,20 @@ func newLoginCmd(cfg *env.Env, tel *telemetry.Client, logger log.Logger) *cobra.
if !isInteractiveMode(cfg) {
return fmt.Errorf("login requires an interactive terminal")
}
tokenStorage, err := auth.NewTokenStorage(cfg.ForceFileKeyring, logger)
if err != nil {
return fmt.Errorf("failed to initialize token storage: %w", err)
}
storedToken, _ := tokenStorage.GetAuthToken()
if cfg.AuthToken != "" || storedToken != "" {
return ui.RunMessage(cmd.Context(), output.MessageEvent{Severity: output.SeverityNote, Text: "You're already logged in"})
}
platformClient := api.NewPlatformClient(cfg.APIEndpoint, logger)
if err := ui.RunLogin(cmd.Context(), version.Version(), platformClient, cfg.AuthToken, cfg.ForceFileKeyring, cfg.WebAppURL, logger); err != nil {
return err
}
if tokenStorage, err := auth.NewTokenStorage(cfg.ForceFileKeyring, logger); err == nil {
if token, err := tokenStorage.GetAuthToken(); err == nil && token != "" {
tel.SetAuthToken(token)
}
if token, err := tokenStorage.GetAuthToken(); err == nil && token != "" {
tel.SetAuthToken(token)
}
return nil
},
Expand Down
7 changes: 7 additions & 0 deletions internal/ui/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ func Run(parentCtx context.Context, runOpts RunOptions) error {
return nil
}

func RunMessage(parentCtx context.Context, event output.MessageEvent) error {
return runWithTUI(parentCtx, withoutHeader(), func(ctx context.Context, sink output.Sink) error {
sink.Emit(event)
return nil
})
}

func IsInteractive() bool {
return term.IsTerminal(int(os.Stdout.Fd())) && term.IsTerminal(int(os.Stdin.Fd()))
}
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/styles/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var (
Foreground(lipgloss.Color(SuccessColor))

Note = lipgloss.NewStyle().
Foreground(lipgloss.Color("33"))
Foreground(lipgloss.Color("69"))

Warning = lipgloss.NewStyle().
Foreground(lipgloss.Color("214"))
Expand Down
39 changes: 39 additions & 0 deletions test/integration/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"io"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
"time"
Expand Down Expand Up @@ -194,3 +196,40 @@ func TestDeviceFlowFailure_RequestNotConfirmed(t *testing.T) {
assert.Error(t, err, "no token should be stored when login fails")
assertCommandTelemetry(t, events, "login", 1)
}

func TestLoginShortCircuitsWhenEnvTokenSet(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("PTY not supported on Windows")
}
t.Parallel()

environ := append(testEnvWithHome(t.TempDir(), ""), string(env.AuthToken)+"=fake-env-token")

out, err := runLstkInPTY(t, testContext(t), environ, "login")
require.NoError(t, err, "login should succeed when env token is set: %s", out)
requireExitCode(t, 0, err)
assert.Contains(t, out, "You're already logged in")
assert.NotContains(t, out, "Opening browser")
assert.NotContains(t, out, "Waiting for authorization")
}

func TestLoginShortCircuitsWhenStoredTokenExists(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("PTY not supported on Windows")
}
t.Parallel()

tmpHome := t.TempDir()
tokenDir := filepath.Join(tmpHome, ".config", "lstk")
require.NoError(t, os.MkdirAll(tokenDir, 0700))
require.NoError(t, os.WriteFile(filepath.Join(tokenDir, "auth-token"), []byte("stored-token"), 0600))

environ := env.Environ(testEnvWithHome(tmpHome, "")).Without(env.AuthToken)

out, err := runLstkInPTY(t, testContext(t), environ, "login")
require.NoError(t, err, "login should succeed when stored token exists: %s", out)
requireExitCode(t, 0, err)
assert.Contains(t, out, "You're already logged in")
assert.NotContains(t, out, "Opening browser")
assert.NotContains(t, out, "Waiting for authorization")
}
Loading