diff --git a/src/org/labkey/test/tests/core/login/PasswordTest.java b/src/org/labkey/test/tests/core/login/PasswordTest.java index 5fea5c0fda..94010eb349 100644 --- a/src/org/labkey/test/tests/core/login/PasswordTest.java +++ b/src/org/labkey/test/tests/core/login/PasswordTest.java @@ -33,6 +33,7 @@ import org.labkey.test.pages.core.login.DatabaseAuthConfigureDialog; import org.labkey.test.pages.core.login.LoginConfigurePage; import org.labkey.test.params.login.DatabaseAuthenticationProvider; +import org.labkey.test.util.APIUserHelper; import org.labkey.test.util.LogMethod; import org.labkey.test.util.LoggedParam; import org.labkey.test.util.core.login.DbLoginUtils; @@ -256,7 +257,11 @@ public void testPasswordParameter() @Test public void testChooseNewPasswordMessages() throws IOException { - // Hold an admin connection open, allowing us to reset the config regardless of what happens during the test + // Test bad API key + signOut(); + signInShouldFailUiAndApi("apikey", "abc123", "The API key you provided is invalid."); + + // Hold an admin API connection open, allowing us to reset the config without the browser session interfering Connection adminConnection = WebTestHelper.getRemoteApiConnection(); DbLoginProperties savedProperties = DbLoginUtils.getDbLoginConfig(adminConnection); @@ -268,25 +273,28 @@ public void testChooseNewPasswordMessages() throws IOException ); // Set a weak password - signOut(); String resetUrl = userInitiatePasswordReset(USER); beginAt(resetUrl); new SetPasswordForm(getDriver()) .setNewPassword(WEAK_PASSWORD) .clickSubmit(); - // Test bogus password first - signOut(); - signInShouldFail("bogus", "The email address and password you entered did not match any accounts on file."); - signIn(USER, WEAK_PASSWORD); + // Test bogus password signOut(); + signInShouldFailUiAndApi(USER, "bogus", "The email address and password you entered did not match any accounts on file."); + + // Test deactivated user + APIUserHelper helper = new APIUserHelper(() -> adminConnection); + helper.deactivateUsers(_userId); + signInShouldFailUiAndApi(USER, WEAK_PASSWORD, "Your account has been deactivated."); + helper.activateUsers(_userId); // Change the configuration and test password that no longer meets complexity requirements DbLoginUtils.setDbLoginConfig(adminConnection, PasswordStrength.Strong, PasswordExpiration.Never ); - signInShouldFail(WEAK_PASSWORD, "Your password does not meet the complexity requirements; please choose a new password."); + signInShouldFailUiAndApi(USER, WEAK_PASSWORD, "Your password does not meet the complexity requirements; please choose a new password."); String strongPassword = VERY_STRONG_PASSWORD + "!"; changeInvalidPassword(WEAK_PASSWORD, strongPassword); @@ -297,7 +305,7 @@ public void testChooseNewPasswordMessages() throws IOException ); // Wait six seconds for expiration sleep(6000); - signInShouldFail(strongPassword, "Your password has expired; please choose a new password."); + signInShouldFailUiAndApi(USER, strongPassword, "Your password has expired; please choose a new password."); changeInvalidPassword(strongPassword, VERY_STRONG_PASSWORD + "@"); } finally @@ -307,10 +315,10 @@ public void testChooseNewPasswordMessages() throws IOException } // Attempt to sign in via UI and API, expecting both to fail with the specified message - private void signInShouldFail(String password, String expectedMessage) throws IOException + private void signInShouldFailUiAndApi(String email, String password, String expectedMessage) throws IOException { - signInShouldFail(USER, password, expectedMessage); - Connection userConnection = new Connection(WebTestHelper.getBaseURL(), USER, password); + signInShouldFail(email, password, expectedMessage); + Connection userConnection = new Connection(WebTestHelper.getBaseURL(), email, password); EnsureLoginCommand ensureLoginCommand = new EnsureLoginCommand(); try { diff --git a/src/org/labkey/test/util/APIUserHelper.java b/src/org/labkey/test/util/APIUserHelper.java index 9f8eac0b84..311b953b6c 100644 --- a/src/org/labkey/test/util/APIUserHelper.java +++ b/src/org/labkey/test/util/APIUserHelper.java @@ -15,6 +15,7 @@ */ package org.labkey.test.util; +import org.apache.commons.lang3.ArrayUtils; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; import org.apache.hc.core5.http.message.BasicNameValuePair; @@ -27,6 +28,7 @@ import org.labkey.remoteapi.Connection; import org.labkey.remoteapi.PostCommand; import org.labkey.remoteapi.SimpleGetCommand; +import org.labkey.remoteapi.SimplePostCommand; import org.labkey.remoteapi.security.CreateUserCommand; import org.labkey.remoteapi.security.CreateUserResponse; import org.labkey.remoteapi.security.DeleteUserCommand; @@ -52,7 +54,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; public class APIUserHelper extends AbstractUserHelper { @@ -239,14 +240,17 @@ private void deleteUser(@NotNull Integer userId) protected void _deleteUsers(boolean failIfNotFound, String... userEmails) { Map userIds = getUserIds(Arrays.asList(userEmails), true); + List validUserIds = new ArrayList<>(); for (String userEmail : new HashSet<>(Arrays.asList(userEmails))) { Integer userId = userIds.get(userEmail); if (failIfNotFound) - assertTrue(userEmail + " was not present", userId != null); + assertNotNull(userEmail + " was not present", userId); if (userId != null) - deleteUser(userId); + validUserIds.add(userId); } + if (!validUserIds.isEmpty()) + deleteUsers(ArrayUtils.toPrimitive(validUserIds.toArray(new Integer[0]))); } private static final Pattern regEmailVerification = Pattern.compile("verification=([A-Za-z0-9]+)"); @@ -289,6 +293,35 @@ public String setInitialPassword(int userId) throw new RuntimeException(e); } } + + public void deleteUsers(int... userIds) + { + updateUsersState(false, true, userIds); + } + + public void deactivateUsers(int... userIds) + { + updateUsersState(false, false, userIds); + } + + public void activateUsers(int... userIds) + { + updateUsersState(true, false, userIds); + } + + private void updateUsersState(boolean activate, boolean delete, int... userIds) + { + SimplePostCommand updateUsers = new SimplePostCommand("user", "updateUsersStateApi"); + updateUsers.setJsonObject(new JSONObject(Map.of("userId", userIds, "activate", activate, "delete", delete))); + try + { + updateUsers.execute(connectionSupplier.get(), null); + } + catch (IOException | CommandException e) + { + throw new RuntimeException(e); + } + } } class SetPasswordCommand extends PostCommand