-
Notifications
You must be signed in to change notification settings - Fork 0
[Release] v2.1.3 login v2 적용 & Slack 채널명 변경 #323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d6bafe7
667a586
b519095
12a446a
959bd79
e56449c
64e58bd
0cc848a
df29bb5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package ssu.eatssu.domain.auth.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import ssu.eatssu.domain.user.entity.DeviceType; | ||
| import ssu.eatssu.global.log.annotation.LogMask; | ||
|
|
||
| // 애플 계정을 통해서 갤럭시 기기에도 접속을 할 수도 있다고 생각해서, DeviceType을 받도록 설계 | ||
| @Schema(title = "애플 로그인 및 회원가입 V2") | ||
| public record AppleLoginRequestV2( | ||
| @LogMask | ||
| @Schema(description = "identityToken", example = "eyJraWQiOiJXNldjT0tCIiwiYWxnIjoi...") | ||
| String identityToken, | ||
| @Schema(description = "deviceType", example = "IOS") | ||
| DeviceType deviceType | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package ssu.eatssu.domain.auth.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.validation.constraints.Email; | ||
| import jakarta.validation.constraints.NotBlank; | ||
| import ssu.eatssu.domain.user.entity.DeviceType; | ||
| import ssu.eatssu.global.log.annotation.LogMask; | ||
|
|
||
| @Schema(title = "카카오 로그인 및 회원가입 V2") | ||
| public record KakaoLoginRequestV2( | ||
| @LogMask | ||
| @NotBlank(message = "이메일을 입력해주세요.") | ||
| @Email(message = "올바른 이메일 주소를 입력해주세요.") | ||
| @Schema(description = "이메일", example = "test@email.com") | ||
| String email, | ||
| @LogMask | ||
| @Schema(description = "providerId", example = "10378247832195") | ||
| String providerId, | ||
| @Schema(description = "deviceType", example = "IOS") | ||
| DeviceType deviceType | ||
| ) {} |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,9 +13,7 @@ | |||||||||||||
| import org.springframework.web.bind.annotation.RequestBody; | ||||||||||||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||||||||||||
| import org.springframework.web.bind.annotation.RestController; | ||||||||||||||
| import ssu.eatssu.domain.auth.dto.AppleLoginRequest; | ||||||||||||||
| import ssu.eatssu.domain.auth.dto.KakaoLoginRequest; | ||||||||||||||
| import ssu.eatssu.domain.auth.dto.ValidRequest; | ||||||||||||||
| import ssu.eatssu.domain.auth.dto.*; | ||||||||||||||
| import ssu.eatssu.domain.auth.service.OAuthService; | ||||||||||||||
| import ssu.eatssu.domain.user.dto.Tokens; | ||||||||||||||
| import ssu.eatssu.global.handler.response.BaseResponse; | ||||||||||||||
|
|
@@ -31,6 +29,7 @@ public class OAuthController { | |||||||||||||
|
|
||||||||||||||
| private final OAuthService oauthService; | ||||||||||||||
|
|
||||||||||||||
| // TODO : 로그인 & 회원 가입 마이그레이션 이후에 지울 것. | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리포지토리 스타일 가이드 7, 8, 9번 규칙에 따라 TODO 주석을 작성해야 합니다. 주석은 한 줄로 작성하고, 작성자 이름과 날짜를 포함하며, |
||||||||||||||
| @Operation(summary = "카카오 회원가입, 로그인 [인증 토큰 필요 X]", description = """ | ||||||||||||||
| 카카오 회원가입, 로그인 API 입니다.<br><br> | ||||||||||||||
| 가입된 회원일 경우 카카오 로그인, 미가입 회원일 경우 회원가입 후 자동 로그인됩니다. | ||||||||||||||
|
|
@@ -49,6 +48,25 @@ public BaseResponse<Tokens> kakaoLogin(@Valid @RequestBody KakaoLoginRequest req | |||||||||||||
| return BaseResponse.success(tokens); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| @Operation(summary = "카카오 회원가입, 로그인 V2 [인증 토큰 필요 X]", description = """ | ||||||||||||||
| 카카오 회원가입, 로그인 V2 API 입니다.<br><br> | ||||||||||||||
| 가입된 회원일 경우 카카오 로그인, 미가입 회원일 경우 회원가입 후 자동 로그인됩니다. | ||||||||||||||
| """) | ||||||||||||||
| @ApiResponses(value = { | ||||||||||||||
| @ApiResponse(responseCode = "200", description = "카카오 회원가입/로그인 성공") | ||||||||||||||
| }) | ||||||||||||||
| @PostMapping("/v2/kakao") | ||||||||||||||
| public BaseResponse<Tokens> kakaoLoginV2(@Valid @RequestBody KakaoLoginRequestV2 request) { | ||||||||||||||
| long startTime = System.currentTimeMillis(); | ||||||||||||||
| Tokens tokens = oauthService.kakaoLoginV2(request); | ||||||||||||||
| long endTime = System.currentTimeMillis(); | ||||||||||||||
| long duration = endTime - startTime; | ||||||||||||||
| log.info("OAuthWarmupRunner 완료 - 소요 시간: {} ms", duration); | ||||||||||||||
|
Comment on lines
+60
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
|
|
||||||||||||||
| return BaseResponse.success(tokens); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // TODO : 로그인 & 회원 가입 마이그레이션 이후에 지울 것. | ||||||||||||||
| @Operation(summary = "애플 회원가입, 로그인 [인증 토큰 필요 X]", description = """ | ||||||||||||||
| 애플 로그인, 회원가입 API 입니다.<br><br> | ||||||||||||||
| 가입된 회원일 경우 카카오 로그인, 미가입 회원일 경우 회원가입 후 자동 로그인됩니다. | ||||||||||||||
|
|
@@ -62,6 +80,19 @@ public BaseResponse<Tokens> appleLogin(@Valid @RequestBody AppleLoginRequest req | |||||||||||||
| return BaseResponse.success(tokens); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| @Operation(summary = "애플 회원가입, 로그인 V2 [인증 토큰 필요 X]", description = """ | ||||||||||||||
| 애플 로그인, 회원가입 API V2 입니다.<br><br> | ||||||||||||||
| 가입된 회원일 경우 카카오 로그인, 미가입 회원일 경우 회원가입 후 자동 로그인됩니다. | ||||||||||||||
| """) | ||||||||||||||
| @ApiResponses(value = { | ||||||||||||||
| @ApiResponse(responseCode = "200", description = "애플 회원가입/로그인 성공") | ||||||||||||||
| }) | ||||||||||||||
| @PostMapping("/v2/apple") | ||||||||||||||
| public BaseResponse<Tokens> appleLoginV2(@Valid @RequestBody AppleLoginRequestV2 request) { | ||||||||||||||
| Tokens tokens = oauthService.appleLoginV2(request); | ||||||||||||||
| return BaseResponse.success(tokens); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| @Operation(summary = "토큰 재발급", description = "accessToken, refreshToken 재발급 API 입니다.") | ||||||||||||||
| @ApiResponses(value = { | ||||||||||||||
| @ApiResponse(responseCode = "200", description = "토큰 재발급 성공") | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,15 +6,13 @@ | |||||||||||||||
| import org.springframework.security.core.Authentication; | ||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||
| import ssu.eatssu.domain.auth.dto.AppleLoginRequest; | ||||||||||||||||
| import ssu.eatssu.domain.auth.dto.KakaoLoginRequest; | ||||||||||||||||
| import ssu.eatssu.domain.auth.dto.OAuthInfo; | ||||||||||||||||
| import ssu.eatssu.domain.auth.dto.ValidRequest; | ||||||||||||||||
| import ssu.eatssu.domain.auth.dto.*; | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리포지토리 스타일 가이드 3번 규칙에 따라 와일드카드(
Suggested change
References
|
||||||||||||||||
| import ssu.eatssu.domain.auth.entity.AppleAuthenticator; | ||||||||||||||||
| import ssu.eatssu.domain.auth.entity.OAuthProvider; | ||||||||||||||||
| import ssu.eatssu.domain.auth.security.JwtTokenProvider; | ||||||||||||||||
| import ssu.eatssu.domain.auth.util.RandomNicknameUtil; | ||||||||||||||||
| import ssu.eatssu.domain.user.dto.Tokens; | ||||||||||||||||
| import ssu.eatssu.domain.user.entity.DeviceType; | ||||||||||||||||
| import ssu.eatssu.domain.user.entity.User; | ||||||||||||||||
| import ssu.eatssu.domain.user.repository.UserRepository; | ||||||||||||||||
| import ssu.eatssu.domain.user.service.UserService; | ||||||||||||||||
|
|
@@ -41,6 +39,21 @@ public Tokens kakaoLogin(KakaoLoginRequest request) { | |||||||||||||||
| return generateOauthJwtTokens(user.getEmail(), KAKAO, request.providerId()); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| /** | ||||||||||||||||
| * V1 -> V2로 넘어가면서 DeviceType(IOS,ANDROID) 정보를 추가로 받게 되었고, 기존에 가입한 유저들은 추가로 기입해 주게 됩니다. | ||||||||||||||||
| */ | ||||||||||||||||
| public Tokens kakaoLoginV2(KakaoLoginRequestV2 request) { | ||||||||||||||||
| User user = userRepository.findByProviderId(request.providerId()) | ||||||||||||||||
| .orElseGet(() -> userService.joinV2(request.email(), KAKAO, request.providerId(),request.deviceType())); | ||||||||||||||||
|
|
||||||||||||||||
| if (user.getDeviceType() == null) { | ||||||||||||||||
| user.updateDeviceType(request.deviceType()); | ||||||||||||||||
| } | ||||||||||||||||
|
Comment on lines
+49
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||
|
|
||||||||||||||||
| return generateOauthJwtTokens(user.getEmail(), KAKAO, request.providerId()); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| public Tokens appleLogin(AppleLoginRequest request) { | ||||||||||||||||
| OAuthInfo oAuthInfo = appleAuthenticator.getOAuthInfoByIdentityToken(request.identityToken()); | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -52,6 +65,24 @@ public Tokens appleLogin(AppleLoginRequest request) { | |||||||||||||||
| return generateOauthJwtTokens(user.getEmail(), APPLE, oAuthInfo.providerId()); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| /** | ||||||||||||||||
| * V1 -> V2로 넘어가면서 DeviceType(IOS,ANDROID) 정보를 추가로 받게 되었고, 기존에 가입한 유저들은 추가로 기입해 주게 됩니다. | ||||||||||||||||
| */ | ||||||||||||||||
| public Tokens appleLoginV2(AppleLoginRequestV2 request) { | ||||||||||||||||
| OAuthInfo oAuthInfo = appleAuthenticator.getOAuthInfoByIdentityToken(request.identityToken()); | ||||||||||||||||
|
|
||||||||||||||||
| User user = userRepository.findByProviderId(oAuthInfo.providerId()) | ||||||||||||||||
| .orElseGet(() -> userService.joinV2(oAuthInfo.email(), APPLE, oAuthInfo.providerId(),request.deviceType())); | ||||||||||||||||
|
|
||||||||||||||||
| updateAppleUserEmail(user, oAuthInfo.email()); | ||||||||||||||||
|
|
||||||||||||||||
| if (user.getDeviceType() == null) { | ||||||||||||||||
| user.updateDeviceType(request.deviceType()); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| return generateOauthJwtTokens(user.getEmail(), APPLE, oAuthInfo.providerId()); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| public Tokens refreshTokens(Authentication authentication) { | ||||||||||||||||
| return jwtTokenProvider.generateTokens(authentication); | ||||||||||||||||
| } | ||||||||||||||||
|
|
@@ -97,5 +128,4 @@ private Tokens generateOauthJwtTokens(String email, OAuthProvider provider, Stri | |||||||||||||||
| private String makeOauthCredentials(OAuthProvider provider, String providerId) { | ||||||||||||||||
| return provider + providerId; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| } | ||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,17 +1,17 @@ | ||||||||||||||||
| package ssu.eatssu.domain.review.dto; | ||||||||||||||||
|
|
||||||||||||||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||||||||||||||
| import lombok.AllArgsConstructor; | ||||||||||||||||
| import lombok.Builder; | ||||||||||||||||
| import lombok.Getter; | ||||||||||||||||
| import ssu.eatssu.domain.review.entity.Review; | ||||||||||||||||
| import ssu.eatssu.domain.review.entity.ReviewMenuLike; | ||||||||||||||||
|
|
||||||||||||||||
| import java.time.LocalDate; | ||||||||||||||||
| import java.util.ArrayList; | ||||||||||||||||
| import java.util.Collections; | ||||||||||||||||
| import java.util.List; | ||||||||||||||||
| import java.util.Set; | ||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||
| import lombok.AllArgsConstructor; | ||||||||||||||||
| import lombok.Builder; | ||||||||||||||||
| import lombok.Getter; | ||||||||||||||||
| import ssu.eatssu.domain.review.entity.Review; | ||||||||||||||||
| import ssu.eatssu.domain.review.entity.ReviewMenuLike; | ||||||||||||||||
|
|
||||||||||||||||
| @AllArgsConstructor | ||||||||||||||||
| @Builder | ||||||||||||||||
|
|
@@ -31,7 +31,7 @@ public class MealReviewResponse { | |||||||||||||||
| private String writerNickname; | ||||||||||||||||
|
|
||||||||||||||||
| @Schema(description = "평점", example = "4") | ||||||||||||||||
| private Double rating; | ||||||||||||||||
| private Integer rating; | ||||||||||||||||
|
|
||||||||||||||||
| @Schema(description = "리뷰 작성 날짜(format = yyyy-MM-dd)", example = "2023-04-07") | ||||||||||||||||
| private LocalDate writtenAt; | ||||||||||||||||
|
|
@@ -60,26 +60,40 @@ public class MealReviewResponse { | |||||||||||||||
|
|
||||||||||||||||
| public static MealReviewResponse from(Review review, | ||||||||||||||||
| Long userId, | ||||||||||||||||
| List<ValidMenuForViewResponse.MenuDto> validMenus,Double rating) { | ||||||||||||||||
| List<ValidMenuForViewResponse.MenuDto> validMenus, Integer rating) { | ||||||||||||||||
|
Comment on lines
61
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
| List<String> imageUrls = new ArrayList<>(); | ||||||||||||||||
| review.getReviewImages().forEach(i -> imageUrls.add(i.getImageUrl())); | ||||||||||||||||
|
|
||||||||||||||||
| // 좋아요한 메뉴 ID 모음 | ||||||||||||||||
| Set<Long> likedMenuIds = review.getMenuLikes().stream() | ||||||||||||||||
| .filter(ReviewMenuLike::getIsLike) | ||||||||||||||||
| .map(like -> like.getMenu().getId()) | ||||||||||||||||
| .collect(Collectors.toSet()); | ||||||||||||||||
|
|
||||||||||||||||
| List<MenuIdNameLikeDto> menuNames = validMenus.stream() | ||||||||||||||||
| .map(valid -> new MenuIdNameLikeDto( | ||||||||||||||||
| valid.getMenuId(), | ||||||||||||||||
| valid.getName(), | ||||||||||||||||
| likedMenuIds.contains(valid.getMenuId()) | ||||||||||||||||
| )) | ||||||||||||||||
| .toList(); | ||||||||||||||||
| List<MenuIdNameLikeDto> menuNames; | ||||||||||||||||
| if (review.getMeal() != null) { | ||||||||||||||||
| Set<Long> likedMenuIds = review.getMenuLikes().stream() | ||||||||||||||||
| .filter(ReviewMenuLike::getIsLike) | ||||||||||||||||
| .map(like -> like.getMenu().getId()) | ||||||||||||||||
| .collect(Collectors.toSet()); | ||||||||||||||||
|
|
||||||||||||||||
| menuNames = validMenus.stream() | ||||||||||||||||
| .map(valid -> new MenuIdNameLikeDto( | ||||||||||||||||
| valid.getMenuId(), | ||||||||||||||||
| valid.getName(), | ||||||||||||||||
| likedMenuIds.contains(valid.getMenuId()) | ||||||||||||||||
| )) | ||||||||||||||||
| .toList(); | ||||||||||||||||
| } else if (review.getMenu() != null) { | ||||||||||||||||
| menuNames = Collections.singletonList( | ||||||||||||||||
| new MenuIdNameLikeDto(review.getMenu().getId(), | ||||||||||||||||
| review.getMenu().getName(), | ||||||||||||||||
| false) | ||||||||||||||||
| ); | ||||||||||||||||
| } else { | ||||||||||||||||
| menuNames = Collections.emptyList(); | ||||||||||||||||
| } | ||||||||||||||||
| Integer resolvedRating = (review.getRating() != null) | ||||||||||||||||
| ? review.getRating() | ||||||||||||||||
| : (review.getRatings() != null ? review.getRatings().getMainRating() : null); | ||||||||||||||||
|
|
||||||||||||||||
| MealReviewResponseBuilder builder = MealReviewResponse.builder() | ||||||||||||||||
| .reviewId(review.getId()) | ||||||||||||||||
| .rating(rating) | ||||||||||||||||
| .rating(resolvedRating) | ||||||||||||||||
| .writtenAt(review.getCreatedDate().toLocalDate()) | ||||||||||||||||
| .content(review.getContent()) | ||||||||||||||||
| .imageUrls(imageUrls) | ||||||||||||||||
|
|
||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
리포지토리 스타일 가이드 3번 규칙에 따라 와일드카드(
*)를 사용한 임포트는 지양해야 합니다. 필요한 클래스를 명시적으로 임포트하여 코드의 가독성과 명확성을 높이는 것이 좋습니다.References