feat: initialize existing development playout PCs
This commit is contained in:
@@ -62,6 +62,73 @@ public sealed class DatabaseRuntime
|
||||
return CreateDefault(fallbackConfigurationPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the Development Live database runtime from the one protected
|
||||
/// current-user LocalAppData legacy INI, or from the protected LocalAppData
|
||||
/// JSON when that INI is absent. Unlike the ordinary compatibility path, this
|
||||
/// never probes executable or operator-selected Res folders and ignores all
|
||||
/// database environment overrides.
|
||||
/// </summary>
|
||||
public static DatabaseRuntime CreateDevelopmentLiveLocalOverride()
|
||||
{
|
||||
var localApplicationData = Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.LocalApplicationData);
|
||||
return CreateDevelopmentLiveLocalOverride(localApplicationData);
|
||||
}
|
||||
|
||||
internal static DatabaseRuntime CreateDevelopmentLiveLocalOverride(
|
||||
string localApplicationData)
|
||||
{
|
||||
try
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(localApplicationData);
|
||||
var localRoot = Path.TrimEndingDirectorySeparator(
|
||||
Path.GetFullPath(localApplicationData));
|
||||
var resourceDirectory = Path.Combine(
|
||||
localRoot,
|
||||
"MBN_STOCK_WEBVIEW",
|
||||
"Res");
|
||||
var legacyIniPath = Path.Combine(resourceDirectory, "MmoneyCoder.ini");
|
||||
if (TryEnsureOrdinaryFile(legacyIniPath))
|
||||
{
|
||||
EnsureNoReparsePointDirectoryChain(resourceDirectory, localRoot);
|
||||
return Create(
|
||||
new LegacyIniDatabaseOptionsLoader(_ => null).Load(legacyIniPath));
|
||||
}
|
||||
|
||||
var configurationDirectory = Path.Combine(
|
||||
localRoot,
|
||||
"MBN_STOCK_WEBVIEW",
|
||||
"Config");
|
||||
EnsureNoReparsePointDirectoryChain(configurationDirectory, localRoot);
|
||||
var jsonPath = Path.Combine(
|
||||
configurationDirectory,
|
||||
"database.local.json");
|
||||
EnsureOrdinaryFile(jsonPath);
|
||||
var options = new DatabaseOptionsLoader(_ => null).Load(jsonPath);
|
||||
if (!options.IsConfigured(MMoneyCoderSharp.Data.DataSourceKind.Oracle) ||
|
||||
!options.IsConfigured(MMoneyCoderSharp.Data.DataSourceKind.MariaDb))
|
||||
{
|
||||
throw new DatabaseConfigurationException(
|
||||
"Development Live database configuration is unavailable.");
|
||||
}
|
||||
|
||||
return Create(options);
|
||||
}
|
||||
catch (DatabaseConfigurationException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception exception) when (
|
||||
exception is ArgumentException or IOException or UnauthorizedAccessException or
|
||||
InvalidDataException or NotSupportedException or
|
||||
System.Security.SecurityException)
|
||||
{
|
||||
throw new DatabaseConfigurationException(
|
||||
"Development Live database configuration is unavailable.");
|
||||
}
|
||||
}
|
||||
|
||||
private static string? ResolveLegacyOverridePath()
|
||||
{
|
||||
var localAppData = Environment.GetFolderPath(
|
||||
@@ -75,6 +142,56 @@ public sealed class DatabaseRuntime
|
||||
"MmoneyCoder.ini");
|
||||
}
|
||||
|
||||
private static void EnsureNoReparsePointDirectoryChain(
|
||||
string directory,
|
||||
string trustedRoot)
|
||||
{
|
||||
var current = Path.TrimEndingDirectorySeparator(Path.GetFullPath(directory));
|
||||
var root = Path.TrimEndingDirectorySeparator(Path.GetFullPath(trustedRoot));
|
||||
while (!string.Equals(current, root, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if ((File.GetAttributes(current) & FileAttributes.ReparsePoint) != 0)
|
||||
{
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
|
||||
var parent = Path.GetDirectoryName(current);
|
||||
if (string.IsNullOrWhiteSpace(parent) ||
|
||||
string.Equals(parent, current, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
|
||||
current = Path.TrimEndingDirectorySeparator(Path.GetFullPath(parent));
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureOrdinaryFile(string path)
|
||||
{
|
||||
var attributes = File.GetAttributes(Path.GetFullPath(path));
|
||||
if ((attributes & (FileAttributes.Directory | FileAttributes.ReparsePoint)) != 0)
|
||||
{
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryEnsureOrdinaryFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
EnsureOrdinaryFile(path);
|
||||
return true;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static DatabaseRuntime Create(DatabaseOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
Reference in New Issue
Block a user