Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenChangePasswordDialog new rules #328 #714

Merged
merged 14 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/System Application/App/Password/src/PasswordDialog.Page.al
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
ExtendedDatatype = Masked;
ToolTip = 'Specifies the current password, before the user defines a new one.';
Visible = ShowOldPassword;
trigger OnValidate()
begin
PasswordDialogImpl.ValidateOldPasswordMatch(OldPasswordToCompare, OldPasswordValue);
JesperSchulz marked this conversation as resolved.
Show resolved Hide resolved
end;
}
field(Password; PasswordValue)
{
Expand All @@ -39,6 +43,8 @@
begin
if RequiresPasswordValidation then
PasswordDialogImpl.ValidatePasswordStrength(PasswordValue);

PasswordDialogImpl.ValidateNewPasswordUniqueness(OldPasswordToCompare, PasswordValue);
end;
}
field(ConfirmPassword; ConfirmPasswordValue)
Expand Down Expand Up @@ -91,6 +97,7 @@
ConfirmPasswordValue: Text;
[NonDebuggable]
OldPasswordValue: Text;
OldPasswordToCompare: SecretText;
ShowOldPassword: Boolean;
ValidPassword: Boolean;
RequiresPasswordValidation: Boolean;
Expand Down Expand Up @@ -150,6 +157,16 @@
Password := OldPasswordValue;
end;

/// <summary>
/// Set the old password value to compare with typed on the page.
/// </summary>
/// <param name="OldPassword">Old password to compare.</param>
[Scope('OnPrem')]
procedure SetOldPasswordToCompareSecretValue(OldPassword: SecretText)

Check failure on line 165 in src/System Application/App/Password/src/PasswordDialog.Page.al

View workflow job for this annotation

GitHub Actions / Build System Application (Default) / System Application (Default)

AA0245 The name of the parameter 'OldPassword' is identical to a field, method, or action in the same scope.

Check failure on line 165 in src/System Application/App/Password/src/PasswordDialog.Page.al

View workflow job for this annotation

GitHub Actions / Build System Application (Translated) / System Application (Translated)

AA0245 The name of the parameter 'OldPassword' is identical to a field, method, or action in the same scope.

Check failure on line 165 in src/System Application/App/Password/src/PasswordDialog.Page.al

View workflow job for this annotation

GitHub Actions / Build System Application (Clean) / System Application (Clean)

AA0245 The name of the parameter 'OldPassword' is identical to a field, method, or action in the same scope.
begin
OldPasswordToCompare := OldPassword;
end;

/// <summary>
/// Enables the Change password mode, it makes the old password field on the page visible.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ codeunit 9811 "Password Dialog Impl."
PasswordMismatchErr: Label 'The passwords that you entered do not match.';
PasswordTooSimpleErr: Label 'The password that you entered does not meet the minimum requirements. It must be at least %1 characters long and contain at least one uppercase letter, one lowercase letter, one number and one special character. It must not have a sequence of 3 or more ascending, descending or repeating characters.', Comment = '%1: The minimum number of characters required in the password';
ConfirmBlankPasswordQst: Label 'Do you want to exit without entering a password?';
PasswordSameAsOldErr: Label 'The new password cannot be the same as the old password.';
OldPasswordMismatchErr: Label 'The old password does not match the entered password.';

procedure ValidatePasswordStrength(Password: SecretText)
var
Expand Down Expand Up @@ -73,6 +75,7 @@ codeunit 9811 "Password Dialog Impl."
PasswordDialog: Page "Password Dialog";
begin
PasswordDialog.EnableChangePassword();
PasswordDialog.SetOldPasswordToCompareSecretValue(OldPassword);
JesperSchulz marked this conversation as resolved.
Show resolved Hide resolved
if PasswordDialog.RunModal() = Action::OK then begin
Password := PasswordDialog.GetPasswordSecretValue();
OldPassword := PasswordDialog.GetOldPasswordSecretValue();
Expand All @@ -92,5 +95,21 @@ codeunit 9811 "Password Dialog Impl."
exit(false);
exit(true);
end;

[NonDebuggable]
procedure ValidateOldPasswordMatch(OldPasswordToCompare: SecretText; OldPasswordEntered: SecretText)
begin
if not OldPasswordToCompare.IsEmpty() then
Drakonian marked this conversation as resolved.
Show resolved Hide resolved
if OldPasswordToCompare.Unwrap() <> OldPasswordEntered.Unwrap() then
Error(OldPasswordMismatchErr);
end;

