Plugin settings - Restart Artemis for plugins that require admin rights

Setup wizard - Restart Artemis device providers that require admin rights
Setup wizard - Gracefully handle errors during device provider enable
Profile editor - Select a valid default brush on clean installs
This commit is contained in:
Robert committed 2021-03-11 20:27:54 +01:00
1 parent b917f36978
commit 985a94dbaf
16 files changed
+363 -151

No files matched your search

@@ -71,7 +71,7 @@ namespace Artemis.Core.Services
Plugin ImportPlugin(string fileName);
/// <summary>
/// Unloads and permanently removes the provided plugin
/// Unloads and permanently removes the provided plugin
/// </summary>
/// <param name="plugin">The plugin to remove</param>
void RemovePlugin(Plugin plugin);
@@ -127,6 +127,13 @@ namespace Artemis.Core.Services
/// <returns></returns>
DeviceProvider GetDeviceProviderByDevice(IRGBDevice device);
/// <summary>
/// Queues an action for the provided plugin for the next time Artemis starts, before plugins are loaded
/// </summary>
/// <param name="plugin">The plugin to queue the action for</param>
/// <param name="pluginAction">The action to take</param>
void QueuePluginAction(Plugin plugin, PluginManagementAction pluginAction);
#region Events
/// <summary>
@@ -27,6 +27,7 @@ namespace Artemis.Core.Services
private readonly ILogger _logger;
private readonly IPluginRepository _pluginRepository;
private readonly List<Plugin> _plugins;
private bool _isElevated;
public PluginManagementService(IKernel kernel, ILogger logger, IPluginRepository pluginRepository)
{
@@ -34,6 +35,8 @@ namespace Artemis.Core.Services
_logger = logger;
_pluginRepository = pluginRepository;
_plugins = new List<Plugin>();
ProcessQueuedActions();
}
private void CopyBuiltInPlugin(FileInfo zipFileInfo, ZipArchive zipArchive)
@@ -181,6 +184,7 @@ namespace Artemis.Core.Services
if (LoadingPlugins)
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
_isElevated = isElevated;
LoadingPlugins = true;
// Unload all currently loaded plugins first
@@ -203,7 +207,7 @@ namespace Artemis.Core.Services
// ReSharper disable InconsistentlySynchronizedField - It's read-only, idc
_logger.Debug("Loaded {count} plugin(s)", _plugins.Count);
bool adminRequired = _plugins.Any(p => p.Entity.IsEnabled && p.Info.RequiresAdmin);
bool adminRequired = _plugins.Any(p => p.Info.RequiresAdmin && p.Entity.IsEnabled && p.Entity.Features.Any(f => f.IsEnabled));
if (!isElevated && adminRequired)
{
_logger.Information("Restarting because one or more plugins requires elevation");
@@ -336,6 +340,19 @@ namespace Artemis.Core.Services
if (plugin.Assembly == null)
throw new ArtemisPluginException(plugin, "Cannot enable a plugin that hasn't successfully been loaded");
if (plugin.Info.RequiresAdmin && plugin.Entity.Features.Any(f => f.IsEnabled) && !_isElevated)
{
if (!saveState)
throw new ArtemisCoreException("Cannot enable a plugin that requires elevation without saving it's state.");
plugin.Entity.IsEnabled = true;
SavePlugin(plugin);
_logger.Information("Restarting because a newly enabled plugin requires elevation");
Utilities.Restart(true, TimeSpan.FromMilliseconds(500));
return;
}
// Create the Ninject child kernel and load the module
plugin.Kernel = new ChildKernel(_kernel, new PluginModule(plugin));
OnPluginEnabling(new PluginEventArgs(plugin));
@@ -523,6 +540,21 @@ namespace Artemis.Core.Services
_logger.Verbose("Enabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
OnPluginFeatureEnabling(new PluginFeatureEventArgs(pluginFeature));
if (pluginFeature.Plugin.Info.RequiresAdmin && !_isElevated)
{
if (!saveState)
throw new ArtemisCoreException("Cannot enable a feature that requires elevation without saving it's state.");
pluginFeature.Entity.IsEnabled = true;
pluginFeature.Plugin.Entity.IsEnabled = true;
SavePlugin(pluginFeature.Plugin);
_logger.Information("Restarting because a newly enabled feature requires elevation");
Utilities.Restart(true, TimeSpan.FromMilliseconds(500));
return;
}
try
{
pluginFeature.SetEnabled(true, isAutoEnable);
@@ -586,6 +618,34 @@ namespace Artemis.Core.Services
#endregion
#region Queued actions
public void QueuePluginAction(Plugin plugin, PluginManagementAction pluginAction)
{
List<PluginQueuedActionEntity> existing = _pluginRepository.GetQueuedActions(plugin.Guid);
if (existing.Any(e => pluginAction == PluginManagementAction.Delete && e is PluginQueuedDeleteEntity))
return;
if (pluginAction == PluginManagementAction.Delete)
_pluginRepository.AddQueuedAction(new PluginQueuedDeleteEntity {PluginGuid = plugin.Guid, Directory = plugin.Directory.FullName});
}
private void ProcessQueuedActions()
{
foreach (PluginQueuedActionEntity pluginQueuedActionEntity in _pluginRepository.GetQueuedActions())
{
if (pluginQueuedActionEntity is PluginQueuedDeleteEntity deleteAction)
{
if (Directory.Exists(deleteAction.Directory))
Directory.Delete(deleteAction.Directory, true);
}
_pluginRepository.RemoveQueuedAction(pluginQueuedActionEntity);
}
}
#endregion
#region Storage
private void SavePlugin(Plugin plugin)
@@ -673,4 +733,20 @@ namespace Artemis.Core.Services
#endregion
}
/// <summary>
/// Represents a type of plugin management action
/// </summary>
public enum PluginManagementAction
{
/// <summary>
/// A plugin management action that removes a plugin
/// </summary>
Delete,
// /// <summary>
// /// A plugin management action that updates a plugin
// /// </summary>
// Update
}
}