Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADD] 스웨거 Response 정보 추가 (제안) #231

Merged
merged 13 commits into from
Mar 20, 2024
Merged
33 changes: 19 additions & 14 deletions smeem-api/src/main/java/com/smeem/api/auth/api/AuthApi.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.smeem.api.auth.api;

import com.smeem.api.auth.api.dto.request.SignInRequest;
import com.smeem.api.common.BaseResponse;
import com.smeem.api.auth.api.dto.response.SignInResponse;
import com.smeem.api.auth.api.dto.response.token.TokenResponse;
import com.smeem.api.common.dto.FailureResponse;
import com.smeem.api.common.dto.SuccessResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand All @@ -24,39 +29,39 @@ public interface AuthApi {
@Parameter(name = "Authorization", description = "Bearer ${Social Platform Access Token}", in = HEADER, required = true)
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "소셜로그인 성공"),
@ApiResponse(responseCode = "4xx", description = "유효하지 않은 요청"),
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다"),
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
@ApiResponse(responseCode = "4xx", description = "유효하지 않은 요청", content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다", content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = FailureResponse.class)))
})
ResponseEntity<BaseResponse<?>> signIn(@RequestHeader("Authorization") final String socialAccessToken, @RequestBody SignInRequest request) throws NoSuchAlgorithmException, InvalidKeySpecException;
ResponseEntity<SuccessResponse<SignInResponse>> signIn(@RequestHeader("Authorization") final String socialAccessToken, @RequestBody SignInRequest request) throws NoSuchAlgorithmException, InvalidKeySpecException;

@Operation(summary = "토큰 재발급 API")
@Parameter(name = "Authorization", description = "Bearer ${Smeme Refresh Token}", in = HEADER, required = true)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "토큰 재발급 성공"),
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다"),
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다", content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = FailureResponse.class)))
})
ResponseEntity<BaseResponse<?>> reissueToken(Principal principal);
ResponseEntity<SuccessResponse<TokenResponse>> reissueToken(Principal principal);


@Operation(summary = "사용자 로그아웃 API")
@Parameter(name = "Authorization", description = "Bearer ${Smeme Access Token}", in = HEADER, required = true)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "로그아웃 성공"),
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다"),
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다", content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = FailureResponse.class)))
})
ResponseEntity<BaseResponse<?>> signOut(Principal principal);
ResponseEntity<SuccessResponse<?>> signOut(Principal principal);


