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"