Skip to content

Commit

Permalink
Merge pull request #178 from Team-HMH/fix/#174-signup-npe
Browse files Browse the repository at this point in the history
refactor - AuthFacade 관련 코드 리팩토링
  • Loading branch information
kseysh authored Jul 17, 2024
2 parents e4c8a63 + cbbffcb commit 1fd02be
Show file tree
Hide file tree
Showing 18 changed files with 211 additions and 109 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,7 @@ application-prod.yml
### Test ###
data.sql

### Querydsl ###
**/generated/

# End of https://www.gitignore.io/api/java,macos,gradle,intellij
11 changes: 9 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ dependencies {
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'

// Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// Querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"

// Open Feign
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0'
Expand All @@ -59,4 +62,8 @@ tasks.named('test') {
useJUnitPlatform()
}

clean {
delete file('src/main/generated')
}

jar.enabled = false

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,7 @@

import org.springframework.data.jpa.repository.JpaRepository;
import sopt.org.hmh.domain.app.domain.HistoryApp;
import sopt.org.hmh.domain.app.domain.exception.AppError;
import sopt.org.hmh.domain.app.domain.exception.AppException;

import java.util.Optional;

public interface HistoryAppRepository extends JpaRepository<HistoryApp, Long> {

Optional<HistoryApp> findFirstByDailyChallengeIdAndAppCodeAndOs(Long dailyChallengeId, String appCode, String os);

default HistoryApp findFirstByDailyChallengeIdAndAppCodeAndOsOrElseThrow(Long dailyChallengeId, String appCode, String os) {
return findFirstByDailyChallengeIdAndAppCodeAndOs(dailyChallengeId, appCode, os).orElseThrow(() -> new AppException(
AppError.APP_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package sopt.org.hmh.domain.app.repository.challenge_app;

import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import sopt.org.hmh.domain.app.domain.ChallengeApp;

public interface ChallengeAppJpaRepository extends JpaRepository<ChallengeApp, Long> {

Optional<ChallengeApp> findFirstByChallengeIdAndAppCodeAndOs(Long challengeId, String appCode, String os);

boolean existsByChallengeIdAndAppCodeAndOs(Long challengeId, String appCode, String os);

List<ChallengeApp> findAllByChallengeId(Long previousChallengeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package sopt.org.hmh.domain.app.repository.challenge_app;

import java.util.List;
import sopt.org.hmh.domain.app.domain.ChallengeApp;
import java.util.Optional;

public interface ChallengeAppRepository {

void saveAll(List<ChallengeApp> challengeApps);

void delete(ChallengeApp appToRemove);

Optional<ChallengeApp> findFirstByChallengeIdAndAppCodeAndOs(Long challengeId, String appCode, String os);

boolean existsByChallengeIdAndAppCodeAndOs(Long challengeId, String appCode, String os);

List<ChallengeApp> findAllByChallengeId(Long previousChallengeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package sopt.org.hmh.domain.app.repository.challenge_app;

import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import sopt.org.hmh.domain.app.domain.ChallengeApp;

@Repository
@RequiredArgsConstructor
public class ChallengeAppRepositoryImpl implements ChallengeAppRepository{

private final ChallengeAppJpaRepository challengeAppJpaRepository;

@Override
public void saveAll(List<ChallengeApp> challengeApps) {
challengeAppJpaRepository.saveAll(challengeApps);
}

@Override
public void delete(ChallengeApp appToRemove) {
challengeAppJpaRepository.delete(appToRemove);
}

@Override
public Optional<ChallengeApp> findFirstByChallengeIdAndAppCodeAndOs(Long challengeId, String appCode, String os) {
return challengeAppJpaRepository.findFirstByChallengeIdAndAppCodeAndOs(challengeId, appCode, os);
}

@Override
public boolean existsByChallengeIdAndAppCodeAndOs(Long challengeId, String appCode, String os) {
return challengeAppJpaRepository.existsByChallengeIdAndAppCodeAndOs(challengeId, appCode, os);
}

@Override
public List<ChallengeApp> findAllByChallengeId(Long previousChallengeId) {
return challengeAppJpaRepository.findAllByChallengeId(previousChallengeId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sopt.org.hmh.domain.app.domain.exception.AppError;
import sopt.org.hmh.domain.app.domain.exception.AppException;
import sopt.org.hmh.domain.app.dto.request.ChallengeAppRequest;
import sopt.org.hmh.domain.app.repository.ChallengeAppRepository;
import sopt.org.hmh.domain.app.repository.challenge_app.ChallengeAppRepository;
import sopt.org.hmh.domain.challenge.domain.Challenge;

@Service
Expand All @@ -18,23 +18,37 @@ public class ChallengeAppService {

public void removeApp(Challenge challenge, String appcode, String os) {
ChallengeApp appToRemove =
challengeAppRepository.findFirstByChallengeIdAndAppCodeAndOsOrElseThrow(challenge.getId(), appcode, os);
this.findFirstByChallengeIdAndAppCodeAndOsOrElseThrow(challenge.getId(), appcode, os);
challengeAppRepository.delete(appToRemove);
}

public void addApps(Challenge challenge, List<ChallengeAppRequest> requests, String os) {
challengeAppRepository.saveAll(
requests.stream().map(
request -> {
validateAppExist(challenge.getId(), request.appCode(), os);
return request.toEntity(challenge, os);
}).toList());
public void addAppsByPreviousChallengeApp(String os, Long previousChallengeId, Challenge challenge) {
this.addApps(challengeAppRepository.findAllByChallengeId(previousChallengeId)
.stream().map(previousApp ->
new ChallengeAppRequest(previousApp.getAppCode(), previousApp.getGoalTime())
.toEntity(challenge, os))
.toList()
);
}

private void validateAppExist(Long challengeId, String appCode, String os) {
if (challengeAppRepository.existsByChallengeIdAndAppCodeAndOs(challengeId, appCode, os)) {
public void addApps(List<ChallengeApp> challengeApps) {
this.validateAppsExist(challengeApps);
challengeAppRepository.saveAll(challengeApps);
}

private void validateAppsExist(List<ChallengeApp> challengeApps) {
challengeApps.forEach(this::validateAppExist);
}

private void validateAppExist(ChallengeApp challengeApp) {
if (challengeAppRepository.existsByChallengeIdAndAppCodeAndOs(
challengeApp.getChallenge().getId(), challengeApp.getAppCode(), challengeApp.getOs())) {
throw new AppException(AppError.APP_EXIST_ALREADY);
}
}

private ChallengeApp findFirstByChallengeIdAndAppCodeAndOsOrElseThrow(Long challengeId, String appCode, String os) {
return challengeAppRepository.findFirstByChallengeIdAndAppCodeAndOs(challengeId, appCode, os)
.orElseThrow(() -> new AppException(AppError.APP_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public ResponseEntity<BaseResponse<?>> orderLogin(
) {
return ResponseEntity
.status(AuthSuccess.LOGIN_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.LOGIN_SUCCESS, authFacade.login(socialAccessToken, request)));
.body(BaseResponse.success(
AuthSuccess.LOGIN_SUCCESS,
authFacade.login(socialAccessToken, request.socialPlatform())
));
}

@PostMapping("/signup")
Expand All @@ -44,7 +47,10 @@ public ResponseEntity<BaseResponse<?>> orderSignup(
) {
return ResponseEntity
.status(AuthSuccess.SIGNUP_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.SIGNUP_SUCCESS, authFacade.signup(socialAccessToken, request, os)));
.body(BaseResponse.success(
AuthSuccess.SIGNUP_SUCCESS,
authFacade.signup(request, socialAccessToken, os)
));
}

@PostMapping("/reissue")
Expand All @@ -54,7 +60,10 @@ public ResponseEntity<BaseResponse<?>> orderReissue(
) {
return ResponseEntity
.status(AuthSuccess.REISSUE_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.REISSUE_SUCCESS, authFacade.reissueToken(refreshToken)));
.body(BaseResponse.success(
AuthSuccess.REISSUE_SUCCESS,
authFacade.reissueToken(refreshToken)
));
}

@GetMapping("/social/token/kakao")
Expand All @@ -63,6 +72,9 @@ public ResponseEntity<BaseResponse<SocialAccessTokenResponse>> orderGetKakaoAcce
) {
return ResponseEntity
.status(AuthSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS, authFacade.getSocialAccessTokenByAuthorizationCode(code)));
.body(BaseResponse.success(
AuthSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS,
authFacade.getSocialAccessTokenByAuthorizationCode(code)
));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package sopt.org.hmh.domain.auth.dto.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;
Expand All @@ -14,26 +13,20 @@ public record SocialSignUpRequest(
@NotNull(message = "소셜 플랫폼은 null일 수 없습니다.")
SocialPlatform socialPlatform,
String name,
@JsonProperty(value = "onboarding")
OnboardingRequest onboardingRequest,
OnboardingRequest onboarding,
@Valid
@JsonProperty(value = "challenge")
ChallengeSignUpRequest challengeSignUpRequest
ChallengeSignUpRequest challenge
) {

public ChallengeRequest toChallengeRequest() {
return new ChallengeRequest(challengeSignUpRequest.period(), challengeSignUpRequest.goalTime());
}

public OnboardingInfo toOnboardingInfo(Long userId) {
return OnboardingInfo.builder()
.averageUseTime(onboardingRequest.averageUseTime())
.averageUseTime(onboarding.averageUseTime())
.userId(userId)
.build();
}

public List<OnboardingProblem> toProblemList(Long onboardingInfoId) {
return onboardingRequest.problemList().stream()
return onboarding.problemList().stream()
.map(problem -> OnboardingProblem.builder()
.onboardingInfoId(onboardingInfoId)
.problem(problem)
Expand Down
54 changes: 29 additions & 25 deletions src/main/java/sopt/org/hmh/domain/auth/service/AuthFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sopt.org.hmh.domain.app.service.ChallengeAppService;
import sopt.org.hmh.domain.auth.dto.response.ReissueResponse;
import sopt.org.hmh.domain.challenge.domain.Challenge;
import sopt.org.hmh.domain.challenge.service.ChallengeFacade;
import sopt.org.hmh.domain.user.domain.User;
import sopt.org.hmh.domain.auth.dto.request.SocialPlatformRequest;
import sopt.org.hmh.domain.auth.dto.request.SocialSignUpRequest;
import sopt.org.hmh.domain.auth.dto.response.LoginResponse;
import sopt.org.hmh.domain.user.service.UserService;
Expand All @@ -27,53 +24,60 @@ public class AuthFacade {
private final KakaoLoginService kakaoLoginService;
private final AppleOAuthProvider appleOAuthProvider;
private final ChallengeFacade challengeFacade;
private final ChallengeAppService challengeAppService;
private final TokenService tokenService;
private final UserService userService;

@Transactional(readOnly = true)
public LoginResponse login(String socialAccessToken, SocialPlatformRequest request) {
SocialPlatform socialPlatform = request.socialPlatform();
public LoginResponse login(String socialAccessToken, SocialPlatform socialPlatform) {
String socialId = this.getSocialIdBySocialAccessToken(socialPlatform, socialAccessToken);
User loginUser = userService.getUserBySocialPlatformAndSocialId(socialPlatform, socialId);

return performLogin(socialAccessToken, socialPlatform, loginUser);
return performLogin(loginUser, socialAccessToken, socialPlatform);
}

@Transactional
public LoginResponse signup(String socialAccessToken, SocialSignUpRequest request, String os) {
public LoginResponse signup(SocialSignUpRequest request, String socialAccessToken, String os) {
SocialPlatform socialPlatform = request.socialPlatform();
String socialId = this.getSocialIdBySocialAccessToken(socialPlatform, socialAccessToken);

userService.validateDuplicateUser(socialId, socialPlatform);
User user = userService.addUser(socialPlatform, socialId, request.name());
Long userId = user.getId();
userService.registerOnboardingInfo(request, userId);
User newUser = userService.addUser(socialPlatform, socialId, request.name());
Long newUserId = newUser.getId();

userService.registerOnboardingInfo(request, newUserId);

Challenge challenge = challengeFacade.addChallenge(userId, request.toChallengeRequest() , os);
challengeAppService.addApps(challenge, request.challengeSignUpRequest().apps(), os);
challengeFacade.startFirstChallengeWithChallengeSignUpRequest(request.challenge(), newUser , os);

return performLogin(socialAccessToken, socialPlatform, user);
return performLogin(newUser, socialAccessToken, socialPlatform);
}

private String getSocialIdBySocialAccessToken(SocialPlatform socialPlatform, String socialAccessToken) {
return switch (socialPlatform.toString()) {
case "KAKAO" -> kakaoLoginService.getSocialIdByKakao(socialAccessToken);
case "APPLE" -> appleOAuthProvider.getApplePlatformId(socialAccessToken);
default -> throw new JwtException(JwtError.INVALID_SOCIAL_ACCESS_TOKEN);
};
if (socialPlatform == SocialPlatform.APPLE) {
return appleOAuthProvider.getApplePlatformId(socialAccessToken);
}
if (socialPlatform == SocialPlatform.KAKAO) {
return kakaoLoginService.getSocialIdByKakao(socialAccessToken);
}
throw new JwtException(JwtError.INVALID_SOCIAL_ACCESS_TOKEN);
}

public ReissueResponse reissueToken(String refreshToken) {
return tokenService.reissueToken(refreshToken);
private LoginResponse performLogin(User loginUser, String socialAccessToken, SocialPlatform socialPlatform) {
this.updateAdditionalUserLoginInfo(loginUser, socialAccessToken, socialPlatform);

Long userId = loginUser.getId();
return new LoginResponse(userId, tokenService.issueToken(userId.toString()));
}

private LoginResponse performLogin(String socialAccessToken, SocialPlatform socialPlatform, User loginUser) {
private void updateAdditionalUserLoginInfo(User loginUser, String socialAccessToken, SocialPlatform socialPlatform) {
userService.recoverIfIsDeletedUser(loginUser);

if (socialPlatform == SocialPlatform.KAKAO) {
kakaoLoginService.updateUserInfoByKakao(loginUser, socialAccessToken);
}
Long userId = loginUser.getId();
return new LoginResponse(userId, tokenService.issueToken(userId.toString()));
}


public ReissueResponse reissueToken(String refreshToken) {
return tokenService.reissueToken(refreshToken);
}

public SocialAccessTokenResponse getSocialAccessTokenByAuthorizationCode(String code) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ResponseEntity<BaseResponse<?>> orderAddChallenge(
@UserId final Long userId,
@RequestHeader("OS") final String os,
@RequestBody @Valid final ChallengeRequest request) {
challengeFacade.addChallenge(userId, request, os);
challengeFacade.startNewChallengeByPreviousChallenge(userId, request, os);

return ResponseEntity
.status(ChallengeSuccess.ADD_CHALLENGE_SUCCESS.getHttpStatus())
Expand Down
Loading

0 comments on commit 1fd02be

Please sign in to comment.