-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
26 changed files
with
990 additions
and
21 deletions.
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthController.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,66 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.api; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.*; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.RefreshTokenReqDto; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.TokenReqDto; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; | ||
import shop.kkeujeok.kkeujeokbackend.auth.application.AuthMemberService; | ||
import shop.kkeujeok.kkeujeokbackend.auth.application.AuthService; | ||
import shop.kkeujeok.kkeujeokbackend.auth.application.AuthServiceFactory; | ||
import shop.kkeujeok.kkeujeokbackend.auth.application.TokenService; | ||
import shop.kkeujeok.kkeujeokbackend.global.jwt.api.dto.TokenDto; | ||
import shop.kkeujeok.kkeujeokbackend.global.oauth.GoogleAuthService; | ||
import shop.kkeujeok.kkeujeokbackend.global.oauth.KakaoAuthService; | ||
import shop.kkeujeok.kkeujeokbackend.global.template.RspTemplate; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; | ||
|
||
@RestController | ||
@Slf4j | ||
@RequestMapping("/api") | ||
@RequiredArgsConstructor | ||
public class AuthController { | ||
private final AuthServiceFactory authServiceFactory; | ||
private final AuthMemberService memberService; | ||
private final TokenService tokenService; | ||
private final GoogleAuthService getGoogleAccessToken; | ||
private final KakaoAuthService kakaoAuthService; | ||
|
||
@GetMapping("oauth2/callback/google") | ||
public JsonNode googleCallback(@RequestParam(name = "code") String code) { | ||
return getGoogleAccessToken.getGoogleIdToken(code); | ||
} | ||
|
||
@GetMapping("oauth2/callback/kakao") | ||
public JsonNode kakaoCallback(@RequestParam(name = "code") String code) { | ||
return kakaoAuthService.getKakaoAccessToken(code); | ||
} | ||
|
||
// @Operation(summary = "로그인 후 토큰 발급", description = "액세스, 리프레쉬 토큰을 발급합니다.") | ||
@PostMapping("/{provider}/token") | ||
public RspTemplate<TokenDto> generateAccessAndRefreshToken( | ||
@PathVariable(name = "provider") String provider, | ||
@RequestBody TokenReqDto tokenReqDto) { | ||
AuthService authService = authServiceFactory.getAuthService(provider); | ||
UserInfo userInfo = authService.getUserInfo(tokenReqDto.authCode()); | ||
|
||
MemberLoginResDto getMemberDto = memberService.saveUserInfo(userInfo, | ||
SocialType.valueOf(provider.toUpperCase())); | ||
TokenDto getToken = tokenService.getToken(getMemberDto); | ||
|
||
return new RspTemplate<>(HttpStatus.OK, "토큰 발급", getToken); | ||
} | ||
|
||
// @Operation(summary = "액세스 토큰 재발급", description = "리프레쉬 토큰으로 액세스 토큰을 발급합니다.") | ||
@PostMapping("/token/access") | ||
public RspTemplate<TokenDto> generateAccessToken(@RequestBody RefreshTokenReqDto refreshTokenReqDto) { | ||
TokenDto getToken = tokenService.generateAccessToken(refreshTokenReqDto); | ||
|
||
return new RspTemplate<>(HttpStatus.OK, "액세스 토큰 발급", getToken); | ||
} | ||
|
||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/RefreshTokenReqDto.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,6 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.api.dto.request; | ||
|
||
public record RefreshTokenReqDto( | ||
String refreshToken | ||
){ | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/TokenReqDto.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,6 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.api.dto.request; | ||
|
||
public record TokenReqDto( | ||
String authCode | ||
) { | ||
} |
10 changes: 10 additions & 0 deletions
10
...java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/AccessAndRefreshTokenResDto.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 shop.kkeujeok.kkeujeokbackend.auth.api.dto.response; | ||
|
||
import lombok.Builder; | ||
|
||
@Builder | ||
public record AccessAndRefreshTokenResDto( | ||
String accessToken, | ||
String refreshToken | ||
) { | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/MemberLoginResDto.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,16 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.api.dto.response; | ||
|
||
|
||
import lombok.Builder; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.Member; | ||
|
||
@Builder | ||
public record MemberLoginResDto( | ||
Member findMember | ||
) { | ||
public static MemberLoginResDto from(Member member) { | ||
return MemberLoginResDto.builder() | ||
.findMember(member) | ||
.build(); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/UserInfo.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,9 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.api.dto.response; | ||
|
||
public record UserInfo( | ||
String email, | ||
String name, | ||
String picture, | ||
String nickname | ||
) { | ||
} |
85 changes: 85 additions & 0 deletions
85
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.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,85 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.application; | ||
|
||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; | ||
import shop.kkeujeok.kkeujeokbackend.global.entity.Status; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.Member; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.Role; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository; | ||
|
||
import java.util.Optional; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
public class AuthMemberService { | ||
private final MemberRepository memberRepository; | ||
|
||
public AuthMemberService(MemberRepository memberRepository) { | ||
this.memberRepository = memberRepository; | ||
} | ||
|
||
@Transactional | ||
public MemberLoginResDto saveUserInfo(UserInfo userInfo, SocialType provider) { | ||
validateNotFoundEmail(userInfo.email()); | ||
|
||
Member member = getExistingMemberOrCreateNew(userInfo, provider); | ||
|
||
validateSocialType(member, provider); | ||
|
||
return MemberLoginResDto.from(member); | ||
} | ||
|
||
private void validateNotFoundEmail(String email) { | ||
if (email == null) { | ||
throw new RuntimeException(); | ||
} | ||
} | ||
|
||
private Member getExistingMemberOrCreateNew(UserInfo userInfo, SocialType provider) { | ||
return memberRepository.findByEmail(userInfo.email()).orElseGet(() -> createMember(userInfo, provider)); | ||
} | ||
|
||
private Member createMember(UserInfo userInfo, SocialType provider) { | ||
String userPicture = getUserPicture(userInfo.picture()); | ||
String name = userInfo.name(); | ||
String nickname = userInfo.nickname(); | ||
|
||
if (name == null && nickname != null) { | ||
name = nickname; | ||
} else if (nickname == null && name != null) { | ||
nickname = name; | ||
} | ||
|
||
return memberRepository.save( | ||
Member.builder() | ||
.status(Status.A) | ||
.email(userInfo.email()) | ||
.name(name) | ||
.picture(userPicture) | ||
.socialType(provider) | ||
.role(Role.ROLE_USER) | ||
.firstLogin(true) | ||
.nickname(nickname) | ||
.build() | ||
); | ||
} | ||
|
||
private String getUserPicture(String picture) { | ||
return Optional.ofNullable(picture) | ||
.map(this::convertToHighRes).orElseThrow(); | ||
} | ||
|
||
private String convertToHighRes(String url){ | ||
return url.replace("s96-c", "s2048-c"); | ||
} | ||
|
||
private void validateSocialType(Member member, SocialType provider) { | ||
if (!provider.equals(member.getSocialType())) { | ||
throw new RuntimeException(); | ||
} | ||
} | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthService.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,9 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.application; | ||
|
||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; | ||
|
||
public interface AuthService { | ||
UserInfo getUserInfo(String authCode); | ||
|
||
String getProvider(); | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactory.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,25 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.application; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@Service | ||
public class AuthServiceFactory { | ||
private final Map<String, AuthService> authServiceMap; | ||
|
||
@Autowired | ||
public AuthServiceFactory(List<AuthService> authServiceList) { | ||
authServiceMap = new HashMap<>(); | ||
for (AuthService authService : authServiceList) { | ||
authServiceMap.put(authService.getProvider(), authService); | ||
} | ||
} | ||
|
||
public AuthService getAuthService(String provider) { | ||
return authServiceMap.get(provider); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.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,65 @@ | ||
package shop.kkeujeok.kkeujeokbackend.auth.application; | ||
|
||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.RefreshTokenReqDto; | ||
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; | ||
import shop.kkeujeok.kkeujeokbackend.global.jwt.TokenProvider; | ||
import shop.kkeujeok.kkeujeokbackend.global.jwt.api.dto.TokenDto; | ||
import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.Token; | ||
import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.repository.TokenRepository; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.Member; | ||
import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
public class TokenService { | ||
|
||
private final TokenProvider tokenProvider; | ||
private final TokenRepository tokenRepository; | ||
private final MemberRepository memberRepository; | ||
|
||
public TokenService(TokenProvider tokenProvider, TokenRepository tokenRepository, MemberRepository memberRepository) { | ||
this.tokenProvider = tokenProvider; | ||
this.tokenRepository = tokenRepository; | ||
this.memberRepository = memberRepository; | ||
} | ||
|
||
@Transactional | ||
public TokenDto getToken(MemberLoginResDto memberLoginResDto) { | ||
TokenDto tokenDto = tokenProvider.generateToken(memberLoginResDto.findMember().getEmail()); | ||
|
||
tokenSaveAndUpdate(memberLoginResDto, tokenDto); | ||
|
||
return tokenDto; | ||
} | ||
|
||
private void tokenSaveAndUpdate(MemberLoginResDto memberLoginResDto, TokenDto tokenDto) { | ||
if (!tokenRepository.existsByMember(memberLoginResDto.findMember())) { | ||
tokenRepository.save(Token.builder() | ||
.member(memberLoginResDto.findMember()) | ||
.refreshToken(tokenDto.refreshToken()) | ||
.build()); | ||
} | ||
|
||
refreshTokenUpdate(memberLoginResDto, tokenDto); | ||
} | ||
|
||
private void refreshTokenUpdate(MemberLoginResDto memberLoginResDto, TokenDto tokenDto) { | ||
Token token = tokenRepository.findByMember(memberLoginResDto.findMember()).orElseThrow(); | ||
token.refreshTokenUpdate(tokenDto.refreshToken()); | ||
} | ||
|
||
@Transactional | ||
public TokenDto generateAccessToken(RefreshTokenReqDto refreshTokenReqDto) { | ||
if (!tokenRepository.existsByRefreshToken(refreshTokenReqDto.refreshToken()) || !tokenProvider.validateToken(refreshTokenReqDto.refreshToken())) { | ||
throw new RuntimeException(); | ||
} | ||
|
||
Token token = tokenRepository.findByRefreshToken(refreshTokenReqDto.refreshToken()).orElseThrow(); | ||
Member member = memberRepository.findById(token.getMember().getId()).orElseThrow(); | ||
|
||
return tokenProvider.generateAccessTokenByRefreshToken(member.getEmail(), token.getRefreshToken()); | ||
} | ||
|
||
} |
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
Oops, something went wrong.