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

[BE] feat: 리뷰 작성과 리뷰 좋아요 기능에 로그인 붙이기 #206

Merged
merged 8 commits into from
Aug 2, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

Expand All @@ -11,9 +12,12 @@ public class AuthHandlerInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
final HttpSession session = request.getSession();
if (session.getAttribute("member") == null) {
throw new IllegalArgumentException("login error");
final HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());
if (httpMethod.equals(HttpMethod.POST) || httpMethod.equals(HttpMethod.PATCH)) {
wugawuga marked this conversation as resolved.
Show resolved Hide resolved
final HttpSession session = request.getSession();
if (session.getAttribute("member") == null) {
throw new IllegalArgumentException("login error");
}
}
return true;
}
Expand Down
13 changes: 12 additions & 1 deletion backend/src/main/java/com/funeat/common/WebConfig.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
package com.funeat.common;

import com.funeat.auth.util.AuthArgumentResolver;
import com.funeat.auth.util.AuthHandlerInterceptor;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

private final CustomPageableHandlerMethodArgumentResolver customPageableHandlerMethodArgumentResolver;
private final AuthArgumentResolver authArgumentResolver;
private final AuthHandlerInterceptor authHandlerInterceptor;

public WebConfig(final CustomPageableHandlerMethodArgumentResolver customPageableHandlerMethodArgumentResolver,
final AuthArgumentResolver authArgumentResolver) {
final AuthArgumentResolver authArgumentResolver,
final AuthHandlerInterceptor authHandlerInterceptor) {
this.customPageableHandlerMethodArgumentResolver = customPageableHandlerMethodArgumentResolver;
this.authArgumentResolver = authArgumentResolver;
this.authHandlerInterceptor = authHandlerInterceptor;
}

@Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(authHandlerInterceptor)
.addPathPatterns("/api/products/*/reviews/*");
wugawuga marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ public class ReviewFavorite {
protected ReviewFavorite() {
}

public ReviewFavorite(final Boolean favorite) {
this.checked = favorite;
}

public ReviewFavorite(final Member member, final Review review) {
this.member = member;
this.review = review;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ public ReviewService(final ReviewRepository reviewRepository, final TagRepositor
}

@Transactional
public void create(final Long productId, final MultipartFile image, final ReviewCreateRequest reviewRequest) {
final Member findMember = memberRepository.findById(reviewRequest.getMemberId())
public void create(final Long productId, final Long memberId, final MultipartFile image,
final ReviewCreateRequest reviewRequest) {
final Member findMember = memberRepository.findById(memberId)
.orElseThrow(IllegalArgumentException::new);
final Product findProduct = productRepository.findById(productId)
.orElseThrow(IllegalArgumentException::new);
Expand Down Expand Up @@ -86,17 +87,17 @@ public void create(final Long productId, final MultipartFile image, final Review
}

@Transactional
public void likeReview(final Long reviewId, final ReviewFavoriteRequest request) {
final Member findMember = memberRepository.findById(request.getMemberId())
public void likeReview(final Long reviewId, final Long memberId, final ReviewFavoriteRequest request) {
final Member findMember = memberRepository.findById(memberId)
.orElseThrow(IllegalArgumentException::new);
final Review findReview = reviewRepository.findById(reviewId)
.orElseThrow(IllegalArgumentException::new);

final ReviewFavorite reviewFavorite = ReviewFavorite.createReviewFavoriteByMemberAndReview(findMember,
findReview, request.getFavorite());

final ReviewFavorite findReviewFavorite = reviewFavoriteRepository.findByMemberAndReview(findMember,
findReview).orElse(reviewFavoriteRepository.save(reviewFavorite));
final ReviewFavorite findReviewFavorite = reviewFavoriteRepository.findByMemberAndReview(findMember, findReview)
.orElse(reviewFavoriteRepository.save(reviewFavorite));

findReviewFavorite.updateChecked(request.getFavorite());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.funeat.review.presentation;

import com.funeat.auth.dto.LoginRequest;
import com.funeat.auth.util.AuthenticationPrincipal;
import com.funeat.review.application.ReviewService;
import com.funeat.review.presentation.dto.RankingReviewsResponse;
import com.funeat.review.presentation.dto.ReviewCreateRequest;
Expand Down Expand Up @@ -30,23 +32,26 @@ public ReviewApiController(final ReviewService reviewService) {

@PostMapping(value = "/api/products/{productId}/reviews", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE,
MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Void> writeReview(@PathVariable Long productId, @RequestPart MultipartFile image,
@RequestPart ReviewCreateRequest reviewRequest) {
reviewService.create(productId, image, reviewRequest);
public ResponseEntity<Void> writeReview(@PathVariable final Long productId,
@AuthenticationPrincipal final LoginRequest loginInfo,
@RequestPart(required = false) final MultipartFile image,
@RequestPart final ReviewCreateRequest reviewRequest) {
reviewService.create(productId, loginInfo.getId(), image, reviewRequest);

return ResponseEntity.created(URI.create("/api/products/" + productId)).build();
}

@PatchMapping("/api/products/{productId}/reviews/{reviewId}")
public ResponseEntity<Void> toggleLikeReview(@PathVariable Long reviewId,
@AuthenticationPrincipal LoginRequest loginInfo,
@RequestBody ReviewFavoriteRequest request) {
reviewService.likeReview(reviewId, request);
reviewService.likeReview(reviewId, loginInfo.getId(), request);

return ResponseEntity.noContent().build();

}

@GetMapping(value = "/api/products/{productId}/reviews")
@GetMapping("/api/products/{productId}/reviews")
public ResponseEntity<SortingReviewsResponse> getSortingReviews(@PathVariable Long productId,
@PageableDefault Pageable pageable) {
final SortingReviewsResponse response = reviewService.sortingReviews(productId, pageable);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.funeat.review.presentation;

import com.funeat.auth.dto.LoginRequest;
import com.funeat.auth.util.AuthenticationPrincipal;
import com.funeat.review.presentation.dto.RankingReviewsResponse;
import com.funeat.review.presentation.dto.ReviewCreateRequest;
import com.funeat.review.presentation.dto.ReviewFavoriteRequest;
Expand Down Expand Up @@ -27,16 +29,17 @@ public interface ReviewController {
description = "리뷰 작성 성공."
)
@PostMapping
ResponseEntity<Void> writeReview(@PathVariable Long productId, @RequestPart MultipartFile image,
@RequestPart ReviewCreateRequest reviewRequest);
ResponseEntity<Void> writeReview(@PathVariable Long productId, @AuthenticationPrincipal LoginRequest loginInfo,
@RequestPart MultipartFile image, @RequestPart ReviewCreateRequest reviewRequest);

@Operation(summary = "리뷰 좋아요", description = "리뷰에 좋아요 또는 취소를 한다.")
@ApiResponse(
responseCode = "204",
description = "리뷰 좋아요(취소) 성공."
)
@PatchMapping
ResponseEntity<Void> toggleLikeReview(@PathVariable Long reviewId, @RequestBody ReviewFavoriteRequest request);
ResponseEntity<Void> toggleLikeReview(@PathVariable Long reviewId, @AuthenticationPrincipal LoginRequest loginInfo,
@RequestBody ReviewFavoriteRequest request);

@Operation(summary = "리뷰를 정렬후 조회", description = "리뷰를 정렬후 조회한다.")
@ApiResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ public class ReviewCreateRequest {
private final List<Long> tagIds;
private final String content;
private final Boolean reBuy;
private final Long memberId;

public ReviewCreateRequest(final Long rating, final List<Long> tagIds, final String content, final Boolean reBuy,
final Long memberId) {
public ReviewCreateRequest(final Long rating, final List<Long> tagIds, final String content, final Boolean reBuy) {
this.rating = rating;
this.tagIds = tagIds;
this.content = content;
this.reBuy = reBuy;
this.memberId = memberId;
}

public Long getRating() {
Expand All @@ -31,10 +28,6 @@ public Boolean getReBuy() {
return reBuy;
}

public Long getMemberId() {
return memberId;
}

public List<Long> getTagIds() {
return tagIds;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
package com.funeat.review.presentation.dto;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class ReviewFavoriteRequest {

private final Boolean favorite;
private final Long memberId;

public ReviewFavoriteRequest(final Boolean favorite, final Long memberId) {
@JsonCreator
public ReviewFavoriteRequest(@JsonProperty("favorite") final Boolean favorite) {
this.favorite = favorite;
this.memberId = memberId;
}

public Boolean getFavorite() {
return favorite;
}

public Long getMemberId() {
return memberId;
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package com.funeat.acceptance.common;

import io.restassured.RestAssured;
import io.restassured.http.Cookies;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;

@SuppressWarnings("NonAsciiCharacters")
public class LoginSteps {

public static Cookies 로그인_쿠키를_얻는다() {
final ExtractableResponse<Response> response = RestAssured.given()
public static String 로그인_쿠키를_얻는다() {
return RestAssured.given()
.queryParam("code", "test")
.when()
.get("/login/oauth2/code/kakao")
.post("/api/login/oauth2/code/kakao")
.then()
.extract();

return response.detailedCookies();
.extract()
.response()
.getCookie("JSESSIONID");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.funeat.acceptance.common.CommonSteps.STATUS_CODE를_검증한다;
import static com.funeat.acceptance.common.CommonSteps.정상_처리;
import static com.funeat.acceptance.common.LoginSteps.로그인_쿠키를_얻는다;
import static com.funeat.acceptance.product.ProductSteps.CU;
import static com.funeat.acceptance.product.ProductSteps.간편식사;
import static com.funeat.acceptance.product.ProductSteps.공통_상품_카테고리_목록_조회_요청;
Expand Down Expand Up @@ -379,14 +380,15 @@ class 리뷰수_기준_내림차순으로_카테고리별_상품_목록_조회 {
final MultiPartSpecification image = 리뷰_사진_명세_요청();

final ReviewCreateRequest request1 = new ReviewCreateRequest(4L,
List.of(tag1.getId(), tag2.getId(), tag3.getId()), "request1", true, memberId);
List.of(tag1.getId(), tag2.getId(), tag3.getId()), "request1", true);
final ReviewCreateRequest request2 = new ReviewCreateRequest(4L, List.of(tag2.getId(), tag3.getId()),
"request2", true, memberId);
final ReviewCreateRequest request3 = new ReviewCreateRequest(3L, List.of(tag2.getId()), "request3", true,
memberId);
리뷰_추가_요청(productId, image, request1);
리뷰_추가_요청(productId, image, request2);
리뷰_추가_요청(productId, image, request3);
"request2", true);
final ReviewCreateRequest request3 = new ReviewCreateRequest(3L, List.of(tag2.getId()), "request3", true);

final var loginCookie = 로그인_쿠키를_얻는다();
리뷰_추가_요청(productId, image, request1, loginCookie);
리뷰_추가_요청(productId, image, request2, loginCookie);
리뷰_추가_요청(productId, image, request3, loginCookie);

// when
final var response = 상품_상세_조회_요청(productId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.funeat.acceptance.common.CommonSteps.정상_생성;
import static com.funeat.acceptance.common.CommonSteps.정상_처리;
import static com.funeat.acceptance.common.CommonSteps.정상_처리_NO_CONTENT;
import static com.funeat.acceptance.common.LoginSteps.로그인_쿠키를_얻는다;
import static com.funeat.acceptance.review.ReviewSteps.리뷰_사진_명세_요청;
import static com.funeat.acceptance.review.ReviewSteps.리뷰_좋아요_요청;
import static com.funeat.acceptance.review.ReviewSteps.리뷰_추가_요청;
Expand Down Expand Up @@ -38,15 +39,15 @@ class ReviewAcceptanceTest extends AcceptanceTest {
@Test
void 리뷰를_작성한다() {
// given
final Long savedMemberId = 멤버_추가_요청();
final Long savedProductId = 상품_추가_요청();
final List<Long> savedTagIds = 태그_추가_요청();
final MultiPartSpecification image = 리뷰_사진_명세_요청();
final var loginCookie = 로그인_쿠키를_얻는다();

final var request = new ReviewCreateRequest(4L, savedTagIds, "test content", true, savedMemberId);
final var request = new ReviewCreateRequest(4L, savedTagIds, "test content", true);

// when
final var response = 리뷰_추가_요청(savedProductId, image, request);
final var response = 리뷰_추가_요청(savedProductId, image, request, loginCookie);

// then
STATUS_CODE를_검증한다(response, 정상_생성);
Expand All @@ -59,14 +60,16 @@ class ReviewAcceptanceTest extends AcceptanceTest {
final Long savedProductId = 상품_추가_요청();
final List<Long> savedTagIds = 태그_추가_요청();
final MultiPartSpecification image = 리뷰_사진_명세_요청();
final var reviewRequest = new ReviewCreateRequest(4L, savedTagIds, "test content", true, savedMemberId);
final var favoriteRequest = new ReviewFavoriteRequest(true, savedMemberId);
final var reviewRequest = new ReviewCreateRequest(4L, savedTagIds, "test content", true);
final var favoriteRequest = new ReviewFavoriteRequest(true);

final var loginCookie = 로그인_쿠키를_얻는다();

리뷰_추가_요청(savedProductId, image, reviewRequest);
리뷰_추가_요청(savedProductId, image, reviewRequest, loginCookie);
final var savedReviewId = reviewRepository.findAll().get(0).getId();

// when
final var response = 리뷰_좋아요_요청(savedProductId, savedReviewId, favoriteRequest);
final var response = 리뷰_좋아요_요청(savedProductId, savedReviewId, favoriteRequest, loginCookie);
final var result = reviewFavoriteRepository.findAll().get(0);

// then
Expand All @@ -82,16 +85,17 @@ class ReviewAcceptanceTest extends AcceptanceTest {
final Long savedProductId = 상품_추가_요청();
final List<Long> savedTagIds = 태그_추가_요청();
final MultiPartSpecification image = 리뷰_사진_명세_요청();
final var reviewRequest = new ReviewCreateRequest(4L, savedTagIds, "test content", true, savedMemberId);
final var favoriteRequest = new ReviewFavoriteRequest(true, savedMemberId);
final var favoriteCancelRequest = new ReviewFavoriteRequest(false, savedMemberId);
final var reviewRequest = new ReviewCreateRequest(4L, savedTagIds, "test content", true);
final var favoriteRequest = new ReviewFavoriteRequest(true);
final var favoriteCancelRequest = new ReviewFavoriteRequest(false);
final var loginCookie = 로그인_쿠키를_얻는다();

리뷰_추가_요청(savedProductId, image, reviewRequest);
리뷰_추가_요청(savedProductId, image, reviewRequest, loginCookie);
final var savedReview = reviewRepository.findAll().get(0);
리뷰_좋아요_요청(savedProductId, savedReview.getId(), favoriteRequest);
리뷰_좋아요_요청(savedProductId, savedReview.getId(), favoriteRequest, loginCookie);

// when
final var response = 리뷰_좋아요_요청(savedProductId, savedReview.getId(), favoriteCancelRequest);
final var response = 리뷰_좋아요_요청(savedProductId, savedReview.getId(), favoriteCancelRequest, loginCookie);
final var result = reviewFavoriteRepository.findAll().get(0);

// then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
public class ReviewSteps {

public static ExtractableResponse<Response> 리뷰_추가_요청(final Long productId, final MultiPartSpecification image,
final ReviewCreateRequest request) {
final ReviewCreateRequest request, final String loginCookie) {
return given()
.cookie("JSESSIONID", loginCookie)
.multiPart(image)
.multiPart("reviewRequest", request, "application/json")
.when()
Expand All @@ -24,8 +25,10 @@ public class ReviewSteps {
}

public static ExtractableResponse<Response> 리뷰_좋아요_요청(final Long productId, final Long reviewId,
final ReviewFavoriteRequest request) {
final ReviewFavoriteRequest request,
final String loginCookie) {
return given()
.cookie("JSESSIONID", loginCookie)
.contentType("application/json")
.body(request)
.when()
Expand Down
Loading
Loading