Skip to content

Commit

Permalink
Feat: 한줄요약 수정 API 구현 (#52)
Browse files Browse the repository at this point in the history
* #40 - fix: 멤버 컬럼 이름 수정

* #40 - feat: 한줄요약 API 구현

* #40 - test: 한줄요약 API 수정 테스트 구현
  • Loading branch information
morenow98 authored Jan 31, 2024
1 parent ee63850 commit a83e945
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,14 @@ public ResponseEntity<Void> registerReview(

return ResponseEntity.created(location).build();
}

@PutMapping("/{review-id}")
public ResponseEntity<Void> updateReview
(@PathVariable(value = "review-id") Long reviewId,
@Valid @RequestBody ReviewUpdateRequest reviewUpdateRequest,
@AuthenticationPrincipal AuthDetails details) {
reviewService.updateReview(reviewId, reviewUpdateRequest, details.getId());

return ResponseEntity.ok().build();
}
}
13 changes: 11 additions & 2 deletions src/main/java/cotato/bookitlist/review/domain/Review.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;
import org.springframework.security.access.AccessDeniedException;

@Entity
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SQLDelete(sql = "UPDATE review SET deleted = true WHERE review_id = ?")
@SQLRestriction("deleted = false")
Expand All @@ -23,7 +24,7 @@ public class Review extends BaseEntity {
private Long id;

@ManyToOne
@JoinColumn(name = "memer_id")
@JoinColumn(name = "member_id")
private Member member;

@ManyToOne
Expand All @@ -48,4 +49,12 @@ private Review(Member member, Book book, String content) {
public static Review of(Member member, Book book, String content) {
return new Review(member, book, content);
}

public void updateReview(Member member, String content) {
if (!this.member.getId().equals(member.getId())) {
throw new AccessDeniedException("권한이 없는 유저입니다.");
}

this.content = content;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cotato.bookitlist.review.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record ReviewUpdateRequest(
@Size(max = 50)
@NotBlank
String content
){
}
31 changes: 31 additions & 0 deletions src/main/java/cotato/bookitlist/review/service/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
import cotato.bookitlist.member.repository.MemberRepository;
import cotato.bookitlist.review.domain.Review;
import cotato.bookitlist.review.dto.request.ReviewRegisterRequest;
import cotato.bookitlist.review.dto.request.ReviewUpdateRequest;
import cotato.bookitlist.review.dto.response.ReviewResponse;
import cotato.bookitlist.review.repository.ReviewRepository;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
@RequiredArgsConstructor
Expand All @@ -31,4 +36,30 @@ public Long registerReview(ReviewRegisterRequest request, Long memberId) {

return reviewRepository.save(review).getId();
}

public void updateReview(Long reviewId, @Valid ReviewUpdateRequest reviewUpdateRequest, Long memberId) {
Member member = memberRepository.getReferenceById(memberId);

Review review = reviewRepository.findById(reviewId)
.orElseThrow(() -> new EntityNotFoundException("한줄요약을 찾을 수 없습니다"));

review.updateReview(member, reviewUpdateRequest.content());
}

public ReviewResponse getReview(Long reviewId) {
Review review = reviewRepository.findById(reviewId)
.orElseThrow(() -> new EntityNotFoundException("존재하지 않는 한줄요약입니다."));

return ReviewResponse.from(review);
}

public List<ReviewResponse> getReviews(Long bookId) {
Book book = bookRepository.findById(bookId)
.orElseThrow(() -> new EntityNotFoundException("존재하지 않는 책입니다."));
List<Review> reviewList = reviewRepository.findAllByBook(book);

return reviewList.stream()
.map(ReviewResponse::from)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import cotato.bookitlist.annotation.WithCustomMockUser;
import cotato.bookitlist.review.dto.request.ReviewRegisterRequest;
import cotato.bookitlist.review.dto.request.ReviewUpdateRequest;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand All @@ -18,6 +19,7 @@
import java.util.List;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand Down Expand Up @@ -91,4 +93,60 @@ private static List<ReviewRegisterRequest> provideInvalidReviewRequest() {
);
}

@Test
@WithCustomMockUser
@DisplayName("한줄요약을 수정한다.")
void givenReviewUpdateRequest_whenUpdatingReview_thenUpdateReview() throws Exception {
//given
ReviewUpdateRequest request = new ReviewUpdateRequest("updateContent");

//when & then
mockMvc.perform(put("/reviews/1")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isOk())
.andDo(print())
;
}

@Test
@WithCustomMockUser
@DisplayName("권한이 없는 한줄요약를 수정하면 에러를 반환한다.")
void givenInvalidMemberId_whenUpdatingReview_thenReturnErrorResponse() throws Exception {
//given
ReviewUpdateRequest request = new ReviewUpdateRequest( "updateContent");

//when & then
mockMvc.perform(put("/reviews/2")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isForbidden())
.andDo(print())
;
}

@ParameterizedTest
@WithCustomMockUser
@MethodSource("provideInvalidReviewUpdateRequest")
@DisplayName("한줄요약 수정시 content 값 예외 검사")
void givenInvalidContent_whenUpdatingReview_thenReturnErrorResponse(ReviewUpdateRequest request) throws Exception {
//given

//when & then
mockMvc.perform(put("/reviews/1")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isBadRequest())
.andDo(print())
;
}

private static List<ReviewUpdateRequest> provideInvalidReviewUpdateRequest() {
String tooLongContent = "TooooooooooooooooooooooooooooooooooooooooooooooLong"; // 51글자

return List.of(
new ReviewUpdateRequest(""),
new ReviewUpdateRequest(tooLongContent)
);
}
}
3 changes: 3 additions & 0 deletions src/test/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ INSERT INTO post (member_id, book_id, title, content, like_count, view_count, de
VALUES (1, 1, 'postTitle', 'postContent', 0, 0, false),
(2, 1, 'postTitle', 'postContent', 0, 0, false);

INSERT INTO review (member_id, book_id, content, like_count, view_count, deleted)
VALUES (1, 1, 'reviewContent', 0, 0, false),
(2, 1, 'reviewContent', 0, 0, false);

0 comments on commit a83e945

Please sign in to comment.