Drop legacy token-only accounts when loading config

This commit is contained in:
CJACK.
2026-03-21 15:01:16 +08:00
parent ca08bb66b9
commit ee88a74dcf
4 changed files with 42 additions and 2 deletions

View File

@@ -194,7 +194,7 @@ func TestPoolAccountConcurrencyAliasEnv(t *testing.T) {
}
}
func TestPoolSkipsTokenOnlyAccount(t *testing.T) {
func TestPoolDropsLegacyTokenOnlyAccountOnLoad(t *testing.T) {
t.Setenv("DS2API_ACCOUNT_MAX_INFLIGHT", "1")
t.Setenv("DS2API_CONFIG_JSON", `{
"keys":["k1"],
@@ -203,7 +203,7 @@ func TestPoolSkipsTokenOnlyAccount(t *testing.T) {
pool := NewPool(config.LoadStore())
status := pool.Status()
if got, ok := status["total"].(int); !ok || got != 1 {
if got, ok := status["total"].(int); !ok || got != 0 {
t.Fatalf("unexpected total in pool status: %#v", status["total"])
}
if got, ok := status["available"].(int); !ok || got != 0 {

View File

@@ -35,6 +35,23 @@ func (c *Config) ClearAccountTokens() {
}
}
// DropInvalidAccounts removes accounts that cannot be addressed by admin APIs
// (no email and no normalizable mobile). This prevents legacy token-only
// records from becoming orphaned empty entries after token stripping.
func (c *Config) DropInvalidAccounts() {
if c == nil || len(c.Accounts) == 0 {
return
}
kept := make([]Account, 0, len(c.Accounts))
for _, acc := range c.Accounts {
if acc.Identifier() == "" {
continue
}
kept = append(kept, acc)
}
c.Accounts = kept
}
type CompatConfig struct {
WideInputStrictOutput *bool `json:"wide_input_strict_output,omitempty"`
}

View File

@@ -29,6 +29,27 @@ func TestLoadStoreClearsTokensFromConfigInput(t *testing.T) {
}
}
func TestLoadStoreDropsLegacyTokenOnlyAccounts(t *testing.T) {
t.Setenv("DS2API_CONFIG_JSON", `{
"accounts":[
{"token":"legacy-token-only"},
{"email":"u@example.com","password":"p","token":"runtime-token"}
]
}`)
store := LoadStore()
accounts := store.Accounts()
if len(accounts) != 1 {
t.Fatalf("expected token-only account to be dropped, got %d accounts", len(accounts))
}
if accounts[0].Identifier() != "u@example.com" {
t.Fatalf("unexpected remaining account: %#v", accounts[0])
}
if accounts[0].Token != "" {
t.Fatalf("expected persisted token to be cleared, got %q", accounts[0].Token)
}
}
func TestStoreUpdateAccountTokenKeepsIdentifierResolvable(t *testing.T) {
t.Setenv("DS2API_CONFIG_JSON", `{
"accounts":[{"email":"user@example.com","password":"p"}]

View File

@@ -40,6 +40,7 @@ func loadConfig() (Config, bool, error) {
if rawCfg != "" {
cfg, err := parseConfigString(rawCfg)
cfg.ClearAccountTokens()
cfg.DropInvalidAccounts()
return cfg, true, err
}
@@ -57,6 +58,7 @@ func loadConfig() (Config, bool, error) {
return Config{}, false, err
}
cfg.ClearAccountTokens()
cfg.DropInvalidAccounts()
if IsVercel() {
// Vercel filesystem is ephemeral/read-only for runtime writes; avoid save errors.
return cfg, true, nil