fix(accounts): удаление аккаунта рапортовало успех, ничего не удаляя
Владелец подключил не тот аккаунт Grok и не смог его убрать: «кнопка не функционирует». Хуже: действие возвращало ok=True с сообщением об успехе, а профиль оставался авторизованным. Причина: сигнатура get_profile_dir — (profile_id, provider), а do_delete_credentials звала её наоборот. Внутри функции есть костыль, молча исправляющий перестановку, но только для трёх провайдеров: antigravity, openai-codex, opencode-go. Для grok, claude и local путь получался неверным (grok_profiles/grok вместо grok_profiles/grok-worker-1), файл «не находился», и срабатывала ветка «учетные данные отсутствовали» с ok=True. То есть удаление работало у трёх провайдеров из шести, а у остальных молча лгало. Теперь используется get_profile_auth_path, который берёт аргументы в правильном порядке. Отсутствие файла больше не считается успехом удаления: возвращается честный отказ «удалять нечего». Проверено на живом профиле: до — авторизован, после удаления — нет, повторная попытка сообщает, что удалять нечего. Тест покрывает все четыре провайдера, у которых костыль не срабатывал. Тесты: 419 passed, ruff чисто. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
0be0a58a5d
commit
d755a07903
2 changed files with 68 additions and 2 deletions
|
|
@ -103,7 +103,15 @@ def do_test_profile(provider: str, profile_id: str) -> Dict[str, Any]:
|
|||
return {'success': False, 'model': model, 'duration_sec': round(time.time() - t0, 2), 'error': str(e)}
|
||||
|
||||
def do_delete_credentials(provider: str, profile_id: str) -> Tuple[bool, str]:
|
||||
auth_p = ProfileAuthManager.get_profile_dir(provider, profile_id) / 'auth.json'
|
||||
# Сигнатура get_profile_dir — (profile_id, provider), а здесь её звали
|
||||
# наоборот. Внутри есть костыль, молча исправляющий перестановку, но только
|
||||
# для antigravity, openai-codex и opencode-go. Для grok, claude и local путь
|
||||
# получался неверным, файл «не находился», и кнопка удаления РАПОРТОВАЛА
|
||||
# УСПЕХ, ничего не удалив. Используем готовый помощник, который берёт
|
||||
# аргументы в правильном порядке.
|
||||
from antigravity_provider.router.profile_manager import get_profile_auth_path
|
||||
|
||||
auth_p = get_profile_auth_path(provider, profile_id)
|
||||
if auth_p.is_file():
|
||||
try:
|
||||
auth_p.unlink()
|
||||
|
|
@ -111,7 +119,9 @@ def do_delete_credentials(provider: str, profile_id: str) -> Tuple[bool, str]:
|
|||
return True, f"Учетные данные для '{profile_id}' удалены"
|
||||
except Exception as e:
|
||||
return False, f'Ошибка удаления: {e}'
|
||||
return True, 'Учетные данные отсутствовали'
|
||||
# Отсутствие файла — это не успех удаления. Раньше такой ответ выглядел
|
||||
# для пользователя как «сработало», хотя аккаунт оставался подключённым.
|
||||
return False, f"Учетных данных для '{profile_id}' не найдено — удалять нечего"
|
||||
|
||||
def do_save_settings(settings: Dict[str, Any]) -> Tuple[bool, str]:
|
||||
settings_file = paths.get_hermes_home() / "hub_settings.json"
|
||||
|
|
|
|||
56
tests/test_delete_credentials.py
Normal file
56
tests/test_delete_credentials.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
"""Кнопка удаления обязана удалять — и говорить правду, если удалять нечего.
|
||||
|
||||
Владелец подключил не тот аккаунт Grok и не смог его убрать: «кнопка не
|
||||
функционирует». Хуже — действие возвращало ok=True с сообщением об
|
||||
успехе, а профиль оставался авторизованным.
|
||||
|
||||
Причина: сигнатура get_profile_dir — (profile_id, provider), а
|
||||
do_delete_credentials звала её наоборот. Внутри есть костыль, молча
|
||||
исправляющий перестановку, но только для antigravity, openai-codex и
|
||||
opencode-go. Для grok, claude и local путь получался неверным, файл «не
|
||||
находился», и удаление рапортовало успех, ничего не сделав.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from antigravity_provider.router.action_handler import do_delete_credentials
|
||||
from antigravity_provider.router.profile_manager import get_profile_auth_path
|
||||
|
||||
|
||||
@pytest.mark.parametrize("provider,profile_id", [
|
||||
("grok", "grok-worker-2"),
|
||||
("claude", "claude-worker-1"),
|
||||
("local", "local-2"),
|
||||
("antigravity", "ag-spare-2"),
|
||||
])
|
||||
def test_delete_removes_credentials_for_every_provider(provider, profile_id, monkeypatch, tmp_path):
|
||||
"""Удаление обязано работать у всех провайдеров, а не у трёх из шести."""
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
|
||||
auth_path = get_profile_auth_path(provider, profile_id)
|
||||
auth_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
auth_path.write_text(json.dumps({"api_key": "secret"}), encoding="utf-8")
|
||||
assert auth_path.is_file()
|
||||
|
||||
ok, msg = do_delete_credentials(provider, profile_id)
|
||||
|
||||
assert ok, f"{provider}: удаление отчиталось об отказе — {msg}"
|
||||
assert not auth_path.is_file(), f"{provider}: файл остался на диске, а действие сообщило успех"
|
||||
|
||||
|
||||
def test_missing_credentials_reported_as_failure(monkeypatch, tmp_path):
|
||||
"""Отсутствие файла — не успех удаления.
|
||||
|
||||
Раньше такой ответ выглядел для пользователя как «сработало», хотя
|
||||
аккаунт оставался подключённым.
|
||||
"""
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
|
||||
ok, msg = do_delete_credentials("grok", "grok-worker-2")
|
||||
|
||||
assert ok is False
|
||||
assert "нечего" in msg or "не найдено" in msg
|
||||
Loading…
Reference in a new issue