From 9e75131948d95e1246d3608071024e85b2d793e8 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Mon, 23 Nov 2020 22:11:26 +0100 Subject: [PATCH] Core - Moved first run code to the static utility class Core - Improved first run code, this closes #504 Storage - Fixed some migrations on fresh databases --- src/Artemis.Core/Artemis.Core.csproj | 1 + .../Services/PluginManagementService.cs | 4 --- .../Utilities/CurrentProcessUtilities.cs | 34 +++++++++++++++++++ src/Artemis.Core/packages.lock.json | 28 +++++++++++++-- .../M1AttributeBasedPropertiesMigration.cs | 2 ++ .../M3PluginEntitiesIndexChangesMigration.cs | 4 ++- .../StorageMigrationService.cs | 15 ++++++-- src/Artemis.UI.Shared/packages.lock.json | 28 +++++++++++++-- src/Artemis.UI/Bootstrapper.cs | 32 ++--------------- src/Artemis.UI/packages.lock.json | 26 +++++++++----- 10 files changed, 124 insertions(+), 50 deletions(-) diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index e19d84e8e..924ce6b5f 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -53,6 +53,7 @@ + diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs index f0cafdff2..5919c0c6a 100644 --- a/src/Artemis.Core/Services/PluginManagementService.cs +++ b/src/Artemis.Core/Services/PluginManagementService.cs @@ -35,10 +35,6 @@ namespace Artemis.Core.Services _logger = logger; _pluginRepository = pluginRepository; _plugins = new List(); - - // Ensure the plugins directory exists - if (!Directory.Exists(Constants.DataFolder + "plugins")) - Directory.CreateDirectory(Constants.DataFolder + "plugins"); } private void CopyBuiltInPlugin(FileInfo zipFileInfo, ZipArchive zipArchive) diff --git a/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs b/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs index 99aa6a3d0..06cd37ef8 100644 --- a/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs +++ b/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs @@ -1,5 +1,8 @@ using System; using System.Diagnostics; +using System.IO; +using System.Security.AccessControl; +using System.Security.Principal; namespace Artemis.Core { @@ -8,6 +11,15 @@ namespace Artemis.Core /// public static class Utilities { + /// + /// Call this before even initializing the Core to make sure the folders required for operation are in place + /// + public static void PrepareFirstLaunch() + { + CreateArtemisFolderIfMissing(Constants.DataFolder); + CreateArtemisFolderIfMissing(Constants.DataFolder + "plugins"); + } + /// /// Attempts to gracefully shut down the application with a delayed kill to ensure the application shut down /// @@ -64,6 +76,28 @@ namespace Artemis.Core return Process.GetCurrentProcess().MainModule!.FileName!; } + private static void CreateArtemisFolderIfMissing(string path) + { + if (!Directory.Exists(path)) + { + DirectoryInfo dataDirectory = Directory.CreateDirectory(path); + + if (!OperatingSystem.IsWindows()) + return; + + // On Windows, ensure everyone has permission (important when running as admin) + DirectorySecurity security = dataDirectory.GetAccessControl(); + SecurityIdentifier everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null); + security.AddAccessRule(new FileSystemAccessRule( + everyone, + FileSystemRights.Modify | FileSystemRights.Synchronize, + InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, + PropagationFlags.None, AccessControlType.Allow) + ); + dataDirectory.SetAccessControl(security); + } + } + #region Events /// diff --git a/src/Artemis.Core/packages.lock.json b/src/Artemis.Core/packages.lock.json index 69a57801e..c9fb9d34a 100644 --- a/src/Artemis.Core/packages.lock.json +++ b/src/Artemis.Core/packages.lock.json @@ -127,6 +127,16 @@ "resolved": "4.5.0", "contentHash": "pL2ChpaRRWI/p4LXyy4RgeWlYF2sgfj/pnVMvBqwNFr5cXg7CXNnWZWxrOONLg8VGdFB8oB+EG2Qw4MLgTOe+A==" }, + "System.IO.FileSystem.AccessControl": { + "type": "Direct", + "requested": "[5.0.0, )", + "resolved": "5.0.0", + "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, "System.Numerics.Vectors": { "type": "Direct", "requested": "[4.5.0, )", @@ -183,8 +193,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -932,6 +942,15 @@ "System.Runtime.Extensions": "4.3.0" } }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, "System.Security.Cryptography.Algorithms": { "type": "Transitive", "resolved": "4.3.0", @@ -1076,6 +1095,11 @@ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" } }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", diff --git a/src/Artemis.Storage/Migrations/M1AttributeBasedPropertiesMigration.cs b/src/Artemis.Storage/Migrations/M1AttributeBasedPropertiesMigration.cs index 18a5e644f..b1697878a 100644 --- a/src/Artemis.Storage/Migrations/M1AttributeBasedPropertiesMigration.cs +++ b/src/Artemis.Storage/Migrations/M1AttributeBasedPropertiesMigration.cs @@ -9,6 +9,8 @@ namespace Artemis.Storage.Migrations public void Apply(LiteRepository repository) { + // DropCollection will open a transaction so commit the current one + repository.Database.Commit(); if (repository.Database.CollectionExists("ProfileEntity")) repository.Database.DropCollection("ProfileEntity"); } diff --git a/src/Artemis.Storage/Migrations/M3PluginEntitiesIndexChangesMigration.cs b/src/Artemis.Storage/Migrations/M3PluginEntitiesIndexChangesMigration.cs index fb1658c26..0d38b175d 100644 --- a/src/Artemis.Storage/Migrations/M3PluginEntitiesIndexChangesMigration.cs +++ b/src/Artemis.Storage/Migrations/M3PluginEntitiesIndexChangesMigration.cs @@ -6,9 +6,11 @@ namespace Artemis.Storage.Migrations public class M3PluginEntitiesIndexChangesMigration : IStorageMigration { public int UserVersion => 3; - + public void Apply(LiteRepository repository) { + // DropCollection will open a transaction so commit the current one + repository.Database.Commit(); if (repository.Database.CollectionExists("PluginEntity")) repository.Database.DropCollection("PluginEntity"); if (repository.Database.CollectionExists("PluginSettingEntity")) diff --git a/src/Artemis.Storage/StorageMigrationService.cs b/src/Artemis.Storage/StorageMigrationService.cs index d5325a5b6..07f2701ec 100644 --- a/src/Artemis.Storage/StorageMigrationService.cs +++ b/src/Artemis.Storage/StorageMigrationService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Artemis.Storage.Migrations.Interfaces; using LiteDB; @@ -32,9 +33,17 @@ namespace Artemis.Storage storageMigration.GetType().Name, _repository.Database.UserVersion, storageMigration.UserVersion); _repository.Database.BeginTrans(); - storageMigration.Apply(_repository); + try + { + storageMigration.Apply(_repository); + } + catch (Exception) + { + _repository.Database.Rollback(); + throw; + } _repository.Database.Commit(); - + _repository.Database.UserVersion = storageMigration.UserVersion; } } diff --git a/src/Artemis.UI.Shared/packages.lock.json b/src/Artemis.UI.Shared/packages.lock.json index 3ea7f2516..eaa3f5270 100644 --- a/src/Artemis.UI.Shared/packages.lock.json +++ b/src/Artemis.UI.Shared/packages.lock.json @@ -181,8 +181,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "TsETIgVJb/AKoYfSP+iCxkuly5d3inZjTdx/ItZLk2CxY85v8083OBS3uai84kK3/baLnS5/b5XGs6zR7SuuHQ==" + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -730,6 +730,15 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.IO.FileSystem.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, "System.IO.FileSystem.Primitives": { "type": "Transitive", "resolved": "4.3.0", @@ -1007,6 +1016,15 @@ "System.Runtime.Extensions": "4.3.0" } }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, "System.Security.Cryptography.Algorithms": { "type": "Transitive", "resolved": "4.3.0", @@ -1151,6 +1169,11 @@ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" } }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", @@ -1301,6 +1324,7 @@ "Serilog.Sinks.File": "4.1.0", "SkiaSharp": "2.80.2", "System.Buffers": "4.5.0", + "System.IO.FileSystem.AccessControl": "5.0.0", "System.Numerics.Vectors": "4.5.0", "System.Reflection.Metadata": "1.8.0", "System.ValueTuple": "4.5.0" diff --git a/src/Artemis.UI/Bootstrapper.cs b/src/Artemis.UI/Bootstrapper.cs index 0af16c76c..6d2049dfc 100644 --- a/src/Artemis.UI/Bootstrapper.cs +++ b/src/Artemis.UI/Bootstrapper.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; -using System.Security.AccessControl; -using System.Security.Principal; using System.Threading.Tasks; using System.Windows; using System.Windows.Markup; using System.Windows.Threading; -using Artemis.Core; using Artemis.Core.Ninject; using Artemis.Core.Services; using Artemis.UI.Ninject; @@ -40,13 +36,12 @@ namespace Artemis.UI protected override void Launch() { Core.Utilities.ShutdownRequested += UtilitiesOnShutdownRequested; + Core.Utilities.PrepareFirstLaunch(); ILogger logger = Kernel.Get(); IViewManager viewManager = Kernel.Get(); - IRegistrationService registrationService = Kernel.Get(); StartupArguments = Args.ToList(); - CreateDataDirectory(logger); // Create the Artemis core try @@ -86,7 +81,7 @@ namespace Artemis.UI } }); - registrationService.RegisterInputProvider(); + Kernel.Get().RegisterInputProvider(); } protected override void ConfigureIoC(IKernel kernel) @@ -127,29 +122,6 @@ namespace Artemis.UI Execute.OnUIThread(() => Application.Current.Shutdown()); } - private static void CreateDataDirectory(ILogger logger) - { - // Ensure the data folder exists - if (Directory.Exists(Constants.DataFolder)) - return; - - logger.Information("Creating data directory at {dataDirectoryFolder}", Constants.DataFolder); - Directory.CreateDirectory(Constants.DataFolder); - - // During creation ensure all local users can access the data folder - // This is needed when later running Artemis as a different user or when Artemis is first run as admin - DirectoryInfo directoryInfo = new DirectoryInfo(Constants.DataFolder); - DirectorySecurity accessControl = directoryInfo.GetAccessControl(); - accessControl.AddAccessRule(new FileSystemAccessRule( - new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), - FileSystemRights.FullControl, - InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, - PropagationFlags.InheritOnly, - AccessControlType.Allow) - ); - directoryInfo.SetAccessControl(accessControl); - } - private void HandleFatalException(Exception e, ILogger logger) { logger.Fatal(e, "Fatal exception during initialization, shutting down."); diff --git a/src/Artemis.UI/packages.lock.json b/src/Artemis.UI/packages.lock.json index bf637b63b..0be5696bf 100644 --- a/src/Artemis.UI/packages.lock.json +++ b/src/Artemis.UI/packages.lock.json @@ -235,8 +235,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "3.1.0", - "contentHash": "z7aeg8oHln2CuNulfhiLYxCVMPEwBl3rzicjvIX+4sUuCwvXw5oXQEtbiU2c0z4qYL5L3Kmx0mMA/+t/SbY67w==" + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -788,6 +788,15 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.IO.FileSystem.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, "System.IO.FileSystem.Primitives": { "type": "Transitive", "resolved": "4.3.0", @@ -1067,11 +1076,11 @@ }, "System.Security.AccessControl": { "type": "Transitive", - "resolved": "4.7.0", - "contentHash": "JECvTt5aFF3WT3gHpfofL2MNNP6v84sxtXxpqhLBCcDRzqsPBmHhQ6shv4DwwN2tRlzsUxtb3G9M3763rbXKDg==", + "resolved": "5.0.0", + "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.0", - "System.Security.Principal.Windows": "4.7.0" + "Microsoft.NETCore.Platforms": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" } }, "System.Security.Cryptography.Algorithms": { @@ -1220,8 +1229,8 @@ }, "System.Security.Principal.Windows": { "type": "Transitive", - "resolved": "4.7.0", - "contentHash": "ojD0PX0XhneCsUbAZVKdb7h/70vyYMDYs85lwEI+LngEONe/17A0cFaRFqZU+sOEidcVswYWikYOQ9PPfjlbtQ==" + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" }, "System.Text.Encoding": { "type": "Transitive", @@ -1373,6 +1382,7 @@ "Serilog.Sinks.File": "4.1.0", "SkiaSharp": "2.80.2", "System.Buffers": "4.5.0", + "System.IO.FileSystem.AccessControl": "5.0.0", "System.Numerics.Vectors": "4.5.0", "System.Reflection.Metadata": "1.8.0", "System.ValueTuple": "4.5.0"