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

Reply via email to