From ae7d863808c6c00999d20408beeda3731509c40c Mon Sep 17 00:00:00 2001 From: vman Date: Fri, 18 Nov 2022 16:01:38 -0500 Subject: Namespace changes and dynamic user lib loading --- .../ConfigurationExtensions.cs | 2 +- .../LoadingExtensions.cs | 2 - .../RoutingExtensions.cs | 9 ++- VNLib.Plugins.Extensions.Loading/S3Config.cs | 4 +- VNLib.Plugins.Extensions.Loading/UserLoading.cs | 84 ++++++++++++++++++++++ VNLib.Plugins.Extensions.Loading/VaultSecrets.cs | 7 +- 6 files changed, 94 insertions(+), 14 deletions(-) create mode 100644 VNLib.Plugins.Extensions.Loading/UserLoading.cs (limited to 'VNLib.Plugins.Extensions.Loading') diff --git a/VNLib.Plugins.Extensions.Loading/ConfigurationExtensions.cs b/VNLib.Plugins.Extensions.Loading/ConfigurationExtensions.cs index 8d2ef8c..17e15e5 100644 --- a/VNLib.Plugins.Extensions.Loading/ConfigurationExtensions.cs +++ b/VNLib.Plugins.Extensions.Loading/ConfigurationExtensions.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using VNLib.Utils.Extensions; -namespace VNLib.Plugins.Extensions.Loading.Configuration +namespace VNLib.Plugins.Extensions.Loading { /// /// Specifies a configuration variable name in the plugin's configuration diff --git a/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs b/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs index 30691ef..9b62e82 100644 --- a/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs +++ b/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs @@ -9,8 +9,6 @@ using System.Runtime.CompilerServices; using VNLib.Utils; using VNLib.Utils.Extensions; using VNLib.Plugins.Essentials.Accounts; -using VNLib.Plugins.Extensions.Loading.Configuration; -using VNLib.Utils.Logging; namespace VNLib.Plugins.Extensions.Loading { diff --git a/VNLib.Plugins.Extensions.Loading/RoutingExtensions.cs b/VNLib.Plugins.Extensions.Loading/RoutingExtensions.cs index 3e539e3..bdbe03c 100644 --- a/VNLib.Plugins.Extensions.Loading/RoutingExtensions.cs +++ b/VNLib.Plugins.Extensions.Loading/RoutingExtensions.cs @@ -5,7 +5,6 @@ using System.Reflection; using System.Collections.Generic; using VNLib.Plugins.Extensions.Loading.Events; -using VNLib.Plugins.Extensions.Loading.Configuration; namespace VNLib.Plugins.Extensions.Loading.Routing { @@ -13,7 +12,7 @@ namespace VNLib.Plugins.Extensions.Loading.Routing /// Provides advanced QOL features to plugin loading /// public static class RoutingExtensions - { + { /// /// Constructs and routes the specific endpoint type for the current plugin /// @@ -41,7 +40,7 @@ namespace VNLib.Plugins.Extensions.Loading.Routing } else { - ConstructorInfo? constructor = endpointType.GetConstructor(new Type[] { typeof(PluginBase), typeof(Dictionary) }); + ConstructorInfo? constructor = endpointType.GetConstructor(new Type[] { typeof(PluginBase), typeof(IReadOnlyDictionary) }); //Make sure the constructor exists _ = constructor ?? throw new EntryPointNotFoundException($"No constructor found for {endpointType.Name}"); //Get config variables for the endpoint @@ -76,7 +75,7 @@ namespace VNLib.Plugins.Extensions.Loading.Routing return plugin.Route(configAttr?.ConfigVarName); } - private static void ScheduleIntervals(PluginBase plugin, T endpointInstance, Type epType, IReadOnlyDictionary? endpointLocalConfig) where T: IEndpoint + private static void ScheduleIntervals(PluginBase plugin, T endpointInstance, Type epType, IReadOnlyDictionary? endpointLocalConfig) where T : IEndpoint { List registered = new(); try @@ -124,7 +123,7 @@ namespace VNLib.Plugins.Extensions.Loading.Routing catch { //Stop all event handles - foreach(EventHandle evh in registered) + foreach (EventHandle evh in registered) { evh.Dispose(); } diff --git a/VNLib.Plugins.Extensions.Loading/S3Config.cs b/VNLib.Plugins.Extensions.Loading/S3Config.cs index 635f739..c8b77fc 100644 --- a/VNLib.Plugins.Extensions.Loading/S3Config.cs +++ b/VNLib.Plugins.Extensions.Loading/S3Config.cs @@ -1,11 +1,11 @@ #nullable enable -namespace VNLib.Plugins.Extensions.Loading.Configuration +namespace VNLib.Plugins.Extensions.Loading { public sealed class S3Config { public string? ServerAddress { get; init; } - public string? ClientId { get; init; } + public string? ClientId { get; init; } public string? ClientSecret { get; init; } public string? BaseBucket { get; init; } public bool? UseSsl { get; init; } diff --git a/VNLib.Plugins.Extensions.Loading/UserLoading.cs b/VNLib.Plugins.Extensions.Loading/UserLoading.cs new file mode 100644 index 0000000..ae55094 --- /dev/null +++ b/VNLib.Plugins.Extensions.Loading/UserLoading.cs @@ -0,0 +1,84 @@ +using System; +using System.Linq; +using System.Threading; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using VNLib.Utils.Logging; +using VNLib.Utils.Extensions; +using VNLib.Plugins.Essentials.Users; + +namespace VNLib.Plugins.Extensions.Loading.Users +{ + /// + /// Contains extension methods for plugins to load the "users" system + /// + public static class UserLoading + { + public const string USER_CUSTOM_ASSEMBLY = "user_custom_asm"; + public const string DEFAULT_USER_ASM = "VNLib.Plugins.Essentials.Users.dll"; + public const string ONLOAD_METHOD_NAME = "OnPluginLoading"; + + private static readonly ConditionalWeakTable> UsersTable = new(); + + /// + /// Gets or loads the plugin's ambient , with the specified user-table name, + /// or the default table name + /// + /// + /// The ambient for the current plugin + /// + /// + public static IUserManager GetUserManager(this PluginBase plugin) + { + plugin.ThrowIfUnloaded(); + //Get stored or load + return UsersTable.GetValue(plugin, LoadUsers).Value; + } + + private static Lazy LoadUsers(PluginBase pbase) + { + //lazy callack + IUserManager LoadManager() + { + //Try to load a custom user assembly for exporting IUserManager + string? customAsm = pbase.PluginConfig.GetPropString(USER_CUSTOM_ASSEMBLY); + //See if host config defined the path + customAsm ??= pbase.HostConfig.GetPropString(USER_CUSTOM_ASSEMBLY); + //Finally default + customAsm ??= DEFAULT_USER_ASM; + + //Try to load a custom assembly + AssemblyLoader loader = pbase.LoadAssembly(customAsm); + try + { + //Get the runtime type + Type runtimeType = loader.Resource.GetType(); + + //Get the onplugin load method + Action? onLoadMethod = runtimeType.GetMethods() + .Where(static p => p.IsPublic && !p.IsAbstract && ONLOAD_METHOD_NAME.Equals(p.Name)) + .Select(p => p.CreateDelegate>(loader.Resource)) + .FirstOrDefault(); + + //Call the onplugin load method + onLoadMethod?.Invoke(pbase); + + if (pbase.IsDebug()) + { + pbase.Log.Verbose("Loading user manager from assembly {name}", runtimeType.AssemblyQualifiedName); + } + + //Return the loaded instance (may raise exception) + return loader.Resource; + } + catch + { + loader.Dispose(); + throw; + } + } + return new Lazy(LoadManager, LazyThreadSafetyMode.PublicationOnly); + } + } +} \ No newline at end of file diff --git a/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs b/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs index 3a35a8e..d920740 100644 --- a/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs +++ b/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs @@ -1,23 +1,22 @@ using System; using System.Linq; +using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; using VaultSharp; using VaultSharp.V1.Commons; using VaultSharp.V1.AuthMethods; using VaultSharp.V1.AuthMethods.Token; using VaultSharp.V1.AuthMethods.AppRole; +using VaultSharp.V1.SecretsEngines.PKI; using VNLib.Utils.Logging; using VNLib.Utils.Extensions; -using VNLib.Plugins.Extensions.Loading.Configuration; -using System.Security.Cryptography.X509Certificates; -using VaultSharp.V1.SecretsEngines.PKI; -using System.Text; namespace VNLib.Plugins.Extensions.Loading { -- cgit