This is an automated email from the ASF dual-hosted git repository. solomax pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openmeetings.git
commit 5f29e028821dbf9a9db54b83892a36842def7745 Author: Maxim Solodovnik <[email protected]> AuthorDate: Thu Aug 14 15:05:05 2025 +0700 [OPENMEETINGS-2799] user web service validates email on user creation --- .../openmeetings/web/pages/auth/TestLoginUI.java | 38 ++++++++++++++-------- .../apache/openmeetings/ws/TestUserService.java | 38 +++++++++++++++++----- .../openmeetings/webservice/UserWebService.java | 15 +++++++-- 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/openmeetings-web/src/test/java/org/apache/openmeetings/web/pages/auth/TestLoginUI.java b/openmeetings-web/src/test/java/org/apache/openmeetings/web/pages/auth/TestLoginUI.java index ec6411083..6d83d916b 100644 --- a/openmeetings-web/src/test/java/org/apache/openmeetings/web/pages/auth/TestLoginUI.java +++ b/openmeetings-web/src/test/java/org/apache/openmeetings/web/pages/auth/TestLoginUI.java @@ -46,6 +46,8 @@ import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.IResource.Attributes; import org.apache.wicket.util.tester.FormTester; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; class TestLoginUI extends AbstractWicketTesterTest { private static final String PATH_REGISTER = "register:form"; @@ -97,11 +99,18 @@ class TestLoginUI extends AbstractWicketTesterTest { assertTrue(countErrors(tester) > 7, "There should be at least 8 errors"); } + @ParameterizedTest + @ValueSource(strings = {"", " ", "aaaaa", "aaa\rbbb@eeeee", "gggg\n@hhhh"}) + void testBadEmailRegister(String email) throws ReflectiveOperationException, SecurityException { + String uid = randomUUID().toString(); + performRegister(uid, email, 1, "account.created"); + FormTester formTester = showRegister(); + formTester.submit("submit"); + assertTrue(countErrors(tester) > 7, "There should be at least 8 errors"); + } + @Test void testRegister() throws ReflectiveOperationException, SecurityException { - tester.startPage(SignInPage.class); - tester.assertRenderedPage(SignInPage.class); - String uid = randomUUID().toString(); boolean verify = isSendVerificationEmail(); try { @@ -153,21 +162,25 @@ class TestLoginUI extends AbstractWicketTesterTest { } private void performRegister(String uid, String lbl) throws ReflectiveOperationException, SecurityException { - AbstractAjaxBehavior b1 = getButtonBehavior("signin", 1); - tester.executeBehavior(b1); - FormTester formTester = tester.newFormTester(PATH_REGISTER); + performRegister(uid, getEmail(uid), 0, lbl); + } + + private void performRegister(String uid, String emailToTest, int errorsExpected, String lbl) throws ReflectiveOperationException, SecurityException { + FormTester formTester = showRegister(); formTester.setValue("login", getLogin(uid)); - formTester.setValue("email", getEmail(uid)); + formTester.setValue("email", emailToTest); formTester.setValue("firstName", "first" + uid); formTester.setValue("lastName", "last" + uid); formTester.setValue("password", USER_PASS); formTester.setValue("confirmPassword", USER_PASS); formTester.setValue("captcha:captchaText", getCaptcha("register:form:captcha:captcha")); formTester.submit("submit"); - checkErrors(0); - tester.assertLabel("registerInfo:content", getEscapedString(lbl)); - AbstractAjaxBehavior b2 = getButtonBehavior("registerInfo", 0); - tester.executeBehavior(b2); + checkErrors(errorsExpected); + if (errorsExpected == 0) { + tester.assertLabel("registerInfo:content", getEscapedString(lbl)); + AbstractAjaxBehavior b2 = getButtonBehavior("registerInfo", 0); + tester.executeBehavior(b2); + } } private void performForget(String uid) throws ReflectiveOperationException, SecurityException { @@ -191,9 +204,6 @@ class TestLoginUI extends AbstractWicketTesterTest { cfgDao.update(c, null); } try { - tester.startPage(SignInPage.class); - tester.assertRenderedPage(SignInPage.class); - String uid = String.valueOf(Math.abs(RND.nextLong())); // number uid is used to prevent password validation errors performRegister(uid, "warn.notverified"); diff --git a/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestUserService.java b/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestUserService.java index 3473340aa..ca63734a8 100644 --- a/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestUserService.java +++ b/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestUserService.java @@ -51,6 +51,8 @@ import org.apache.openmeetings.util.OmException; import org.apache.wicket.util.string.StringValue; import org.apache.wicket.util.string.Strings; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; class TestUserService extends AbstractWebServiceTest { private static final String DUMMY_PICTURE_URL = "https://openmeetings.apache.org/images/logo.png"; @@ -128,7 +130,9 @@ class TestUserService extends AbstractWebServiceTest { assertEquals(userId1, userId2, "User should be the same"); } - private UserDTO doAddUser(String uuid, String extId) { + private static record AddUserResult<T>(UserDTO initial, T created) {} + + private <T> AddUserResult<T> sendAddUser(String uuid, String email, String extId, int expCode, Class<T> expected) { String[] tzList = TimeZone.getAvailableIDs(); String tz = TimeZone.getTimeZone(tzList[RND.nextInt(tzList.length)]).getID(); ServiceResult r = login(); @@ -139,23 +143,39 @@ class TestUserService extends AbstractWebServiceTest { u.setFirstname("testF" + uuid); u.setLastname("testL" + uuid); u.setAddress(new Address()); - u.getAddress().setEmail(uuid + "@local"); + u.getAddress().setEmail(email); u.getAddress().setCountry(Locale.getDefault().getCountry()); u.setTimeZoneId(tz); if (!Strings.isEmpty(extId)) { u.setExternalId(extId); u.setExternalType(UNIT_TEST_EXT_TYPE); } - UserDTO user = getClient(getUserUrl()) + Response resp = getClient(getUserUrl()) .path("/") .query("sid", r.getMessage()) .type(APPLICATION_FORM_URLENCODED) - .post(new Form().param("user", u.toString()).param("confirm", "" + false), UserDTO.class); - assertNotNull(user, "Valid UserDTO should be returned"); - assertNotNull(user.getId(), "Id should not be NULL"); - assertEquals(u.getLogin(), user.getLogin(), "Login should match"); - assertEquals(tz, user.getTimeZoneId(), "Timezone should match"); - return user; + .post(new Form().param("user", u.toString()).param("confirm", "" + false)); + + assertEquals(expCode, resp.getStatus(), "Not allowed error"); + assertTrue(resp.hasEntity()); + return new AddUserResult<T>(u, resp.readEntity(expected)); + } + + private UserDTO doAddUser(String uuid, String extId) { + AddUserResult<UserDTO> result = sendAddUser(uuid, uuid + "@local", extId, 200, UserDTO.class); + assertNotNull(result.created, "Valid UserDTO should be returned"); + assertNotNull(result.created.getId(), "Id should not be NULL"); + assertEquals(result.initial.getLogin(), result.created.getLogin(), "Login should match"); + assertEquals(result.initial.getTimeZoneId(), result.created.getTimeZoneId(), "Timezone should match"); + return result.created; + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", "aaaaa", "aaa\rbbb@eeeee", "gggg\n@hhhh"}) + void addUserBadEmailTest(String email) { + String uuid = randomUUID().toString(); + AddUserResult<ServiceResult> result = sendAddUser(uuid, email, uuid, 500, ServiceResult.class); + assertEquals(ServiceResult.Type.ERROR.name(), result.created.getType()); } @Test diff --git a/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/UserWebService.java b/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/UserWebService.java index 18be94ffc..18bf1ceb2 100644 --- a/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/UserWebService.java +++ b/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/UserWebService.java @@ -46,6 +46,7 @@ import jakarta.ws.rs.core.MediaType; import org.apache.cxf.feature.Features; import org.apache.openmeetings.core.util.StrongPasswordValidator; +import org.apache.openmeetings.db.dao.label.LabelDao; import org.apache.openmeetings.db.dao.server.SOAPLoginDao; import org.apache.openmeetings.db.dao.user.GroupDao; import org.apache.openmeetings.db.dao.user.IUserManager; @@ -66,9 +67,9 @@ import org.apache.openmeetings.webservice.error.ServiceException; import org.apache.openmeetings.webservice.schema.ServiceResultWrapper; import org.apache.openmeetings.webservice.schema.UserDTOListWrapper; import org.apache.openmeetings.webservice.schema.UserDTOWrapper; +import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator; import org.apache.wicket.util.string.Strings; import org.apache.wicket.validation.IValidationError; -import org.apache.wicket.validation.IValidator; import org.apache.wicket.validation.Validatable; import org.apache.wicket.validation.ValidationError; import org.slf4j.Logger; @@ -228,9 +229,8 @@ public class UserWebService extends BaseWebService { user.setLanguageId(1L); } User jsonUser = uMapper.get(user); - IValidator<String> passValidator = new StrongPasswordValidator(false, jsonUser); Validatable<String> passVal = new Validatable<>(user.getPassword()); - passValidator.validate(passVal); + new StrongPasswordValidator(false, jsonUser).validate(passVal); if (!passVal.isValid()) { StringBuilder sb = new StringBuilder(); for (IValidationError err : passVal.getErrors()) { @@ -239,6 +239,7 @@ public class UserWebService extends BaseWebService { log.trace("addNewUser::weak password '*****', msg: {}", sb); throw new InternalServiceException(sb.toString()); } + checkEmail(user.getAddress().getEmail()); Object ouser; try { jsonUser.addGroup(groupDao.get(getDefaultGroup())); @@ -268,6 +269,14 @@ public class UserWebService extends BaseWebService { }); } + private void checkEmail(String email) { + Validatable<String> emailVal = new Validatable<>(email); + RfcCompliantEmailAddressValidator.getInstance().validate(emailVal); + if (!emailVal.isValid()) { + throw new InternalServiceException(LabelDao.getString("234", 1L)); + } + } + /** * * Delete a certain user by its id
