From 10f5f3c5c8af24900aeaa593152afa66274469e3 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 18 Nov 2023 18:51:23 -0800 Subject: [PATCH] New: Require password confirmation when setting or changing password (cherry picked from commit b248163df598dc611ee919d525eb7357256d73d5) --- .../AuthenticationRequiredModalContent.js | 15 +++++++++- .../src/Settings/General/SecuritySettings.js | 16 ++++++++++ src/NzbDrone.Core/Localization/Core/en.json | 2 ++ .../Validation/Paths/FileExistsValidator.cs | 2 +- .../Config/HostConfigController.cs | 29 +++++++++++++++---- .../Config/HostConfigResource.cs | 1 + 6 files changed, 58 insertions(+), 7 deletions(-) diff --git a/frontend/src/FirstRun/AuthenticationRequiredModalContent.js b/frontend/src/FirstRun/AuthenticationRequiredModalContent.js index 426d573a5..3c341c0c5 100644 --- a/frontend/src/FirstRun/AuthenticationRequiredModalContent.js +++ b/frontend/src/FirstRun/AuthenticationRequiredModalContent.js @@ -34,7 +34,8 @@ function AuthenticationRequiredModalContent(props) { authenticationMethod, authenticationRequired, username, - password + password, + passwordConfirmation } = settings; const authenticationEnabled = authenticationMethod && authenticationMethod.value !== 'none'; @@ -120,6 +121,18 @@ function AuthenticationRequiredModalContent(props) { {...password} /> + + + {translate('PasswordConfirmation')} + + + : null } diff --git a/frontend/src/Settings/General/SecuritySettings.js b/frontend/src/Settings/General/SecuritySettings.js index 9986de3d9..5358c6107 100644 --- a/frontend/src/Settings/General/SecuritySettings.js +++ b/frontend/src/Settings/General/SecuritySettings.js @@ -124,6 +124,7 @@ class SecuritySettings extends Component { authenticationRequired, username, password, + passwordConfirmation, apiKey, certificateValidation } = settings; @@ -193,6 +194,21 @@ class SecuritySettings extends Component { null } + { + authenticationEnabled ? + + {translate('PasswordConfirmation')} + + + : + null + } + {translate('ApiKey')} diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 7ad228a08..9f1173ad0 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -86,6 +86,7 @@ "AuthenticationRequired": "Authentication Required", "AuthenticationRequiredHelpText": "Change which requests authentication is required for. Do not change unless you understand the risks.", "AuthenticationRequiredPasswordHelpTextWarning": "Enter a new password", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirm new password", "AuthenticationRequiredUsernameHelpTextWarning": "Enter a new username", "AuthenticationRequiredWarning": "To prevent remote access without authentication, {appName} now requires authentication to be enabled. You can optionally disable authentication from local addresses.", "Auto": "Auto", @@ -824,6 +825,7 @@ "ParseModalHelpTextDetails": "{appName} will attempt to parse the title and show you details about it", "ParseModalUnableToParse": "Unable to parse the provided title, please try again.", "Password": "Password", + "PasswordConfirmation": "Password Confirmation", "Path": "Path", "Paused": "Paused", "Peers": "Peers", diff --git a/src/NzbDrone.Core/Validation/Paths/FileExistsValidator.cs b/src/NzbDrone.Core/Validation/Paths/FileExistsValidator.cs index 5393ce57b..327765537 100644 --- a/src/NzbDrone.Core/Validation/Paths/FileExistsValidator.cs +++ b/src/NzbDrone.Core/Validation/Paths/FileExistsValidator.cs @@ -1,4 +1,4 @@ -using FluentValidation.Validators; +using FluentValidation.Validators; using NzbDrone.Common.Disk; namespace NzbDrone.Core.Validation.Paths diff --git a/src/Radarr.Api.V3/Config/HostConfigController.cs b/src/Radarr.Api.V3/Config/HostConfigController.cs index 23fb54b60..086180b86 100644 --- a/src/Radarr.Api.V3/Config/HostConfigController.cs +++ b/src/Radarr.Api.V3/Config/HostConfigController.cs @@ -47,6 +47,9 @@ namespace Radarr.Api.V3.Config SharedValidator.RuleFor(c => c.Password).NotEmpty().When(c => c.AuthenticationMethod == AuthenticationType.Basic || c.AuthenticationMethod == AuthenticationType.Forms); + SharedValidator.RuleFor(c => c.PasswordConfirmation) + .Must((resource, p) => IsMatchingPassword(resource)).WithMessage("Must match Password"); + SharedValidator.RuleFor(c => c.SslPort).ValidPort().When(c => c.EnableSsl); SharedValidator.RuleFor(c => c.SslPort).NotEqual(c => c.Port).When(c => c.EnableSsl); @@ -81,6 +84,23 @@ namespace Radarr.Api.V3.Config return cert != null; } + private bool IsMatchingPassword(HostConfigResource resource) + { + var user = _userService.FindUser(); + + if (user != null && user.Password == resource.Password) + { + return true; + } + + if (resource.Password == resource.PasswordConfirmation) + { + return true; + } + + return false; + } + protected override HostConfigResource GetResourceById(int id) { return GetHostConfig(); @@ -93,11 +113,10 @@ namespace Radarr.Api.V3.Config resource.Id = 1; var user = _userService.FindUser(); - if (user != null) - { - resource.Username = user.Username; - resource.Password = user.Password; - } + + resource.Username = user?.Username ?? string.Empty; + resource.Password = user?.Password ?? string.Empty; + resource.PasswordConfirmation = string.Empty; return resource; } diff --git a/src/Radarr.Api.V3/Config/HostConfigResource.cs b/src/Radarr.Api.V3/Config/HostConfigResource.cs index 7d4aed6f3..1edae531f 100644 --- a/src/Radarr.Api.V3/Config/HostConfigResource.cs +++ b/src/Radarr.Api.V3/Config/HostConfigResource.cs @@ -19,6 +19,7 @@ namespace Radarr.Api.V3.Config public bool AnalyticsEnabled { get; set; } public string Username { get; set; } public string Password { get; set; } + public string PasswordConfirmation { get; set; } public string LogLevel { get; set; } public string ConsoleLogLevel { get; set; } public string Branch { get; set; }