auth: remove unused RemoveAllContexts · Entire

auth: remove unused RemoveAllContexts

74c24b2·

toothbrush·1mo ago·2 files·+0 added/-80 removed

Dead since logout --all was redefined to revoke server-side sessions rather than nuke all local contexts. Nothing else references it.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

7dc263eaaac8View transcript

Changes

2

61 unmodified lines

return nil
}

// RemoveAllContexts deletes every stored context and its keyring token — a
// full local logout. Returns the number of contexts removed. Best-effort on
the keyring deletes; the contexts.json clear is what makes the CLI fully
logged out.
func RemoveAllContexts() (int, error) {
    var removed int
    if err := contexts.Modify(contexts.DefaultConfigDir(), func(f *contexts.File) (bool, error) {
        if len(f.Contexts) == 0 && f.CurrentContext == "" {
            return false, nil
        }
        for _, c := range f.Contexts {
            if c.KeychainService != "" && c.Handle != "" {
                // Delete both slots: the access token and its paired refresh
                // token. Dropping the refresh slot is what actually scrubs the
                // machine — otherwise a leftover refresh token outlives logout.
                _ = tokenstore.Delete(c.KeychainService, c.Handle)                            //nolint:errcheck // best-effort; the contexts.json clear below is authoritative
                _ = tokenstore.Delete(tokenstore.RefreshService(c.KeychainService), c.Handle) //nolint:errcheck // best-effort; absent refresh slot is fine
            }
            removed++
        }
        f.Contexts = nil
        f.CurrentContext = ""
        return true, nil
    }); err != nil {
        return 0, fmt.Errorf("remove all contexts: %w", err)
    }
    return removed, nil
}

// SetCurrentContext makes name the active context. Returns an error when
// no context with that name exists (a stale current pointer is a foot-gun).
func SetCurrentContext(name string) error {

Mcmd/entire/cli/auth/context_store.go-29

268 unmodified lines

func TestRemoveAllContexts(t *testing.T) {
    cfgDir := t.TempDir()
    t.Setenv("ENTIRE_CONFIG_DIR", cfgDir)
    restore := tokenstore.UseFileBackendForTesting(filepath.Join(t.TempDir(), "tokens.json"))
    t.Cleanup(restore)

exp := time.Now().Add(time.Hour).Unix()
    if _, err := RecordLoginContext(makeJWT(t, fmt.Sprintf(`{"iss":"https://a.example.com","handle":"alice","exp":%d}`, exp)), "entr_a", true); err != nil {
        t.Fatalf("record a: %v", err)
    }
    if _, err := RecordLoginContext(makeJWT(t, fmt.Sprintf(`{"iss":"https://b.example.com","handle":"bob","exp":%d}`, exp)), "entr_b", true); err != nil {
        t.Fatalf("record b: %v", err)
    }
    n, err := RemoveAllContexts()
    if err != nil {
        t.Fatalf("RemoveAllContexts: %v", err)
    }
    if n != 2 {
        t.Fatalf("removed %d, want 2", n)
    }
    f, err := contexts.Load(cfgDir)
    if err != nil {
        t.Fatalf("load: %v", err)
    }
    if len(f.Contexts) != 0 || f.CurrentContext != "" {
        t.Fatalf("expected fully cleared, got contexts=%d current=%q", len(f.Contexts), f.CurrentContext)
    }
    // Every refresh slot must be gone too, for both removed contexts.
    for _, tc := range []struct{ iss, handle string }{
        {"https://a.example.com", "alice"},
        {"https://b.example.com", "bob"},
    } {
        svc := tokenstore.CoreKeyringService(tc.iss)
        if v, err := tokenstore.Get(svc, tc.handle); !errors.Is(err, tokenstore.ErrNotFound) {
            t.Fatalf("access slot for %s survived: value=%q err=%v", tc.handle, v, err)
        }
        if v, err := tokenstore.Get(tokenstore.RefreshService(svc), tc.handle); !errors.Is(err, tokenstore.ErrNotFound) {
            t.Fatalf("refresh slot for %s survived: value=%q err=%v", tc.handle, v, err)
        }
    }

// Idempotent.
    n2, err := RemoveAllContexts()
    if err != nil {
        t.Fatalf("second RemoveAllContexts: %v", err)
    }
    if n2 != 0 {
        t.Fatalf("second call removed %d, want 0", n2)
    }
}

func TestRemoveCurrentContext_DoesNotSwitchToAnother(t *testing.T) {
    cfgDir := t.TempDir()
    t.Setenv("ENTIRE_CONFIG_DIR", cfgDir)