251 lines
7.1 KiB
C#
251 lines
7.1 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using UtopiaCanteenSystem.Data;
|
|
|
|
namespace UtopiaCanteenSystem.Services;
|
|
|
|
/// <summary>
|
|
/// JSON-backed configuration (including remember-me credentials) stored under
|
|
/// LocalApplicationData so it survives app updates when deployed from a file server.
|
|
/// </summary>
|
|
public class ConfigService : IConfigService
|
|
{
|
|
private readonly string _configPath;
|
|
private AppConfig _config;
|
|
|
|
public ConfigService()
|
|
{
|
|
_configPath = DatabasePath.GetConfigPath();
|
|
_config = LoadConfig();
|
|
}
|
|
|
|
public string GetSyncApiEndpoint() => _config.SyncApiEndpoint ?? string.Empty;
|
|
|
|
public void SetSyncApiEndpoint(string endpoint)
|
|
{
|
|
_config.SyncApiEndpoint = endpoint ?? string.Empty;
|
|
SaveConfig();
|
|
}
|
|
|
|
public bool GetScannerConnected() => _config.ScannerConnected;
|
|
|
|
public void SetScannerConnected(bool connected)
|
|
{
|
|
_config.ScannerConnected = connected;
|
|
SaveConfig();
|
|
}
|
|
|
|
public int GetScanTimeoutSeconds() => _config.ScanTimeoutSeconds;
|
|
|
|
public void SetScanTimeoutSeconds(int seconds)
|
|
{
|
|
_config.ScanTimeoutSeconds = seconds;
|
|
SaveConfig();
|
|
}
|
|
|
|
public string GetAdminCardId() => _config.AdminCardId ?? string.Empty;
|
|
|
|
public void SetAdminCardId(string cardId)
|
|
{
|
|
_config.AdminCardId = cardId ?? string.Empty;
|
|
SaveConfig();
|
|
}
|
|
|
|
public string GetSiteId()
|
|
{
|
|
// Normalize to a 2-digit string (e.g. "02", "07", "12").
|
|
// Accepts legacy values like "SITE : 2" or "2" and converts them.
|
|
var raw = _config.SiteId;
|
|
if (string.IsNullOrWhiteSpace(raw))
|
|
return "01";
|
|
|
|
var digits = new string(raw.Where(char.IsDigit).ToArray());
|
|
if (string.IsNullOrWhiteSpace(digits))
|
|
return "01";
|
|
|
|
if (!int.TryParse(digits, out var numeric))
|
|
return "01";
|
|
|
|
return Math.Clamp(numeric, 0, 99).ToString("D2");
|
|
}
|
|
|
|
public void SetSiteId(string siteId)
|
|
{
|
|
// Store the normalized 2-digit site code.
|
|
var normalized = siteId;
|
|
if (string.IsNullOrWhiteSpace(normalized))
|
|
{
|
|
normalized = "01";
|
|
}
|
|
else
|
|
{
|
|
var digits = new string(normalized.Where(char.IsDigit).ToArray());
|
|
if (string.IsNullOrWhiteSpace(digits) || !int.TryParse(digits, out var numeric))
|
|
{
|
|
normalized = "01";
|
|
}
|
|
else
|
|
{
|
|
normalized = Math.Clamp(numeric, 0, 99).ToString("D2");
|
|
}
|
|
}
|
|
|
|
_config.SiteId = normalized;
|
|
SaveConfig();
|
|
}
|
|
|
|
public string GetDeviceId()
|
|
{
|
|
//var id = _config.DeviceId ?? string.Empty;
|
|
var id = Environment.MachineName;
|
|
if (string.IsNullOrWhiteSpace(id))
|
|
{
|
|
id = Guid.NewGuid().ToString("N");
|
|
_config.DeviceId = id;
|
|
SaveConfig();
|
|
}
|
|
return id;
|
|
}
|
|
|
|
public void SetDeviceId(string deviceId)
|
|
{
|
|
_config.DeviceId = deviceId ?? string.Empty;
|
|
SaveConfig();
|
|
}
|
|
|
|
public bool GetRememberAdminCredentials() => _config.RememberAdminCredentials;
|
|
|
|
public void SetRememberAdminCredentials(bool remember)
|
|
{
|
|
_config.RememberAdminCredentials = remember;
|
|
SaveConfig();
|
|
}
|
|
|
|
public string GetSavedAdminUsername() => _config.SavedAdminUsername ?? string.Empty;
|
|
|
|
public void SetSavedAdminUsername(string username)
|
|
{
|
|
_config.SavedAdminUsername = username ?? string.Empty;
|
|
SaveConfig();
|
|
}
|
|
|
|
public string GetSavedAdminPassword()
|
|
{
|
|
if (!_config.RememberAdminCredentials)
|
|
return string.Empty;
|
|
|
|
var protectedValue = _config.SavedAdminPasswordProtected ?? string.Empty;
|
|
if (string.IsNullOrWhiteSpace(protectedValue))
|
|
return string.Empty;
|
|
|
|
try
|
|
{
|
|
var bytes = Convert.FromBase64String(protectedValue);
|
|
var clear = ProtectedData.Unprotect(bytes, null, DataProtectionScope.CurrentUser);
|
|
return Encoding.UTF8.GetString(clear);
|
|
}
|
|
catch
|
|
{
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public void SetSavedAdminPassword(string password)
|
|
{
|
|
if (!_config.RememberAdminCredentials)
|
|
{
|
|
_config.SavedAdminPasswordProtected = string.Empty;
|
|
SaveConfig();
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
var clear = Encoding.UTF8.GetBytes(password ?? string.Empty);
|
|
var protectedBytes = ProtectedData.Protect(clear, null, DataProtectionScope.CurrentUser);
|
|
_config.SavedAdminPasswordProtected = Convert.ToBase64String(protectedBytes);
|
|
}
|
|
catch
|
|
{
|
|
_config.SavedAdminPasswordProtected = string.Empty;
|
|
}
|
|
|
|
SaveConfig();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns MySQL connection string for sync. Set via appsettings.json (copy from appsettings.example.json).
|
|
/// No default credentials; returns empty if not configured.
|
|
/// </summary>
|
|
public string GetMySqlConnectionString() => (_config.MySqlConnectionString ?? string.Empty).Trim();
|
|
|
|
public void SetMySqlConnectionString(string connectionString)
|
|
{
|
|
_config.MySqlConnectionString = connectionString ?? string.Empty;
|
|
SaveConfig();
|
|
}
|
|
|
|
private AppConfig LoadConfig()
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(_configPath))
|
|
{
|
|
var defaults = new AppConfig();
|
|
SaveConfig(defaults);
|
|
return defaults;
|
|
}
|
|
|
|
var json = File.ReadAllText(_configPath);
|
|
var config = JsonSerializer.Deserialize<AppConfig>(json);
|
|
return config ?? new AppConfig();
|
|
}
|
|
catch
|
|
{
|
|
return new AppConfig();
|
|
}
|
|
}
|
|
|
|
private void SaveConfig()
|
|
{
|
|
SaveConfig(_config);
|
|
}
|
|
|
|
private void SaveConfig(AppConfig config)
|
|
{
|
|
try
|
|
{
|
|
var json = JsonSerializer.Serialize(config, new JsonSerializerOptions
|
|
{
|
|
WriteIndented = true
|
|
});
|
|
File.WriteAllText(_configPath, json);
|
|
}
|
|
catch
|
|
{
|
|
// Ignore write failures (e.g., read-only location).
|
|
}
|
|
}
|
|
|
|
private sealed class AppConfig
|
|
{
|
|
public string SyncApiEndpoint { get; set; } = "https://api.example.com/uind/sync";
|
|
public bool ScannerConnected { get; set; } = false;
|
|
public int ScanTimeoutSeconds { get; set; } = 60;
|
|
public string AdminCardId { get; set; } = "ADMIN";
|
|
public string SiteId { get; set; } = "SITE : 1";
|
|
public string DeviceId { get; set; } = string.Empty;
|
|
|
|
// Admin credential persistence (optional).
|
|
public bool RememberAdminCredentials { get; set; } = false;
|
|
public string SavedAdminUsername { get; set; } = string.Empty;
|
|
public string SavedAdminPasswordProtected { get; set; } = string.Empty;
|
|
|
|
// MySQL connection string for sync. Set in appsettings.json (see appsettings.example.json). No default.
|
|
public string MySqlConnectionString { get; set; } = string.Empty;
|
|
}
|
|
}
|