diff --git a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java index 19e8bdc7..2e7443ae 100644 --- a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java +++ b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java @@ -50,7 +50,9 @@ private static OAuthUserInfo ofKakao(final Map attributes) { String name = (String) profile.get("name"); return OAuthUserInfo.builder() - .name(name) + .name("김모수") + .phoneNumber("010-1234-5678") + .birthDay(LocalDate.EPOCH) .email("test123@gmali.com") .build(); } else { diff --git a/src/main/java/life/mosu/mosuserver/application/user/MyUserService.java b/src/main/java/life/mosu/mosuserver/application/user/MyUserService.java index 42588f50..a55e3a5e 100644 --- a/src/main/java/life/mosu/mosuserver/application/user/MyUserService.java +++ b/src/main/java/life/mosu/mosuserver/application/user/MyUserService.java @@ -6,11 +6,11 @@ import life.mosu.mosuserver.domain.user.UserJpaRepository; import life.mosu.mosuserver.global.exception.CustomRuntimeException; import life.mosu.mosuserver.global.exception.ErrorCode; -import life.mosu.mosuserver.presentation.user.dto.ChangePasswordRequest; -import life.mosu.mosuserver.presentation.user.dto.ChangePasswordResponse; -import life.mosu.mosuserver.presentation.user.dto.FindLoginIdRequest; -import life.mosu.mosuserver.presentation.user.dto.FindLoginIdResponse; -import life.mosu.mosuserver.presentation.user.dto.FindPasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.request.ChangePasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.request.FindLoginIdRequest; +import life.mosu.mosuserver.presentation.user.dto.request.FindPasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.response.ChangePasswordResponse; +import life.mosu.mosuserver.presentation.user.dto.response.FindLoginIdResponse; import lombok.RequiredArgsConstructor; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; diff --git a/src/main/java/life/mosu/mosuserver/application/user/UserService.java b/src/main/java/life/mosu/mosuserver/application/user/UserService.java index 9f42c387..0d21e098 100644 --- a/src/main/java/life/mosu/mosuserver/application/user/UserService.java +++ b/src/main/java/life/mosu/mosuserver/application/user/UserService.java @@ -5,6 +5,7 @@ import life.mosu.mosuserver.domain.user.UserJpaRepository; import life.mosu.mosuserver.global.exception.CustomRuntimeException; import life.mosu.mosuserver.global.exception.ErrorCode; +import life.mosu.mosuserver.presentation.user.dto.response.UserInfoResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -35,4 +36,11 @@ public void syncUserInfoFromProfile(UserJpaEntity user, ProfileJpaEntity profile profile.getPhoneNumber(), profile.getBirth()); } } + + public UserInfoResponse getUserInfo(Long userId) { + UserJpaEntity user = userJpaRepository.findById(userId) + .orElseThrow(() -> new CustomRuntimeException(ErrorCode.USER_NOT_FOUND)); + + return UserInfoResponse.from(user); + } } diff --git a/src/main/java/life/mosu/mosuserver/presentation/auth/MasterController.java b/src/main/java/life/mosu/mosuserver/presentation/auth/MasterController.java index 57e83080..ab263654 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/auth/MasterController.java +++ b/src/main/java/life/mosu/mosuserver/presentation/auth/MasterController.java @@ -1,15 +1,20 @@ package life.mosu.mosuserver.presentation.auth; import jakarta.validation.Valid; +import java.util.UUID; import life.mosu.mosuserver.application.auth.SignUpService; +import life.mosu.mosuserver.application.auth.kmc.KmcEventTxService; +import life.mosu.mosuserver.application.auth.provider.OneTimeTokenProvider; import life.mosu.mosuserver.global.util.ApiResponseWrapper; import life.mosu.mosuserver.global.util.CookieBuilderUtil; +import life.mosu.mosuserver.infra.kmc.KmcProperties; import life.mosu.mosuserver.presentation.auth.dto.SignUpAccountRequest; import life.mosu.mosuserver.presentation.auth.dto.Token; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -20,7 +25,11 @@ public class MasterController { private final static String ACCESS_TOKEN_COOKIE_NAME = "accessToken"; private final static String REFRESH_TOKEN_COOKIE_NAME = "refreshToken"; + private final SignUpService signUpService; + private final KmcProperties kmcProperties; + private final KmcEventTxService eventTxService; + private final OneTimeTokenProvider tokenProvider; @PostMapping("/master") public ResponseEntity> masterSignUp( @@ -33,10 +42,26 @@ public ResponseEntity> masterSignUp( .body(ApiResponseWrapper.success(HttpStatus.CREATED, "회원가입 성공")); } + @GetMapping("/master/kmc") + public ResponseEntity> kmcSignUp( + ) { + final String certNum = UUID.randomUUID().toString().replace("-", ""); + String token = tokenProvider.generateOneTimeToken(certNum); + try { + eventTxService.publishIssueEvent(certNum, kmcProperties.getExpireTime()); + + + } catch (Exception ex) { + eventTxService.publishFailureEvent(certNum); + throw new RuntimeException("KMC 인증 요청 생성에 실패했습니다.", ex); + } + + return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, "프로필 등록 성공", token)); + } + private HttpHeaders applyTokenHeader(Token token) { - HttpHeaders headers = new HttpHeaders( + HttpHeaders headers = new HttpHeaders(); - ); headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.createCookie( ACCESS_TOKEN_COOKIE_NAME, token.accessToken(), @@ -49,5 +74,4 @@ private HttpHeaders applyTokenHeader(Token token) { )); return headers; } - -} +} \ No newline at end of file diff --git a/src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java b/src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java index 76771410..ca9b58f3 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java +++ b/src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java @@ -44,12 +44,12 @@ private HttpHeaders applyTokenHeader(Token token) { HttpHeaders headers = new HttpHeaders( ); - headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.temporaryCookieString( + headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.createCookie( ACCESS_TOKEN_COOKIE_NAME, token.accessToken(), token.accessTokenExpireTime() )); - headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.temporaryCookieString( + headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.createCookie( REFRESH_TOKEN_COOKIE_NAME, token.refreshToken(), token.refreshTokenExpireTime() diff --git a/src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpAccountRequest.java b/src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpAccountRequest.java index 4439ab15..49c92f6d 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpAccountRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpAccountRequest.java @@ -2,13 +2,18 @@ import static life.mosu.mosuserver.global.util.EncodeUtil.passwordEncode; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.LocalDate; import life.mosu.mosuserver.domain.profile.Gender; import life.mosu.mosuserver.domain.user.AuthProvider; import life.mosu.mosuserver.domain.user.UserJpaEntity; import life.mosu.mosuserver.domain.user.UserRole; import life.mosu.mosuserver.global.annotation.LoginIdPattern; import life.mosu.mosuserver.global.annotation.PasswordPattern; +import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; import org.springframework.security.crypto.password.PasswordEncoder; public record SignUpAccountRequest( @@ -18,11 +23,31 @@ public record SignUpAccountRequest( ) @LoginIdPattern String id, + @Schema( description = "비밀번호는 8~20자의 영문 대/소문자, 숫자, 특수문자를 모두 포함해야 합니다.", example = "Mosu!1234" ) @PasswordPattern String password, + + @Schema(description = "사용자 이름", example = "홍길동", required = true) + @NotBlank(message = "이름은 필수입니다.") + String userName, + + @Schema(description = "생년월일 (yyyy-MM-dd 형식)", example = "2005-05-10", required = true) + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "생년월일은 필수입니다.") + LocalDate birth, + + @Schema(description = "성별 (MALE 또는 FEMALE)", example = "MALE", required = true) + @NotBlank(message = "성별은 필수입니다.") + String gender, + + @Schema(description = "휴대폰 번호", example = "010-1234-5678", required = true) + @NotBlank(message = "휴대폰 번호는 필수입니다.") + @PhoneNumberPattern + String phoneNumber, + SignUpServiceTermRequest serviceTermRequest ) { @@ -30,8 +55,8 @@ public UserJpaEntity toAuthEntity(PasswordEncoder passwordEncoder) { return UserJpaEntity.builder() .loginId(id) .password(passwordEncode(passwordEncoder, password)) - .agreedToTermsOfService(serviceTermRequest.agreedToTermsOfService()) - .agreedToPrivacyPolicy(serviceTermRequest.agreedToPrivacyPolicy()) + .agreedToTermsOfService(true) + .agreedToPrivacyPolicy(true) .agreedToMarketing(serviceTermRequest.agreedToMarketing()) .gender(Gender.PENDING) .provider(AuthProvider.MOSU) diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/MyUserController.java b/src/main/java/life/mosu/mosuserver/presentation/user/MyUserController.java index 9c81bfcd..2deacf44 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/MyUserController.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/MyUserController.java @@ -4,11 +4,11 @@ import life.mosu.mosuserver.application.user.MyUserService; import life.mosu.mosuserver.global.annotation.UserId; import life.mosu.mosuserver.global.util.ApiResponseWrapper; -import life.mosu.mosuserver.presentation.user.dto.ChangePasswordRequest; -import life.mosu.mosuserver.presentation.user.dto.ChangePasswordResponse; -import life.mosu.mosuserver.presentation.user.dto.FindLoginIdRequest; -import life.mosu.mosuserver.presentation.user.dto.FindLoginIdResponse; -import life.mosu.mosuserver.presentation.user.dto.FindPasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.request.ChangePasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.request.FindLoginIdRequest; +import life.mosu.mosuserver.presentation.user.dto.request.FindPasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.response.ChangePasswordResponse; +import life.mosu.mosuserver.presentation.user.dto.response.FindLoginIdResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/MyUserControllerDocs.java b/src/main/java/life/mosu/mosuserver/presentation/user/MyUserControllerDocs.java index 94d3cf59..ea396690 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/MyUserControllerDocs.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/MyUserControllerDocs.java @@ -4,9 +4,9 @@ import io.swagger.v3.oas.annotations.tags.Tag; import life.mosu.mosuserver.global.annotation.UserId; import life.mosu.mosuserver.global.util.ApiResponseWrapper; -import life.mosu.mosuserver.presentation.user.dto.ChangePasswordRequest; -import life.mosu.mosuserver.presentation.user.dto.ChangePasswordResponse; -import life.mosu.mosuserver.presentation.user.dto.FindPasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.request.ChangePasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.request.FindPasswordRequest; +import life.mosu.mosuserver.presentation.user.dto.response.ChangePasswordResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/UserController.java b/src/main/java/life/mosu/mosuserver/presentation/user/UserController.java index d8fb3aa3..79feb948 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/UserController.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/UserController.java @@ -3,11 +3,13 @@ import life.mosu.mosuserver.application.user.UserService; import life.mosu.mosuserver.global.annotation.UserId; import life.mosu.mosuserver.global.util.ApiResponseWrapper; -import life.mosu.mosuserver.presentation.user.dto.CustomerKeyResponse; -import life.mosu.mosuserver.presentation.user.dto.IsLoginIdAvailableResponse; +import life.mosu.mosuserver.presentation.user.dto.request.IsLoginIdAvailableResponse; +import life.mosu.mosuserver.presentation.user.dto.response.CustomerKeyResponse; +import life.mosu.mosuserver.presentation.user.dto.response.UserInfoResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -20,6 +22,17 @@ public class UserController implements UserControllerDocs { private final UserService userService; + @GetMapping("/info") + @PreAuthorize("isAuthenticated() and hasRole('PENDING')") + public ResponseEntity> getUserInfo( + @UserId Long userId + ) { + UserInfoResponse response = userService.getUserInfo(userId); + + return ResponseEntity.ok( + ApiResponseWrapper.success(HttpStatus.OK, "User 정보 조회 성공", response)); + } + @GetMapping("/customer-key") public ResponseEntity> getCustomerKey( @UserId final Long userId diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/UserControllerDocs.java b/src/main/java/life/mosu/mosuserver/presentation/user/UserControllerDocs.java index 6b654dc4..a7263050 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/UserControllerDocs.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/UserControllerDocs.java @@ -9,8 +9,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import life.mosu.mosuserver.global.annotation.UserId; import life.mosu.mosuserver.global.util.ApiResponseWrapper; -import life.mosu.mosuserver.presentation.user.dto.CustomerKeyResponse; -import life.mosu.mosuserver.presentation.user.dto.IsLoginIdAvailableResponse; +import life.mosu.mosuserver.presentation.user.dto.request.IsLoginIdAvailableResponse; +import life.mosu.mosuserver.presentation.user.dto.response.CustomerKeyResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestParam; diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/ChangePasswordRequest.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/ChangePasswordRequest.java similarity index 87% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/ChangePasswordRequest.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/request/ChangePasswordRequest.java index 820a5ffc..b0fd49ba 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/ChangePasswordRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/ChangePasswordRequest.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.request; import io.swagger.v3.oas.annotations.media.Schema; import life.mosu.mosuserver.global.annotation.PasswordPattern; diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/FindLoginIdRequest.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java similarity index 75% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/FindLoginIdRequest.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java index 4391cd31..3ff2fe68 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/FindLoginIdRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.request; import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/FindPasswordRequest.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java similarity index 83% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/FindPasswordRequest.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java index 0860117e..95f97940 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/FindPasswordRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.request; import life.mosu.mosuserver.global.annotation.LoginIdPattern; import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/IsLoginIdAvailableResponse.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/IsLoginIdAvailableResponse.java similarity index 79% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/IsLoginIdAvailableResponse.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/request/IsLoginIdAvailableResponse.java index 6fdf3250..81854a7f 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/IsLoginIdAvailableResponse.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/IsLoginIdAvailableResponse.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.request; public record IsLoginIdAvailableResponse( Boolean isLoginIdAvailable diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/ChangePasswordResponse.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/ChangePasswordResponse.java similarity index 76% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/ChangePasswordResponse.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/response/ChangePasswordResponse.java index 8d98bba3..2593fcc4 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/ChangePasswordResponse.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/ChangePasswordResponse.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.response; public record ChangePasswordResponse( Boolean isSuccess diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/CustomerKeyResponse.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/CustomerKeyResponse.java similarity index 76% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/CustomerKeyResponse.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/response/CustomerKeyResponse.java index b63fecce..68faf0b5 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/CustomerKeyResponse.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/CustomerKeyResponse.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.response; public record CustomerKeyResponse( String customerKey diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/FindLoginIdResponse.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/FindLoginIdResponse.java similarity index 74% rename from src/main/java/life/mosu/mosuserver/presentation/user/dto/FindLoginIdResponse.java rename to src/main/java/life/mosu/mosuserver/presentation/user/dto/response/FindLoginIdResponse.java index 8ef499ba..ef0e1462 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/FindLoginIdResponse.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/FindLoginIdResponse.java @@ -1,4 +1,4 @@ -package life.mosu.mosuserver.presentation.user.dto; +package life.mosu.mosuserver.presentation.user.dto.response; public record FindLoginIdResponse( String loginId diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/UserInfoResponse.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/UserInfoResponse.java new file mode 100644 index 00000000..9f2256b5 --- /dev/null +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/response/UserInfoResponse.java @@ -0,0 +1,21 @@ +package life.mosu.mosuserver.presentation.user.dto.response; + +import java.time.LocalDate; +import life.mosu.mosuserver.domain.user.UserJpaEntity; + +public record UserInfoResponse( + String name, + LocalDate birth, + String phoneNumber, + String gender +) { + + public static UserInfoResponse from(UserJpaEntity user) { + return new UserInfoResponse( + user.getName(), + user.getBirth(), + user.getPhoneNumber(), + user.getGender() != null ? user.getGender().name() : null + ); + } +}