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
SYED MUSTUFA AHMED NAQVI 2026-06-02 14:30:45 +05:00
parent c659bbaa86
commit ca7e388989
2 changed files with 60 additions and 4 deletions

View File

@ -1,4 +1,5 @@
using System.IO; using System.IO;
using UtopiaCanteenSystem.Services.Logging;
namespace UtopiaCanteenSystem.Data; namespace UtopiaCanteenSystem.Data;
@ -11,6 +12,7 @@ public static class DatabasePath
private static string? _appDataFolder; private static string? _appDataFolder;
private static string? _dbPath; private static string? _dbPath;
private static string _productFolderName = "UtopiaCanteenSystem"; private static string _productFolderName = "UtopiaCanteenSystem";
private static bool _useInteractiveLocalAppData;
/// <summary> /// <summary>
/// Use "UtopiaCanteenBackend" for the Windows Service; default is legacy WPF folder name. /// Use "UtopiaCanteenBackend" for the Windows Service; default is legacy WPF folder name.
@ -18,6 +20,7 @@ public static class DatabasePath
public static void UseBackendServiceStorage() public static void UseBackendServiceStorage()
{ {
_productFolderName = "UtopiaCanteenBackend"; _productFolderName = "UtopiaCanteenBackend";
_useInteractiveLocalAppData = true;
_appDataFolder = null; _appDataFolder = null;
_dbPath = null; _dbPath = null;
} }
@ -25,6 +28,7 @@ public static class DatabasePath
public static void UseClientStorage() public static void UseClientStorage()
{ {
_productFolderName = "UtopiaCanteenClient"; _productFolderName = "UtopiaCanteenClient";
_useInteractiveLocalAppData = false;
_appDataFolder = null; _appDataFolder = null;
_dbPath = null; _dbPath = null;
} }
@ -37,11 +41,63 @@ public static class DatabasePath
if (_appDataFolder != null) if (_appDataFolder != null)
return _appDataFolder; 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), Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
_productFolderName); _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> /// <summary>

View File

@ -7,7 +7,7 @@ namespace UtopiaCanteenSystem.Services.Logging;
/// <summary> /// <summary>
/// Resolves the logged-on Windows user's profile paths when the app runs as a service (SYSTEM). /// Resolves the logged-on Windows user's profile paths when the app runs as a service (SYSTEM).
/// </summary> /// </summary>
internal static class InteractiveUserPath public static class InteractiveUserPath
{ {
public static string? TryGetLocalAppDataPath() public static string? TryGetLocalAppDataPath()
{ {