diff options
author | vman <public@vaughnnugent.com> | 2022-11-18 16:08:51 -0500 |
---|---|---|
committer | vman <public@vaughnnugent.com> | 2022-11-18 16:08:51 -0500 |
commit | 526c2364b9ad685d1c000fc8a168bf1305aaa8b7 (patch) | |
tree | a2bc01607320a6a75e1a869d5bd34e79fd63c595 /VNLib.Plugins.Essentials.Accounts/Endpoints/PasswordResetEndpoint.cs | |
parent | 2080400119be00bdc354f3121d84ec2f89606ac7 (diff) |
Add project files.
Diffstat (limited to 'VNLib.Plugins.Essentials.Accounts/Endpoints/PasswordResetEndpoint.cs')
-rw-r--r-- | VNLib.Plugins.Essentials.Accounts/Endpoints/PasswordResetEndpoint.cs | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/VNLib.Plugins.Essentials.Accounts/Endpoints/PasswordResetEndpoint.cs b/VNLib.Plugins.Essentials.Accounts/Endpoints/PasswordResetEndpoint.cs new file mode 100644 index 0000000..81bba51 --- /dev/null +++ b/VNLib.Plugins.Essentials.Accounts/Endpoints/PasswordResetEndpoint.cs @@ -0,0 +1,116 @@ +using System; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using System.Collections.Generic; + +using FluentValidation; + +using VNLib.Utils.Memory; +using VNLib.Utils.Extensions; +using VNLib.Plugins.Essentials.Users; +using VNLib.Plugins.Essentials.Extensions; +using VNLib.Plugins.Extensions.Validation; +using VNLib.Plugins.Extensions.Loading; +using VNLib.Plugins.Extensions.Loading.Users; +using VNLib.Plugins.Essentials.Endpoints; + +namespace VNLib.Plugins.Essentials.Accounts.Endpoints +{ + + /// <summary> + /// Password reset for user's that are logged in and know + /// their passwords to reset their MFA methods + /// </summary> + [ConfigurationName("password_endpoint")] + internal sealed class PasswordChangeEndpoint : ProtectedWebEndpoint + { + private readonly IUserManager Users; + private readonly PasswordHashing Passwords; + + public PasswordChangeEndpoint(PluginBase pbase, IReadOnlyDictionary<string, JsonElement> config) + { + string? path = config["path"].GetString(); + InitPathAndLog(path, pbase.Log); + + Users = pbase.GetUserManager(); + Passwords = pbase.GetPasswords(); + } + + protected override async ValueTask<VfReturnType> PostAsync(HttpEntity entity) + { + ValErrWebMessage webm = new(); + //get the request body + using JsonDocument? request = await entity.GetJsonFromFileAsync(); + if (request == null) + { + webm.Result = "No request specified"; + entity.CloseResponseJson(HttpStatusCode.BadRequest, webm); + return VfReturnType.VirtualSkip; + } + //get the user's old password + using PrivateString? currentPass = (PrivateString?)request.RootElement.GetPropString("current"); + //Get password as a private string + using PrivateString? newPass = (PrivateString?)request.RootElement.GetPropString("new_password"); + if (PrivateString.IsNullOrEmpty(currentPass)) + { + webm.Result = "You must specifiy your current password."; + entity.CloseResponseJson(HttpStatusCode.UnprocessableEntity, webm); + return VfReturnType.VirtualSkip; + } + if (PrivateString.IsNullOrEmpty(newPass)) + { + webm.Result = "You must specifiy a new password."; + entity.CloseResponseJson(HttpStatusCode.UnprocessableEntity, webm); + return VfReturnType.VirtualSkip; + } + //Test the password against minimum + if (!AccountValidations.PasswordValidator.Validate((string)newPass, webm)) + { + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + if (webm.Assert(!currentPass.Equals(newPass), "Passwords cannot be the same.")) + { + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + //get the user's entry in the table + using IUser? user = await Users.GetUserAndPassFromIDAsync(entity.Session.UserID); + if(webm.Assert(user != null, "An error has occured, please log-out and try again")) + { + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + //Make sure the account's origin is a local profile + if (webm.Assert(user.IsLocalAccount(), "External accounts cannot be modified")) + { + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + //Verify the user's old password + if (!Passwords.Verify(user.PassHash, currentPass)) + { + webm.Result = "Please check your current password"; + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + //Hash the user's new password + using PrivateString newPassHash = Passwords.Hash(newPass); + //Update the user's password + if (!await Users.UpdatePassAsync(user, newPassHash)) + { + //error + webm.Result = "Your password could not be updated"; + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + await user.ReleaseAsync(); + //delete the user's MFA entry so they can re-enable it + webm.Result = "Your password has been updated"; + webm.Success = true; + entity.CloseResponse(webm); + return VfReturnType.VirtualSkip; + } + } +} |