Переиспользовать каталог полей конфигурации ИИ и покрыть битый шифротекст
ci / build-test (pull_request) Successful in 2m49s

This commit is contained in:
2026-09-15 22:09:17 +03:00
parent ea4ed73327
commit 09358f07f2
2 changed files with 17 additions and 7 deletions
@@ -27,11 +27,8 @@ public sealed class AiGlobalConfigService(IGlobalSettingsStore store, ISecretCip
// задаёт оператор (остальным облачным адрес фиксирован каталогом, SSRF-гейт).
private const string CustomProviderId = "custom";
// Ключи JSON значения aiConfig (camelCase, как пишет SaveAsync).
// Ключ JSON значения aiConfig с id провайдера (остальные поля — SettingsFieldKeys).
private const string ProviderIdProperty = "providerId";
private const string ApiKeyProperty = "apiKey";
private const string BaseUrlProperty = "baseUrl";
private const string ModelProperty = "model";
// Геометрия маски секрета: короткий (≤8) → «x…»; иначе «1234…5678».
private const int MaskShortMaxLength = 8;
@@ -81,19 +78,19 @@ public sealed class AiGlobalConfigService(IGlobalSettingsStore store, ISecretCip
return EmptySnapshot();
}
string baseUrl = ReadString(root, BaseUrlProperty);
string baseUrl = ReadString(root, SettingsFieldKeys.BaseUrl);
if (baseUrl.Length == 0 || !IsBaseUrlMutable(meta))
{
baseUrl = meta.Base;
}
string model = ReadString(root, ModelProperty);
string model = ReadString(root, SettingsFieldKeys.Model);
if (model.Length == 0)
{
model = meta.Models.FirstOrDefault() ?? string.Empty;
}
string apiKey = cipher.Decrypt(ReadString(root, ApiKeyProperty));
string apiKey = cipher.Decrypt(ReadString(root, SettingsFieldKeys.ApiKey));
return new AiGlobalConfigSnapshot(providerId, baseUrl, model, apiKey);
}
catch (JsonException)
@@ -116,6 +116,19 @@ public sealed class AiGlobalConfigServiceTests
Assert.False(snapshot.Configured);
}
[Fact]
public async Task GetSnapshotAsync_BrokenCiphertext_LeavesKeyEmptyWithoutThrowing()
{
_store.Preload(
GlobalSettingsKeys.AiConfig,
"{\"providerId\":\"deepseek\",\"baseUrl\":\"\",\"model\":\"\",\"apiKey\":\"enc:не-base64!\"}");
AiGlobalConfigSnapshot snapshot = await _service.GetSnapshotAsync(CancellationToken.None);
Assert.Equal(string.Empty, snapshot.ApiKey);
Assert.False(snapshot.Configured);
}
[Theory]
[InlineData("sk-operator-key-123", true)]
[InlineData("sk-1…-123", false)] // маска из снимка