Переиспользовать каталог полей конфигурации ИИ и покрыть битый шифротекст
ci / build-test (pull_request) Successful in 2m49s
ci / build-test (pull_request) Successful in 2m49s
This commit is contained in:
@@ -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)] // маска из снимка
|
||||
|
||||
Reference in New Issue
Block a user