using System.Security.Cryptography; using System.Text.Json; using KronaStaffTerminal.Models; namespace KronaStaffTerminal.Services; public sealed class TerminalStore { private static readonly byte[] Entropy = "Krona.Staff.Terminal.v1"u8.ToArray(); private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true }; private readonly string _filePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Krona", "StaffTerminal", "terminal-state.dat"); public async Task LoadAsync() { try { var sourcePath = File.Exists(_filePath) ? _filePath : FindLegacyPackagedState(); if (sourcePath is null) return new TerminalState(); var encrypted = await File.ReadAllBytesAsync(sourcePath); var clear = ProtectedData.Unprotect(encrypted, Entropy, DataProtectionScope.CurrentUser); var state = JsonSerializer.Deserialize(clear, JsonOptions) ?? new TerminalState(); if (!string.Equals(sourcePath, _filePath, StringComparison.OrdinalIgnoreCase)) { await SaveAsync(state); } return state; } catch { return new TerminalState(); } } public async Task SaveAsync(TerminalState state) { var directory = Path.GetDirectoryName(_filePath)!; Directory.CreateDirectory(directory); var clear = JsonSerializer.SerializeToUtf8Bytes(state, JsonOptions); var encrypted = ProtectedData.Protect(clear, Entropy, DataProtectionScope.CurrentUser); var temporaryPath = _filePath + ".tmp"; await File.WriteAllBytesAsync(temporaryPath, encrypted); File.Move(temporaryPath, _filePath, true); } private static string? FindLegacyPackagedState() { var packagesPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Packages"); if (!Directory.Exists(packagesPath)) return null; return Directory.EnumerateDirectories(packagesPath, "223A9635-262B-4298-9F19-1D2FE0A6B5F7_*") .Select(directory => Path.Combine(directory, "LocalCache", "Local", "Krona", "StaffTerminal", "terminal-state.dat")) .FirstOrDefault(File.Exists); } }