Skip to content
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

[refac] 소셜로그인 코드 리펙토링 #24

Merged
merged 3 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion server-yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class HankkiserverApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("api/v1")
@RequestMapping("/api/v1")
public class AuthController {

private final AuthService authService;
Expand Down Expand Up @@ -46,8 +46,8 @@ public ResponseEntity<BaseResponse<?>> withdraw(

@PostMapping("/auth/reissue")
public ResponseEntity<BaseResponse<?>> reissue(
@RequestHeader(HttpHeaders.AUTHORIZATION) final String refreshtoken) {
final UserReissueResponse response = authService.reissue(refreshtoken);
@RequestHeader(HttpHeaders.AUTHORIZATION) final String refreshToken) {
final UserReissueResponse response = authService.reissue(refreshToken);
return ApiResponse.success(SuccessCode.OK, response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,35 @@
import org.hankki.hankkiserver.domain.user.model.User;
import org.hankki.hankkiserver.domain.user.model.UserInfo;
import org.hankki.hankkiserver.domain.user.model.Platform;
import org.hankki.hankkiserver.common.exception.EntityNotFoundException;
import org.hankki.hankkiserver.common.exception.InvalidValueException;
import org.hankki.hankkiserver.common.exception.UnauthorizedException;
import org.hankki.hankkiserver.external.openfeign.apple.AppleOAuthProvider;
import org.hankki.hankkiserver.external.openfeign.dto.SocialInfoDto;
import org.hankki.hankkiserver.domain.user.repository.UserInfoRepository;
import org.hankki.hankkiserver.domain.user.repository.UserRepository;
import org.hankki.hankkiserver.api.auth.controller.request.UserLoginRequest;
import org.hankki.hankkiserver.api.auth.service.response.UserLoginResponse;
import org.hankki.hankkiserver.api.auth.service.response.UserReissueResponse;
import org.hankki.hankkiserver.external.openfeign.kakao.KakaoOAuthProvider;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

import static org.hankki.hankkiserver.domain.user.model.MemberStatus.ACTIVE;
import static org.hankki.hankkiserver.domain.user.model.MemberStatus.INACTIVE;
import static org.hankki.hankkiserver.domain.user.model.Platform.*;
import static org.hankki.hankkiserver.domain.user.model.User.createUser;
import static org.hankki.hankkiserver.domain.user.model.UserInfo.createMemberInfo;
import static org.hankki.hankkiserver.domain.user.model.Platform.APPLE;
import static org.hankki.hankkiserver.domain.user.model.Platform.KAKAO;
import static org.hankki.hankkiserver.auth.filter.JwtAuthenticationFilter.BEARER;
import static org.hankki.hankkiserver.domain.user.model.User.createUser;

@Service
@Transactional
@RequiredArgsConstructor
public class AuthService {

private final UserRepository userRepository;
private final UserInfoRepository userInfoRepository;
private final UserFinder userFinder;
private final UserSaver userSaver;
private final UserInfoFinder userInfoFinder;
private final UserInfoSaver userInfoSaver;
private final UserInfoDeleter userInfoDeleter;
private final JwtProvider jwtProvider;
private final JwtValidator jwtValidator;
private final KakaoOAuthProvider kakaoOAuthProvider;
Expand All @@ -44,50 +45,48 @@ public class AuthService {
public UserLoginResponse login(
final String token,
final UserLoginRequest request) {
Platform platform = getEnumPlatformFromStringPlatform(request.platform());
Platform platform = Platform.getEnumPlatformFromStringPlatform(request.platform());
SocialInfoDto socialInfo = getSocialInfo(token, platform, request.name());
boolean isRegistered = isRegisteredUser(platform, socialInfo);
User findUser = loadOrCreateUser(platform, socialInfo, isRegistered);
boolean isRegistered = userFinder.isRegisteredUser(platform, socialInfo);
User findUser = loadOrCreateUser(platform, socialInfo);
Token issuedToken = generateTokens(findUser.getId());
return UserLoginResponse.of(issuedToken, isRegistered);
}

public void logOut(final Long userId) {
UserInfo findUserInfo = getUserInfo(userId);
updateRefreshToken(null, findUserInfo);
public void logOut(final long userId) {
UserInfo findUserInfo = userInfoFinder.getUserInfo(userId);
findUserInfo.updateRefreshToken(null);
}

public void withdraw(final Long userId, final String code) {
User user = getUser(userId);
if (user.getPlatform() == APPLE){
public void withdraw(final long userId, final String code) {
User user = userFinder.getUser(userId);
if (APPLE == user.getPlatform()){
try {
String refreshToken = appleOAuthProvider.getAppleToken(code);
appleOAuthProvider.requestRevoke(refreshToken);
} catch (Exception e) {
throw new InvalidValueException(ErrorCode.APPLE_REVOKE_FAILED);
}
}

userRepository.softDeleteById(userId, INACTIVE);
userInfoRepository.softDeleteByUserId(userId);
user.softDelete(INACTIVE);
user.softDelete();
userInfoDeleter.softDelete(userId);
}

@Transactional(noRollbackFor = UnauthorizedException.class)
public UserReissueResponse reissue(final String refreshToken) {
Long userId = jwtProvider.getSubject(refreshToken.substring(BEARER.length()));
long userId = jwtProvider.getSubject(refreshToken.substring(BEARER.length()));
validateRefreshToken(refreshToken, userId);
UserInfo findUserInfo = getUserInfo(userId);
Token issueToken = jwtProvider.issueToken(userId);
updateRefreshToken(issueToken.refreshToken(), findUserInfo);
return UserReissueResponse.of(issueToken);
UserInfo findUserInfo = userInfoFinder.getUserInfo(userId);
Token issuedTokens = jwtProvider.issueTokens(userId);
findUserInfo.updateRefreshToken(issuedTokens.refreshToken());
return UserReissueResponse.of(issuedTokens);
}

private Token generateTokens(final Long userId) {
Token issuedToken = jwtProvider.issueToken(userId);
UserInfo findUserInfo = getUserInfo(userId);
updateRefreshToken(issuedToken.refreshToken(), findUserInfo);
return issuedToken;
private Token generateTokens(final long userId) {
Token issuedTokens = jwtProvider.issueTokens(userId);
UserInfo findUserInfo = userInfoFinder.getUserInfo(userId);
findUserInfo.updateRefreshToken(issuedTokens.refreshToken());
return issuedTokens;
}

private SocialInfoDto getSocialInfo(
Expand All @@ -96,76 +95,43 @@ private SocialInfoDto getSocialInfo(
final String name) {
if (KAKAO == platform){
return kakaoOAuthProvider.getKakaoUserInfo(providerToken);
} else if (APPLE == platform){
return appleOAuthProvider.getAppleUserInfo(providerToken, name);
}
throw new EntityNotFoundException(ErrorCode.INVALID_PLATFORM_TYPE);
return appleOAuthProvider.getAppleUserInfo(providerToken, name);
}

private boolean isRegisteredUser(Platform platform, SocialInfoDto socialInfo){
return userRepository.existsByPlatformAndSerialIdAndMemberStatus(
platform,
socialInfo.serialId(),
ACTIVE);
private User loadOrCreateUser(final Platform platform, final SocialInfoDto socialInfo) {
return userFinder.findUserByPlatFormAndSeralId(platform, socialInfo.serialId())
.map(this::updateUserInfo)
.orElseGet(() -> {
User newUser = createUser(
socialInfo.name(),
socialInfo.email(),
socialInfo.serialId(),
platform);
saveUserAndUserInfo(newUser);
return newUser;
});
}

private User loadOrCreateUser(Platform platform, SocialInfoDto socialInfo, boolean isRegistered){
if (!isRegistered){
User newUser = createUser(
socialInfo.name(),
socialInfo.email(),
socialInfo.serialId(),
platform);
saveUser(newUser);
return newUser;
}

User findUser = getUser(platform, socialInfo.serialId());
if (INACTIVE == findUser.getMemberStatus()) {
findUser.softDelete(ACTIVE);
userRepository.save(findUser);
}
return findUser;
}

private User getUser(
final Platform platform,
final String serialId) {
return userRepository.findByPlatformAndSerialId(platform, serialId)
.orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND));
}

private User getUser(final Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND));
}

private UserInfo getUserInfo(final Long memberId) {
return userInfoRepository.findByUserId(memberId)
.orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_INFO_NOT_FOUND));
private User updateUserInfo(final User user) {
user.updateStatus(ACTIVE);
userInfoFinder.getUserInfo(user.getId()).updateNickname(user.getName());
return user;
}

private String getRefreshToken(final Long userId) {
return userInfoRepository.findByUserId(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorCode.REFRESH_TOKEN_NOT_FOUND))
return userInfoFinder.getUserInfo(userId)
.getRefreshToken();
}

private void saveUser(final User user) {
userRepository.save(user);
UserInfo userInfo = createMemberInfo(user, null);
userInfoRepository.save(userInfo);
}

private void updateRefreshToken(
final String refreshToken,
final UserInfo userInfo) {
userInfo.updateRefreshToken(refreshToken);
private void saveUserAndUserInfo(final User user) {
userSaver.saveUser(user);
UserInfo userInfo = UserInfo.createMemberInfo(user, null);
userInfoSaver.saveUserInfo(userInfo);
}

private void validateRefreshToken(
final String refreshToken,
final Long userId) {
private void validateRefreshToken(final String refreshToken, final long userId) {
try {
jwtValidator.validateRefreshToken(refreshToken);
String storedRefreshToken = getRefreshToken(userId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.hankki.hankkiserver.api.auth.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.common.code.ErrorCode;
import org.hankki.hankkiserver.common.exception.EntityNotFoundException;
import org.hankki.hankkiserver.domain.user.model.Platform;
import org.hankki.hankkiserver.domain.user.model.User;
import org.hankki.hankkiserver.domain.user.repository.UserRepository;
import org.hankki.hankkiserver.external.openfeign.dto.SocialInfoDto;
import org.springframework.stereotype.Component;

import java.util.Optional;

import static org.hankki.hankkiserver.domain.user.model.MemberStatus.ACTIVE;

@Component
@RequiredArgsConstructor
public class UserFinder {

private final UserRepository userRepository;

public User getUser(final long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND));
}

public boolean isRegisteredUser(final Platform platform, final SocialInfoDto socialInfo) {
return userRepository.existsByPlatformAndSerialIdAndMemberStatus(
platform,
socialInfo.serialId(),
ACTIVE);
}

public Optional<User> findUserByPlatFormAndSeralId(final Platform platform, final String serialId) {
return userRepository.findByPlatformAndSerialId(platform, serialId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.hankki.hankkiserver.api.auth.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.domain.user.repository.UserInfoRepository;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserInfoDeleter {

private final UserInfoRepository userInfoRepository;

public void softDelete(final long userId) {
userInfoRepository.softDeleteByUserId(userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.hankki.hankkiserver.api.auth.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.common.code.ErrorCode;
import org.hankki.hankkiserver.common.exception.EntityNotFoundException;
import org.hankki.hankkiserver.domain.user.model.UserInfo;
import org.hankki.hankkiserver.domain.user.repository.UserInfoRepository;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserInfoFinder {

private final UserInfoRepository userInfoRepository;

public UserInfo getUserInfo(final long userId) {
return userInfoRepository.findByUserId(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_INFO_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.hankki.hankkiserver.api.auth.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.domain.user.model.UserInfo;
import org.hankki.hankkiserver.domain.user.repository.UserInfoRepository;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserInfoSaver {

private final UserInfoRepository userInfoRepository;

public void saveUserInfo(final UserInfo userInfo) {
userInfoRepository.save(userInfo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.hankki.hankkiserver.api.auth.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.domain.user.model.User;
import org.hankki.hankkiserver.domain.user.repository.UserRepository;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserSaver {

private final UserRepository userRepository;

public void saveUser(final User user) {
userRepository.save(user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class UserIdArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
boolean hasUserIdAnnotation = parameter.hasParameterAnnotation(UserId.class);
boolean isLongType = Long.class.isAssignableFrom(parameter.getParameterType());
boolean isLongType = parameter.getParameterType().equals(Long.class);
return hasUserIdAnnotation && isLongType;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class JwtProvider {

private final JwtGenerator jwtGenerator;

public Token issueToken(Long userId) {
public Token issueTokens(Long userId) {
return Token.of(jwtGenerator.generateToken(userId, true),
jwtGenerator.generateToken(userId, false));
}
Expand Down
Loading
Loading