diff --git a/src/main/java/com/example/solidconnection/auth/dto/EmailSignInRequest.java b/src/main/java/com/example/solidconnection/auth/dto/EmailSignInRequest.java index 925fb62cd..3987bc508 100644 --- a/src/main/java/com/example/solidconnection/auth/dto/EmailSignInRequest.java +++ b/src/main/java/com/example/solidconnection/auth/dto/EmailSignInRequest.java @@ -1,12 +1,16 @@ package com.example.solidconnection.auth.dto; +import com.example.solidconnection.auth.dto.validation.Password; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; public record EmailSignInRequest( @NotBlank(message = "이메일을 입력해주세요.") + @Email(message = "유효한 이메일 주소를 입력해주세요.") String email, + @Password @NotBlank(message = "비밀번호를 입력해주세요.") String password ) { diff --git a/src/main/java/com/example/solidconnection/auth/dto/EmailSignUpTokenRequest.java b/src/main/java/com/example/solidconnection/auth/dto/EmailSignUpTokenRequest.java index 52e50e5b2..ffafa222d 100644 --- a/src/main/java/com/example/solidconnection/auth/dto/EmailSignUpTokenRequest.java +++ b/src/main/java/com/example/solidconnection/auth/dto/EmailSignUpTokenRequest.java @@ -1,13 +1,16 @@ package com.example.solidconnection.auth.dto; +import com.example.solidconnection.auth.dto.validation.Password; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; public record EmailSignUpTokenRequest( - @Email(message = "이메일을 입력해주세요.") + @NotBlank(message = "이메일을 입력해주세요.") + @Email(message = "유효한 이메일 주소를 입력해주세요.") String email, + @Password @NotBlank(message = "비밀번호를 입력해주세요.") String password ) { diff --git a/src/main/java/com/example/solidconnection/auth/dto/validation/Password.java b/src/main/java/com/example/solidconnection/auth/dto/validation/Password.java new file mode 100644 index 000000000..a896b5724 --- /dev/null +++ b/src/main/java/com/example/solidconnection/auth/dto/validation/Password.java @@ -0,0 +1,20 @@ +package com.example.solidconnection.auth.dto.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; + +@Target({ElementType.FIELD, ElementType.RECORD_COMPONENT}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = PasswordValidator.class) +public @interface Password { + + String message() default "비밀번호는 영문, 숫자, 특수문자를 포함한 8자리 이상이어야 합니다."; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/com/example/solidconnection/auth/dto/validation/PasswordValidator.java b/src/main/java/com/example/solidconnection/auth/dto/validation/PasswordValidator.java new file mode 100644 index 000000000..77f8da213 --- /dev/null +++ b/src/main/java/com/example/solidconnection/auth/dto/validation/PasswordValidator.java @@ -0,0 +1,16 @@ +package com.example.solidconnection.auth.dto.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +public class PasswordValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null || value.isBlank()) { + return true; + } + + return value.matches("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-={}\\[\\]|:;\"'<>,.?/`~])\\S{8,}$"); + } +} diff --git a/src/test/java/com/example/solidconnection/auth/dto/validation/PasswordValidatorTest.java b/src/test/java/com/example/solidconnection/auth/dto/validation/PasswordValidatorTest.java new file mode 100644 index 000000000..8beb4c99e --- /dev/null +++ b/src/test/java/com/example/solidconnection/auth/dto/validation/PasswordValidatorTest.java @@ -0,0 +1,42 @@ +package com.example.solidconnection.auth.dto.validation; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("비밀번호 유효성 검사 테스트") +class PasswordValidatorTest { + + private final PasswordValidator validator = new PasswordValidator(); + + @Test + void 정상_패턴이면_true를_반환한다() { + assertThat(validator.isValid("abcd123!", null)).isTrue(); + } + + @Test + void 숫자가_없으면_false를_반환한다() { + assertThat(validator.isValid("abcdefg!", null)).isFalse(); + } + + @Test + void 영문자가_없으면_false를_반환한다() { + assertThat(validator.isValid("1234567!", null)).isFalse(); + } + + @Test + void 특수문자가_없으면_false를_반환한다() { + assertThat(validator.isValid("abcd1234", null)).isFalse(); + } + + @Test + void 공백을_포함하면_false를_반환한다() { + assertThat(validator.isValid("abcd123! ", null)).isFalse(); + } + + @Test + void 길이가_8자_미만이면_false를_반환한다() { + assertThat(validator.isValid("ab1!ab", null)).isFalse(); + } +}