Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/Team-HMH/HMH-Server into…
Browse files Browse the repository at this point in the history
… refactor/#101-change-domain-challenge

# Conflicts:
#	src/main/java/sopt/org/hmh/domain/user/service/UserService.java
  • Loading branch information
jumining committed Apr 4, 2024
2 parents dc39821 + 0f24ea1 commit e15de09
Show file tree
Hide file tree
Showing 37 changed files with 550 additions and 206 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ application-local.yml
application-prod.yml

### Test ###
/src/test/
data.sql

# End of https://www.gitignore.io/api/java,macos,gradle,intellij
14 changes: 14 additions & 0 deletions src/HMH-Server.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/main/java" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="SonarLintModuleSettings">
<option name="uniqueId" value="f14dac82-c004-41f9-a37e-fbdf99afe9a4" />
</component>
</module>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.hmh.domain.user.controller;
package sopt.org.hmh.domain.auth.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -7,15 +7,15 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import sopt.org.hmh.domain.user.dto.request.SocialPlatformRequest;
import sopt.org.hmh.domain.user.dto.request.SocialSignUpRequest;
import sopt.org.hmh.domain.auth.dto.request.SocialPlatformRequest;
import sopt.org.hmh.domain.auth.dto.request.SocialSignUpRequest;
import sopt.org.hmh.global.auth.UserId;
import sopt.org.hmh.global.auth.jwt.JwtConstants;
import sopt.org.hmh.global.common.response.BaseResponse;

