diff --git a/src/Artemis.Core/Ninject/CoreModule.cs b/src/Artemis.Core/Ninject/CoreModule.cs index a245b74e7..67b09bc8e 100644 --- a/src/Artemis.Core/Ninject/CoreModule.cs +++ b/src/Artemis.Core/Ninject/CoreModule.cs @@ -1,4 +1,6 @@ using System.IO; +using System.Security.AccessControl; +using System.Security.Principal; using Artemis.Core.Exceptions; using Artemis.Core.Plugins.Settings; using Artemis.Core.Services.Interfaces; @@ -44,10 +46,6 @@ namespace Artemis.Core.Ninject Kernel.Bind().ToMethod(t => { - // Ensure the data folder exists - if (!Directory.Exists(Constants.DataFolder)) - Directory.CreateDirectory(Constants.DataFolder); - try { return new LiteRepository(Constants.ConnectionString); diff --git a/src/Artemis.Core/Plugins/Modules/Module.cs b/src/Artemis.Core/Plugins/Modules/Module.cs index 7f77ca5f8..8a2420589 100644 --- a/src/Artemis.Core/Plugins/Modules/Module.cs +++ b/src/Artemis.Core/Plugins/Modules/Module.cs @@ -91,6 +91,12 @@ namespace Artemis.Core.Plugins.Modules /// public bool IsActivated { get; internal set; } + /// + /// Gets whether this module's activation was due to an override, can only be true if is + /// true + /// + public bool IsActivatedOverride { get; set; } + /// /// A list of activation requirements /// Note: if empty the module is always activated @@ -182,6 +188,7 @@ namespace Artemis.Core.Plugins.Modules if (IsActivated) return; + IsActivatedOverride = isOverride; ModuleActivated(isOverride); IsActivated = true; } @@ -191,6 +198,7 @@ namespace Artemis.Core.Plugins.Modules if (!IsActivated) return; + IsActivatedOverride = false; IsActivated = false; ModuleDeactivated(isOverride); } diff --git a/src/Artemis.Core/Services/ModuleService.cs b/src/Artemis.Core/Services/ModuleService.cs index af12ee739..7a5560262 100644 --- a/src/Artemis.Core/Services/ModuleService.cs +++ b/src/Artemis.Core/Services/ModuleService.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using System.Timers; using Artemis.Core.Events; using Artemis.Core.Exceptions; +using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.Modules; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; @@ -156,20 +157,36 @@ namespace Artemis.Core.Services private async Task ActivateModule(Module module, bool isOverride) { - module.Activate(isOverride); + try + { + module.Activate(isOverride); - // If this is a profile module, activate the last active profile after module activation - if (module is ProfileModule profileModule) - await _profileService.ActivateLastProfileAnimated(profileModule); + // If this is a profile module, activate the last active profile after module activation + if (module is ProfileModule profileModule) + await _profileService.ActivateLastProfileAnimated(profileModule); + } + catch (Exception e) + { + _logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to activate module and last profile.", e), "Failed to activate module and last profile"); + throw; + } } private async Task DeactivateModule(Module module, bool isOverride) { - // If this is a profile module, activate the last active profile after module activation - if (module.IsActivated && module is ProfileModule profileModule) - await profileModule.ChangeActiveProfileAnimated(null, null); + try + { + // If this is a profile module, activate the last active profile after module activation + if (module.IsActivated && module is ProfileModule profileModule) + await profileModule.ChangeActiveProfileAnimated(null, null); - module.Deactivate(isOverride); + module.Deactivate(isOverride); + } + catch (Exception e) + { + _logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to deactivate module and last profile.", e), "Failed to deactivate module and last profile"); + throw; + } } private void PopulatePriorities() diff --git a/src/Artemis.UI/Bootstrapper.cs b/src/Artemis.UI/Bootstrapper.cs index be17d3cbb..c337f7cd0 100644 --- a/src/Artemis.UI/Bootstrapper.cs +++ b/src/Artemis.UI/Bootstrapper.cs @@ -1,13 +1,15 @@ 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.Documents; using System.Windows.Markup; using System.Windows.Threading; -using Artemis.Core.Models.Profile.Conditions; +using Artemis.Core; using Artemis.Core.Ninject; using Artemis.Core.Services.Interfaces; using Artemis.UI.Ninject; @@ -37,11 +39,12 @@ namespace Artemis.UI protected override void Launch() { - StartupArguments = Args.ToList(); - var logger = Kernel.Get(); var viewManager = Kernel.Get(); + StartupArguments = Args.ToList(); + CreateDataDirectory(logger); + // Create the Artemis core try { @@ -113,6 +116,29 @@ namespace Artemis.UI e.Handled = true; } + private 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 + var directoryInfo = new DirectoryInfo(Constants.DataFolder); + var 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.");