@Operation(summary = "회원 탈퇴 API")
@Parameter(name = "Authorization", description = "Bearer ${Smeme Access Token}", in = HEADER, required = true)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "회원 탈퇴 성공"),
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다"),
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰입니다", content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = FailureResponse.class)))
})
ResponseEntity<BaseResponse<?>> withDrawl(Principal principal);
ResponseEntity<SuccessResponse<?>> withDrawl(Principal principal);

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.smeem.api.auth.service.TokenService;
import com.smeem.api.auth.service.dto.request.SignInServiceRequest;
import com.smeem.api.common.ApiResponseUtil;
import com.smeem.api.common.BaseResponse;
import com.smeem.api.common.dto.SuccessResponse;
import com.smeem.common.util.Util;
import lombok.RequiredArgsConstructor;
import lombok.val;
Expand All @@ -31,29 +31,29 @@ public class AuthController implements AuthApi {

@Override
@PostMapping
public ResponseEntity<BaseResponse<?>> signIn(@RequestHeader("Authorization") final String socialAccessToken,
@RequestBody SignInRequest request) throws NoSuchAlgorithmException, InvalidKeySpecException {
public ResponseEntity<SuccessResponse<SignInResponse>> signIn(@RequestHeader("Authorization") final String socialAccessToken,
@RequestBody SignInRequest request) throws NoSuchAlgorithmException, InvalidKeySpecException {
val response = SignInResponse.from(authService.signIn(socialAccessToken, SignInServiceRequest.of(request)));
return ApiResponseUtil.success(SUCCESS_SIGNIN, response);
}

@Override
@PostMapping("/token")
public ResponseEntity<BaseResponse<?>> reissueToken(Principal principal) {
public ResponseEntity<SuccessResponse<TokenResponse>> reissueToken(Principal principal) {
val response = TokenResponse.from(tokenService.issueToken(Util.getMemberId(principal)));
return ApiResponseUtil.success(SUCCESS_ISSUE_TOKEN, response);
}

@Override
@PostMapping("/sign-out")
public ResponseEntity<BaseResponse<?>> signOut(Principal principal) {
public ResponseEntity<SuccessResponse<?>> signOut(Principal principal) {
authService.signOut(Util.getMemberId(principal));
return ApiResponseUtil.success(SUCCESS_SIGNOUT);
}

@Override
@DeleteMapping
public ResponseEntity<BaseResponse<?>> withDrawl(Principal principal) {
public ResponseEntity<SuccessResponse<?>> withDrawl(Principal principal) {
authService.withdraw(Util.getMemberId(principal));
return ApiResponseUtil.success(SUCCESS_WITHDRAW);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.smeem.api.common.ApiResponseUtil;
import com.smeem.api.common.BaseResponse;
import com.smeem.api.common.dto.FailureResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
Expand Down Expand Up @@ -32,7 +32,7 @@ private void setResponse(HttpServletResponse response) throws IOException {
response.getWriter().println(objectMapper.writeValueAsString(getFailureResponse()));
}

private ResponseEntity<BaseResponse<?>> getFailureResponse() {
private ResponseEntity<FailureResponse> getFailureResponse() {
return ApiResponseUtil.failure(INVALID_TOKEN);
}
}
12 changes: 8 additions & 4 deletions smeem-api/src/main/java/com/smeem/api/badge/api/BadgeApi.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.smeem.api.badge.api;

import com.smeem.api.common.BaseResponse;
import com.smeem.api.badge.api.dto.response.BadgeListResponse;
import com.smeem.api.common.dto.FailureResponse;
import com.smeem.api.common.dto.SuccessResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand All @@ -20,9 +24,9 @@ public interface BadgeApi {
@Parameter(name = "Authorization", description = "Bearer ${Smeme Access Token}", in = HEADER, required = true)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "뱃지 리스트 조회 성공"),
@ApiResponse(responseCode = "4011", description = "유효하지 않은 토큰입니다"),
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
@ApiResponse(responseCode = "4011", description = "유효하지 않은 토큰입니다", content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = FailureResponse.class)))
})
ResponseEntity<BaseResponse<?>> getBadges(Principal principal);
ResponseEntity<SuccessResponse<BadgeListResponse>> getBadges(Principal principal);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.smeem.api.badge.api.dto.response.BadgeListResponse;
import com.smeem.api.badge.service.BadgeService;
import com.smeem.api.common.ApiResponseUtil;
import com.smeem.api.common.BaseResponse;
import com.smeem.api.common.dto.SuccessResponse;
import com.smeem.common.util.Util;
import lombok.RequiredArgsConstructor;
import lombok.val;
Expand All @@ -25,7 +25,7 @@ public class BadgeController implements BadgeApi {

@Override
@GetMapping
public ResponseEntity<BaseResponse<?>> getBadges(Principal principal) {
public ResponseEntity<SuccessResponse<BadgeListResponse>> getBadges(Principal principal) {
val response = BadgeListResponse.from(badgeService.getBadges(Util.getMemberId(principal)));
return ApiResponseUtil.success(SUCCESS_GET_BADGES, response);
}
Expand Down
18 changes: 10 additions & 8 deletions smeem-api/src/main/java/com/smeem/api/common/ApiResponseUtil.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.smeem.api.common;

import com.smeem.api.common.dto.FailureResponse;
import com.smeem.api.common.dto.SuccessResponse;
import com.smeem.common.code.failure.FailureCode;
import com.smeem.common.code.success.SuccessCode;
import org.springframework.http.ResponseEntity;
Expand All @@ -8,28 +10,28 @@

public interface ApiResponseUtil {

static ResponseEntity<BaseResponse<?>> success(SuccessCode code) {
static ResponseEntity<SuccessResponse<?>> success(SuccessCode code) {
return ResponseEntity
.status(code.getStatus())
.body(BaseResponse.of(true, code.getMessage()));
.body(SuccessResponse.of(code.getMessage()));
}

static <T> ResponseEntity<BaseResponse<?>> success(SuccessCode code, T data) {
static <T> ResponseEntity<SuccessResponse<T>> success(SuccessCode code, T data) {
return ResponseEntity
.status(code.getStatus())
.body(BaseResponse.of(code.getMessage(), data));
.body(SuccessResponse.of(code.getMessage(), data));
}

static <T> ResponseEntity<BaseResponse<?>> success(SuccessCode code, URI uri, T data) {
static <T> ResponseEntity<SuccessResponse<T>> success(SuccessCode code, URI uri, T data) {
return ResponseEntity
.status(code.getStatus())
.location(uri)
.body(BaseResponse.of(code.getMessage(), data));
.body(SuccessResponse.of(code.getMessage(), data));
}

static ResponseEntity<BaseResponse<?>> failure(FailureCode code) {
static ResponseEntity<FailureResponse> failure(FailureCode code) {
return ResponseEntity
.status(code.getStatus())
.body(BaseResponse.of(false, code.getMessage()));
.body(FailureResponse.of(code.getMessage()));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.smeem.api.common.advicer;

import com.smeem.api.common.ApiResponseUtil;
import com.smeem.api.common.BaseResponse;
import com.smeem.api.common.dto.FailureResponse;
import com.smeem.common.exception.*;
import com.smeem.external.discord.DiscordAlarmSender;
import lombok.RequiredArgsConstructor;
Expand All @@ -19,57 +19,57 @@ public class ErrorHandler {
private final DiscordAlarmSender discordAlarmSender;

@ExceptionHandler(TrainingTimeException.class)
public ResponseEntity<BaseResponse<?>> trainingTimeException(TrainingTimeException exception) {
public ResponseEntity<FailureResponse> trainingTimeException(TrainingTimeException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(TokenException.class)
public ResponseEntity<BaseResponse<?>> tokenException(TokenException exception) {
public ResponseEntity<FailureResponse> tokenException(TokenException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(BadgeException.class)
public ResponseEntity<BaseResponse<?>> badgeException(BadgeException exception) {
public ResponseEntity<FailureResponse> badgeException(BadgeException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(DiaryException.class)
public ResponseEntity<BaseResponse<?>> diaryException(DiaryException exception) {
public ResponseEntity<FailureResponse> diaryException(DiaryException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(MemberException.class)
public ResponseEntity<BaseResponse<?>> memberException(MemberException exception) {
public ResponseEntity<FailureResponse> memberException(MemberException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(GoalException.class)
public ResponseEntity<BaseResponse<?>> goalException(GoalException exception) {
public ResponseEntity<FailureResponse> goalException(GoalException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(TopicException.class)
public ResponseEntity<BaseResponse<?>> topicException(TopicException exception) {
public ResponseEntity<FailureResponse> topicException(TopicException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(AppleException.class)
public ResponseEntity<BaseResponse<?>> appleException(AppleException exception) {
public ResponseEntity<FailureResponse> appleException(AppleException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(FcmException.class)
public ResponseEntity<BaseResponse<?>> fcmException(FcmException exception) {
public ResponseEntity<FailureResponse> fcmException(FcmException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(AuthException.class)
public ResponseEntity<BaseResponse<?>> authException(AuthException exception) {
public ResponseEntity<FailureResponse> authException(AuthException exception) {
return ApiResponseUtil.failure(exception.getFailureCode());
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<BaseResponse<?>> baseException(RuntimeException exception) {
public ResponseEntity<FailureResponse> baseException(RuntimeException exception) {
sendDiscordAlarm(exception);
return ApiResponseUtil.failure(SERVER_ERROR);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.smeem.api.common.dto;

import lombok.Builder;

import static lombok.AccessLevel.PRIVATE;

@Builder(access = PRIVATE)
public record FailureResponse(
boolean success,
String message
) {

public static FailureResponse of(String message) {
return FailureResponse.builder()
.success(false)
.message(message)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.smeem.api.common;
package com.smeem.api.common.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Builder;
Expand All @@ -7,24 +7,24 @@
import static lombok.AccessLevel.PRIVATE;

@Builder(access = PRIVATE)
public record BaseResponse<T>(
public record SuccessResponse<T>(
boolean success,
String message,
@JsonInclude(value = NON_NULL)
T data
) {

public static <T> BaseResponse<?> of(String message, T data) {
return BaseResponse.builder()
public static <T> SuccessResponse<T> of(String message, T data) {
return SuccessResponse.<T>builder()
.success(true)
.message(message)
.data(data)
.build();
}

public static BaseResponse<?> of(boolean isSuccess, String message) {
return BaseResponse.builder()
.success(isSuccess)
public static SuccessResponse<?> of(String message) {
return SuccessResponse.builder()
.success(true)
.message(message)
.build();
}
Expand Down
Loading
Loading