Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,16 @@ public class AuthController {
public ApiResult<Void> signUp(
@RequestBody @Valid AuthRequest.SignUp request
) {
authService.signUp(request.getEmail(), request.getPassword());
authService.signUp(
request.getEmail(),
request.getNickname(),
request.getPassword(),
request.isServiceTermsAgreed(),
request.isElectronicFinanceTermsAgreed(),
request.isPrivacyCollectionAgreed(),
request.isMarketingInfoAgreed(),
request.isOver14Agreed()
);

return ApiResult.ok();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ public static class SignUp {

@NotBlank
private String password;

@NotBlank
private String nickname;

private boolean serviceTermsAgreed;

private boolean electronicFinanceTermsAgreed;

private boolean privacyCollectionAgreed;

private boolean marketingInfoAgreed;

private boolean over14Agreed;
}

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public class User extends BaseEntity {
@Column(nullable = false, unique = true)
private String email;

@Column(unique = true)
private String nickname;

// TODO: 기획 논의 이후 비밀번호 정책 정규식 설정
private String password;

Expand All @@ -47,27 +50,77 @@ public class User extends BaseEntity {

private String oAuthRefreshToken;

@Column(nullable = false)
private boolean serviceTermsAgreed;

@Column(nullable = false)
private boolean electronicFinanceTermsAgreed;

@Column(nullable = false)
private boolean privacyCollectionAgreed;

@Column(nullable = false)
private boolean marketingInfoAgreed;

@Column(nullable = false)
private boolean over14Agreed;


@Builder
private User(UUID publicId, String email, String password, AuthProvider provider,
UserRole role, String oAuthUserId, String oAuthAccessToken, String oAuthRefreshToken) {
private User(
UUID publicId,
String email,
String nickname,
String password,
AuthProvider provider,
UserRole role,
String oAuthUserId,
String oAuthAccessToken,
String oAuthRefreshToken,
boolean serviceTermsAgreed,
boolean electronicFinanceTermsAgreed,
boolean privacyCollectionAgreed,
boolean marketingInfoAgreed,
boolean over14Agreed
) {
this.publicId = publicId;
this.email = email;
this.nickname = nickname;
this.password = password;
this.provider = provider;
this.role = role;
this.oAuthUserId = oAuthUserId;
this.oAuthAccessToken = oAuthAccessToken;
this.oAuthRefreshToken = oAuthRefreshToken;
this.serviceTermsAgreed = serviceTermsAgreed;
this.electronicFinanceTermsAgreed = electronicFinanceTermsAgreed;
this.privacyCollectionAgreed = privacyCollectionAgreed;
this.marketingInfoAgreed = marketingInfoAgreed;
this.over14Agreed = over14Agreed;
}

public static User createLocalUser(String email, String password) {
public static User createLocalUser(
String email,
String nickname,
String password,
boolean serviceTermsAgreed,
boolean electronicFinanceTermsAgreed,
boolean privacyCollectionAgreed,
boolean marketingInfoAgreed,
boolean over14Agreed
) {
return User.builder()
.publicId(UUID.randomUUID())
.email(email)
.nickname(nickname)
.password(password)
.provider(AuthProvider.LOCAL)
.role(UserRole.MEMBER)
.serviceTermsAgreed(serviceTermsAgreed)
.electronicFinanceTermsAgreed(electronicFinanceTermsAgreed)
.privacyCollectionAgreed(privacyCollectionAgreed)
.marketingInfoAgreed(marketingInfoAgreed)
.over14Agreed(over14Agreed)
.build();
}

Expand All @@ -81,11 +134,17 @@ public static User createOAuthUser(
return User.builder()
.publicId(UUID.randomUUID())
.email(email)
.nickname(null)
.provider(provider)
.role(UserRole.MEMBER)
.oAuthUserId(oAuthUserId)
.oAuthAccessToken(oAuthAccessToken)
.oAuthRefreshToken(oAuthRefreshToken)
.serviceTermsAgreed(false)
.electronicFinanceTermsAgreed(false)
.privacyCollectionAgreed(false)
.marketingInfoAgreed(false)
.over14Agreed(false)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ public static UserSignedUpEvent from (User user) {
EVENT_TYPE,
LocalDateTime.now(),
user.getPublicId(),
// TODO: 닉네임으로 변경 예정
user.getEmail()
user.getNickname()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public interface UserRepository extends JpaRepository<User, Long> {

boolean existsByEmail(String email);

boolean existsByNickname(String nickname);

default User findByEmailOrThrow(String email) {
return findByEmail(email).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_EMAIL)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.truve.platform.auth.service.service;

import java.util.UUID;
import java.util.regex.Pattern;

import org.springframework.data.util.Pair;
import org.springframework.security.crypto.password.PasswordEncoder;
Expand All @@ -23,6 +24,7 @@
@Service
@RequiredArgsConstructor
public class AuthService {
private static final Pattern NICKNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9가-힣]{2,10}$");

private final UserRepository userRepository;
private final EmailVerificationRepository emailVerificationRepository;
Expand Down Expand Up @@ -99,7 +101,16 @@ public void logout(String accessToken) {
}

@Transactional
public void signUp(String email, String password) {
public void signUp(
String email,
String nickname,
String password,
boolean serviceTermsAgreed,
boolean electronicFinanceTermsAgreed,
boolean privacyCollectionAgreed,
boolean marketingInfoAgreed,
boolean over14Agreed
) {

String verifiedAt = emailVerificationRepository.isVerifiedEmail(email);
Preconditions.validate(!(verifiedAt == null || verifiedAt.isBlank()), ErrorCode.NOT_VERIFIED_EMAIL);
Expand All @@ -108,10 +119,31 @@ public void signUp(String email, String password) {
!userRepository.existsByEmail(email),
ErrorCode.ALREADY_EXISTS_EMAIL
);
Preconditions.validate(
nickname != null && NICKNAME_PATTERN.matcher(nickname).matches(),
ErrorCode.INVALID_NICKNAME
);
Preconditions.validate(
!userRepository.existsByNickname(nickname),
ErrorCode.ALREADY_EXISTS_NICKNAME
);
Preconditions.validate(
serviceTermsAgreed && electronicFinanceTermsAgreed && privacyCollectionAgreed && over14Agreed,
ErrorCode.REQUIRED_TERMS_NOT_AGREED
);

String encodedPassword = passwordEncoder.encode(password);

User user = User.createLocalUser(email, encodedPassword);
User user = User.createLocalUser(
email,
nickname,
encodedPassword,
serviceTermsAgreed,
electronicFinanceTermsAgreed,
privacyCollectionAgreed,
marketingInfoAgreed,
over14Agreed
);

userRepository.save(user);
emailVerificationRepository.deleteVerifiedEmail(email);
Expand Down
2 changes: 1 addition & 1 deletion auth-server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ spring:

jpa:
hibernate:
ddl-auto: validate
ddl-auto: update
show-sql: false

kafka:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ class AuthControllerTest {
String body = """
{
"email": "new@test.com",
"password": "password123"
"password": "password123",
"nickname": "tester",
"serviceTermsAgreed": true,
"electronicFinanceTermsAgreed": true,
"privacyCollectionAgreed": true,
"marketingInfoAgreed": false,
"over14Agreed": true
}
""";

Expand All @@ -57,7 +63,7 @@ class AuthControllerTest {
// then
resultActions.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value("ok"));
verify(authService).signUp("new@test.com", "password123");
verify(authService).signUp("new@test.com", "tester", "password123", true, true, true, false, true);
}

@Test
Expand All @@ -67,11 +73,17 @@ class AuthControllerTest {
String body = """
{
"email": "dup@test.com",
"password": "password123"
"password": "password123",
"nickname": "tester",
"serviceTermsAgreed": true,
"electronicFinanceTermsAgreed": true,
"privacyCollectionAgreed": true,
"marketingInfoAgreed": false,
"over14Agreed": true
}
""";
willThrow(new CustomException(ErrorCode.ALREADY_EXISTS_EMAIL))
.given(authService).signUp(anyString(), anyString());
.given(authService).signUp(anyString(), anyString(), anyString(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean());

// when
ResultActions resultActions = mockMvc.perform(post("/api/auth/sign-up")
Expand All @@ -84,6 +96,66 @@ class AuthControllerTest {
.andExpect(jsonPath("$.code").value(ErrorCode.ALREADY_EXISTS_EMAIL.getCode()));
}

@Test
@DisplayName("필수 약관 미동의로 회원가입 요청하면 400을 반환한다.")
void 회원가입_실패_필수_약관_미동의() throws Exception {
// given
String body = """
{
"email": "new@test.com",
"password": "password123",
"nickname": "tester",
"serviceTermsAgreed": true,
"electronicFinanceTermsAgreed": false,
"privacyCollectionAgreed": true,
"marketingInfoAgreed": false,
"over14Agreed": true
}
""";
willThrow(new CustomException(ErrorCode.REQUIRED_TERMS_NOT_AGREED))
.given(authService).signUp(anyString(), anyString(), anyString(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean());

// when
ResultActions resultActions = mockMvc.perform(post("/api/auth/sign-up")
.contentType(MediaType.APPLICATION_JSON)
.content(body));

// then
resultActions.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.errorType").value("CLIENT_ERROR"))
.andExpect(jsonPath("$.code").value(ErrorCode.REQUIRED_TERMS_NOT_AGREED.getCode()));
}

@Test
@DisplayName("닉네임 형식 오류로 회원가입 요청하면 400을 반환한다.")
void 회원가입_실패_닉네임_형식_오류() throws Exception {
// given
String body = """
{
"email": "new@test.com",
"password": "password123",
"nickname": "a b",
"serviceTermsAgreed": true,
"electronicFinanceTermsAgreed": true,
"privacyCollectionAgreed": true,
"marketingInfoAgreed": false,
"over14Agreed": true
}
""";
willThrow(new CustomException(ErrorCode.INVALID_NICKNAME))
.given(authService).signUp(anyString(), anyString(), anyString(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean());

// when
ResultActions resultActions = mockMvc.perform(post("/api/auth/sign-up")
.contentType(MediaType.APPLICATION_JSON)
.content(body));

// then
resultActions.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.errorType").value("CLIENT_ERROR"))
.andExpect(jsonPath("$.code").value(ErrorCode.INVALID_NICKNAME.getCode()));
}

@Test
@DisplayName("로그인에 성공하면 accessToken을 반환하고 refreshToken 쿠키를 설정한다.")
void 로그인_성공() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
class UserTest {

private static final String EMAIL = "test@truve.com";
private static final String NICKNAME = "tester";
private static final String PASSWORD = "encoded-password";
private static final String OAUTH_USER_ID = "oauth-user-id";
private static final String OAUTH_ACCESS_TOKEN = "oauth-access-token";
Expand All @@ -28,15 +29,21 @@ class CreateLocalUserTest {
@DisplayName("createLocalUser 호출 시 LOCAL/MEMBER 권한으로 사용자를 생성한다.")
void createLocalUser_success() {
// when
User user = User.createLocalUser(EMAIL, PASSWORD);
User user = User.createLocalUser(EMAIL, NICKNAME, PASSWORD, true, true, true, false, true);

// then
assertAll(
() -> assertThat(user.getPublicId()).isInstanceOf(UUID.class),
() -> assertThat(user.getEmail()).isEqualTo(EMAIL),
() -> assertThat(user.getNickname()).isEqualTo(NICKNAME),
() -> assertThat(user.getPassword()).isEqualTo(PASSWORD),
() -> assertThat(user.getProvider()).isEqualTo(AuthProvider.LOCAL),
() -> assertThat(user.getRole()).isEqualTo(UserRole.MEMBER),
() -> assertThat(user.isServiceTermsAgreed()).isTrue(),
() -> assertThat(user.isElectronicFinanceTermsAgreed()).isTrue(),
() -> assertThat(user.isPrivacyCollectionAgreed()).isTrue(),
() -> assertThat(user.isMarketingInfoAgreed()).isFalse(),
() -> assertThat(user.isOver14Agreed()).isTrue(),
() -> assertThat(user.getOAuthUserId()).isNull(),
() -> assertThat(user.getOAuthAccessToken()).isNull(),
() -> assertThat(user.getOAuthRefreshToken()).isNull()
Expand Down Expand Up @@ -64,9 +71,15 @@ void createOAuthUser_success() {
assertAll(
() -> assertThat(user.getPublicId()).isInstanceOf(UUID.class),
() -> assertThat(user.getEmail()).isEqualTo(EMAIL),
() -> assertThat(user.getNickname()).isNull(),
() -> assertThat(user.getPassword()).isNull(),
() -> assertThat(user.getProvider()).isEqualTo(AuthProvider.KAKAO),
() -> assertThat(user.getRole()).isEqualTo(UserRole.MEMBER),
() -> assertThat(user.isServiceTermsAgreed()).isFalse(),
() -> assertThat(user.isElectronicFinanceTermsAgreed()).isFalse(),
() -> assertThat(user.isPrivacyCollectionAgreed()).isFalse(),
() -> assertThat(user.isMarketingInfoAgreed()).isFalse(),
() -> assertThat(user.isOver14Agreed()).isFalse(),
() -> assertThat(user.getOAuthUserId()).isEqualTo(OAUTH_USER_ID),
() -> assertThat(user.getOAuthAccessToken()).isEqualTo(OAUTH_ACCESS_TOKEN),
() -> assertThat(user.getOAuthRefreshToken()).isEqualTo(OAUTH_REFRESH_TOKEN)
Expand Down
Loading