diff --git a/internal/cmd/auth_accounts.go b/internal/cmd/auth_accounts.go index 420f6dd5..0b95efbc 100644 --- a/internal/cmd/auth_accounts.go +++ b/internal/cmd/auth_accounts.go @@ -381,6 +381,22 @@ func (c *AuthRemoveCmd) Run(ctx context.Context, flags *RootFlags) error { if err := store.DeleteToken(client, email); err != nil { return err } + + // Clean up config.json: remove aliases pointing to this email and the + // account-client entry for this email. + if updateErr := config.UpdateConfig(func(cfg *config.File) error { + for alias, target := range cfg.AccountAliases { + if strings.EqualFold(target, email) { + delete(cfg.AccountAliases, alias) + } + } + delete(cfg.AccountClients, email) + delete(cfg.AccountClients, strings.ToLower(email)) + return nil + }); updateErr != nil { + return updateErr + } + return writeResult(ctx, u, kv("deleted", true), kv("email", email), diff --git a/internal/cmd/auth_cmd_test.go b/internal/cmd/auth_cmd_test.go index 74355e0c..9f398cf2 100644 --- a/internal/cmd/auth_cmd_test.go +++ b/internal/cmd/auth_cmd_test.go @@ -490,3 +490,60 @@ func TestAuthListRemoveTokensListDelete_JSON(t *testing.T) { t.Fatalf("expected empty keys, got: %#v", emptyKeysResp.Keys) } } + +func TestAuthRemove_CleansUpConfig(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, "xdg-config")) + t.Setenv("GOG_KEYRING_BACKEND", "file") + + origOpen := openSecretsStore + t.Cleanup(func() { openSecretsStore = origOpen }) + + store := newMemSecretsStore() + _ = store.SetToken("custom-client", "remove@example.com", secrets.Token{RefreshToken: "rt-remove"}) + openSecretsStore = func() (secrets.Store, error) { return store, nil } + + // Write config with alias and client entries for the email we will remove. + cfg := config.File{ + AccountAliases: map[string]string{ + "work": "remove@example.com", + "keep": "other@example.com", + }, + AccountClients: map[string]string{ + "remove@example.com": "custom-client", + "other@example.com": "default", + }, + } + if err := config.WriteConfig(cfg); err != nil { + t.Fatalf("WriteConfig: %v", err) + } + + // Run auth remove. + _ = captureStdout(t, func() { + _ = captureStderr(t, func() { + if err := Execute([]string{"--json", "--force", "auth", "remove", "remove@example.com"}); err != nil { + t.Fatalf("Execute remove: %v", err) + } + }) + }) + + // Verify config was cleaned up. + updated, err := config.ReadConfig() + if err != nil { + t.Fatalf("ReadConfig: %v", err) + } + + if _, ok := updated.AccountAliases["work"]; ok { + t.Fatalf("expected alias 'work' to be removed, but it still exists") + } + if v, ok := updated.AccountAliases["keep"]; !ok || v != "other@example.com" { + t.Fatalf("expected alias 'keep' to be preserved, got: %v", updated.AccountAliases) + } + if _, ok := updated.AccountClients["remove@example.com"]; ok { + t.Fatalf("expected account_clients entry for remove@example.com to be removed") + } + if v, ok := updated.AccountClients["other@example.com"]; !ok || v != "default" { + t.Fatalf("expected account_clients entry for other@example.com to be preserved, got: %v", updated.AccountClients) + } +}