diff --git a/.gitignore b/.gitignore
index 7b79b7ca..894ecfdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/src/HMH-Server.iml b/src/HMH-Server.iml
new file mode 100644
index 00000000..abfb34a9
--- /dev/null
+++ b/src/HMH-Server.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java b/src/main/java/sopt/org/hmh/domain/auth/controller/AuthApi.java
similarity index 64%
rename from src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java
rename to src/main/java/sopt/org/hmh/domain/auth/controller/AuthApi.java
index 0177c935..77878853 100644
--- a/src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/controller/AuthApi.java
@@ -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;
@@ -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> orderLogin(
@@ -34,17 +34,4 @@ ResponseEntity> orderSignup(
ResponseEntity> orderReissue(
@Parameter(hidden = true) @RequestHeader(JwtConstants.AUTHORIZATION) final String refreshToken
);
-
- @Operation(summary = "로그아웃")
- ResponseEntity> orderLogout(@UserId @Parameter(hidden = true) final Long userId);
-
- @Operation(summary = "유저 정보 불러오기")
- ResponseEntity> orderGetUserInfo(@UserId @Parameter(hidden = true) final Long userId);
-
- @Operation(summary = "회원 탈퇴")
- public ResponseEntity> orderGetUserPoint(@UserId final Long userId);
-
- @Operation(
- summary = "회원 탈퇴")
- ResponseEntity> orderWithdraw(@UserId @Parameter(hidden = true) final Long userId);
}
diff --git a/src/main/java/sopt/org/hmh/domain/auth/controller/AuthController.java b/src/main/java/sopt/org/hmh/domain/auth/controller/AuthController.java
new file mode 100644
index 00000000..f12e88a5
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/auth/controller/AuthController.java
@@ -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> 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> 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> 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> 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)));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/request/OnboardingRequest.java b/src/main/java/sopt/org/hmh/domain/auth/dto/request/OnboardingRequest.java
similarity index 82%
rename from src/main/java/sopt/org/hmh/domain/user/dto/request/OnboardingRequest.java
rename to src/main/java/sopt/org/hmh/domain/auth/dto/request/OnboardingRequest.java
index 3c0fa3ba..e9a94fa0 100644
--- a/src/main/java/sopt/org/hmh/domain/user/dto/request/OnboardingRequest.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/dto/request/OnboardingRequest.java
@@ -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;
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/request/SocialPlatformRequest.java b/src/main/java/sopt/org/hmh/domain/auth/dto/request/SocialPlatformRequest.java
similarity index 74%
rename from src/main/java/sopt/org/hmh/domain/user/dto/request/SocialPlatformRequest.java
rename to src/main/java/sopt/org/hmh/domain/auth/dto/request/SocialPlatformRequest.java
index 02bf7840..cfec598a 100644
--- a/src/main/java/sopt/org/hmh/domain/user/dto/request/SocialPlatformRequest.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/dto/request/SocialPlatformRequest.java
@@ -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;
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/request/SocialSignUpRequest.java b/src/main/java/sopt/org/hmh/domain/auth/dto/request/SocialSignUpRequest.java
similarity index 91%
rename from src/main/java/sopt/org/hmh/domain/user/dto/request/SocialSignUpRequest.java
rename to src/main/java/sopt/org/hmh/domain/auth/dto/request/SocialSignUpRequest.java
index 84cb8cbc..9861dc6f 100644
--- a/src/main/java/sopt/org/hmh/domain/user/dto/request/SocialSignUpRequest.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/dto/request/SocialSignUpRequest.java
@@ -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;
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/response/LoginResponse.java b/src/main/java/sopt/org/hmh/domain/auth/dto/response/LoginResponse.java
similarity index 82%
rename from src/main/java/sopt/org/hmh/domain/user/dto/response/LoginResponse.java
rename to src/main/java/sopt/org/hmh/domain/auth/dto/response/LoginResponse.java
index 114f4af2..cf9f4d78 100644
--- a/src/main/java/sopt/org/hmh/domain/user/dto/response/LoginResponse.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/dto/response/LoginResponse.java
@@ -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(
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/response/ReissueResponse.java b/src/main/java/sopt/org/hmh/domain/auth/dto/response/ReissueResponse.java
similarity index 88%
rename from src/main/java/sopt/org/hmh/domain/user/dto/response/ReissueResponse.java
rename to src/main/java/sopt/org/hmh/domain/auth/dto/response/ReissueResponse.java
index 0ceec7c0..119600c9 100644
--- a/src/main/java/sopt/org/hmh/domain/user/dto/response/ReissueResponse.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/dto/response/ReissueResponse.java
@@ -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;
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserError.java b/src/main/java/sopt/org/hmh/domain/auth/exception/AuthError.java
similarity index 81%
rename from src/main/java/sopt/org/hmh/domain/user/domain/exception/UserError.java
rename to src/main/java/sopt/org/hmh/domain/auth/exception/AuthError.java
index 7d2e336d..2b80ff6b 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserError.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/exception/AuthError.java
@@ -1,11 +1,11 @@
-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 객체가 없습니다."),
@@ -13,9 +13,7 @@ public enum UserError implements ErrorBase {
// 403 FORBIDDEN
NOT_SIGNUP_USER(HttpStatus.FORBIDDEN, "회원가입된 유저가 아닙니다. 회원가입을 진행해주세요."),
-
- // 404 NOT FOUND
- NOT_FOUND_USER(HttpStatus.NOT_FOUND, "유저를 찾을 수 없습니다.");
+ ;
private final HttpStatus status;
private final String errorMessage;
diff --git a/src/main/java/sopt/org/hmh/domain/auth/exception/AuthException.java b/src/main/java/sopt/org/hmh/domain/auth/exception/AuthException.java
new file mode 100644
index 00000000..d68559b5
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/auth/exception/AuthException.java
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/auth/exception/AuthSuccess.java b/src/main/java/sopt/org/hmh/domain/auth/exception/AuthSuccess.java
new file mode 100644
index 00000000..e382ef95
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/auth/exception/AuthSuccess.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/repository/OnboardingInfoRepository.java b/src/main/java/sopt/org/hmh/domain/auth/repository/OnboardingInfoRepository.java
similarity index 60%
rename from src/main/java/sopt/org/hmh/domain/user/repository/OnboardingInfoRepository.java
rename to src/main/java/sopt/org/hmh/domain/auth/repository/OnboardingInfoRepository.java
index 5d28859a..3fdb1d65 100644
--- a/src/main/java/sopt/org/hmh/domain/user/repository/OnboardingInfoRepository.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/repository/OnboardingInfoRepository.java
@@ -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 {
}
diff --git a/src/main/java/sopt/org/hmh/domain/user/repository/ProblemRepository.java b/src/main/java/sopt/org/hmh/domain/auth/repository/ProblemRepository.java
similarity index 59%
rename from src/main/java/sopt/org/hmh/domain/user/repository/ProblemRepository.java
rename to src/main/java/sopt/org/hmh/domain/auth/repository/ProblemRepository.java
index 396bd0c0..5e60683e 100644
--- a/src/main/java/sopt/org/hmh/domain/user/repository/ProblemRepository.java
+++ b/src/main/java/sopt/org/hmh/domain/auth/repository/ProblemRepository.java
@@ -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 {
}
diff --git a/src/main/java/sopt/org/hmh/domain/auth/service/AuthService.java b/src/main/java/sopt/org/hmh/domain/auth/service/AuthService.java
new file mode 100644
index 00000000..e37ff19d
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/auth/service/AuthService.java
@@ -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);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java b/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java
deleted file mode 100644
index e7359a7b..00000000
--- a/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package sopt.org.hmh.domain.user.controller;
-
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.DeleteMapping;
-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.user.domain.exception.UserSuccess;
-import sopt.org.hmh.domain.user.dto.request.SocialPlatformRequest;
-import sopt.org.hmh.domain.user.dto.request.SocialSignUpRequest;
-import sopt.org.hmh.domain.user.service.UserService;
-import sopt.org.hmh.global.auth.UserId;
-import sopt.org.hmh.global.auth.social.SocialAccessTokenResponse;
-import sopt.org.hmh.global.common.response.BaseResponse;
-import sopt.org.hmh.global.common.response.EmptyJsonResponse;
-
-@RestController
-@RequiredArgsConstructor
-@RequestMapping("/api/v1/user")
-public class UserController implements UserApi{
-
- private final UserService userService;
-
- @PostMapping("/login")
- @Override
- public ResponseEntity> orderLogin(
- @RequestHeader("Authorization") final String socialAccessToken,
- @RequestBody final SocialPlatformRequest request
- ) {
- return ResponseEntity
- .status(UserSuccess.LOGIN_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.LOGIN_SUCCESS, userService.login(socialAccessToken, request)));
- }
-
- @PostMapping("/signup")
- @Override
- public ResponseEntity> orderSignup(
- @RequestHeader("Authorization") final String socialAccessToken,
- @RequestHeader("OS") final String os,
- @RequestBody final SocialSignUpRequest request
- ) {
- return ResponseEntity
- .status(UserSuccess.SIGNUP_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.SIGNUP_SUCCESS, userService.signup(socialAccessToken, request, os)));
- }
-
- @PostMapping("/reissue")
- @Override
- public ResponseEntity> orderReissue(
- @RequestHeader("Authorization") final String refreshToken
- ) {
- return ResponseEntity
- .status(UserSuccess.REISSUE_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.REISSUE_SUCCESS, userService.reissueToken(refreshToken)));
- }
-
- @PostMapping("/logout")
- @Override
- public ResponseEntity> orderLogout(@UserId final Long userId) {
- userService.logout(userId);
- return ResponseEntity
- .status(UserSuccess.LOGOUT_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.LOGOUT_SUCCESS, new EmptyJsonResponse()));
- }
-
- @GetMapping
- @Override
- public ResponseEntity> orderGetUserInfo(@UserId final Long userId) {
- return ResponseEntity
- .status(UserSuccess.GET_USER_INFO_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.GET_USER_INFO_SUCCESS, userService.getUserInfo(userId)));
- }
-
- @GetMapping("/point")
- @Override
- public ResponseEntity> orderGetUserPoint(@UserId final Long userId) {
- return ResponseEntity
- .status(UserSuccess.GET_USER_POINT_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.GET_USER_POINT_SUCCESS, userService.getUserPoint(userId)));
- }
-
- @DeleteMapping
- @Override
- public ResponseEntity> orderWithdraw(@UserId final Long userId) {
- userService.withdraw(userId);
- return ResponseEntity
- .status(UserSuccess.WITHDRAW_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.WITHDRAW_SUCCESS, new EmptyJsonResponse()));
- }
-
- @GetMapping("/social/token/kakao")
- public ResponseEntity> orderGetKakaoAccessToken(
- @RequestParam("code") final String code
- ) {
- return ResponseEntity
- .status(UserSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS.getHttpStatus())
- .body(BaseResponse.success(UserSuccess.GET_SOCIAL_ACCESS_TOKEN_SUCCESS, userService.getSocialAccessTokenByAuthorizationCode(code)));
- }
-}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserPointResponse.java b/src/main/java/sopt/org/hmh/domain/user/dto/response/UserPointResponse.java
deleted file mode 100644
index 082bc9ae..00000000
--- a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserPointResponse.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package sopt.org.hmh.domain.user.dto.response;
-
-import sopt.org.hmh.domain.user.domain.User;
-
-public record UserPointResponse(
- Integer point
-) {
- public static UserPointResponse of(User user) {
- return new UserPointResponse(
- user.getPoint()
- );
- }
-}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/service/ExpiredUserDeleteScheduler.java b/src/main/java/sopt/org/hmh/domain/user/service/ExpiredUserDeleteScheduler.java
deleted file mode 100644
index 0c2ea49a..00000000
--- a/src/main/java/sopt/org/hmh/domain/user/service/ExpiredUserDeleteScheduler.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package sopt.org.hmh.domain.user.service;
-
-import java.time.LocalDateTime;
-import lombok.RequiredArgsConstructor;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-@Component
-@RequiredArgsConstructor
-@Transactional
-public class ExpiredUserDeleteScheduler {
-
- private final UserService userService;
-
- @Scheduled(cron = "0 0 4 * * ?")
- public void deleteExpiredUser() {
- userService.deleteExpiredUser(LocalDateTime.now());
- }
-}
diff --git a/src/main/java/sopt/org/hmh/domain/users/controller/UserApi.java b/src/main/java/sopt/org/hmh/domain/users/controller/UserApi.java
new file mode 100644
index 00000000..f03019d8
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/users/controller/UserApi.java
@@ -0,0 +1,24 @@
+package sopt.org.hmh.domain.users.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import org.springframework.http.ResponseEntity;
+import sopt.org.hmh.global.auth.UserId;
+import sopt.org.hmh.global.common.response.BaseResponse;
+
+public interface UserApi {
+
+ @Operation(summary = "로그아웃")
+ ResponseEntity> orderLogout(@UserId @Parameter(hidden = true) final Long userId);
+
+ @Operation(summary = "유저 정보 불러오기")
+ ResponseEntity> orderGetUserInfo(@UserId @Parameter(hidden = true) final Long userId);
+
+ @Operation(summary = "유저 포인트 정보 불러오기")
+ public ResponseEntity> orderGetUserPoint(@UserId final Long userId);
+
+ @Operation(
+ summary = "회원 탈퇴")
+ ResponseEntity> orderWithdraw(@UserId @Parameter(hidden = true) final Long userId);
+
+}
diff --git a/src/main/java/sopt/org/hmh/domain/users/controller/UserController.java b/src/main/java/sopt/org/hmh/domain/users/controller/UserController.java
new file mode 100644
index 00000000..478f267c
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/users/controller/UserController.java
@@ -0,0 +1,56 @@
+package sopt.org.hmh.domain.users.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import sopt.org.hmh.domain.users.domain.exception.UserSuccess;
+import sopt.org.hmh.domain.users.service.UserService;
+import sopt.org.hmh.global.auth.UserId;
+import sopt.org.hmh.global.common.response.BaseResponse;
+import sopt.org.hmh.global.common.response.EmptyJsonResponse;
+
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/v1/user")
+public class UserController implements UserApi{
+
+ private final UserService userService;
+
+ @PostMapping("/logout")
+ @Override
+ public ResponseEntity> orderLogout(@UserId final Long userId) {
+ userService.logout(userId);
+ return ResponseEntity
+ .status(UserSuccess.LOGOUT_SUCCESS.getHttpStatus())
+ .body(BaseResponse.success(UserSuccess.LOGOUT_SUCCESS, new EmptyJsonResponse()));
+ }
+
+ @GetMapping
+ @Override
+ public ResponseEntity> orderGetUserInfo(@UserId final Long userId) {
+ return ResponseEntity
+ .status(UserSuccess.GET_USER_INFO_SUCCESS.getHttpStatus())
+ .body(BaseResponse.success(UserSuccess.GET_USER_INFO_SUCCESS, userService.getUserInfo(userId)));
+ }
+
+ @GetMapping("/point")
+ @Override
+ public ResponseEntity> orderGetUserPoint(@UserId final Long userId) {
+ return ResponseEntity
+ .status(UserSuccess.GET_USER_POINT_SUCCESS.getHttpStatus())
+ .body(BaseResponse.success(UserSuccess.GET_USER_POINT_SUCCESS, userService.getUserInfo(userId).point()));
+ }
+
+ @DeleteMapping
+ public ResponseEntity> orderWithdraw(@UserId final Long userId) {
+ userService.withdraw(userId);
+ return ResponseEntity
+ .status(UserSuccess.WITHDRAW_SUCCESS.getHttpStatus())
+ .body(BaseResponse.success(UserSuccess.WITHDRAW_SUCCESS, new EmptyJsonResponse()));
+ }
+
+}
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/OnboardingInfo.java b/src/main/java/sopt/org/hmh/domain/users/domain/OnboardingInfo.java
similarity index 94%
rename from src/main/java/sopt/org/hmh/domain/user/domain/OnboardingInfo.java
rename to src/main/java/sopt/org/hmh/domain/users/domain/OnboardingInfo.java
index 08db01bb..04f92495 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/OnboardingInfo.java
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/OnboardingInfo.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.domain;
+package sopt.org.hmh.domain.users.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/OnboardingProblem.java b/src/main/java/sopt/org/hmh/domain/users/domain/OnboardingProblem.java
similarity index 94%
rename from src/main/java/sopt/org/hmh/domain/user/domain/OnboardingProblem.java
rename to src/main/java/sopt/org/hmh/domain/users/domain/OnboardingProblem.java
index 5220bd5b..f2d37faf 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/OnboardingProblem.java
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/OnboardingProblem.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.domain;
+package sopt.org.hmh.domain.users.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/User.java b/src/main/java/sopt/org/hmh/domain/users/domain/User.java
similarity index 97%
rename from src/main/java/sopt/org/hmh/domain/user/domain/User.java
rename to src/main/java/sopt/org/hmh/domain/users/domain/User.java
index fd1c2df0..6d5058b9 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/User.java
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/User.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.domain;
+package sopt.org.hmh.domain.users.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/UserConstants.java b/src/main/java/sopt/org/hmh/domain/users/domain/UserConstants.java
similarity index 86%
rename from src/main/java/sopt/org/hmh/domain/user/domain/UserConstants.java
rename to src/main/java/sopt/org/hmh/domain/users/domain/UserConstants.java
index 7a96a680..02c59884 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/UserConstants.java
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/UserConstants.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.domain;
+package sopt.org.hmh.domain.users.domain;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserError.java b/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserError.java
new file mode 100644
index 00000000..5978b116
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserError.java
@@ -0,0 +1,31 @@
+package sopt.org.hmh.domain.users.domain.exception;
+
+import lombok.AllArgsConstructor;
+import org.springframework.http.HttpStatus;
+import sopt.org.hmh.global.common.exception.base.ErrorBase;
+
+@AllArgsConstructor
+public enum UserError implements ErrorBase {
+
+ // 404 NOT FOUND
+ NOT_FOUND_USER(HttpStatus.NOT_FOUND, "유저를 찾을 수 없습니다."),
+ ;
+
+ private final HttpStatus status;
+ private final String errorMessage;
+
+ @Override
+ public int getHttpStatusCode() {
+ return this.status.value();
+ }
+
+ @Override
+ public HttpStatus getHttpStatus() {
+ return this.status;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return this.errorMessage;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserException.java b/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserException.java
similarity index 78%
rename from src/main/java/sopt/org/hmh/domain/user/domain/exception/UserException.java
rename to src/main/java/sopt/org/hmh/domain/users/domain/exception/UserException.java
index 81c000a2..176f0832 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserException.java
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserException.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.domain.exception;
+package sopt.org.hmh.domain.users.domain.exception;
import sopt.org.hmh.global.common.exception.base.ExceptionBase;
@@ -7,4 +7,4 @@ public class UserException extends ExceptionBase {
public UserException(UserError errorBase) {
super(errorBase);
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java b/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserSuccess.java
similarity index 70%
rename from src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java
rename to src/main/java/sopt/org/hmh/domain/users/domain/exception/UserSuccess.java
index cae47ddb..a8cf03bb 100644
--- a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java
+++ b/src/main/java/sopt/org/hmh/domain/users/domain/exception/UserSuccess.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.domain.exception;
+package sopt.org.hmh.domain.users.domain.exception;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
@@ -8,16 +8,10 @@
public enum UserSuccess implements SuccessBase {
// 200 OK
- LOGIN_SUCCESS(HttpStatus.OK, "로그인에 성공했습니다."),
- REISSUE_SUCCESS(HttpStatus.OK, "토큰 재발급에 성공했습니다."),
- LOGOUT_SUCCESS(HttpStatus.OK, "로그아웃에 성공했습니다."),
GET_USER_INFO_SUCCESS(HttpStatus.OK, "유저의 정보를 불러오는데에 성공했습니다."),
GET_USER_POINT_SUCCESS(HttpStatus.OK, "유저의 포인트 정보를 불러오는데에 성공했습니다."),
+ LOGOUT_SUCCESS(HttpStatus.OK, "로그아웃에 성공했습니다."),
WITHDRAW_SUCCESS(HttpStatus.OK, "회원 탈퇴를 성공하였습니다."),
- GET_SOCIAL_ACCESS_TOKEN_SUCCESS(HttpStatus.OK, "소셜 액세스 토큰 발급을 성공했습니다."),
-
- // 201 CREATED
- SIGNUP_SUCCESS(HttpStatus.CREATED, "회원 가입에 성공했습니다."),
;
private final HttpStatus status;
@@ -37,4 +31,4 @@ public HttpStatus getHttpStatus() {
public String getSuccessMessage() {
return this.successMessage;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserInfoResponse.java b/src/main/java/sopt/org/hmh/domain/users/dto/response/UserInfoResponse.java
similarity index 72%
rename from src/main/java/sopt/org/hmh/domain/user/dto/response/UserInfoResponse.java
rename to src/main/java/sopt/org/hmh/domain/users/dto/response/UserInfoResponse.java
index 0cf207b8..006a435a 100644
--- a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserInfoResponse.java
+++ b/src/main/java/sopt/org/hmh/domain/users/dto/response/UserInfoResponse.java
@@ -1,6 +1,6 @@
-package sopt.org.hmh.domain.user.dto.response;
+package sopt.org.hmh.domain.users.dto.response;
-import sopt.org.hmh.domain.user.domain.User;
+import sopt.org.hmh.domain.users.domain.User;
public record UserInfoResponse(
String name,
diff --git a/src/main/java/sopt/org/hmh/domain/user/repository/UserRepository.java b/src/main/java/sopt/org/hmh/domain/users/repository/UserRepository.java
similarity index 72%
rename from src/main/java/sopt/org/hmh/domain/user/repository/UserRepository.java
rename to src/main/java/sopt/org/hmh/domain/users/repository/UserRepository.java
index f37f1ebf..64db18da 100644
--- a/src/main/java/sopt/org/hmh/domain/user/repository/UserRepository.java
+++ b/src/main/java/sopt/org/hmh/domain/users/repository/UserRepository.java
@@ -1,4 +1,4 @@
-package sopt.org.hmh.domain.user.repository;
+package sopt.org.hmh.domain.users.repository;
import java.time.LocalDateTime;
import java.util.List;
@@ -6,16 +6,18 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
-import sopt.org.hmh.domain.user.domain.User;
-import sopt.org.hmh.domain.user.domain.exception.UserError;
-import sopt.org.hmh.domain.user.domain.exception.UserException;
+import sopt.org.hmh.domain.users.domain.User;
+import sopt.org.hmh.domain.auth.exception.AuthError;
+import sopt.org.hmh.domain.auth.exception.AuthException;
+import sopt.org.hmh.domain.users.domain.exception.UserError;
+import sopt.org.hmh.domain.users.domain.exception.UserException;
import sopt.org.hmh.global.auth.social.SocialPlatform;
public interface UserRepository extends JpaRepository {
default User findBySocialPlatformAndSocialIdOrThrowException(SocialPlatform socialPlatform, String socialId) {
- return findBySocialPlatformAndSocialId(socialPlatform, socialId).orElseThrow(() -> new UserException(
- UserError.NOT_SIGNUP_USER));
+ return findBySocialPlatformAndSocialId(socialPlatform, socialId).orElseThrow(() -> new AuthException(
+ AuthError.NOT_SIGNUP_USER));
}
default User findByIdOrThrowException(Long userId) {
diff --git a/src/main/java/sopt/org/hmh/domain/users/service/ExpiredUserDeleteScheduler.java b/src/main/java/sopt/org/hmh/domain/users/service/ExpiredUserDeleteScheduler.java
new file mode 100644
index 00000000..15546b27
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/users/service/ExpiredUserDeleteScheduler.java
@@ -0,0 +1,30 @@
+package sopt.org.hmh.domain.users.service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import sopt.org.hmh.domain.challenge.service.ChallengeService;
+import sopt.org.hmh.domain.users.repository.UserRepository;
+
+@Component
+@RequiredArgsConstructor
+@Transactional
+public class ExpiredUserDeleteScheduler {
+
+ private final UserRepository userRepository;
+ private final ChallengeService challengeService;
+
+ @Scheduled(cron = "0 0 4 * * ?")
+ public void deleteExpiredUser() {
+ deleteExpiredUser(LocalDateTime.now());
+ }
+
+ public void deleteExpiredUser(LocalDateTime currentDate) {
+ List expiredUserList = userRepository.findIdByDeletedAtBeforeAndIsDeletedIsTrue(currentDate);
+ userRepository.deleteAllById(expiredUserList);
+ challengeService.deleteChallengeRelatedByUserId(expiredUserList);
+ }
+}
diff --git a/src/main/java/sopt/org/hmh/domain/users/service/UserService.java b/src/main/java/sopt/org/hmh/domain/users/service/UserService.java
new file mode 100644
index 00000000..33eb784c
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/domain/users/service/UserService.java
@@ -0,0 +1,92 @@
+package sopt.org.hmh.domain.users.service;
+
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import sopt.org.hmh.domain.auth.dto.request.SocialSignUpRequest;
+import sopt.org.hmh.domain.auth.exception.AuthError;
+import sopt.org.hmh.domain.auth.exception.AuthException;
+import sopt.org.hmh.domain.auth.repository.OnboardingInfoRepository;
+import sopt.org.hmh.domain.auth.repository.ProblemRepository;
+import sopt.org.hmh.domain.users.domain.OnboardingInfo;
+import sopt.org.hmh.domain.users.domain.OnboardingProblem;
+import sopt.org.hmh.domain.users.domain.User;
+import sopt.org.hmh.domain.users.domain.UserConstants;
+import sopt.org.hmh.domain.users.dto.response.UserInfoResponse;
+import sopt.org.hmh.domain.users.repository.UserRepository;
+import sopt.org.hmh.global.auth.redis.RedisManagerService;
+import sopt.org.hmh.global.auth.social.SocialPlatform;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class UserService {
+
+ private final RedisManagerService redisManagerService;
+ private final UserRepository userRepository;
+ private final OnboardingInfoRepository onboardingInfoRepository;
+ private final ProblemRepository problemRepository;
+
+
+ @Transactional
+ public void withdraw(Long userId) {
+ redisManagerService.deleteRefreshToken(userId);
+ userRepository.findByIdOrThrowException(userId).softDelete();
+ }
+
+ public void logout(Long userId) {
+ redisManagerService.deleteRefreshToken(userId);
+ }
+
+ public UserInfoResponse getUserInfo(Long userId) {
+ return UserInfoResponse.of(userRepository.findByIdOrThrowException(userId));
+ }
+
+ public User getUserBySocialPlatformAndSocialId(SocialPlatform socialPlatform, String socialId) {
+ User user = userRepository.findBySocialPlatformAndSocialIdOrThrowException(socialPlatform, socialId);
+ if (user.isDeleted()) {
+ user.recover();
+ }
+ return user;
+ }
+
+ public void validateDuplicateUser(String socialId, SocialPlatform socialPlatform) {
+ if (userRepository.existsBySocialPlatformAndSocialId(socialPlatform, socialId)) {
+ throw new AuthException(AuthError.DUPLICATE_USER);
+ }
+ }
+
+ public User addUser(SocialPlatform socialPlatform, String socialId, String name) {
+ return userRepository.save(
+ User.builder()
+ .socialPlatform(socialPlatform)
+ .socialId(socialId)
+ .name(validateName(name))
+ .build()
+ );
+ }
+
+ private String validateName(String name) {
+ if (!StringUtils.hasText(name)) {
+ return UserConstants.DEFAULT_USER_NAME;
+ }
+ return name;
+ }
+
+ public void registerOnboardingInfo(SocialSignUpRequest request) {
+ OnboardingInfo onboardingInfo = OnboardingInfo.builder()
+ .averageUseTime(request.onboardingRequest().averageUseTime())
+ .build();
+ Long onboardingInfoId = onboardingInfoRepository.save(onboardingInfo).getId();
+
+ List problemList = request.onboardingRequest().problemList().stream()
+ .map(problem -> OnboardingProblem.builder()
+ .onboardingInfoId(onboardingInfoId)
+ .problem(problem).build())
+ .toList();
+ problemRepository.saveAll(problemList);
+ }
+
+}
diff --git a/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java b/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java
index 6a5c8e24..185280db 100644
--- a/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java
+++ b/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java
@@ -24,6 +24,7 @@ public class JwtGenerator {
private Long ACCESS_TOKEN_EXPIRATION_TIME;
@Value("${jwt.refresh-token-expiration-time}")
private Long REFRESH_TOKEN_EXPIRATION_TIME;
+
private final TokenRepository tokenRepository;
public String generateToken(Long userId, boolean isRefreshToken) {
@@ -49,6 +50,12 @@ public String generateToken(Long userId, boolean isRefreshToken) {
return token;
}
+ public JwtParser getJwtParser() {
+ return Jwts.parserBuilder()
+ .setSigningKey(getSigningKey())
+ .build();
+ }
+
private Date generateNowDate() {
return new Date();
}
@@ -57,7 +64,7 @@ private Date generateExpirationDate(boolean isRefreshToken, Date now) {
return new Date(now.getTime() + calculateExpirationTime(isRefreshToken));
}
- public SecretKey getSigningKey() {
+ private SecretKey getSigningKey() {
return Keys.hmacShaKeyFor(encodeSecretKey().getBytes());
}
@@ -73,9 +80,4 @@ private String encodeSecretKey() {
.encodeToString(JWT_SECRET.getBytes(StandardCharsets.UTF_8));
}
- public JwtParser getJwtParser() {
- return Jwts.parserBuilder()
- .setSigningKey(getSigningKey())
- .build();
- }
}
\ No newline at end of file
diff --git a/src/main/java/sopt/org/hmh/global/auth/jwt/JwtProvider.java b/src/main/java/sopt/org/hmh/global/auth/jwt/JwtProvider.java
index 91424c4e..dceb8aba 100644
--- a/src/main/java/sopt/org/hmh/global/auth/jwt/JwtProvider.java
+++ b/src/main/java/sopt/org/hmh/global/auth/jwt/JwtProvider.java
@@ -11,8 +11,8 @@ public class JwtProvider {
private final JwtGenerator jwtGenerator;
public TokenResponse issueToken(Long userId) {
- return TokenResponse.of(jwtGenerator.generateToken(userId, true),
- jwtGenerator.generateToken(userId, false));
+ return TokenResponse.of(jwtGenerator.generateToken(userId, false),
+ jwtGenerator.generateToken(userId, true));
}
public Long getSubject(String token) {
diff --git a/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java b/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java
new file mode 100644
index 00000000..66292c1e
--- /dev/null
+++ b/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java
@@ -0,0 +1,40 @@
+package sopt.org.hmh.global.auth.jwt;
+
+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.global.auth.jwt.exception.JwtError;
+import sopt.org.hmh.global.auth.jwt.exception.JwtException;
+import sopt.org.hmh.global.auth.redis.RedisManagerService;
+
+@Service
+@RequiredArgsConstructor
+public class TokenService {
+
+ private final JwtProvider jwtProvider;
+ private final JwtValidator jwtValidator;
+ private final RedisManagerService redisManagerService;
+
+ @Transactional
+ public ReissueResponse reissueToken(String refreshToken) {
+ String parsedRefreshToken = parseTokenString(refreshToken);
+ Long userId = jwtProvider.getSubject(parsedRefreshToken);
+ jwtValidator.validateRefreshToken(parsedRefreshToken);
+ redisManagerService.deleteRefreshToken(userId);
+ return ReissueResponse.of(jwtProvider.issueToken(userId));
+ }
+
+ private String parseTokenString(String tokenString) {
+ String[] parsedTokens = tokenString.split(" ");
+ if (parsedTokens.length != 2) {
+ throw new JwtException(JwtError.INVALID_TOKEN_HEADER);
+ }
+ return parsedTokens[1];
+ }
+
+ public TokenResponse issueToken(Long userId) {
+ return jwtProvider.issueToken(userId);
+ }
+
+}
diff --git a/src/main/java/sopt/org/hmh/global/auth/redis/TokenService.java b/src/main/java/sopt/org/hmh/global/auth/redis/RedisManagerService.java
similarity index 88%
rename from src/main/java/sopt/org/hmh/global/auth/redis/TokenService.java
rename to src/main/java/sopt/org/hmh/global/auth/redis/RedisManagerService.java
index 9357150a..812a5681 100644
--- a/src/main/java/sopt/org/hmh/global/auth/redis/TokenService.java
+++ b/src/main/java/sopt/org/hmh/global/auth/redis/RedisManagerService.java
@@ -7,13 +7,10 @@
@Service
@RequiredArgsConstructor
-public class TokenService {
+public class RedisManagerService {
private final TokenRepository tokenRepository;
- /**
- * Refresh 토큰 삭제
- */
public void deleteRefreshToken(Long userId) {
if (tokenRepository.existsById(userId)) {
tokenRepository.deleteById(userId);
diff --git a/src/main/java/sopt/org/hmh/global/auth/social/kakao/fegin/KakaoLoginService.java b/src/main/java/sopt/org/hmh/global/auth/social/kakao/fegin/KakaoLoginService.java
index c1aff229..04616e5d 100644
--- a/src/main/java/sopt/org/hmh/global/auth/social/kakao/fegin/KakaoLoginService.java
+++ b/src/main/java/sopt/org/hmh/global/auth/social/kakao/fegin/KakaoLoginService.java
@@ -6,7 +6,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
-import sopt.org.hmh.domain.user.domain.User;
+import sopt.org.hmh.domain.users.domain.User;
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.SocialAccessTokenResponse;
diff --git a/src/test/java/sopt/org/hmh/HmhApplicationTests.java b/src/test/java/sopt/org/hmh/HmhApplicationTests.java
new file mode 100644
index 00000000..a35f1001
--- /dev/null
+++ b/src/test/java/sopt/org/hmh/HmhApplicationTests.java
@@ -0,0 +1,13 @@
+package sopt.org.hmh;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HmhApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}