2017-06-12 17:47:31 -04:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Reflection;
|
2018-04-08 02:44:42 -04:00
|
|
|
|
using SharedLibraryCore.Interfaces;
|
2018-08-23 17:16:30 -04:00
|
|
|
|
using System.Linq;
|
2020-01-31 21:15:07 -05:00
|
|
|
|
using SharedLibraryCore;
|
2020-10-24 16:02:38 -04:00
|
|
|
|
using IW4MAdmin.Application.API.Master;
|
2020-11-11 18:31:26 -05:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
2020-10-24 16:02:38 -04:00
|
|
|
|
using SharedLibraryCore.Configuration;
|
2020-11-11 18:31:26 -05:00
|
|
|
|
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-11-11 18:31:26 -05:00
|
|
|
|
namespace IW4MAdmin.Application.Misc
|
2017-06-12 17:47:31 -04:00
|
|
|
|
{
|
2020-02-11 17:44:06 -05:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// implementation of IPluginImporter
|
|
|
|
|
/// discovers plugins and script plugins
|
|
|
|
|
/// </summary>
|
2020-01-31 21:15:07 -05:00
|
|
|
|
public class PluginImporter : IPluginImporter
|
2017-06-12 17:47:31 -04:00
|
|
|
|
{
|
2020-10-24 16:02:38 -04:00
|
|
|
|
private IEnumerable<PluginSubscriptionContent> _pluginSubscription;
|
2020-02-11 17:44:06 -05:00
|
|
|
|
private static readonly string PLUGIN_DIR = "Plugins";
|
2020-01-31 21:15:07 -05:00
|
|
|
|
private readonly ILogger _logger;
|
2020-10-24 16:02:38 -04:00
|
|
|
|
private readonly IRemoteAssemblyHandler _remoteAssemblyHandler;
|
|
|
|
|
private readonly IMasterApi _masterApi;
|
|
|
|
|
private readonly ApplicationConfiguration _appConfig;
|
2020-01-31 21:15:07 -05:00
|
|
|
|
|
2020-11-11 18:31:26 -05:00
|
|
|
|
public PluginImporter(ILogger<PluginImporter> logger, ApplicationConfiguration appConfig, IMasterApi masterApi, IRemoteAssemblyHandler remoteAssemblyHandler)
|
2020-01-31 21:15:07 -05:00
|
|
|
|
{
|
|
|
|
|
_logger = logger;
|
2020-10-24 16:02:38 -04:00
|
|
|
|
_masterApi = masterApi;
|
|
|
|
|
_remoteAssemblyHandler = remoteAssemblyHandler;
|
|
|
|
|
_appConfig = appConfig;
|
2020-01-31 21:15:07 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2020-02-11 17:44:06 -05:00
|
|
|
|
/// discovers all the script plugins in the plugins dir
|
2020-01-31 21:15:07 -05:00
|
|
|
|
/// </summary>
|
2020-02-11 17:44:06 -05:00
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public IEnumerable<IPlugin> DiscoverScriptPlugins()
|
2017-06-12 17:47:31 -04:00
|
|
|
|
{
|
2020-02-11 17:44:06 -05:00
|
|
|
|
string pluginDir = $"{Utilities.OperatingDirectory}{PLUGIN_DIR}{Path.DirectorySeparatorChar}";
|
2018-08-28 17:32:59 -04:00
|
|
|
|
|
|
|
|
|
if (Directory.Exists(pluginDir))
|
|
|
|
|
{
|
2020-10-24 16:02:38 -04:00
|
|
|
|
var scriptPluginFiles = Directory.GetFiles(pluginDir, "*.js").AsEnumerable().Union(GetRemoteScripts());
|
2018-08-28 17:32:59 -04:00
|
|
|
|
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogDebug("Discovered {count} potential script plugins", scriptPluginFiles.Count());
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-10-24 16:02:38 -04:00
|
|
|
|
if (scriptPluginFiles.Count() > 0)
|
2020-02-11 17:44:06 -05:00
|
|
|
|
{
|
|
|
|
|
foreach (string fileName in scriptPluginFiles)
|
|
|
|
|
{
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogDebug("Discovered script plugin {fileName}", fileName);
|
|
|
|
|
var plugin = new ScriptPlugin(_logger, fileName);
|
2020-02-11 17:44:06 -05:00
|
|
|
|
yield return plugin;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-12 17:47:31 -04:00
|
|
|
|
}
|
2020-02-11 17:44:06 -05:00
|
|
|
|
}
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-02-11 17:44:06 -05:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// discovers all the C# assembly plugins and commands
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
2021-03-22 12:09:25 -04:00
|
|
|
|
public (IEnumerable<Type>, IEnumerable<Type>, IEnumerable<Type>) DiscoverAssemblyPluginImplementations()
|
2020-02-11 17:44:06 -05:00
|
|
|
|
{
|
2021-03-22 12:09:25 -04:00
|
|
|
|
var pluginDir = $"{Utilities.OperatingDirectory}{PLUGIN_DIR}{Path.DirectorySeparatorChar}";
|
2020-02-11 17:44:06 -05:00
|
|
|
|
var pluginTypes = Enumerable.Empty<Type>();
|
|
|
|
|
var commandTypes = Enumerable.Empty<Type>();
|
2021-03-22 12:09:25 -04:00
|
|
|
|
var configurationTypes = Enumerable.Empty<Type>();
|
2018-08-26 20:20:47 -04:00
|
|
|
|
|
2020-02-11 17:44:06 -05:00
|
|
|
|
if (Directory.Exists(pluginDir))
|
2017-06-12 17:47:31 -04:00
|
|
|
|
{
|
2020-02-11 17:44:06 -05:00
|
|
|
|
var dllFileNames = Directory.GetFiles(pluginDir, "*.dll");
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogDebug("Discovered {count} potential plugin assemblies", dllFileNames.Length);
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-02-11 17:44:06 -05:00
|
|
|
|
if (dllFileNames.Length > 0)
|
2017-06-12 17:47:31 -04:00
|
|
|
|
{
|
2020-10-24 16:02:38 -04:00
|
|
|
|
// we only want to load the most recent assembly in case of duplicates
|
|
|
|
|
var assemblies = dllFileNames.Select(_name => Assembly.LoadFrom(_name))
|
|
|
|
|
.Union(GetRemoteAssemblies())
|
|
|
|
|
.GroupBy(_assembly => _assembly.FullName).Select(_assembly => _assembly.OrderByDescending(_assembly => _assembly.GetName().Version).First());
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-02-11 17:44:06 -05:00
|
|
|
|
pluginTypes = assemblies
|
|
|
|
|
.SelectMany(_asm => _asm.GetTypes())
|
|
|
|
|
.Where(_assemblyType => _assemblyType.GetInterface(nameof(IPlugin), false) != null);
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogDebug("Discovered {count} plugin implementations", pluginTypes.Count());
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-02-11 17:44:06 -05:00
|
|
|
|
commandTypes = assemblies
|
|
|
|
|
.SelectMany(_asm => _asm.GetTypes())
|
|
|
|
|
.Where(_assemblyType => _assemblyType.IsClass && _assemblyType.BaseType == typeof(Command));
|
|
|
|
|
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogDebug("Discovered {count} plugin commands", commandTypes.Count());
|
2021-03-22 12:09:25 -04:00
|
|
|
|
|
|
|
|
|
configurationTypes = assemblies
|
|
|
|
|
.SelectMany(asm => asm.GetTypes())
|
|
|
|
|
.Where(asmType =>
|
|
|
|
|
asmType.IsClass && asmType.GetInterface(nameof(IBaseConfiguration), false) != null);
|
|
|
|
|
|
|
|
|
|
_logger.LogDebug("Discovered {count} configuration implementations", configurationTypes.Count());
|
2017-06-12 17:47:31 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-31 21:15:07 -05:00
|
|
|
|
|
2021-03-22 12:09:25 -04:00
|
|
|
|
return (pluginTypes, commandTypes, configurationTypes);
|
2017-06-12 17:47:31 -04:00
|
|
|
|
}
|
2020-10-24 16:02:38 -04:00
|
|
|
|
|
|
|
|
|
private IEnumerable<Assembly> GetRemoteAssemblies()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (_pluginSubscription == null)
|
|
|
|
|
_pluginSubscription = _masterApi.GetPluginSubscription(Guid.Parse(_appConfig.Id), _appConfig.SubscriptionId).Result;
|
|
|
|
|
|
|
|
|
|
return _remoteAssemblyHandler.DecryptAssemblies(_pluginSubscription.Where(sub => sub.Type == PluginType.Binary).Select(sub => sub.Content).ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogWarning(ex, "Could not load remote assemblies");
|
2020-10-24 16:02:38 -04:00
|
|
|
|
return Enumerable.Empty<Assembly>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerable<string> GetRemoteScripts()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (_pluginSubscription == null)
|
|
|
|
|
_pluginSubscription = _masterApi.GetPluginSubscription(Guid.Parse(_appConfig.Id), _appConfig.SubscriptionId).Result;
|
|
|
|
|
|
|
|
|
|
return _remoteAssemblyHandler.DecryptScripts(_pluginSubscription.Where(sub => sub.Type == PluginType.Script).Select(sub => sub.Content).ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2020-11-11 18:31:26 -05:00
|
|
|
|
_logger.LogWarning(ex,"Could not load remote scripts");
|
2020-10-24 16:02:38 -04:00
|
|
|
|
return Enumerable.Empty<string>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum PluginType
|
|
|
|
|
{
|
|
|
|
|
Binary,
|
|
|
|
|
Script
|
2017-06-12 17:47:31 -04:00
|
|
|
|
}
|
|
|
|
|
}
|