[NonDebuggable]
procedure ValidateNewPasswordUniqueness(OldPasswordToCompare: SecretText; NewPassword: SecretText)
begin
if not OldPasswordToCompare.IsEmpty() then
Drakonian marked this conversation as resolved.
Show resolved Hide resolved
if OldPasswordToCompare.Unwrap() = NewPassword.Unwrap() then
Error(PasswordSameAsOldErr);
end;
}

Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ codeunit 9810 "Password Dialog Management"
/// Opens a dialog for the user to change a password and returns the old and new typed passwords if there is no validation error,
/// otherwise an empty text are returned.
/// </summary>
/// <param name="OldPassword">Out parameter, the old password user typed on the dialog.</param>
/// <param name="OldPassword">Out parameter, the old password to compare with the password user typed on the dialog.</param>
JesperSchulz marked this conversation as resolved.
Show resolved Hide resolved
/// <param name="Password">Out parameter, the new password user typed on the dialog.</param>
procedure OpenChangePasswordDialog(var OldPassword: SecretText; var Password: SecretText)
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ codeunit 135033 "Password Dialog Test"
DisablePasswordValidation: Boolean;
PasswordMissmatch: Boolean;
ValidPasswordTxt: Label 'Some Password 2!';
AnotherValidPasswordTxt: Label 'Some Password 3!';
InValidPasswordTxt: Label 'Some Password';
AnotherPasswordTxt: Label 'Another Password';
PasswordSameAsOldErr: Label 'The new password cannot be the same as the old password.';
OldPasswordMismatchErr: Label 'The old password does not match the entered password.';

[Test]
[HandlerFunctions('PasswordDialogModalPageHandler')]
Expand Down Expand Up @@ -221,6 +224,29 @@ codeunit 135033 "Password Dialog Test"
Assert.AreEqual(ValidPasswordTxt, GetPasswordValue(Password), 'A diferrent password was expected.')
end;

[Test]
[HandlerFunctions('ChangePasswordDialogWitldOldPasswordModalPageHandler')]
procedure OpenChangePasswordDialogWithOldPasswordTest();
var
Password: SecretText;
OldPassword: SecretText;
begin
// [SCENARIO] Open Password dialog in change password mode. Old password
Drakonian marked this conversation as resolved.
Show resolved Hide resolved
// The old password has been passed on.
PermissionsMock.Set('All Objects');

// [GIVEN] The old password is for comparison that the old password matches the entered user and
// the new password does not match the old password.
OldPassword := SecretStrSubstNo(ValidPasswordTxt);

// [WHEN] The password dialog is opened in change password mode.
PasswordDialogManagement.OpenChangePasswordDialog(OldPassword, Password);

// [THEN] The Old and New passwords are retrieved.
Assert.AreEqual(ValidPasswordTxt, GetPasswordValue(OldPassword), 'A diferrent password was expected.');
Assert.AreEqual(AnotherValidPasswordTxt, GetPasswordValue(Password), 'A diferrent password was expected.')
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Password Dialog Management", 'OnSetMinPasswordLength', '', true, true)]
local procedure OnSetMinimumPAsswordLength(var MinPasswordLength: Integer);
begin
Expand All @@ -243,14 +269,29 @@ codeunit 135033 "Password Dialog Test"
[ModalPageHandler]
procedure ChangePasswordDialogModalPageHandler(var PasswordDialog: TestPage "Password Dialog");
begin
Assert.IsTrue(PasswordDialog.OldPassword.Visible(), 'Old Password Field should not be visible.');
Assert.IsTrue(PasswordDialog.ConfirmPassword.Visible(), 'Confirm Password Field should not be visible.');
Assert.IsTrue(PasswordDialog.OldPassword.Visible(), 'Old Password Field should be visible.');
Assert.IsTrue(PasswordDialog.ConfirmPassword.Visible(), 'Confirm Password Field should be visible.');
PasswordDialog.OldPassword.SetValue(InValidPasswordTxt);
PasswordDialog.Password.SetValue(ValidPasswordTxt);
PasswordDialog.ConfirmPassword.SetValue(ValidPasswordTxt);
PasswordDialog.OK().Invoke();
end;

[ModalPageHandler]
procedure ChangePasswordDialogWitldOldPasswordModalPageHandler(var PasswordDialog: TestPage "Password Dialog");
Drakonian marked this conversation as resolved.
Show resolved Hide resolved
begin
Assert.IsTrue(PasswordDialog.OldPassword.Visible(), 'Old Password Field should be visible.');
Assert.IsTrue(PasswordDialog.ConfirmPassword.Visible(), 'Confirm Password Field should be visible.');
asserterror PasswordDialog.OldPassword.SetValue(InValidPasswordTxt);
Assert.ExpectedError(OldPasswordMismatchErr);
PasswordDialog.OldPassword.SetValue(ValidPasswordTxt);
asserterror PasswordDialog.Password.SetValue(ValidPasswordTxt);
Assert.ExpectedError(PasswordSameAsOldErr);
PasswordDialog.Password.SetValue(AnotherValidPasswordTxt);
PasswordDialog.ConfirmPassword.SetValue(AnotherValidPasswordTxt);
PasswordDialog.OK().Invoke();
end;

[ConfirmHandler]
procedure ConfirmHandler(Question: Text[1024]; var Reply: Boolean);
begin
Expand Down
Loading