fix(admin): не блокировать сохранение настроек недоступным уровнем AI
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled

Валидация ai_level срабатывала на любой PUT /admin/settings, включая
случаи, когда фронт отправлял уже сохранённый (не изменённый) уровень —
на слабом железе это намертво блокировало правку любых других настроек.
Бэкенд теперь сравнивает patch.ai_level с текущим значением и проверяет
доступность только при фактической смене уровня; фронт дополнительно
отправляет в PUT только реально изменённые поля.
This commit is contained in:
2026-07-27 20:25:31 +03:00
parent 4b92f89efe
commit e55a6aebe7
3 changed files with 88 additions and 13 deletions

View File

@@ -478,6 +478,52 @@ async def test_update_rejects_unavailable_ai_level(
assert cfg.ai_level == "min"
async def test_update_unrelated_setting_passes_when_current_ai_level_unavailable(
db_session: AsyncSession, clean_instance_settings: None
) -> None:
"""Баг: фронт всегда отправляет текущий `ai_level` вместе с любой другой
правкой (см. `AdminSettingsTab.handleSave`) — если уже сохранённый
уровень стал недоступен (слабое железо/модель не докачана), это не
должно блокировать сохранение несвязанной настройки. Валидация нужна
только при фактической смене уровня (см. docstring `update`)."""
service = InstanceSettingsService(db_session)
await service.ensure_bootstrapped(PLUGINS_YAML)
stmt = (
pg_insert(InstanceSetting)
.values(key="ai_level", value={"level": "medium"})
.on_conflict_do_update(index_elements=["key"], set_={"value": {"level": "medium"}})
)
await db_session.execute(stmt)
await db_session.commit()
assert not detect_ai_levels(await service.get())[1].available # "medium" недоступен
# ai_level в патче совпадает с уже сохранённым — не должно проверяться.
cfg = await service.update(
SettingsUpdateIn(ai_level="medium", registration_team_choice=True)
)
assert cfg.ai_level == "medium"
assert cfg.registration_team_choice is True
async def test_update_still_rejects_switching_to_unavailable_ai_level(
db_session: AsyncSession, clean_instance_settings: None
) -> None:
"""Фактическая попытка ПЕРЕКЛЮЧИТЬ уровень на недоступный по-прежнему
отклоняется — даже если AI (транскрибация/суммаризация) выключен: иначе
администратор молча сохранит нерабочую конфигурацию, которая проявится
только при последующем включении AI."""
service = InstanceSettingsService(db_session)
await service.ensure_bootstrapped(PLUGINS_YAML)
await service.update(SettingsUpdateIn(transcription_enabled=False))
with pytest.raises(InvalidAiLevelError):
await service.update(SettingsUpdateIn(ai_level="medium"))
cfg = await service.get()
assert cfg.ai_level == "min"
async def test_update_rejects_invalid_timezone(
db_session: AsyncSession, clean_instance_settings: None
) -> None: