From d15303e584571dcc506f806dfb8ce59ea0309dbb Mon Sep 17 00:00:00 2001 From: vnugent Date: Sun, 5 Nov 2023 21:22:28 -0500 Subject: user/acc updates and fix social oauth --- .../src/LoadingExtensions.cs | 58 +++++---- .../src/UserManager.cs | 117 ------------------ .../src/Users/UserManager.cs | 137 +++++++++++++++++++++ .../src/Users/UserPassValResult.cs | 52 ++++++++ 4 files changed, 225 insertions(+), 139 deletions(-) delete mode 100644 lib/VNLib.Plugins.Extensions.Loading/src/UserManager.cs create mode 100644 lib/VNLib.Plugins.Extensions.Loading/src/Users/UserManager.cs create mode 100644 lib/VNLib.Plugins.Extensions.Loading/src/Users/UserPassValResult.cs (limited to 'lib') diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs index fa39b44..554e40f 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs @@ -100,6 +100,39 @@ namespace VNLib.Plugins.Extensions.Loading public static T GetOrCreateSingleton(PluginBase plugin, Func serviceFactory) => (T)GetOrCreateSingleton(plugin, typeof(T), p => serviceFactory(p)!); + + /// + /// Gets the full file path for the assembly asset file name within the assets + /// directory. + /// + /// + /// The name of the assembly (ex: 'file.dll') to search for + /// Directory search flags + /// The full path to the assembly asset file, or null if the file does not exist + /// + public static string? GetAssetFilePath(this PluginBase plugin, string assemblyName, SearchOption searchOption) + { + plugin.ThrowIfUnloaded(); + _ = assemblyName ?? throw new ArgumentNullException(nameof(assemblyName)); + + /* + * Allow an assets directory to limit the scope of the search for the desired + * assembly, otherwise search all plugins directories + */ + + string? assetDir = plugin.GetAssetsPath(); + assetDir ??= plugin.GetPluginsPath(); + + /* + * This should never happen since this method can only be called from a + * plugin context, which means this path was used to load the current plugin + */ + _ = assetDir ?? throw new ArgumentNullException(ConfigurationExtensions.PLUGIN_ASSET_KEY, "No plugin path is defined for the current host configuration, this is likely a bug"); + + //Get the first file that matches the search file + return Directory.EnumerateFiles(assetDir, assemblyName, searchOption).FirstOrDefault(); + } + /// /// Loads an assembly into the current plugin's load context and will unload when disposed /// or the plugin is unloaded from the host application. @@ -115,7 +148,6 @@ namespace VNLib.Plugins.Extensions.Loading /// The managing the loaded assmbly in the current AppDomain /// /// - /// /// /// The assembly is searched within the 'assets' directory specified in the plugin config /// or the global plugins ('path' key) directory if an assets directory is not defined. @@ -126,27 +158,9 @@ namespace VNLib.Plugins.Extensions.Loading SearchOption dirSearchOption = SearchOption.AllDirectories, AssemblyLoadContext? explictAlc = null) { - plugin.ThrowIfUnloaded(); - _ = assemblyName ?? throw new ArgumentNullException(nameof(assemblyName)); - - - /* - * Allow an assets directory to limit the scope of the search for the desired - * assembly, otherwise search all plugins directories - */ - - string? assetDir = plugin.GetAssetsPath(); - assetDir ??= plugin.GetPluginsPath(); - - /* - * This should never happen since this method can only be called from a - * plugin context, which means this path was used to load the current plugin - */ - _ = assetDir ?? throw new ArgumentNullException(ConfigurationExtensions.PLUGIN_ASSET_KEY, "No plugin path is defined for the current host configuration, this is likely a bug"); - - //Get the first file that matches the search file - string? asmFile = Directory.EnumerateFiles(assetDir, assemblyName, dirSearchOption).FirstOrDefault(); - _ = asmFile ?? throw new FileNotFoundException($"Failed to load custom assembly {assemblyName} from plugin directory"); + //Get the file path for the assembly + string asmFile = GetAssetFilePath(plugin, assemblyName, dirSearchOption) + ?? throw new FileNotFoundException($"Failed to load custom assembly {assemblyName} from plugin directory"); //Get the plugin's load context if not explicitly supplied explictAlc ??= GetPluginLoadContext(); diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/UserManager.cs b/lib/VNLib.Plugins.Extensions.Loading/src/UserManager.cs deleted file mode 100644 index e668b3e..0000000 --- a/lib/VNLib.Plugins.Extensions.Loading/src/UserManager.cs +++ /dev/null @@ -1,117 +0,0 @@ -/* -* Copyright (c) 2023 Vaughn Nugent -* -* Library: VNLib -* Package: VNLib.Plugins.Extensions.Loading -* File: UserManager.cs -* -* UserManager.cs is part of VNLib.Plugins.Extensions.Loading which is part of the larger -* VNLib collection of libraries and utilities. -* -* VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ - -using System; -using System.Threading; -using System.Threading.Tasks; - -using VNLib.Utils; -using VNLib.Utils.Memory; -using VNLib.Utils.Logging; -using VNLib.Plugins.Essentials.Users; - -namespace VNLib.Plugins.Extensions.Loading.Users -{ - /// - /// Provides a singleton service that dynamically loads - /// a user manager for the plugin. - /// - [ConfigurationName("users", Required = false)] - public class UserManager : IUserManager - { - public const string USER_CUSTOM_ASSEMBLY = "custom_assembly"; - public const string DEFAULT_USER_ASM = "VNLib.Plugins.Essentials.Users.dll"; - - private readonly IUserManager _dynamicLoader; - - public UserManager(PluginBase plugin) - { - //Load the default user assembly - _dynamicLoader = LoadUserAssembly(plugin, DEFAULT_USER_ASM); - } - - public UserManager(PluginBase plugin, IConfigScope config) - { - //Get the service configuration - string customAsm = config[USER_CUSTOM_ASSEMBLY].GetString() ?? DEFAULT_USER_ASM; - //Load the assembly - _dynamicLoader = LoadUserAssembly(plugin, customAsm); - } - - private static IUserManager LoadUserAssembly(PluginBase plugin, string customAsm) - { - //Try to load a custom assembly - IUserManager externManager = plugin.CreateServiceExternal(customAsm); - - if (plugin.IsDebug()) - { - plugin.Log.Debug("Loading user manager from assembly {name}", externManager.GetType().AssemblyQualifiedName); - } - - return externManager; - } - - /// - public Task CreateUserAsync(string userid, string emailAddress, ulong privilages, PrivateString passHash, CancellationToken cancellation = default) - { - return _dynamicLoader.CreateUserAsync(userid, emailAddress, privilages, passHash, cancellation); - } - - /// - public Task GetUserAndPassFromEmailAsync(string emailAddress, CancellationToken cancellationToken = default) - { - return _dynamicLoader.GetUserAndPassFromEmailAsync(emailAddress, cancellationToken); - } - - /// - public Task GetUserAndPassFromIDAsync(string userid, CancellationToken cancellation = default) - { - return _dynamicLoader.GetUserAndPassFromIDAsync(userid, cancellation); - } - - /// - public Task GetUserCountAsync(CancellationToken cancellation = default) - { - return _dynamicLoader.GetUserCountAsync(cancellation); - } - - /// - public Task GetUserFromEmailAsync(string emailAddress, CancellationToken cancellationToken = default) - { - return _dynamicLoader.GetUserFromEmailAsync(emailAddress, cancellationToken); - } - - /// - public Task GetUserFromIDAsync(string userId, CancellationToken cancellationToken = default) - { - return _dynamicLoader.GetUserFromIDAsync(userId, cancellationToken); - } - - /// - public Task UpdatePassAsync(IUser user, PrivateString newPass, CancellationToken cancellation = default) - { - return _dynamicLoader.UpdatePassAsync(user, newPass, cancellation); - } - } -} \ No newline at end of file diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Users/UserManager.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Users/UserManager.cs new file mode 100644 index 0000000..3e9dbde --- /dev/null +++ b/lib/VNLib.Plugins.Extensions.Loading/src/Users/UserManager.cs @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Extensions.Loading +* File: UserManager.cs +* +* UserManager.cs is part of VNLib.Plugins.Extensions.Loading which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; +using System.Threading; +using System.Threading.Tasks; + +using VNLib.Utils; +using VNLib.Utils.Memory; +using VNLib.Utils.Logging; +using VNLib.Plugins.Essentials.Users; +using VNLib.Plugins.Essentials.Accounts; + +namespace VNLib.Plugins.Extensions.Loading.Users +{ + /// + /// Provides a singleton service that dynamically loads + /// a user manager for the plugin. + /// + [ConfigurationName("users", Required = false)] + public class UserManager : IUserManager + { + + public const string USER_CUSTOM_ASSEMBLY = "custom_assembly"; + public const string DEFAULT_USER_ASM = "VNLib.Plugins.Essentials.Users.dll"; + + private readonly IUserManager _dynamicLoader; + + public UserManager(PluginBase plugin) + { + //Load the default user assembly + _dynamicLoader = LoadUserAssembly(plugin, DEFAULT_USER_ASM); + } + + public UserManager(PluginBase plugin, IConfigScope config) + { + //Get the service configuration + string customAsm = config[USER_CUSTOM_ASSEMBLY].GetString() ?? DEFAULT_USER_ASM; + //Load the assembly + _dynamicLoader = LoadUserAssembly(plugin, customAsm); + } + + private static IUserManager LoadUserAssembly(PluginBase plugin, string customAsm) + { + //Try to load a custom assembly + IUserManager externManager = plugin.CreateServiceExternal(customAsm); + + if (plugin.IsDebug()) + { + plugin.Log.Debug("Loading user manager from assembly {name}", externManager.GetType().AssemblyQualifiedName); + } + + return externManager; + } + + /// + /// Gets the underlying that was dynamically loaded. + /// + /// The user manager instance + public IUserManager InternalManager => _dynamicLoader; + + /// + public Task CreateUserAsync(IUserCreationRequest creation, string? userId, CancellationToken cancellation = default) + { + return _dynamicLoader.CreateUserAsync(creation, userId, cancellation); + } + + /// + public IPasswordHashingProvider? GetHashProvider() + { + return _dynamicLoader.GetHashProvider(); + } + + /// + public Task GetUserCountAsync(CancellationToken cancellation = default) + { + return _dynamicLoader.GetUserCountAsync(cancellation); + } + + /// + public Task GetUserFromEmailAsync(string emailAddress, CancellationToken cancellationToken = default) + { + return _dynamicLoader.GetUserFromEmailAsync(emailAddress, cancellationToken); + } + + /// + public Task GetUserFromIDAsync(string userId, CancellationToken cancellationToken = default) + { + return _dynamicLoader.GetUserFromIDAsync(userId, cancellationToken); + } + + /// + public Task RecoverPasswordAsync(IUser user, CancellationToken cancellation = default) + { + return _dynamicLoader.RecoverPasswordAsync(user, cancellation); + } + + /// + public Task UpdatePasswordAsync(IUser user, PrivateString newPass, CancellationToken cancellation = default) + { + return _dynamicLoader.UpdatePasswordAsync(user, newPass, cancellation); + } + + /// + public Task ValidatePasswordAsync(IUser user, PrivateString password, PassValidateFlags flags, CancellationToken cancellation = default) + { + return _dynamicLoader.ValidatePasswordAsync(user, password, flags, cancellation); + } + + /// + public string ComputeSafeUserId(string input) + { + return _dynamicLoader.ComputeSafeUserId(input); + } + } +} \ No newline at end of file diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Users/UserPassValResult.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Users/UserPassValResult.cs new file mode 100644 index 0000000..ccfc62d --- /dev/null +++ b/lib/VNLib.Plugins.Extensions.Loading/src/Users/UserPassValResult.cs @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Extensions.Loading +* File: UserPassValResult.cs +* +* UserPassValResult.cs is part of VNLib.Plugins.Extensions.Loading which is +* part of the larger VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System.Threading; + +using VNLib.Utils.Memory; +using VNLib.Plugins.Essentials.Users; + +namespace VNLib.Plugins.Extensions.Loading.Users +{ + /// + /// Result codes for + /// + public static class UserPassValResult + { + /// + /// The passwords matched + /// + public const int Success = 1; + + /// + /// Failed because the user did not have a password stored + /// + public const int Null = 0; + + /// + /// Failed because the passwords did not match + /// + public const int Failed = -1; + } +} \ No newline at end of file -- cgit