-
Notifications
You must be signed in to change notification settings - Fork 0
Release v.1.0.5 #2
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
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
f805455
infra: cicd시 서비스 컨테이너만 재시작하도록 수정
sudhdkso 3de6b77
Merge pull request #139 from dnd-side-project/main
sudhdkso 99647bb
feat: 카카오 소셜 로그인 기능 추가
sudhdkso 7fbdc66
test: 카카오 소셜 로그인 테스트 코드 추가
sudhdkso e2b43b3
test: 테스트 코드 오류 수정
sudhdkso b134966
docs: 소셜로그인 문서 추가
sudhdkso 3422555
test: 테스트 쿠키 설정 수정
sudhdkso 480218f
infra: 카카오 api 및 쿠키 설정 업데이트
sudhdkso 6355e3d
feat: 비회원 토큰 발급시 쿠키로 추가로 보낼 수 있도록 수정
sudhdkso 0be580b
test: 로그인 기능에 대한 테스트 코드 추가
sudhdkso c68fc21
test: 게스트 로그인 쿠키 추가
sudhdkso 44c1850
infra: 카카오 api 테스트용 앱키 설정
sudhdkso d2232e7
Merge pull request #141 from dnd-side-project/feat/#140-kakao-login
sudhdkso b0cab98
refactor: Kakao 관련 데이터 KakaoProperties로 분리 및 JsonProperty 어노테이션 적용
sudhdkso b02294b
refactor: 로그인 플로우 분리 및 인증 메서드 역할 명확화
sudhdkso 4475648
test: User에 추가된 데이터 추가 및 빌더패턴으로 변경
sudhdkso a3e0a4a
feat: 게스트/카카오 유저 저장 요청 DTO 분리 및 User 기반 JWT 토큰 발급 메서드 추가
sudhdkso 400df17
refactor: 불필요한 property설정 삭제
sudhdkso 27f0fbb
test: 회원 등록 로직 변경에 따른 테스트코드 수정
sudhdkso ad45cef
refactor: User 도메인 CQRS 패턴 적용 UserCreator/UserReader로 명령과 조회 분리
sudhdkso ed17bd3
feat: 카카오 + 서비스 로그아웃 기능 추가
sudhdkso 0b6b55d
test: 로그아웃 및 회원 생성,조회에 대한 테스트 코드 추가
sudhdkso b830b39
infra: cicd 워크 플로우 수정
sudhdkso db01dd3
refactor: 테스트 코드 메서드 오타 수정 및 로그아웃 리팩토링
sudhdkso df33cc1
Merge pull request #5 from moddo-kr/feat/#140-kakao-login
sudhdkso File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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
94 changes: 81 additions & 13 deletions
94
src/main/java/com/dnd/moddo/domain/auth/controller/AuthController.java
This file contains hidden or 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 |
|---|---|---|
| @@ -1,29 +1,97 @@ | ||
| package com.dnd.moddo.domain.auth.controller; | ||
|
|
||
| import java.util.Collections; | ||
|
|
||
| import org.springframework.http.HttpHeaders; | ||
| import org.springframework.http.ResponseCookie; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.validation.annotation.Validated; | ||
| import org.springframework.web.bind.annotation.CookieValue; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PutMapping; | ||
| import org.springframework.web.bind.annotation.RequestHeader; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RequestParam; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| import com.dnd.moddo.domain.auth.service.AuthService; | ||
| import com.dnd.moddo.domain.auth.service.RefreshTokenService; | ||
| import com.dnd.moddo.global.config.CookieProperties; | ||
| import com.dnd.moddo.global.jwt.dto.RefreshResponse; | ||
| import com.dnd.moddo.global.jwt.dto.TokenResponse; | ||
| import com.dnd.moddo.global.jwt.service.JwtService; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| @RequiredArgsConstructor | ||
| @RestController | ||
| @RequestMapping("/api/v1/user") | ||
| @Validated | ||
| @RequestMapping("/api/v1") | ||
| public class AuthController { | ||
|
|
||
| private final AuthService authService; | ||
| private final RefreshTokenService refreshTokenService; | ||
| private final AuthService authService; | ||
| private final RefreshTokenService refreshTokenService; | ||
| private final CookieProperties cookieProperties; | ||
| private final JwtService jwtService; | ||
|
|
||
| @GetMapping("/user/guest/token") | ||
| public ResponseEntity<TokenResponse> getGuestToken() { | ||
| TokenResponse tokenResponse = authService.loginWithGuest(); | ||
|
|
||
| String cookie = createCookie("accessToken", tokenResponse.accessToken()).toString(); | ||
|
|
||
| return ResponseEntity.ok() | ||
| .header(HttpHeaders.SET_COOKIE, cookie) | ||
| .body(tokenResponse); | ||
| } | ||
|
|
||
| @PutMapping("/user/reissue/token") | ||
| public RefreshResponse reissueAccessToken(@RequestHeader(value = "Authorization") @NotBlank String refreshToken) { | ||
| return refreshTokenService.execute(refreshToken); | ||
| } | ||
|
|
||
| @GetMapping("/login/oauth2/callback") | ||
| public ResponseEntity<Void> kakaoLoginCallback(@RequestParam @NotBlank String code) { | ||
|
|
||
| TokenResponse tokenResponse = authService.loginOrRegisterWithKakao(code); | ||
|
|
||
| String cookie = createCookie("accessToken", tokenResponse.accessToken()).toString(); | ||
|
|
||
| return ResponseEntity.ok() | ||
| .header(HttpHeaders.SET_COOKIE, cookie) | ||
| .build(); | ||
| } | ||
|
|
||
| @GetMapping("/logout") | ||
| public ResponseEntity<?> kakaoLogout(@CookieValue(value = "accessToken") String token) { | ||
| String cookie = expireCookie("accessToken").toString(); | ||
| Long userId = jwtService.getUserId(token); | ||
| authService.logout(userId); | ||
| return ResponseEntity.ok() | ||
| .header(HttpHeaders.SET_COOKIE, cookie) | ||
| .body(Collections.singletonMap("message", "Logout successful")); | ||
| } | ||
|
|
||
| private ResponseCookie createCookie(String name, String key) { | ||
| return ResponseCookie.from(name, key) | ||
| .httpOnly(cookieProperties.httpOnly()) | ||
| .secure(cookieProperties.secure()) | ||
| .path(cookieProperties.path()) | ||
| .sameSite(cookieProperties.sameSite()) | ||
| .maxAge(cookieProperties.maxAge()) | ||
| .build(); | ||
|
|
||
| } | ||
|
|
||
| @GetMapping("/guest/token") | ||
| public ResponseEntity<TokenResponse> getGuestToken() { | ||
| return ResponseEntity.ok(authService.createGuestUser()); | ||
| } | ||
| private ResponseCookie expireCookie(String name) { | ||
| return ResponseCookie.from(name, null) | ||
| .httpOnly(cookieProperties.httpOnly()) | ||
| .secure(cookieProperties.secure()) | ||
| .path(cookieProperties.path()) | ||
| .sameSite(cookieProperties.sameSite()) | ||
| .maxAge(0L) | ||
| .build(); | ||
| } | ||
|
|
||
| @PutMapping("/reissue/token") | ||
| public RefreshResponse reissueAccessToken(@RequestHeader(value = "Authorization") @NotBlank String refreshToken) { | ||
| return refreshTokenService.execute(refreshToken); | ||
| } | ||
| } |
4 changes: 4 additions & 0 deletions
4
src/main/java/com/dnd/moddo/domain/auth/dto/KakaoLogoutResponse.java
This file contains hidden or 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,4 @@ | ||
| package com.dnd.moddo.domain.auth.dto; | ||
|
|
||
| public record KakaoLogoutResponse(Long id) { | ||
| } |
25 changes: 25 additions & 0 deletions
25
src/main/java/com/dnd/moddo/domain/auth/dto/KakaoProfile.java
This file contains hidden or 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,25 @@ | ||
| package com.dnd.moddo.domain.auth.dto; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
|
|
||
| public record KakaoProfile( | ||
| Long id, | ||
| @JsonProperty("kakao_account") KakaoAccount kakaoAccount, | ||
| Properties properties | ||
| ) { | ||
| public record Properties( | ||
| String nickname | ||
| ) { | ||
| } | ||
|
|
||
| public record KakaoAccount( | ||
| String email, | ||
| Profile profile | ||
| ) { | ||
| } | ||
|
|
||
| public record Profile( | ||
| String nickname | ||
| ) { | ||
| } | ||
| } |
9 changes: 9 additions & 0 deletions
9
src/main/java/com/dnd/moddo/domain/auth/dto/KakaoTokenResponse.java
This file contains hidden or 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,9 @@ | ||
| package com.dnd.moddo.domain.auth.dto; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
|
|
||
| public record KakaoTokenResponse( | ||
| @JsonProperty("access_token") String accessToken, | ||
| @JsonProperty("expires_in") int expiresIn | ||
| ) { | ||
| } |
68 changes: 51 additions & 17 deletions
68
src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java
This file contains hidden or 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 |
|---|---|---|
| @@ -1,43 +1,77 @@ | ||
| package com.dnd.moddo.domain.auth.service; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| import java.util.UUID; | ||
|
|
||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import com.dnd.moddo.domain.auth.dto.KakaoLogoutResponse; | ||
| import com.dnd.moddo.domain.auth.dto.KakaoProfile; | ||
| import com.dnd.moddo.domain.auth.dto.KakaoTokenResponse; | ||
| import com.dnd.moddo.domain.user.dto.request.GuestUserSaveRequest; | ||
| import com.dnd.moddo.domain.user.dto.request.UserSaveRequest; | ||
| import com.dnd.moddo.domain.user.entity.User; | ||
| import com.dnd.moddo.domain.user.entity.type.Authority; | ||
| import com.dnd.moddo.domain.user.repository.UserRepository; | ||
| import com.dnd.moddo.domain.user.service.CommandUserService; | ||
| import com.dnd.moddo.domain.user.service.QueryUserService; | ||
| import com.dnd.moddo.global.exception.ModdoException; | ||
| import com.dnd.moddo.global.jwt.dto.TokenResponse; | ||
| import com.dnd.moddo.global.jwt.utill.JwtProvider; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| @RequiredArgsConstructor | ||
| @Service | ||
| @Slf4j | ||
| public class AuthService { | ||
|
|
||
| private final UserRepository userRepository; | ||
| private final CommandUserService commandUserService; | ||
| private final QueryUserService queryUserService; | ||
| private final JwtProvider jwtProvider; | ||
| private final KakaoClient kakaoClient; | ||
|
|
||
| @Transactional | ||
| public TokenResponse createGuestUser() { | ||
| public TokenResponse loginWithGuest() { | ||
| String guestEmail = "guest-" + UUID.randomUUID() + "@guest.com"; | ||
| GuestUserSaveRequest request = new GuestUserSaveRequest(guestEmail, "Guest"); | ||
|
|
||
| User guestUser = User.builder() | ||
| .email(guestEmail) | ||
| .name("Guest") | ||
| .profile(null) | ||
| .createdAt(LocalDateTime.now()) | ||
| .expiredAt(LocalDateTime.now().plusMonths(1)) | ||
| .authority(Authority.USER) | ||
| .isMember(false) | ||
| .build(); | ||
| User user = commandUserService.createGuestUser(request); | ||
|
|
||
| userRepository.save(guestUser); | ||
| return jwtProvider.generateToken(user); | ||
| } | ||
|
|
||
| @Transactional | ||
| public TokenResponse loginOrRegisterWithKakao(String code) { | ||
| KakaoTokenResponse tokenResponse = kakaoClient.join(code); | ||
| KakaoProfile kakaoProfile = kakaoClient.getKakaoProfile(tokenResponse.accessToken()); | ||
|
|
||
| String email = kakaoProfile.kakaoAccount().email(); | ||
| String nickname = kakaoProfile.properties().nickname(); | ||
| Long kakaoId = kakaoProfile.id(); | ||
|
|
||
| if (email == null || nickname == null || kakaoId == null) { | ||
| throw new ModdoException(HttpStatus.BAD_REQUEST, "카카오 프로필 정보가 누락되었습니다."); | ||
| } | ||
|
|
||
| UserSaveRequest request = new UserSaveRequest(email, nickname, kakaoId); | ||
| User user = commandUserService.getOrCreateUser(request); | ||
|
|
||
| return jwtProvider.generateToken(guestUser.getId(), guestUser.getEmail(), guestUser.getAuthority().toString(), | ||
| guestUser.getIsMember()); | ||
| log.info("[USER_LOGIN] 로그인 성공 : code = {}, kakaoId = {}, nickname = {}", code, kakaoId, nickname); | ||
|
|
||
| return jwtProvider.generateToken(user); | ||
| } | ||
|
|
||
| public void logout(Long userId) { | ||
| queryUserService.findKakaoIdById(userId).ifPresent(kakaoId -> { | ||
| KakaoLogoutResponse logoutResponse = kakaoClient.logout(kakaoId); | ||
|
|
||
| if (!kakaoId.equals(logoutResponse.id())) { | ||
| throw new ModdoException(HttpStatus.INTERNAL_SERVER_ERROR, "카카오 로그아웃 실패: id 불일치"); | ||
| } | ||
|
|
||
| log.info("[USER_LOGOUT] 카카오 로그아웃 성공: userId={}, kakaoId={}", userId, kakaoId); | ||
| }); | ||
| } | ||
|
|
||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.