From 66b7a23f167bd77f076d422ba3a89967fd741ea2 Mon Sep 17 00:00:00 2001 From: EunChanNam Date: Fri, 17 Nov 2023 12:24:15 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=EB=A5=BC=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20API=20=EB=AA=85=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 19 +++----- .../auth/presentation/AuthController.java | 11 ++++- .../auth/presentation/MailAuthController.java | 17 +++++-- .../presentation/TokenReissueController.java | 9 +++- .../global/config/SwaggerConfig.java | 47 +++++++++++++++++++ .../HairStyleSearchController.java | 22 +++++++-- .../presentation/WishHairController.java | 24 +++++++--- .../point/presentation/PointController.java | 21 ++++++--- .../presentation/LikeReviewController.java | 23 ++++++--- .../review/presentation/ReviewController.java | 17 +++++-- .../presentation/ReviewSearchController.java | 29 +++++++++--- .../user/presentation/UserController.java | 43 ++++++++++++----- .../user/presentation/UserInfoController.java | 17 +++++-- 13 files changed, 233 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/inq/wishhair/wesharewishhair/global/config/SwaggerConfig.java diff --git a/build.gradle b/build.gradle index f45120c..3293ebc 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ dependencies { //P6Spy implementation("com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0") - //javax.annotation import 버그 해결 + //javax.annotation implementation 'javax.annotation:javax.annotation-api:1.3.2' //jwt @@ -43,24 +43,19 @@ dependencies { runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' implementation 'javax.xml.bind:jaxb-api:2.3.0' //jwt 토큰 생성시 에러 해결 - //test - testImplementation 'org.springframework.boot:spring-boot-starter-test' - //JPA implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //spring implementation 'org.springframework.boot:spring-boot-starter-web' - - //validation + implementation 'org.springframework.boot:spring-boot-starter-security' + testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' //mail implementation 'org.springframework.boot:spring-boot-starter-mail' - //thymeleaf - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - //lombok compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' @@ -78,14 +73,14 @@ dependencies { //네이버 클라우드 implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' - //Spring Security - implementation 'org.springframework.boot:spring-boot-starter-security' - // queryDSL implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" + + //swagger + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' } def querydslDir = "src/main/generated" diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/AuthController.java b/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/AuthController.java index dab72b8..e0acfef 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/AuthController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/AuthController.java @@ -13,8 +13,13 @@ import com.inq.wishhair.wesharewishhair.global.dto.response.Success; import com.inq.wishhair.wesharewishhair.global.resolver.dto.AuthInfo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Auth API") @RestController @RequestMapping("/api/auth") @RequiredArgsConstructor @@ -22,14 +27,18 @@ public class AuthController { private final AuthService authService; + @Operation(summary = "로그인 API", description = "로그인을 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping("/login") public ResponseEntity login(final @RequestBody LoginRequest loginRequest) { LoginResponse response = authService.login(loginRequest.email(), loginRequest.pw()); return ResponseEntity.ok(response); } + @Operation(summary = "로그아웃 API", description = "로그아웃을 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping("/logout") - public ResponseEntity logout(@FetchAuthInfo AuthInfo authInfo) { + public ResponseEntity logout(@Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo) { authService.logout(authInfo.userId()); return ResponseEntity.ok(new Success()); } diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthController.java b/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthController.java index 366652b..ca44191 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthController.java @@ -13,8 +13,13 @@ import com.inq.wishhair.wesharewishhair.user.domain.entity.Email; import com.inq.wishhair.wesharewishhair.user.application.utils.UserValidator; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Auth API") @RestController @RequestMapping("/api/email") @RequiredArgsConstructor @@ -23,27 +28,33 @@ public class MailAuthController { private final UserValidator userValidator; private final MailAuthService mailAuthService; + @Operation(summary = "이메일 중복체크 API", description = "이메일 중복체크를 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping("/check") public ResponseEntity checkDuplicateEmail( - final @RequestBody MailRequest request + @Parameter(description = "이메일") @RequestBody MailRequest request ) { userValidator.validateEmailIsNotDuplicated(new Email(request.email())); return ResponseEntity.ok(new Success()); } + @Operation(summary = "인증메일 발송 API", description = "인증메일을 발송한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping("/send") public ResponseEntity sendAuthorizationMail( - final @RequestBody MailRequest mailRequest + @Parameter(description = "이메일") @RequestBody MailRequest mailRequest ) { mailAuthService.requestMailAuthorization(mailRequest.email()); return ResponseEntity.ok(new Success()); } + @Operation(summary = "이메일 인증 API", description = "이메일을 인증한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping("/validate") public ResponseEntity authorizeKey( - final @RequestBody AuthKeyRequest request + @Parameter(description = "메일 인증 폼") @RequestBody AuthKeyRequest request ) { mailAuthService.checkAuthCode(request.email(), request.authKey()); diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/TokenReissueController.java b/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/TokenReissueController.java index d4c70c0..2cd1a35 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/TokenReissueController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/auth/presentation/TokenReissueController.java @@ -10,8 +10,13 @@ import com.inq.wishhair.wesharewishhair.global.annotation.FetchAuthInfo; import com.inq.wishhair.wesharewishhair.global.resolver.dto.AuthInfo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Auth API") @RestController @RequestMapping("/api") @RequiredArgsConstructor @@ -19,8 +24,10 @@ public class TokenReissueController { private final TokenReissueService tokenReissueService; + @Operation(summary = "토큰 재발급 API", description = "토큰을 재발급한다") + @ApiResponse(responseCode = "200", description = "엑세스 토큰 + 리프레쉬 토큰", useReturnTypeSchema = true) @PostMapping("/tokens/reissue") - public ResponseEntity reissueToken(@FetchAuthInfo AuthInfo authInfo) { + public ResponseEntity reissueToken(@Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo) { TokenResponse response = tokenReissueService.reissueToken(authInfo.userId(), authInfo.token()); return ResponseEntity.ok(response); } diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/global/config/SwaggerConfig.java b/src/main/java/com/inq/wishhair/wesharewishhair/global/config/SwaggerConfig.java new file mode 100644 index 0000000..a7e7e5f --- /dev/null +++ b/src/main/java/com/inq/wishhair/wesharewishhair/global/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.inq.wishhair.wesharewishhair.global.config; + +import java.util.List; + +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; + +@OpenAPIDefinition( + info = @Info( + title = "We Share Wish Hair API", + description = "We Share Wish Hair API 명세", + version = "v1")) +@Configuration +public class SwaggerConfig { + + private static final String AUTHORIZATION = "Authorization"; + + @Bean + public OpenAPI openAPI(){ + SecurityScheme securityScheme = new SecurityScheme() + .type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT") + .in(SecurityScheme.In.HEADER).name(AUTHORIZATION); + SecurityRequirement securityRequirement = new SecurityRequirement().addList(AUTHORIZATION); + + return new OpenAPI() + .components(new Components().addSecuritySchemes(AUTHORIZATION, securityScheme)) + .security(List.of(securityRequirement)); + } + + @Bean + public GroupedOpenApi chatOpenApi() { + String[] paths = {"/api/**"}; + + return GroupedOpenApi.builder() + .group("API v1") + .pathsToMatch(paths) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java b/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java index 22823c8..fb0c62c 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java @@ -18,8 +18,12 @@ import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleSimpleResponse; import com.inq.wishhair.wesharewishhair.hairstyle.domain.hashtag.Tag; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; +@io.swagger.v3.oas.annotations.tags.Tag(name = "HairStyle API") @RestController @RequiredArgsConstructor @RequestMapping("/api/hair_styles") @@ -27,29 +31,37 @@ public class HairStyleSearchController { private final HairStyleSearchService hairStyleSearchService; + @Operation(summary = "헤어스타일 추천 API", description = "헤어스타일 추천을 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/recommend") public ResponseWrapper respondRecommendedHairStyle( - @RequestParam(defaultValue = "ERROR") List tags, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "태그 정보") @RequestParam(defaultValue = "ERROR") List tags, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { return hairStyleSearchService.recommendHair(tags, authInfo.userId()); } + @Operation(summary = "얼굴형에 맞는 헤어스타일 추천 API", description = "얼굴형 정보로만 헤어스타일을 추천한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/home") public ResponseWrapper findHairStyleByFaceShape( - @FetchAuthInfo AuthInfo authInfo + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { return hairStyleSearchService.recommendHairByFaceShape(authInfo.userId()); } + @Operation(summary = "찜한 헤어스타일 조회 API", description = "찜한 헤어스타일을 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/wish") public PagedResponse findWishHairStyles( - @FetchAuthInfo AuthInfo authInfo, - @PageableDefault Pageable pageable) { + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo, + @Parameter(description = "페이징 정보") @PageableDefault Pageable pageable) { return hairStyleSearchService.findWishHairStyles(authInfo.userId(), pageable); } + @Operation(summary = "모든 헤어스타일 API", description = "모든 헤어스타일의 간략한 정보를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping public ResponseWrapper findAllHairStyles() { return hairStyleSearchService.findAllHairStyle(); diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/WishHairController.java b/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/WishHairController.java index 07c1089..7c30181 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/WishHairController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/WishHairController.java @@ -14,8 +14,13 @@ import com.inq.wishhair.wesharewishhair.hairstyle.application.WishHairService; import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.WishHairResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "HairStyle API") @RestController @RequiredArgsConstructor @RequestMapping("/api/hair_styles/wish/") @@ -23,31 +28,36 @@ public class WishHairController { private final WishHairService wishHairService; + @Operation(summary = "찜 API", description = "찜를 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping(path = "{hairStyleId}") public ResponseEntity executeWish( - @PathVariable Long hairStyleId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "헤어스타일 아이디") @PathVariable Long hairStyleId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { - wishHairService.executeWish(hairStyleId, authInfo.userId()); return ResponseEntity.ok(new Success()); } + @Operation(summary = "찜 취소 API", description = "찜를 취소한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @DeleteMapping(path = "{hairStyleId}") public ResponseEntity cancelWish( - @PathVariable Long hairStyleId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "헤어스타일 아이디") @PathVariable Long hairStyleId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { wishHairService.cancelWish(hairStyleId, authInfo.userId()); return ResponseEntity.ok(new Success()); } + @Operation(summary = "헤어스타일 찜 확인 API", description = "찜를 취소한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping(path = {"{hairStyleId}"}) public ResponseEntity checkIsWishing( - @PathVariable Long hairStyleId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "헤어스타일 아이디") @PathVariable Long hairStyleId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { WishHairResponse result = wishHairService.checkIsWishing(hairStyleId, authInfo.userId()); return ResponseEntity.ok(result); diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/point/presentation/PointController.java b/src/main/java/com/inq/wishhair/wesharewishhair/point/presentation/PointController.java index f318648..2fbddb1 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/point/presentation/PointController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/point/presentation/PointController.java @@ -18,33 +18,40 @@ import com.inq.wishhair.wesharewishhair.point.application.dto.PointUseRequest; import com.inq.wishhair.wesharewishhair.point.application.PointService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Point API") @RestController @RequestMapping("/api/points") @RequiredArgsConstructor public class PointController { private final PointService pointService; + private final PointSearchService pointSearchService; + @Operation(summary = "포인트 사용 API", description = "포인트를 사용한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping("/use") public ResponseEntity usePoint( - final @RequestBody PointUseRequest request, - final @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "포인트 사용 폼") @RequestBody PointUseRequest request, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { pointService.usePoint(request, authInfo.userId()); return ResponseEntity.ok(new Success()); } - private final PointSearchService pointSearchService; - + @Operation(summary = "포인트 내역 조회 API", description = "포인트 내역을 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping public ResponseEntity> findPointHistories( - final @FetchAuthInfo AuthInfo authInfo, - final @PageableDefault Pageable pageable + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo, + @Parameter(description = "페이징 정보") @PageableDefault Pageable pageable ) { - return ResponseEntity.ok(pointSearchService.getPointHistories(authInfo.userId(), pageable)); } } diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/LikeReviewController.java b/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/LikeReviewController.java index 8ebfd97..c059cb7 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/LikeReviewController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/LikeReviewController.java @@ -14,8 +14,13 @@ import com.inq.wishhair.wesharewishhair.review.application.LikeReviewService; import com.inq.wishhair.wesharewishhair.review.application.dto.response.LikeReviewResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Review API") @RestController @RequiredArgsConstructor @RequestMapping("/api/reviews/like/") @@ -23,28 +28,34 @@ public class LikeReviewController { private final LikeReviewService likeReviewService; + @Operation(summary = "좋아요 API", description = "좋아요 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping(path = "{reviewId}") public ResponseEntity executeLike( - @PathVariable Long reviewId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "리뷰 아이디") @PathVariable Long reviewId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { likeReviewService.executeLike(reviewId, authInfo.userId()); return ResponseEntity.ok(new Success()); } + @Operation(summary = "좋아요 취소 API", description = "좋아요를 취소한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @DeleteMapping("/{reviewId}") public ResponseEntity cancelLike( - @PathVariable Long reviewId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "리뷰 아이디") @PathVariable Long reviewId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { likeReviewService.cancelLike(reviewId, authInfo.userId()); return ResponseEntity.ok(new Success()); } + @Operation(summary = "좋아요 확인 API", description = "좋아요한 상태인지 확인한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping(path = "{reviewId}") public ResponseEntity checkIsLiking( - @FetchAuthInfo AuthInfo authInfo, - @PathVariable Long reviewId + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo, + @Parameter(description = "리뷰 아이디") @PathVariable Long reviewId ) { LikeReviewResponse result = likeReviewService.checkIsLiking(authInfo.userId(), reviewId); return ResponseEntity.ok(result); diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewController.java b/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewController.java index bdc3a41..11705d9 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewController.java @@ -18,8 +18,13 @@ import com.inq.wishhair.wesharewishhair.review.application.dto.request.ReviewUpdateRequest; import com.inq.wishhair.wesharewishhair.review.application.ReviewService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Review API") @RestController @RequiredArgsConstructor @RequestMapping("/api/reviews") @@ -27,10 +32,12 @@ public class ReviewController { private final ReviewService reviewService; + @Operation(summary = "리뷰 등록 API", description = "리뷰를 등록한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PostMapping public ResponseEntity createReview( @ModelAttribute ReviewCreateRequest reviewCreateRequest, - @FetchAuthInfo AuthInfo authInfo + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { Long reviewId = reviewService.createReview(reviewCreateRequest, authInfo.userId()); @@ -39,9 +46,11 @@ public ResponseEntity createReview( .body(new Success()); } + @Operation(summary = "리뷰 삭제 API", description = "리뷰를 삭제한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @DeleteMapping(path = "{reviewId}") public ResponseEntity deleteReview( - @FetchAuthInfo AuthInfo authInfo, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo, @PathVariable Long reviewId ) { reviewService.deleteReview(reviewId, authInfo.userId()); @@ -49,10 +58,12 @@ public ResponseEntity deleteReview( return ResponseEntity.ok(new Success()); } + @Operation(summary = "리뷰 수정 API", description = "리뷰를 수정한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PatchMapping public ResponseEntity updateReview( @ModelAttribute ReviewUpdateRequest request, - @FetchAuthInfo AuthInfo authInfo + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { reviewService.updateReview(request, authInfo.userId()); diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewSearchController.java b/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewSearchController.java index 8661201..707fce1 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewSearchController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/review/presentation/ReviewSearchController.java @@ -20,8 +20,13 @@ import com.inq.wishhair.wesharewishhair.review.application.dto.response.ReviewResponse; import com.inq.wishhair.wesharewishhair.review.application.dto.response.ReviewSimpleResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Review API") @RestController @RequiredArgsConstructor @RequestMapping("/api/reviews") @@ -29,45 +34,57 @@ public class ReviewSearchController { private final ReviewSearchService reviewSearchService; + @Operation(summary = "리뷰 단건 조회 API", description = "좋아요 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping(path = "{reviewId}") public ResponseEntity findReview( - @PathVariable Long reviewId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "리뷰 아이디") @PathVariable Long reviewId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { ReviewDetailResponse result = reviewSearchService.findReviewById(authInfo.userId(), reviewId); return ResponseEntity.ok(result); } + @Operation(summary = "리뷰 조회 API", description = "리뷰를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping public ResponseEntity> findPagingReviews( + @Parameter(description = "페이징 정보(기본 좋아요 개수로 정렬)") @PageableDefault(sort = LIKES, direction = Sort.Direction.DESC) Pageable pageable, - @FetchAuthInfo AuthInfo authInfo + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { PagedResponse result = reviewSearchService.findPagedReviews(authInfo.userId(), pageable); return ResponseEntity.ok(result); } + @Operation(summary = "나의 리뷰 조회 API", description = "내가 작성한 리뷰를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/my") public ResponseEntity> findMyReviews( + @Parameter(description = "페이징 정보(최신순으로 정렬)") @PageableDefault(sort = DATE, direction = Sort.Direction.DESC) Pageable pageable, - @FetchAuthInfo AuthInfo authInfo + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { PagedResponse result = reviewSearchService.findMyReviews(authInfo.userId(), pageable); return ResponseEntity.ok(result); } + @Operation(summary = "이달의 리뷰 조회 API", description = "이달의 리뷰를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/month") public ResponseWrapper findReviewOfMonth() { return reviewSearchService.findReviewOfMonth(); } + @Operation(summary = "헤어스타일 리뷰 조회 API", description = "헤어스타일의 리뷰를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/hair_style/{hairStyleId}") public ResponseWrapper findHairStyleReview( - @PathVariable Long hairStyleId, - @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "헤어스타일 아이디") @PathVariable Long hairStyleId, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { return reviewSearchService.findReviewByHairStyle(authInfo.userId(), hairStyleId); } diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserController.java b/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserController.java index 7d06599..4cb98e5 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserController.java @@ -22,8 +22,13 @@ import com.inq.wishhair.wesharewishhair.user.presentation.dto.request.UserUpdateRequest; import com.inq.wishhair.wesharewishhair.user.application.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "User API") @RestController @RequiredArgsConstructor @RequestMapping("/api/users") @@ -31,8 +36,12 @@ public class UserController { private final UserService userService; + @Operation(summary = "회원가입 API", description = "회원가입 한다") + @ApiResponse(responseCode = "201", useReturnTypeSchema = true) @PostMapping - public ResponseEntity signUp(@RequestBody SignUpRequest createRequest) { + public ResponseEntity signUp( + @Parameter(description = "회원가입 폼") @RequestBody SignUpRequest createRequest + ) { Long userId = userService.createUser(createRequest); return ResponseEntity @@ -40,47 +49,57 @@ public ResponseEntity signUp(@RequestBody SignUpRequest createRequest) .body(new Success()); } + @Operation(summary = "회원 탈퇴 API", description = "회원탈퇴를 한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @DeleteMapping - public ResponseEntity deleteUser(final @FetchAuthInfo AuthInfo authInfo) { + public ResponseEntity deleteUser(final @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo) { userService.deleteUser(authInfo.userId()); return ResponseEntity.ok(new Success()); } + @Operation(summary = "비밀번호 갱신 API", description = "비밀번호 찾기로 비밀번호를 갱신한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PatchMapping("/refresh/password") - public ResponseEntity refreshPassword(@RequestBody PasswordRefreshRequest request) { - + public ResponseEntity refreshPassword( + @Parameter(description = "비밀번호 갱신 폼") @RequestBody PasswordRefreshRequest request + ) { userService.refreshPassword(request); return ResponseEntity.ok(new Success()); } + @Operation(summary = "사용자 정보 수정 API", description = "사용자 정보를 수정한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PatchMapping - public ResponseEntity updateUser(@RequestBody UserUpdateRequest request, - final @FetchAuthInfo AuthInfo authInfo + public ResponseEntity updateUser( + @Parameter(description = "사용자 정보 수정 폼") @RequestBody UserUpdateRequest request, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { - userService.updateUser(authInfo.userId(), request); return ResponseEntity.ok(new Success()); } + @Operation(summary = "비밀번호 변경 API", description = "비밀번호를 변경한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PatchMapping("/password") public ResponseEntity updatePassword( - final @RequestBody PasswordUpdateRequest request, - final @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "비밀번호 변경 폼") @RequestBody PasswordUpdateRequest request, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { userService.updatePassword(authInfo.userId(), request); return ResponseEntity.ok(new Success()); } + @Operation(summary = "얼굴형 분석 API", description = "얼굴형을 분석한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @PatchMapping("/face_shape") public ResponseEntity> updateFaceShape( - final @ModelAttribute FaceShapeUpdateRequest request, - final @FetchAuthInfo AuthInfo authInfo + @Parameter(description = "얼굴형 분석 폼") @ModelAttribute FaceShapeUpdateRequest request, + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { - SimpleResponseWrapper result = userService.updateFaceShape(authInfo.userId(), request.getFile()); return ResponseEntity.ok(result); diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserInfoController.java b/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserInfoController.java index 0c06a99..0a12988 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserInfoController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/user/presentation/UserInfoController.java @@ -12,8 +12,13 @@ import com.inq.wishhair.wesharewishhair.user.application.dto.response.UserInfo; import com.inq.wishhair.wesharewishhair.user.application.dto.response.UserInformation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "User API") @RestController @RequestMapping("/api/users") @RequiredArgsConstructor @@ -21,17 +26,21 @@ public class UserInfoController { private final UserInfoService userInfoService; + @Operation(summary = "마이페이지 정보 조회 API", description = "마이페이지 정보를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/my_page") - public ResponseEntity getMyPageInfo(final @FetchAuthInfo AuthInfo authInfo) { + public ResponseEntity getMyPageInfo(@Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo) { MyPageResponse result = userInfoService.getMyPageInfo(authInfo.userId()); return ResponseEntity.ok(result); } + @Operation(summary = "사용자 정보 조회 API", description = "사용자 정보 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/info") public ResponseEntity getUserInformation( - final @FetchAuthInfo AuthInfo authInfo + @Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo ) { UserInformation result = userInfoService.getUserInformation(authInfo.userId()); @@ -39,8 +48,10 @@ public ResponseEntity getUserInformation( return ResponseEntity.ok(result); } + @Operation(summary = "간략한 사용자 정보 조회 API", description = "간락한 사용자 정보를 조회한다") + @ApiResponse(responseCode = "200", useReturnTypeSchema = true) @GetMapping("/home_info") - public ResponseEntity getUserInfo(final @FetchAuthInfo AuthInfo authInfo) { + public ResponseEntity getUserInfo(@Parameter(hidden = true) @FetchAuthInfo AuthInfo authInfo) { UserInfo result = userInfoService.getUserInfo(authInfo.userId());