refactor: split node agent and Go control plane
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using WxAgent.Core;
|
||||
|
||||
namespace WxAgent.Windows;
|
||||
|
||||
public static class DatabaseKeyStore
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = CreateJsonOptions();
|
||||
|
||||
public static string DefaultPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WxAgent", "database-keys.json");
|
||||
|
||||
public static async Task SaveAsync(IReadOnlyList<AccountKeySet> accounts, string? path, CancellationToken cancellationToken)
|
||||
{
|
||||
var fullPath = Path.GetFullPath(path ?? DefaultPath);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
|
||||
var temporary = fullPath + ".tmp-" + Guid.NewGuid().ToString("N");
|
||||
try
|
||||
{
|
||||
await using (new FileStream(temporary, FileMode.CreateNew, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
}
|
||||
|
||||
RestrictToCurrentUser(temporary);
|
||||
await using (var stream = new FileStream(temporary, FileMode.Truncate, FileAccess.Write, FileShare.None, 81920, FileOptions.Asynchronous | FileOptions.WriteThrough))
|
||||
{
|
||||
await JsonSerializer.SerializeAsync(stream, accounts, JsonOptions, cancellationToken);
|
||||
await stream.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
File.Move(temporary, fullPath, true);
|
||||
RestrictToCurrentUser(fullPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (File.Exists(temporary))
|
||||
{
|
||||
File.Delete(temporary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<IReadOnlyList<AccountKeySet>> LoadAsync(string? path, CancellationToken cancellationToken)
|
||||
{
|
||||
var fullPath = Path.GetFullPath(path ?? DefaultPath);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
await using var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 81920, FileOptions.Asynchronous);
|
||||
return await JsonSerializer.DeserializeAsync<List<AccountKeySet>>(stream, JsonOptions, cancellationToken) ?? [];
|
||||
}
|
||||
|
||||
private static JsonSerializerOptions CreateJsonOptions()
|
||||
{
|
||||
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
return options;
|
||||
}
|
||||
|
||||
internal static void RestrictToCurrentUser(string path)
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var identity = WindowsIdentity.GetCurrent().User ?? throw new InvalidOperationException("Current Windows user SID is unavailable.");
|
||||
var security = new FileSecurity();
|
||||
security.SetOwner(identity);
|
||||
security.SetAccessRuleProtection(isProtected: true, preserveInheritance: false);
|
||||
security.AddAccessRule(new FileSystemAccessRule(identity, FileSystemRights.FullControl, AccessControlType.Allow));
|
||||
new FileInfo(path).SetAccessControl(security);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user