@Tag(name = "회원 관련 API")
@SecurityRequirement(name = JwtConstants.AUTHORIZATION)
public interface UserApi {
public interface AuthApi {

@Operation(summary = "소셜 로그인")
ResponseEntity<BaseResponse<?>> orderLogin(
Expand All @@ -34,17 +34,4 @@ ResponseEntity<BaseResponse<?>> orderSignup(
ResponseEntity<BaseResponse<?>> orderReissue(
@Parameter(hidden = true) @RequestHeader(JwtConstants.AUTHORIZATION) final String refreshToken
);

@Operation(summary = "로그아웃")
ResponseEntity<BaseResponse<?>> orderLogout(@UserId @Parameter(hidden = true) final Long userId);

@Operation(summary = "유저 정보 불러오기")
ResponseEntity<BaseResponse<?>> orderGetUserInfo(@UserId @Parameter(hidden = true) final Long userId);

@Operation(summary = "회원 탈퇴")
public ResponseEntity<BaseResponse<?>> orderGetUserPoint(@UserId final Long userId);

@Operation(
summary = "회원 탈퇴")
ResponseEntity<BaseResponse<?>> orderWithdraw(@UserId @Parameter(hidden = true) final Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package sopt.org.hmh.domain.auth.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sopt.org.hmh.domain.auth.exception.AuthSuccess;
import sopt.org.hmh.domain.auth.dto.request.SocialPlatformRequest;
import sopt.org.hmh.domain.auth.dto.request.SocialSignUpRequest;
import sopt.org.hmh.domain.auth.service.AuthService;
import sopt.org.hmh.global.auth.social.SocialAccessTokenResponse;
import sopt.org.hmh.global.common.response.BaseResponse;

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

private final AuthService authService;

@PostMapping("/login")
@Override
public ResponseEntity<BaseResponse<?>> orderLogin(
@RequestHeader("Authorization") final String socialAccessToken,
@RequestBody final SocialPlatformRequest request
) {
return ResponseEntity
.status(AuthSuccess.LOGIN_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.LOGIN_SUCCESS, authService.login(socialAccessToken, request)));
}

@PostMapping("/signup")
@Override
public ResponseEntity<BaseResponse<?>> orderSignup(
@RequestHeader("Authorization") final String socialAccessToken,
@RequestHeader("OS") final String os,
@RequestBody final SocialSignUpRequest request
) {
return ResponseEntity
.status(AuthSuccess.SIGNUP_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.SIGNUP_SUCCESS, authService.signup(socialAccessToken, request, os)));
}

@PostMapping("/reissue")
@Override
public ResponseEntity<BaseResponse<?>> orderReissue(
@RequestHeader("Authorization") final String refreshToken
) {
return ResponseEntity
.status(AuthSuccess.REISSUE_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.REISSUE_SUCCESS, authService.reissueToken(refreshToken)));
}

@GetMapping("/social/token/kakao")
public ResponseEntity<BaseResponse<SocialAccessTokenResponse>> orderGetKakaoAccessToken(
@RequestParam("code") final String code
) {
return ResponseEntity
.status(AuthSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS.getHttpStatus())
.body(BaseResponse.success(AuthSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS, authService.getSocialAccessTokenByAuthorizationCode(code)));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.hmh.domain.user.dto.request;
package sopt.org.hmh.domain.auth.dto.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.hmh.domain.user.dto.request;
package sopt.org.hmh.domain.auth.dto.request;

import sopt.org.hmh.global.auth.social.SocialPlatform;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.hmh.domain.user.dto.request;
package sopt.org.hmh.domain.auth.dto.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import sopt.org.hmh.domain.challenge.dto.request.ChallengeSignUpRequest;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package sopt.org.hmh.domain.user.dto.response;
package sopt.org.hmh.domain.auth.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import sopt.org.hmh.domain.user.domain.User;
import sopt.org.hmh.domain.users.domain.User;
import sopt.org.hmh.global.auth.jwt.TokenResponse;

public record LoginResponse(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.hmh.domain.user.dto.response;
package sopt.org.hmh.domain.auth.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import sopt.org.hmh.global.auth.jwt.TokenResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package sopt.org.hmh.domain.user.domain.exception;
package sopt.org.hmh.domain.auth.exception;

import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import sopt.org.hmh.global.common.exception.base.ErrorBase;

@AllArgsConstructor
public enum UserError implements ErrorBase {
public enum AuthError implements ErrorBase {

// 400 BAD REQUEST
INVALID_USER(HttpStatus.BAD_REQUEST, "Principle 객체가 없습니다."),
DUPLICATE_USER(HttpStatus.BAD_REQUEST, "이미 회원가입된 유저입니다."),

// 403 FORBIDDEN
NOT_SIGNUP_USER(HttpStatus.FORBIDDEN, "회원가입된 유저가 아닙니다. 회원가입을 진행해주세요."),

// 404 NOT FOUND
NOT_FOUND_USER(HttpStatus.NOT_FOUND, "유저를 찾을 수 없습니다.");
;

private final HttpStatus status;
private final String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package sopt.org.hmh.domain.auth.exception;

import sopt.org.hmh.global.common.exception.base.ExceptionBase;

public class AuthException extends ExceptionBase {

public AuthException(AuthError errorBase) {
super(errorBase);
}
}
36 changes: 36 additions & 0 deletions src/main/java/sopt/org/hmh/domain/auth/exception/AuthSuccess.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package sopt.org.hmh.domain.auth.exception;

import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import sopt.org.hmh.global.common.exception.base.SuccessBase;

@AllArgsConstructor
public enum AuthSuccess implements SuccessBase {

// 200 OK
LOGIN_SUCCESS(HttpStatus.OK, "로그인에 성공했습니다."),
REISSUE_SUCCESS(HttpStatus.OK, "토큰 재발급에 성공했습니다."),
GET_SOCIAL_ACCESS_TOKEN_SUCCESS(HttpStatus.OK, "소셜 액세스 토큰 발급을 성공했습니다."),

// 201 CREATED
SIGNUP_SUCCESS(HttpStatus.CREATED, "회원 가입에 성공했습니다."),
;

private final HttpStatus status;
private final String successMessage;

@Override
public int getHttpStatusCode() {
return this.status.value();
}

@Override
public HttpStatus getHttpStatus() {
return this.status;
}

@Override
public String getSuccessMessage() {
return this.successMessage;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package sopt.org.hmh.domain.user.repository;
package sopt.org.hmh.domain.auth.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import sopt.org.hmh.domain.user.domain.OnboardingInfo;
import sopt.org.hmh.domain.users.domain.OnboardingInfo;

public interface OnboardingInfoRepository extends JpaRepository<OnboardingInfo, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package sopt.org.hmh.domain.user.repository;
package sopt.org.hmh.domain.auth.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import sopt.org.hmh.domain.user.domain.OnboardingProblem;
import sopt.org.hmh.domain.users.domain.OnboardingProblem;

public interface ProblemRepository extends JpaRepository<OnboardingProblem, Long> {
}
89 changes: 89 additions & 0 deletions src/main/java/sopt/org/hmh/domain/auth/service/AuthService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package sopt.org.hmh.domain.auth.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sopt.org.hmh.domain.auth.dto.response.ReissueResponse;
import sopt.org.hmh.domain.challenge.service.ChallengeService;
import sopt.org.hmh.domain.users.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.users.service.UserService;
import sopt.org.hmh.global.auth.jwt.TokenService;
import sopt.org.hmh.global.auth.jwt.exception.JwtError;
import sopt.org.hmh.global.auth.jwt.exception.JwtException;
import sopt.org.hmh.global.auth.social.SocialPlatform;
import sopt.org.hmh.global.auth.social.SocialAccessTokenResponse;
import sopt.org.hmh.global.auth.social.apple.fegin.AppleOAuthProvider;
import sopt.org.hmh.global.auth.social.kakao.fegin.KakaoLoginService;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AuthService {

private final KakaoLoginService kakaoLoginService;
private final AppleOAuthProvider appleOAuthProvider;

private final ChallengeService challengeService;
private final TokenService tokenService;
private final UserService userService;

@Transactional
public LoginResponse login(String socialAccessToken, SocialPlatformRequest request) {

SocialPlatform socialPlatform = request.socialPlatform();
String socialId = getSocialIdBySocialAccessToken(socialPlatform, socialAccessToken);

User loginUser = userService.getUserBySocialPlatformAndSocialId(socialPlatform, socialId);

return performLogin(socialAccessToken, socialPlatform, loginUser);
}

@Transactional
public LoginResponse signup(String socialAccessToken, SocialSignUpRequest request, String os) {

SocialPlatform socialPlatform = request.socialPlatform();
String socialId = getSocialIdBySocialAccessToken(socialPlatform, socialAccessToken);

userService.validateDuplicateUser(socialId, socialPlatform);

User user = userService.addUser(socialPlatform, socialId, request.name());

challengeService.updateChallengeForPeriodWithInfo(
challengeService.addChallenge(user.getId(),
request.challengeSignUpRequest().period(),
request.challengeSignUpRequest().goalTime()),
request.challengeSignUpRequest().apps(),
os);
userService.registerOnboardingInfo(request);

return performLogin(socialAccessToken, socialPlatform, user);
}

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);
};
}

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


private LoginResponse performLogin(String socialAccessToken, SocialPlatform socialPlatform, User loginUser) {
if (socialPlatform == SocialPlatform.KAKAO) {
kakaoLoginService.updateUserInfoByKakao(loginUser, socialAccessToken);
}
return LoginResponse.of(loginUser, tokenService.issueToken(loginUser.getId()));
}

public SocialAccessTokenResponse getSocialAccessTokenByAuthorizationCode(String code) {
return kakaoLoginService.getKakaoAccessToken(code);
}

}
Loading

0 comments on commit e15de09

Please sign in to comment.