diff options
Diffstat (limited to 'lib/Plugins.Essentials')
8 files changed, 415 insertions, 143 deletions
diff --git a/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs b/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs index a5fb074..396d496 100644 --- a/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs +++ b/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs @@ -48,7 +48,7 @@ namespace VNLib.Plugins.Essentials.Accounts { /// <summary> - /// The size in bytes of the random passwords generated when invoking the <see cref="SetRandomPasswordAsync(IPasswordHashingProvider, IUserManager, IUser, int)"/> + /// The size in bytes of the random passwords generated when invoking the /// </summary> public const int RANDOM_PASS_SIZE = 240; @@ -90,56 +90,37 @@ namespace VNLib.Plugins.Essentials.Accounts #region Password/User helper extensions /// <summary> - /// Generates and sets a random password for the specified user account + /// Validates a password associated with the specified user /// </summary> - /// <param name="manager">The configured <see cref="IUserManager"/> to process the password update on</param> - /// <param name="user">The user instance to update the password on</param> - /// <param name="passHashing">The <see cref="PasswordHashing"/> instance to hash the random password with</param> - /// <param name="size">Size (in bytes) of the generated random password</param> - /// <returns>A value indicating the results of the event (number of rows affected, should evaluate to true)</returns> - /// <exception cref="VnArgon2Exception"></exception> - /// <exception cref="ArgumentException"></exception> + /// <param name="manager"></param> + /// <param name="user">The user to validate the password against</param> + /// <param name="password">The password to test against the user</param> + /// <param name="flags">Validation flags</param> + /// <param name="cancellation">A token to cancel the validation</param> /// <exception cref="ArgumentNullException"></exception> - public static async Task<ERRNO> SetRandomPasswordAsync(this IPasswordHashingProvider passHashing, IUserManager manager, IUser user, int size = RANDOM_PASS_SIZE) + /// <returns>A value greater than 0 if successful, 0 or negative values if a failure occured</returns> + public static async Task<ERRNO> ValidatePasswordAsync(this IUserManager manager, IUser user, string password, PassValidateFlags flags, CancellationToken cancellation) { _ = manager ?? throw new ArgumentNullException(nameof(manager)); - _ = user ?? throw new ArgumentNullException(nameof(user)); - _ = passHashing ?? throw new ArgumentNullException(nameof(passHashing)); - if (user.IsReleased) - { - throw new ObjectDisposedException("The specifed user object has been released"); - } - //Alloc a buffer - using IMemoryHandle<byte> buffer = MemoryUtil.SafeAlloc<byte>(size); - //Use the CGN to get a random set - RandomHash.GetRandomBytes(buffer.Span); - //Hash the new random password - using PrivateString passHash = passHashing.Hash(buffer.Span); - //Write the password to the user account - return await manager.UpdatePassAsync(user, passHash); + using PrivateString ps = new(password, false); + return await manager.ValidatePasswordAsync(user, ps, flags, cancellation).ConfigureAwait(false); } - + /// <summary> - /// Creates a new user with a random user id and the specified email address and password. - /// If privileges are left null, the minimum privileges will be set. + /// Updates a password associated with the specified user. If the update fails, the transaction + /// is rolled back. /// </summary> /// <param name="manager"></param> - /// <param name="emailAddress">The user's email address or secondary id</param> - /// <param name="password">The user's password</param> - /// <param name="privileges">Optional user privilage level</param> - /// <param name="cancellation">A token to cancel the operation</param> - /// <returns>A task that resolves the new user</returns> + /// <param name="user">The user account to update the password of</param> + /// <param name="password">The new password to set</param> /// <exception cref="ArgumentNullException"></exception> - /// <exception cref="UserExistsException"></exception> - /// <exception cref="UserCreationFailedException"></exception> - public static Task<IUser> CreateUserAsync(this IUserManager manager, string emailAddress, PrivateString password, ulong? privileges, CancellationToken cancellation = default) + /// <param name="cancellation">A token to cancel the operation</param> + /// <returns>The result of the operation, the result should be 1 (aka true)</returns> + public static async Task<ERRNO> UpdatePasswordAsync(this IUserManager manager, IUser user, string password, CancellationToken cancellation = default) { _ = manager ?? throw new ArgumentNullException(nameof(manager)); - //Create a random user id - string randomId = GetRandomUserId(); - //Set the default/minimum privileges - privileges ??= MINIMUM_LEVEL; - return manager.CreateUserAsync(randomId, emailAddress, privileges.Value, password, cancellation); + using PrivateString ps = new(password, false); + return await manager.UpdatePasswordAsync(user, ps, cancellation).ConfigureAwait(false); } /// <summary> @@ -169,14 +150,6 @@ namespace VNLib.Plugins.Essentials.Accounts public static void SetAccountOrigin(this IUser ud, string origin) => ud[ACC_ORIGIN_ENTRY] = origin; /// <summary> - /// Gets a random user-id generated from crypograhic random number - /// then hashed (SHA1) and returns a hexadecimal string - /// </summary> - /// <returns>The random string user-id</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string GetRandomUserId() => RandomHash.GetRandomHash(HashAlg.SHA1, 64, HashEncodingMode.Hexadecimal); - - /// <summary> /// Generates a cryptographically secure random password, then hashes it /// and returns the hash of the new password /// </summary> @@ -207,58 +180,6 @@ namespace VNLib.Plugins.Essentials.Accounts } /// <summary> - /// Asynchronously verifies the desired user's password. If the user is not found or the password is not found - /// returns false. Returns true if the user exist's has a valid password hash and matches the supplied password value. - /// </summary> - /// <param name="manager"></param> - /// <param name="userId">The id of the user to check the password against</param> - /// <param name="rawPassword">The raw password of the user to compare hashes against</param> - /// <param name="hashing">The password hashing tools</param> - /// <param name="cancellation">A token to cancel the operation</param> - /// <returns>A task that completes with the value of the password hashing match.</returns> - /// <exception cref="ArgumentNullException"></exception> - public static async Task<bool> VerifyPasswordAsync(this IUserManager manager, string userId, PrivateString rawPassword, IPasswordHashingProvider hashing, CancellationToken cancellation) - { - _ = manager ?? throw new ArgumentNullException(nameof(manager)); - _ = userId ?? throw new ArgumentNullException(nameof(userId)); - _ = rawPassword ?? throw new ArgumentNullException(nameof(rawPassword)); - _ = hashing ?? throw new ArgumentNullException(nameof(hashing)); - - //Get the user, may be null if the user does not exist - using IUser? user = await manager.GetUserAndPassFromIDAsync(userId, cancellation); - - if(user == null) - { - return false; - } - - if(user.PassHash == null) - { - return false; - } - - return hashing.Verify(user.PassHash.ToReadOnlySpan(), rawPassword.ToReadOnlySpan()); - } - - /// <summary> - /// Verifies the user's raw password against the hashed password using the specified - /// <see cref="PasswordHashing"/> instance - /// </summary> - /// <param name="user"></param> - /// <param name="rawPassword"></param> - /// <param name="hashing">The <see cref="IPasswordHashingProvider"/> provider instance</param> - /// <returns>True if the password </returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool VerifyPassword(this IUser user, PrivateString rawPassword, IPasswordHashingProvider hashing) - { - _ = user ?? throw new ArgumentNullException(nameof(user)); - _ = rawPassword ?? throw new ArgumentNullException(nameof(rawPassword)); - _ = hashing ?? throw new ArgumentNullException(nameof(hashing)); - - return user.PassHash != null && hashing.Verify(user.PassHash.ToReadOnlySpan(), rawPassword.ToReadOnlySpan()); - } - - /// <summary> /// Verifies a password against its previously encoded hash. /// </summary> /// <param name="provider"></param> diff --git a/lib/Plugins.Essentials/src/Accounts/UserCreationRequest.cs b/lib/Plugins.Essentials/src/Accounts/UserCreationRequest.cs new file mode 100644 index 0000000..e346af1 --- /dev/null +++ b/lib/Plugins.Essentials/src/Accounts/UserCreationRequest.cs @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: UserCreationRequest.cs +* +* UserCreationRequest.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials 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.Essentials 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 VNLib.Utils.Memory; +using VNLib.Plugins.Essentials.Users; + +namespace VNLib.Plugins.Essentials.Accounts +{ + /// <summary> + /// A concrete implementation of <see cref="IUserCreationRequest"/> + /// that can be used to create a new user. + /// </summary> + public class UserCreationRequest : IUserCreationRequest + { + ///<inheritdoc/> + public PrivateString? Password { get; init; } + + ///<inheritdoc/> + public ulong Privileges { get; init; } = AccountUtil.MINIMUM_LEVEL; + + ///<inheritdoc/> + public string EmailAddress { get; init; } = string.Empty; + + ///<inheritdoc/> + public bool UseRawPassword { get; init; } + + ///<inheritdoc/> + public UserStatus InitialStatus { get; init; } = UserStatus.Unverified; + } +}
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Extensions/ICookieController.cs b/lib/Plugins.Essentials/src/Extensions/ICookieController.cs new file mode 100644 index 0000000..b88e648 --- /dev/null +++ b/lib/Plugins.Essentials/src/Extensions/ICookieController.cs @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: ICookieController.cs +* +* ICookieController.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials 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.Essentials 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/. +*/ + +namespace VNLib.Plugins.Essentials.Extensions +{ + /// <summary> + /// Manges a single cookie for connections + /// </summary> + public interface ICookieController + { + /// <summary> + /// Sets the cookie value for the given entity + /// </summary> + /// <param name="entity">The http connection to set the cookie value for</param> + /// <param name="value">The cookie value</param> + void SetCookie(HttpEntity entity, string value); + + /// <summary> + /// Gets the cookie value for the given entity + /// </summary> + /// <param name="entity">The entity to get the cookie for</param> + /// <returns>The cookie value if set, null otherwise</returns> + string? GetCookie(HttpEntity entity); + + /// <summary> + /// Expires an existing request cookie for the given entity, avoiding + /// setting the response cookie unless necessary + /// </summary> + /// <param name="entity">The http connection to expire the cookie on</param> + /// <param name="force">Forcibly set the response cookie regardless of it's existence</param> + void ExpireCookie(HttpEntity entity, bool force); + } +}
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs b/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs new file mode 100644 index 0000000..1893b6e --- /dev/null +++ b/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs @@ -0,0 +1,124 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: SingleCookieController.cs +* +* SingleCookieController.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials 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.Essentials 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.Collections.Generic; + +using VNLib.Net.Http; + +namespace VNLib.Plugins.Essentials.Extensions +{ + /// <summary> + /// Implements a sinlge cookie controller + /// </summary> + public class SingleCookieController : ICookieController + { + private readonly string _cookieName; + private readonly TimeSpan _validFor; + + /// <summary> + /// Creates a new <see cref="SingleCookieController"/> instance + /// </summary> + /// <param name="cookieName">The name of the cookie to manage</param> + /// <param name="validFor">The max-age cookie value</param> + public SingleCookieController(string cookieName, TimeSpan validFor) + { + _cookieName = cookieName; + _validFor = validFor; + } + + /// <summary> + /// The domain of the cookie + /// </summary> + public string? Domain { get; init; } + + /// <summary> + /// The path of the cookie + /// </summary> + public string? Path { get; init; } + + /// <summary> + /// Whether the cookie is secure + /// </summary> + public bool Secure { get; init; } + + /// <summary> + /// Whether the cookie is HTTP only + /// </summary> + public bool HttpOnly { get; init; } + + /// <summary> + /// The SameSite policy of the cookie + /// </summary> + public CookieSameSite SameSite { get; init; } + + + /// <summary> + /// Optionally clears the cookie (does not force) + /// </summary> + /// <param name="entity">The entity to clear the cookie for</param> + public void ExpireCookie(HttpEntity entity) => ExpireCookie(entity, false); + + ///<inheritdoc/> + public void ExpireCookie(HttpEntity entity, bool force) + { + _ = entity ?? throw new ArgumentNullException(nameof(entity)); + SetCookieInternal(entity, string.Empty, force); + } + + ///<inheritdoc/> + public string? GetCookie(HttpEntity entity) + { + _ = entity ?? throw new ArgumentNullException(nameof(entity)); + return entity.Server.RequestCookies.GetValueOrDefault(_cookieName); + } + + ///<inheritdoc/> + public void SetCookie(HttpEntity entity, string value) + { + _ = entity ?? throw new ArgumentNullException(nameof(entity)); + SetCookieInternal(entity, value, true); + } + + private void SetCookieInternal(HttpEntity entity, string value, bool force) + { + //Only set cooke if already exists or force is true + if (entity.Server.RequestCookies.ContainsKey(value) || force) + { + //Build and set cookie + HttpCookie cookie = new(_cookieName, value) + { + Secure = Secure, + HttpOnly = HttpOnly, + ValidFor = _validFor, + SameSite = SameSite, + Path = Path, + Domain = Domain + }; + + entity.Server.SetCookie(in cookie); + } + } + } +}
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Users/IUser.cs b/lib/Plugins.Essentials/src/Users/IUser.cs index a36ba70..315c8c5 100644 --- a/lib/Plugins.Essentials/src/Users/IUser.cs +++ b/lib/Plugins.Essentials/src/Users/IUser.cs @@ -27,14 +27,19 @@ using System.Collections.Generic; using VNLib.Utils; using VNLib.Utils.Async; -using VNLib.Utils.Memory; namespace VNLib.Plugins.Essentials.Users { + /// <summary> /// Represents an abstract user account /// </summary> - public interface IUser : IAsyncExclusiveResource, IDisposable, IObjectStorage, IEnumerable<KeyValuePair<string, string>>, IIndexable<string, string> + public interface IUser : + IAsyncExclusiveResource, + IDisposable, + IObjectStorage, + IEnumerable<KeyValuePair<string, string>>, + IIndexable<string, string> { /// <summary> /// The user's privilege level @@ -52,9 +57,9 @@ namespace VNLib.Plugins.Essentials.Users DateTimeOffset Created { get; } /// <summary> - /// The user's password hash if retreived from the backing store, otherwise null + /// The user's email address /// </summary> - PrivateString? PassHash { get; } + string EmailAddress { get; set; } /// <summary> /// Status of account @@ -62,16 +67,6 @@ namespace VNLib.Plugins.Essentials.Users UserStatus Status { get; set; } /// <summary> - /// Is the account only usable from local network? - /// </summary> - bool LocalOnly { get; set; } - - /// <summary> - /// The user's email address - /// </summary> - string EmailAddress { get; set; } - - /// <summary> /// Marks the user for deletion on release /// </summary> void Delete(); diff --git a/lib/Plugins.Essentials/src/Users/IUserCreationRequest.cs b/lib/Plugins.Essentials/src/Users/IUserCreationRequest.cs new file mode 100644 index 0000000..a5b9a30 --- /dev/null +++ b/lib/Plugins.Essentials/src/Users/IUserCreationRequest.cs @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: IUserCreationRequest.cs +* +* IUserCreationRequest.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials 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.Essentials 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 VNLib.Utils.Memory; + +namespace VNLib.Plugins.Essentials.Users +{ + /// <summary> + /// A request to create a new user + /// </summary> + public interface IUserCreationRequest + { + /// <summary> + /// The value to store in the users password field. By default this + /// value will be hashed before being stored in the database, unless + /// <see cref="UseRawPassword"/> is set to true. + /// </summary> + PrivateString? Password { get; } + + /// <summary> + /// The user's initial privilege level + /// </summary> + ulong Privileges { get; } + + /// <summary> + /// The user's email address + /// </summary> + string EmailAddress { get; } + + /// <summary> + /// Should the password be stored as-is in the database? + /// </summary> + bool UseRawPassword { get; } + + /// <summary> + /// The user's initial status + /// </summary> + UserStatus InitialStatus { get; } + } +}
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Users/IUserManager.cs b/lib/Plugins.Essentials/src/Users/IUserManager.cs index b731033..400a5d0 100644 --- a/lib/Plugins.Essentials/src/Users/IUserManager.cs +++ b/lib/Plugins.Essentials/src/Users/IUserManager.cs @@ -28,15 +28,37 @@ using System.Threading.Tasks; using VNLib.Utils; using VNLib.Utils.Memory; +using VNLib.Plugins.Essentials.Accounts; namespace VNLib.Plugins.Essentials.Users { + /// <summary> /// A backing store that provides user accounts /// </summary> public interface IUserManager { /// <summary> + /// Gets the internal password hash provider if one is available + /// </summary> + /// <returns>The internal hash provider if available, null otherwise</returns> + IPasswordHashingProvider? GetHashProvider(); + + /// <summary> + /// Computes uinuqe user-id that is safe for use in the database. + /// </summary> + /// <param name="input">The value to convert to a safe user-id</param> + /// <returns>The safe-user id</returns> + string ComputeSafeUserId(string input); + + /// <summary> + /// Gets the number of entries in the current user table + /// </summary> + /// <param name="cancellation">A token to cancel the operation</param> + /// <returns>The number of users in the table, or -1 if the operation failed</returns> + Task<long> GetUserCountAsync(CancellationToken cancellation = default); + + /// <summary> /// Attempts to get a user object without their password from the database asynchronously /// </summary> /// <param name="userId">The id of the user</param> @@ -55,36 +77,42 @@ namespace VNLib.Plugins.Essentials.Users Task<IUser?> GetUserFromEmailAsync(string emailAddress, CancellationToken cancellationToken = default); /// <summary> - /// Attempts to get a user object with their password from the database on the current thread + /// Creates a new user account in the store as per the request. The user-id field is optional, + /// and if set to null or empty, will be generated automatically by the store. /// </summary> - /// <param name="userid">The id of the user</param> + /// <param name="userId">An optional user id to force</param> /// <param name="cancellation">A token to cancel the operation</param> - /// <returns>The user's <see cref="IUser"/> object, null if the user was not found</returns> + /// <param name="creation">The account email address</param> + /// <returns>An object representing a user's account if successful, null otherwise</returns> + /// <exception cref="UserExistsException"></exception> /// <exception cref="ArgumentNullException"></exception> - Task<IUser?> GetUserAndPassFromIDAsync(string userid, CancellationToken cancellation = default); + /// <exception cref="UserCreationFailedException"></exception> + Task<IUser> CreateUserAsync(IUserCreationRequest creation, string? userId, CancellationToken cancellation = default); /// <summary> - /// Attempts to get a user object with their password from the database asynchronously + /// Validates a password associated with the specified user /// </summary> - /// <param name="emailAddress">The user's email address</param> - /// <param name="cancellationToken">A token to cancel the operation</param> - /// <returns>The user's <see cref="IUser"/> object, null if the user was not found</returns> - /// <exception cref="ArgumentNullException"></exception> - Task<IUser?> GetUserAndPassFromEmailAsync(string emailAddress, CancellationToken cancellationToken = default); + /// <param name="user">The user to validate the password against</param> + /// <param name="password">The password to test against the user</param> + /// <param name="flags">Validation flags</param> + /// <param name="cancellation">A token to cancel the validation</param> + /// <returns>A value greater than 0 if successful, 0 or negative values if a failure occured</returns> + Task<ERRNO> ValidatePasswordAsync(IUser user, PrivateString password, PassValidateFlags flags, CancellationToken cancellation = default); /// <summary> - /// Creates a new user in the current user's table and if successful returns the new user object (without password) + /// An operation that will attempt to recover a user's password if possible. Not all user + /// managment systems allow recovering passwords for users. This method should return + /// null if the operation is not supported. + /// <para> + /// The returned value will likely not be the user's raw password but instead a hashed + /// or encrypted version of the password. + /// </para> /// </summary> - /// <param name="userid">The user id</param> - /// <param name="privileges">A number representing the privilage level of the account</param> - /// <param name="passHash">Value to store in the password field</param> - /// <param name="cancellation">A token to cancel the operation</param> - /// <param name="emailAddress">The account email address</param> - /// <returns>An object representing a user's account if successful, null otherwise</returns> - /// <exception cref="UserExistsException"></exception> - /// <exception cref="ArgumentNullException"></exception> - /// <exception cref="UserCreationFailedException"></exception> - Task<IUser> CreateUserAsync(string userid, string emailAddress, ulong privileges, PrivateString passHash, CancellationToken cancellation = default); + /// <param name="user">The user to recover the password for</param> + /// <param name="cancellation">A token to cancel the opertion</param> + /// <returns>The password if found</returns> + /// <exception cref="NotSupportedException"></exception> + Task<PrivateString?> RecoverPasswordAsync(IUser user, CancellationToken cancellation = default); /// <summary> /// Updates a password associated with the specified user. If the update fails, the transaction @@ -94,13 +122,6 @@ namespace VNLib.Plugins.Essentials.Users /// <param name="newPass">The new password to set</param> /// <param name="cancellation">A token to cancel the operation</param> /// <returns>The result of the operation, the result should be 1 (aka true)</returns> - Task<ERRNO> UpdatePassAsync(IUser user, PrivateString newPass, CancellationToken cancellation = default); - - /// <summary> - /// Gets the number of entries in the current user table - /// </summary> - /// <param name="cancellation">A token to cancel the operation</param> - /// <returns>The number of users in the table, or -1 if the operation failed</returns> - Task<long> GetUserCountAsync(CancellationToken cancellation = default); + Task<ERRNO> UpdatePasswordAsync(IUser user, PrivateString newPass, CancellationToken cancellation = default); } }
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Users/PassValidateFlags.cs b/lib/Plugins.Essentials/src/Users/PassValidateFlags.cs new file mode 100644 index 0000000..f6ff43a --- /dev/null +++ b/lib/Plugins.Essentials/src/Users/PassValidateFlags.cs @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: PassValidateFlags.cs +* +* PassValidateFlags.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials 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.Essentials 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; + +namespace VNLib.Plugins.Essentials.Users +{ + /// <summary> + /// Flags for password validation + /// </summary> + [Flags] + public enum PassValidateFlags + { + /// <summary> + /// No flags/default + /// </summary> + None = 0, + + /// <summary> + /// Bypasses hashing of the password if possible + /// </summary> + BypassHashing = 1, + } +}
\ No newline at end of file |