Move Backend Storage to Interactive User Profile
Resolves backend SQLite/config storage from the logged-on Windows user instead of LOCAL SYSTEM and migrates existing systemprofile backend files when needed.feature/centralized-offline-canteen
parent
c659bbaa86
commit
ca7e388989
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO;
|
||||
using UtopiaCanteenSystem.Services.Logging;
|
||||
|
||||
namespace UtopiaCanteenSystem.Data;
|
||||
|
||||
|
|
@ -11,6 +12,7 @@ public static class DatabasePath
|
|||
private static string? _appDataFolder;
|
||||
private static string? _dbPath;
|
||||
private static string _productFolderName = "UtopiaCanteenSystem";
|
||||
private static bool _useInteractiveLocalAppData;
|
||||
|
||||
/// <summary>
|
||||
/// Use "UtopiaCanteenBackend" for the Windows Service; default is legacy WPF folder name.
|
||||
|
|
@ -18,6 +20,7 @@ public static class DatabasePath
|
|||
public static void UseBackendServiceStorage()
|
||||
{
|
||||
_productFolderName = "UtopiaCanteenBackend";
|
||||
_useInteractiveLocalAppData = true;
|
||||
_appDataFolder = null;
|
||||
_dbPath = null;
|
||||
}
|
||||
|
|
@ -25,6 +28,7 @@ public static class DatabasePath
|
|||
public static void UseClientStorage()
|
||||
{
|
||||
_productFolderName = "UtopiaCanteenClient";
|
||||
_useInteractiveLocalAppData = false;
|
||||
_appDataFolder = null;
|
||||
_dbPath = null;
|
||||
}
|
||||
|
|
@ -37,11 +41,63 @@ public static class DatabasePath
|
|||
if (_appDataFolder != null)
|
||||
return _appDataFolder;
|
||||
|
||||
_appDataFolder = Path.Combine(
|
||||
var localAppDataRoot = ResolveLocalAppDataRoot();
|
||||
_appDataFolder = Path.Combine(localAppDataRoot, _productFolderName);
|
||||
Directory.CreateDirectory(_appDataFolder);
|
||||
MigrateBackendSystemProfileStorageIfNeeded(_appDataFolder);
|
||||
return _appDataFolder;
|
||||
}
|
||||
|
||||
private static string ResolveLocalAppDataRoot()
|
||||
{
|
||||
if (_useInteractiveLocalAppData)
|
||||
{
|
||||
var interactive = InteractiveUserPath.TryGetLocalAppDataPath();
|
||||
if (!string.IsNullOrWhiteSpace(interactive))
|
||||
return interactive;
|
||||
}
|
||||
|
||||
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
}
|
||||
|
||||
private static void MigrateBackendSystemProfileStorageIfNeeded(string newFolder)
|
||||
{
|
||||
if (!_useInteractiveLocalAppData)
|
||||
return;
|
||||
|
||||
var systemProfileFolder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
_productFolderName);
|
||||
Directory.CreateDirectory(_appDataFolder);
|
||||
return _appDataFolder;
|
||||
|
||||
if (string.Equals(systemProfileFolder, newFolder, StringComparison.OrdinalIgnoreCase) ||
|
||||
!Directory.Exists(systemProfileFolder))
|
||||
return;
|
||||
|
||||
var oldDbPath = Path.Combine(systemProfileFolder, "utopia_canteen.db");
|
||||
var newDbPath = Path.Combine(newFolder, "utopia_canteen.db");
|
||||
if (File.Exists(oldDbPath) && !File.Exists(newDbPath))
|
||||
{
|
||||
CopyIfMissing(oldDbPath, newDbPath);
|
||||
CopyIfMissing(Path.Combine(systemProfileFolder, "utopia_canteen.db-wal"), Path.Combine(newFolder, "utopia_canteen.db-wal"));
|
||||
CopyIfMissing(Path.Combine(systemProfileFolder, "utopia_canteen.db-shm"), Path.Combine(newFolder, "utopia_canteen.db-shm"));
|
||||
}
|
||||
|
||||
CopyIfMissing(Path.Combine(systemProfileFolder, "backend-settings.json"), Path.Combine(newFolder, "backend-settings.json"));
|
||||
}
|
||||
|
||||
private static void CopyIfMissing(string sourcePath, string destinationPath)
|
||||
{
|
||||
if (!File.Exists(sourcePath) || File.Exists(destinationPath))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
File.Copy(sourcePath, destinationPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If migration fails, the app will continue with files already present or create new ones.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace UtopiaCanteenSystem.Services.Logging;
|
|||
/// <summary>
|
||||
/// Resolves the logged-on Windows user's profile paths when the app runs as a service (SYSTEM).
|
||||
/// </summary>
|
||||
internal static class InteractiveUserPath
|
||||
public static class InteractiveUserPath
|
||||
{
|
||||
public static string? TryGetLocalAppDataPath()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue