-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from Yanol-Market/feature/39
Feature/39 회원가입
- Loading branch information
Showing
12 changed files
with
285 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
src/main/java/site/goldenticket/domain/user/controller/UserController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package site.goldenticket.domain.user.controller; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.*; | ||
import site.goldenticket.common.response.CommonResponse; | ||
import site.goldenticket.domain.user.dto.JoinRequest; | ||
import site.goldenticket.domain.user.dto.JoinResponse; | ||
import site.goldenticket.domain.user.service.UserService; | ||
|
||
import static org.springframework.http.HttpStatus.CREATED; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/users") | ||
public class UserController { | ||
|
||
private final UserService userService; | ||
|
||
@GetMapping("/check/email") | ||
public ResponseEntity<CommonResponse<Boolean>> duplicateEmail(@RequestParam String email) { | ||
return ResponseEntity.ok(CommonResponse.ok(userService.isExistEmail(email))); | ||
} | ||
|
||
@GetMapping("/check/nickname") | ||
public ResponseEntity<CommonResponse<Boolean>> duplicateNickname(@RequestParam String nickname) { | ||
return ResponseEntity.ok(CommonResponse.ok(userService.isExistNickname(nickname))); | ||
} | ||
|
||
@PostMapping | ||
public ResponseEntity<CommonResponse<JoinResponse>> join(@RequestBody @Validated JoinRequest joinRequest) { | ||
JoinResponse response = userService.join(joinRequest); | ||
return new ResponseEntity<>(CommonResponse.ok(response), CREATED); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/site/goldenticket/domain/user/dto/AgreementRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package site.goldenticket.domain.user.dto; | ||
|
||
import jakarta.validation.constraints.NotEmpty; | ||
import site.goldenticket.domain.user.entity.Agreement; | ||
import site.goldenticket.domain.user.entity.User; | ||
|
||
public record AgreementRequest( | ||
@NotEmpty(message = "마케팅 동의는 필수 선택 사항입니다.") | ||
Boolean isMarketing | ||
) { | ||
|
||
public Agreement toEntity(User user) { | ||
Agreement agreement = Agreement.builder() | ||
.marketing(isMarketing) | ||
.build(); | ||
agreement.registerUser(user); | ||
return agreement; | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/main/java/site/goldenticket/domain/user/dto/JoinRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package site.goldenticket.domain.user.dto; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotEmpty; | ||
import jakarta.validation.constraints.Pattern; | ||
import jakarta.validation.constraints.Size; | ||
import site.goldenticket.domain.user.entity.User; | ||
|
||
public record JoinRequest( | ||
@NotEmpty(message = "비밀번호는 필수 입력 항목입니다.") | ||
@Size(min = 2, message = "이름은 두 글자 이상의 한글이어야 합니다.") | ||
String name, | ||
@NotEmpty(message = "닉네임은 필수 입력 항목입니다.") | ||
@Size(max = 15, message = "닉네임은 1글자 이상, 15자 이하여야 합니다.") | ||
String nickname, | ||
@NotEmpty(message = "이메일은 필수 입력 항목입니다.") | ||
@Email(message = "이메일은 유효한 형식이어야 합니다.") | ||
String email, | ||
@NotEmpty(message = "비밀번호는 필수 입력 항목입니다.") | ||
@Size(min = 6, max = 20, message = "비밀번호는 6자 이상, 20자 이하여야 합니다.") | ||
String password, | ||
@NotEmpty(message = "휴대폰 번호는 필수 입력 항목입니다.") | ||
@Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$", message = "000-0000-0000 형식이여야 합니다.") | ||
String phoneNumber, | ||
Long yanoljaId, | ||
AgreementRequest agreement | ||
) { | ||
|
||
public User toEntity(String encodePassword) { | ||
User user = User.builder() | ||
.name(name) | ||
.nickname(nickname) | ||
.email(email) | ||
.password(encodePassword) | ||
.phoneNumber(phoneNumber) | ||
.yanoljaId(yanoljaId) | ||
.build(); | ||
agreement.toEntity(user); | ||
return user; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/site/goldenticket/domain/user/dto/JoinResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package site.goldenticket.domain.user.dto; | ||
|
||
import site.goldenticket.domain.user.entity.User; | ||
|
||
public record JoinResponse(Long id) { | ||
|
||
public static JoinResponse from(User user) { | ||
return new JoinResponse(user.getId()); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/site/goldenticket/domain/user/entity/Agreement.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package site.goldenticket.domain.user.entity; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.*; | ||
import site.goldenticket.common.entiy.BaseTimeEntity; | ||
|
||
import static jakarta.persistence.FetchType.LAZY; | ||
|
||
@Getter | ||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@ToString(exclude = {"user"}) | ||
public class Agreement extends BaseTimeEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@OneToOne(fetch = LAZY) | ||
@JoinColumn(name = "user_id") | ||
private User user; | ||
|
||
private Boolean marketing; | ||
|
||
@Builder | ||
private Agreement(Boolean marketing) { | ||
this.marketing = marketing; | ||
} | ||
|
||
public void registerUser(User user) { | ||
this.user = user; | ||
user.registerAlertSetting(this); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
src/main/java/site/goldenticket/domain/user/service/UserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package site.goldenticket.domain.user.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import site.goldenticket.common.exception.CustomException; | ||
import site.goldenticket.domain.user.dto.JoinRequest; | ||
import site.goldenticket.domain.user.dto.JoinResponse; | ||
import site.goldenticket.domain.user.entity.User; | ||
import site.goldenticket.domain.user.repository.UserRepository; | ||
|
||
import static site.goldenticket.common.response.ErrorCode.ALREADY_EXIST_EMAIL; | ||
import static site.goldenticket.common.response.ErrorCode.ALREADY_EXIST_NICKNAME; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class UserService { | ||
|
||
private final UserRepository userRepository; | ||
private final PasswordEncoder passwordEncoder; | ||
|
||
public boolean isExistEmail(String email) { | ||
log.info("Duplicated Check Email = {}", email); | ||
return userRepository.findByEmail(email).isPresent(); | ||
} | ||
|
||
public boolean isExistNickname(String nickname) { | ||
log.info("Duplicated Check Nickname = {}", nickname); | ||
return userRepository.existsByNickname(nickname); | ||
} | ||
|
||
@Transactional | ||
public JoinResponse join(JoinRequest joinRequest) { | ||
joinValidate(joinRequest); | ||
log.info("Join User Info = {}", joinRequest); | ||
|
||
String encodePassword = passwordEncoder.encode(joinRequest.password()); | ||
User user = joinRequest.toEntity(encodePassword); | ||
userRepository.save(user); | ||
return JoinResponse.from(user); | ||
} | ||
|
||
private void joinValidate(JoinRequest joinRequest) { | ||
if (isExistEmail(joinRequest.email())) { | ||
throw new CustomException(ALREADY_EXIST_EMAIL); | ||
} | ||
|
||
if (isExistNickname(joinRequest.nickname())) { | ||
throw new CustomException(ALREADY_EXIST_NICKNAME); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,24 +2,21 @@ | |
|
||
import site.goldenticket.domain.user.entity.User; | ||
|
||
import static site.goldenticket.domain.user.entity.RoleType.ROLE_USER; | ||
|
||
public final class UserUtils { | ||
|
||
public static String EMAIL = "[email protected]"; | ||
public static String PASSWORD = "password"; | ||
public static String NAME = "name"; | ||
public static String NICKNAME = "nickname"; | ||
public static String PHONENUMBER = "010-0000-0000"; | ||
public static String PHONE_NUMBER = "010-0000-0000"; | ||
|
||
public static User createUser(String encodePassword) { | ||
return User.builder() | ||
.email(EMAIL) | ||
.password(encodePassword) | ||
.name(NAME) | ||
.nickname(NICKNAME) | ||
.phoneNumber(PHONENUMBER) | ||
.role(ROLE_USER) | ||
.phoneNumber(PHONE_NUMBER) | ||
.build(); | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
src/test/java/site/goldenticket/domain/user/controller/UserControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package site.goldenticket.domain.user.controller; | ||
|
||
import io.restassured.RestAssured; | ||
import io.restassured.response.ExtractableResponse; | ||
import io.restassured.response.Response; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import site.goldenticket.common.config.ApiTest; | ||
import site.goldenticket.domain.user.dto.AgreementRequest; | ||
import site.goldenticket.domain.user.dto.JoinRequest; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.springframework.http.HttpStatus.CREATED; | ||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; | ||
import static site.goldenticket.common.utils.UserUtils.*; | ||
|
||
@DisplayName("UserController 검증") | ||
class UserControllerTest extends ApiTest { | ||
|
||
@Test | ||
@DisplayName("회원가입 검증") | ||
void join() { | ||
// given | ||
JoinRequest request = new JoinRequest( | ||
NAME, | ||
NICKNAME, | ||
EMAIL, | ||
PASSWORD, | ||
PHONE_NUMBER, | ||
null, | ||
new AgreementRequest(true) | ||
); | ||
|
||
String url = "/users"; | ||
|
||
// when | ||
ExtractableResponse<Response> result = RestAssured | ||
.given().log().all() | ||
.contentType(APPLICATION_JSON_VALUE) | ||
.body(request) | ||
.when() | ||
.post(url) | ||
.then().log().all() | ||
.extract(); | ||
|
||
// then | ||
assertThat(result.statusCode()).isEqualTo(CREATED.value()); | ||
assertThat(result.jsonPath().getLong("data.id")).isEqualTo(1L); | ||
} | ||
} |