diff --git a/src/main/java/org/ays/admin_user/model/dto/request/AdminUserRegisterApplicationCompleteRequest.java b/src/main/java/org/ays/admin_user/model/dto/request/AdminUserRegisterApplicationCompleteRequest.java index a16391b50..af3549e31 100644 --- a/src/main/java/org/ays/admin_user/model/dto/request/AdminUserRegisterApplicationCompleteRequest.java +++ b/src/main/java/org/ays/admin_user/model/dto/request/AdminUserRegisterApplicationCompleteRequest.java @@ -1,12 +1,12 @@ package org.ays.admin_user.model.dto.request; import jakarta.validation.Valid; -import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import org.ays.common.model.dto.request.AysPhoneNumberRequest; +import org.ays.common.util.validation.Email; import org.ays.common.util.validation.Name; /** diff --git a/src/main/java/org/ays/common/util/validation/Email.java b/src/main/java/org/ays/common/util/validation/Email.java new file mode 100644 index 000000000..4507a89a9 --- /dev/null +++ b/src/main/java/org/ays/common/util/validation/Email.java @@ -0,0 +1,39 @@ +package org.ays.common.util.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to validate email using {@link EmailValidator}. + */ +@Target(value = ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = EmailValidator.class) +public @interface Email { + + /** + * Returns the error message when email is not valid. + * + * @return the error message + */ + String message() default "MUST BE VALID"; + + /** + * Returns the validation groups to which this constraint belongs. + * + * @return the validation groups + */ + Class[] groups() default {}; + + /** + * Returns the payload associated to this constraint. + * + * @return the payload + */ + Class[] payload() default {}; +} diff --git a/src/main/java/org/ays/common/util/validation/EmailValidator.java b/src/main/java/org/ays/common/util/validation/EmailValidator.java new file mode 100644 index 000000000..0efedae30 --- /dev/null +++ b/src/main/java/org/ays/common/util/validation/EmailValidator.java @@ -0,0 +1,44 @@ +package org.ays.common.util.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.springframework.util.StringUtils; + +/** + * A custom validator implementation for the {@link Email} annotation. + * Validates whether the provided email invalid domain + * specified regular expression. + */ +class EmailValidator implements ConstraintValidator { + + private static final String EMAIL_REGEX = + "^[a-zA-Z0-9çğıöşü._%+-]+[a-zA-Z0-9çğıöşü]+@[a-zA-Z0-9]+[.-]?[a-zA-Z0-9]+\\.[a-zA-Z]{2,}$"; + + /** + * Checks whether the given value is a valid email or not. + *

Some valid emails are:

+ * + * + *

Some invalid emails are:

+ * + * + * @param email object to validate + * @return true if the value is valid, false otherwise + */ + @Override + public boolean isValid(String email, ConstraintValidatorContext constraintValidatorContext) { + + if (!StringUtils.hasText(email)) { + return true; + } + return email.matches(EMAIL_REGEX); + } +} diff --git a/src/test/java/org/ays/admin_user/controller/AdminUserRegisterApplicationControllerTest.java b/src/test/java/org/ays/admin_user/controller/AdminUserRegisterApplicationControllerTest.java index fe14ced60..3e436b753 100644 --- a/src/test/java/org/ays/admin_user/controller/AdminUserRegisterApplicationControllerTest.java +++ b/src/test/java/org/ays/admin_user/controller/AdminUserRegisterApplicationControllerTest.java @@ -450,6 +450,79 @@ void givenInvalidAdminUserRegisterApplicationCompleteRequestWithParametrizedInva .completeRegistration(Mockito.anyString(), Mockito.any()); } + @ParameterizedTest + @ValueSource(strings = { + "abc.def@mail.c", + "abc.def@mail#archive.com", + "abc.def@mail", + "abcdef@mail..com", + "abc-@mail.com" + }) + void givenInvalidAdminUserRegisterApplicationCompleteRequestWithParametrizedInvalidEmails_whenEmailsAreNotValid_thenReturnValidationError(String invalidEmail) throws Exception { + + // Given + String mockId = AysRandomUtil.generateUUID(); + AdminUserRegisterApplicationCompleteRequest mockRequest = new AdminUserRegisterApplicationCompleteRequestBuilder() + .withValidFields() + .withEmail(invalidEmail) + .build(); + + // Then + String endpoint = BASE_PATH.concat("/registration-application/").concat(mockId).concat("/complete"); + MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders + .post(endpoint, mockRequest); + + AysError mockErrorResponse = AysErrorBuilder.VALIDATION_ERROR; + + aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse) + .andExpect(AysMockResultMatchersBuilders.status() + .isBadRequest()) + .andExpect(AysMockResultMatchersBuilders.subErrors() + .isNotEmpty()); + + // Verify + Mockito.verify(adminUserRegisterService, Mockito.never()) + .completeRegistration(Mockito.anyString(), Mockito.any()); + } + + @ParameterizedTest + @ValueSource(strings = { + "abcdef@mail.com", + "abc+def@archive.com", + "john.doe123@example.co.uk", + "admin_123@example.org", + "admin-test@ays.com", + "üşengeç-birkız@mail.com" + }) + void givenValidAdminUserRegisterApplicationCompleteRequestWithParametrizedValidEmails_whenEmailsAreValid_thenReturnSuccessResponse(String validEmail) throws Exception { + // Given + String mockId = AysRandomUtil.generateUUID(); + AdminUserRegisterApplicationCompleteRequest mockRequest = new AdminUserRegisterApplicationCompleteRequestBuilder() + .withValidFields() + .withEmail(validEmail) + .build(); + + // When + Mockito.doNothing().when(adminUserRegisterService).completeRegistration(Mockito.anyString(), Mockito.any()); + + // Then + String endpoint = BASE_PATH.concat("/registration-application/").concat(mockId).concat("/complete"); + MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders + .post(endpoint, mockRequest); + + AysResponse mockResponse = AysResponseBuilder.SUCCESS; + + aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse) + .andExpect(AysMockResultMatchersBuilders.status() + .isOk()) + .andExpect(AysMockResultMatchersBuilders.response() + .doesNotExist()); + + // Verify + Mockito.verify(adminUserRegisterService, Mockito.times(1)) + .completeRegistration(Mockito.anyString(), Mockito.any()); + } + @Test void givenValidAdminUserRegisterApplicationId_whenApproveAdminUserRegisterApplication_thenReturnNothing() throws Exception { // Given