138 lines
4.9 KiB
C#
138 lines
4.9 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
} |