diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 2b9666e..5213cb3 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -2,12 +2,11 @@ name: ModernFarmer CI/CD on: push: - branches: ["dev"] + branches: ["feature_11/에러처리-추가"] pull_request: branches: ["dev"] - permissions: contents: read @@ -76,4 +75,4 @@ jobs: docker rm ModernFarmerUser docker rmi ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 - docker run -d -p 80:8080 --name ModernFarmerUser ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 + docker run -d -p 80:8081 --name ModernFarmerUser ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/CustomExceptionContext.java b/src/main/java/modernfarmer/server/farmususer/global/exception/CustomExceptionContext.java new file mode 100644 index 0000000..bb79779 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/CustomExceptionContext.java @@ -0,0 +1,21 @@ +package modernfarmer.server.farmususer.global.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum CustomExceptionContext implements ExceptionContext{ + + + FIREBASE_CONFIG_EXCEPTION(HttpStatus.BAD_REQUEST, 1005, "파이어베이스 설정 오류입니다."), + NOT_FOUND_MEDICINE_ERROR(HttpStatus.NOT_FOUND, 1006, "해당 약 정보를 찾을 수 없습니다."), + REFRESH_TOKEN_DIFFERENT(HttpStatus.BAD_REQUEST , 1000,"접근이 올바르지 않습니다."); + // DOMAIN PER EXCEPTIONS ... + + + private final HttpStatus httpStatus; + private final int code; + private final String message; +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/ErrorResponse.java b/src/main/java/modernfarmer/server/farmususer/global/exception/ErrorResponse.java new file mode 100644 index 0000000..472b87c --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/ErrorResponse.java @@ -0,0 +1,13 @@ +package modernfarmer.server.farmususer.global.exception; + +import lombok.*; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@ToString +public class ErrorResponse { + + private int code; + private String message; +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/ExceptionContext.java b/src/main/java/modernfarmer/server/farmususer/global/exception/ExceptionContext.java new file mode 100644 index 0000000..8f2bbb7 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/ExceptionContext.java @@ -0,0 +1,11 @@ +package modernfarmer.server.farmususer.global.exception; + +import org.springframework.http.HttpStatus; + +public interface ExceptionContext { + HttpStatus getHttpStatus(); + + String getMessage(); + + int getCode(); +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/GlobalExceptionHandler.java b/src/main/java/modernfarmer/server/farmususer/global/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..17d97cc --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/GlobalExceptionHandler.java @@ -0,0 +1,43 @@ +package modernfarmer.server.farmususer.global.exception; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; +import java.util.Objects; + +@Slf4j +@RequiredArgsConstructor +@RestControllerAdvice +public class GlobalExceptionHandler { + private final int INVALID_PARAMETER_CODE = 400; + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleInputFieldException(MethodArgumentNotValidException e) { + FieldError mainError = e.getFieldErrors().get(0); + String[] errorInfo = Objects.requireNonNull(mainError.getDefaultMessage()).split(":"); + String message = errorInfo[0]; + return ResponseEntity.badRequest().body(new ErrorResponse(INVALID_PARAMETER_CODE, message)); + } + + @ExceptionHandler(ModernFarmerException.class) + public ResponseEntity handleModernFarmerException(ModernFarmerException e) { + return ResponseEntity.status(e.getHttpStatus()).body(new ErrorResponse(e.getCode(), e.getMessage())); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity unhandledException(Exception e, HttpServletRequest request) { + log.error("UnhandledException: {} {} errMessage={}\n", + request.getMethod(), + request.getRequestURI(), + e.getMessage() + ); + return ResponseEntity.internalServerError() + .body(new ErrorResponse(500, "서버와의 접속이 원활하지 않습니다.")); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/ModernFarmerException.java b/src/main/java/modernfarmer/server/farmususer/global/exception/ModernFarmerException.java new file mode 100644 index 0000000..6a40961 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/ModernFarmerException.java @@ -0,0 +1,19 @@ +package modernfarmer.server.farmususer.global.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public class ModernFarmerException extends RuntimeException { + private final HttpStatus httpStatus; + private final String message; + private final int code; + + public ModernFarmerException(HttpStatus httpStatus, String message, int code) { + this.httpStatus = httpStatus; + this.message = message; + this.code = code; + } + + +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/badrequest/BadRequestException.java b/src/main/java/modernfarmer/server/farmususer/global/exception/badrequest/BadRequestException.java new file mode 100644 index 0000000..b91018d --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/badrequest/BadRequestException.java @@ -0,0 +1,13 @@ +package modernfarmer.server.farmususer.global.exception.badrequest; + + +import lombok.Getter; +import modernfarmer.server.farmususer.global.exception.ExceptionContext; +import modernfarmer.server.farmususer.global.exception.ModernFarmerException; + +@Getter +public class BadRequestException extends ModernFarmerException { + public BadRequestException(ExceptionContext context){ + super(context.getHttpStatus(), context.getMessage(), context.getCode()); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/badrequest/FirebaseConfigException.java b/src/main/java/modernfarmer/server/farmususer/global/exception/badrequest/FirebaseConfigException.java new file mode 100644 index 0000000..fa3c385 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/badrequest/FirebaseConfigException.java @@ -0,0 +1,10 @@ +package modernfarmer.server.farmususer.global.exception.badrequest; + + +import static modernfarmer.server.farmususer.global.exception.CustomExceptionContext.FIREBASE_CONFIG_EXCEPTION; + +public class FirebaseConfigException extends BadRequestException { + public FirebaseConfigException(){ + super(FIREBASE_CONFIG_EXCEPTION); + } +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundException.java b/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundException.java new file mode 100644 index 0000000..a522576 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundException.java @@ -0,0 +1,16 @@ +package modernfarmer.server.farmususer.global.exception.notfound; + + +import lombok.Getter; +import modernfarmer.server.farmususer.global.exception.ExceptionContext; +import modernfarmer.server.farmususer.global.exception.ModernFarmerException; +import org.springframework.http.HttpStatus; + +@Getter +public class NotFoundException extends ModernFarmerException { + public NotFoundException(ExceptionContext context) { + super(context.getHttpStatus(), context.getMessage(), context.getCode()); + } + + +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundMedicineException.java b/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundMedicineException.java new file mode 100644 index 0000000..2d02c6c --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundMedicineException.java @@ -0,0 +1,12 @@ +package modernfarmer.server.farmususer.global.exception.notfound; + + +import modernfarmer.server.farmususer.global.exception.ModernFarmerException; + +import static modernfarmer.server.farmususer.global.exception.CustomExceptionContext.NOT_FOUND_MEDICINE_ERROR; + +public class NotFoundMedicineException extends NotFoundException { + public NotFoundMedicineException() { + super(NOT_FOUND_MEDICINE_ERROR); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundRefreshTokenException.java b/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundRefreshTokenException.java new file mode 100644 index 0000000..37e735c --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/notfound/NotFoundRefreshTokenException.java @@ -0,0 +1,10 @@ +package modernfarmer.server.farmususer.global.exception.notfound; + +import static modernfarmer.server.farmususer.global.exception.CustomExceptionContext.REFRESH_TOKEN_DIFFERENT; + +public class NotFoundRefreshTokenException extends NotFoundException{ + + public NotFoundRefreshTokenException() { + super(REFRESH_TOKEN_DIFFERENT); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java b/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java index fd8a8bf..60eed70 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java +++ b/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java @@ -4,7 +4,9 @@ import lombok.extern.slf4j.Slf4j; import modernfarmer.server.farmususer.user.dto.response.ResponseDto; import modernfarmer.server.farmususer.user.dto.response.TokenResponseDto; + import modernfarmer.server.farmususer.user.service.AuthService; +import modernfarmer.server.farmususer.user.service.UserService; import modernfarmer.server.farmususer.user.util.JwtTokenProvider; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -19,7 +21,7 @@ @RequiredArgsConstructor public class UserController { - private final AuthService authService; + private final UserService userService; private final JwtTokenProvider jwtTokenProvider; @@ -29,7 +31,7 @@ public ResponseDto logout(HttpServletRequest request) { String userId = jwtTokenProvider.getUserId(request); - ResponseDto logoutResponseDto = authService.logout(Long.valueOf(userId)); + ResponseDto logoutResponseDto = userService.logout(Long.valueOf(userId)); log.info("로그아웃 완료"); @@ -42,7 +44,7 @@ public TokenResponseDto reissueToken(HttpServletRequest request) { String userId = jwtTokenProvider.getUserId(request); String refreshToken = jwtTokenProvider.resolveToken(request); - TokenResponseDto reissueTokenResponseDto = authService.reissueToken(refreshToken, Long.valueOf(userId)); + TokenResponseDto reissueTokenResponseDto = userService.reissueToken(refreshToken, Long.valueOf(userId)); log.info("토큰 재발급 완료"); diff --git a/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java b/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java index 32da0bd..20add15 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java +++ b/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java @@ -3,13 +3,10 @@ import lombok.extern.slf4j.Slf4j; import modernfarmer.server.farmususer.user.dto.response.GoogleUserResponseDto; import modernfarmer.server.farmususer.user.dto.response.KakaoUserResponseDto; -import modernfarmer.server.farmususer.user.dto.response.ResponseDto; import modernfarmer.server.farmususer.user.dto.response.TokenResponseDto; import modernfarmer.server.farmususer.user.entity.User; import modernfarmer.server.farmususer.user.repository.UserRepository; import modernfarmer.server.farmususer.user.util.JwtTokenProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpStatus; @@ -144,69 +141,6 @@ public TokenResponseDto kakaoLogin(String accessToken) { } - public ResponseDto logout(Long userId) { - deleteValueByKey(String.valueOf(userId)); - - ResponseDto responseDto = ResponseDto.builder() - .message("OK") - .code(200) - .build(); - return responseDto; - } - - public TokenResponseDto reissueToken(String refreshToken, Long userId) { - TokenResponseDto reissueTokenResponse; - - if(!jwtTokenProvider.validateRefreshToken(refreshToken)){ - - reissueTokenResponse = TokenResponseDto.builder() - .code(417) - .message("재로그인하시오") - .build(); - - return reissueTokenResponse; - } - - String redisRefreshToken = redisTemplate.opsForValue().get(userId.toString()); - - if(redisRefreshToken.equals(refreshToken)){ - - String userRole = userRepository.findUserRole(userId); - - reissueTokenResponse= TokenResponseDto - .builder() - .code(200) - .message("OK") - .accessToken(jwtTokenProvider.createAccessToken(userId, userRole)) - .refreshToken(refreshToken) - .build(); - - return reissueTokenResponse; - - } - - reissueTokenResponse = TokenResponseDto.builder() - .code(403) - .message("접근이 올바르지 않습니다.") - .build(); - - return reissueTokenResponse; - - } - - - - - public void deleteValueByKey(String key) { - redisTemplate.delete(key); - } - - - - - - - public Mono getUserKakaoInfo(String accessToken) { return webClient .get() diff --git a/src/main/java/modernfarmer/server/farmususer/user/service/UserService.java b/src/main/java/modernfarmer/server/farmususer/user/service/UserService.java new file mode 100644 index 0000000..b3cc99f --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/service/UserService.java @@ -0,0 +1,74 @@ +package modernfarmer.server.farmususer.user.service; + +import modernfarmer.server.farmususer.global.exception.notfound.NotFoundRefreshTokenException; +import modernfarmer.server.farmususer.user.dto.response.ResponseDto; +import modernfarmer.server.farmususer.user.dto.response.TokenResponseDto; +import modernfarmer.server.farmususer.user.repository.UserRepository; +import modernfarmer.server.farmususer.user.util.JwtTokenProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.Objects; + + +@Service +public class UserService { + + public JwtTokenProvider jwtTokenProvider; + public RedisTemplate redisTemplate; + + public UserRepository userRepository; + + private final WebClient webClient; + + @Autowired + public UserService(WebClient webClient, UserRepository userRepository, JwtTokenProvider jwtTokenProvider, RedisTemplate redisTemplate) { + this.webClient = webClient; + this.userRepository = userRepository; + this.jwtTokenProvider = jwtTokenProvider; + this.redisTemplate = redisTemplate; + } + + + public ResponseDto logout(Long userId) { + deleteValueByKey(String.valueOf(userId)); + + ResponseDto responseDto = ResponseDto.builder() + .message("OK") + .code(200) + .build(); + return responseDto; + } + + public TokenResponseDto reissueToken(String refreshToken, Long userId) { + TokenResponseDto reissueTokenResponse; + + String redisRefreshToken = redisTemplate.opsForValue().get(userId.toString()); + + if(refreshToken.equals(redisRefreshToken)){ + + String userRole = userRepository.findUserRole(userId); + + reissueTokenResponse= TokenResponseDto + .builder() + .code(200) + .message("OK") + .accessToken(jwtTokenProvider.createAccessToken(userId, userRole)) + .refreshToken(refreshToken) + .build(); + + return reissueTokenResponse; + + + } + throw new NotFoundRefreshTokenException(); + + } + + public void deleteValueByKey(String key) { + redisTemplate.delete(key); + } + +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java b/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java index 998d757..12d657b 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java +++ b/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java @@ -26,10 +26,10 @@ public class JwtTokenProvider { private String secretKey; - private final long accessTokenTime = 30L * 24L * 60 * 60 * 1000; // 1달 토큰 유효 + private final long accessTokenTime = 30L * 1000;; // 1달 토큰 유효 - private final long refreshTokenTime = 1L * 60 * 1000 * 2; // 1달 토큰 유효 + private final long refreshTokenTime = 30L * 1000 * 2; // 1달 토큰 유효 @PostConstruct protected void init() {