feat: 初始功能
This commit is contained in:
138
Services/JsonSettingsService.cs
Normal file
138
Services/JsonSettingsService.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using CloudPrint.Client.Models;
|
||||
using CloudPrint.Client.Services.Abstractions;
|
||||
|
||||
namespace CloudPrint.Client.Services;
|
||||
|
||||
public sealed class JsonSettingsService : ISettingsService
|
||||
{
|
||||
private static readonly JsonSerializerOptions SerializerOptions = new()
|
||||
{
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
private readonly string _settingsPath;
|
||||
private readonly ISecretProtector _secretProtector;
|
||||
|
||||
public JsonSettingsService()
|
||||
: this(new DpapiSecretProtector())
|
||||
{
|
||||
}
|
||||
|
||||
public JsonSettingsService(ISecretProtector secretProtector)
|
||||
: this(secretProtector, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CloudPrint.Client", "settings.json"))
|
||||
{
|
||||
}
|
||||
|
||||
public JsonSettingsService(ISecretProtector secretProtector, string settingsPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(settingsPath))
|
||||
{
|
||||
throw new ArgumentException("设置文件路径不能为空", nameof(settingsPath));
|
||||
}
|
||||
|
||||
_secretProtector = secretProtector;
|
||||
_settingsPath = settingsPath;
|
||||
}
|
||||
|
||||
public ClientSettings Load()
|
||||
{
|
||||
if (!File.Exists(_settingsPath))
|
||||
{
|
||||
return new ClientSettings();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(_settingsPath);
|
||||
var dto = JsonSerializer.Deserialize<SettingsFileDto>(json, SerializerOptions);
|
||||
return dto?.ToSettings(_secretProtector) ?? new ClientSettings();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new ClientSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(ClientSettings settings)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
|
||||
var directory = Path.GetDirectoryName(_settingsPath);
|
||||
if (!string.IsNullOrWhiteSpace(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var json = JsonSerializer.Serialize(SettingsFileDto.FromSettings(settings, _secretProtector), SerializerOptions);
|
||||
File.WriteAllText(_settingsPath, json);
|
||||
}
|
||||
|
||||
private sealed class SettingsFileDto
|
||||
{
|
||||
public string ServerAddress { get; set; } = "http://localhost:8080";
|
||||
public string ApiKey { get; set; } = string.Empty; // Legacy plaintext field.
|
||||
public string ProtectedApiKey { get; set; } = string.Empty;
|
||||
public string AdminUsername { get; set; } = string.Empty;
|
||||
public string AdminAccessToken { get; set; } = string.Empty; // Legacy plaintext field.
|
||||
public string ProtectedAdminAccessToken { get; set; } = string.Empty;
|
||||
public string StoreName { get; set; } = "默认打印店";
|
||||
public bool AllowInsecureGrpc { get; set; } = true;
|
||||
public string LibraryRoot { get; set; } = string.Empty;
|
||||
public string PrintCacheRoot { get; set; } = string.Empty;
|
||||
public int MaxUploadSizeMb { get; set; } = 50;
|
||||
public int HeartbeatIntervalSeconds { get; set; } = 15;
|
||||
|
||||
public ClientSettings ToSettings(ISecretProtector protector)
|
||||
{
|
||||
return new ClientSettings
|
||||
{
|
||||
ServerAddress = ServerAddress,
|
||||
ApiKey = ReadSecret(ProtectedApiKey, ApiKey, protector),
|
||||
AdminUsername = AdminUsername,
|
||||
AdminAccessToken = ReadSecret(ProtectedAdminAccessToken, AdminAccessToken, protector),
|
||||
StoreName = StoreName,
|
||||
AllowInsecureGrpc = AllowInsecureGrpc,
|
||||
LibraryRoot = LibraryRoot,
|
||||
PrintCacheRoot = PrintCacheRoot,
|
||||
MaxUploadSizeMb = MaxUploadSizeMb,
|
||||
HeartbeatIntervalSeconds = HeartbeatIntervalSeconds
|
||||
};
|
||||
}
|
||||
|
||||
public static SettingsFileDto FromSettings(ClientSettings settings, ISecretProtector protector)
|
||||
{
|
||||
return new SettingsFileDto
|
||||
{
|
||||
ServerAddress = settings.ServerAddress,
|
||||
ProtectedApiKey = protector.Protect(settings.ApiKey),
|
||||
AdminUsername = settings.AdminUsername,
|
||||
ProtectedAdminAccessToken = protector.Protect(settings.AdminAccessToken),
|
||||
StoreName = settings.StoreName,
|
||||
AllowInsecureGrpc = settings.AllowInsecureGrpc,
|
||||
LibraryRoot = settings.LibraryRoot,
|
||||
PrintCacheRoot = settings.PrintCacheRoot,
|
||||
MaxUploadSizeMb = settings.MaxUploadSizeMb,
|
||||
HeartbeatIntervalSeconds = settings.HeartbeatIntervalSeconds
|
||||
};
|
||||
}
|
||||
|
||||
private static string ReadSecret(string protectedValue, string legacyPlainText, ISecretProtector protector)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(protectedValue))
|
||||
{
|
||||
return legacyPlainText;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return protector.Unprotect(protectedValue);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return legacyPlainText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user