Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,8 @@ public void softDelete() {
public boolean isReply() {
return this.parent != null;
}

public boolean isOwnedBy(Long userId) {
return author != null && userId != null && userId.equals(author.getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public List<CommentResponse> getReplies(Long parentId, Long viewerId) {
@Transactional
public void delete(Long commentId, Long requesterId) {
Comment comment = findActiveCommentOrThrow(commentId);
if (!comment.getAuthor().getId().equals(requesterId)) {
if (!comment.isOwnedBy(requesterId)) {
throw new GeneralException(ErrorStatus.COMMENT_FORBIDDEN);
}
comment.softDelete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ public void increaseViewCount() {
public void softDelete() {
this.deleted = true;
}

public boolean isOwnedBy(Long userId) {
return author != null && userId != null && userId.equals(author.getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public FreePostReport report(Long reporterId, Long postId, FreePostReportReason
User reporter = findReporterOrThrow(reporterId);
FreePost post = findPostOrThrow(postId);

if (post.getAuthor().getId().equals(reporterId)) {
if (post.isOwnedBy(reporterId)) {
throw new GeneralException(ErrorStatus.FREE_POST_REPORT_SELF_NOT_ALLOWED);
}
if (freePostReportRepository.existsByReporter_IdAndPost_Id(reporterId, postId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public FreePostDetailResponse getDetail(Long viewerId, Long postId) {
@Transactional
public void delete(Long postId, Long requesterId) {
FreePost post = findActivePostOrThrow(postId);
if (!post.getAuthor().getId().equals(requesterId)) {
if (!post.isOwnedBy(requesterId)) {
throw new GeneralException(ErrorStatus.POST_FORBIDDEN);
}
post.softDelete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public RecordPost getDetail(Long postId) {
@Transactional
public void delete(Long postId, Long requesterId) {
RecordPost post = findActivePostOrThrow(postId);
if (!post.getAuthor().getId().equals(requesterId)) {
if (!post.isOwnedBy(requesterId)) {
throw new GeneralException(ErrorStatus.POST_FORBIDDEN);
}
post.softDelete();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.semosan.api.domain.community.comment.service;

import com.semosan.api.common.exception.GeneralException;
import com.semosan.api.common.status.ErrorStatus;
import com.semosan.api.domain.community.comment.entity.Comment;
import com.semosan.api.domain.community.comment.repository.CommentRepository;
import com.semosan.api.domain.community.notification.service.CommunityNotificationService;
Expand All @@ -20,6 +22,7 @@
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -91,6 +94,36 @@ void replySavesReplyAndDelegatesNotification() throws Exception {
.sendReplyNotification(post, replyAuthor, parent, mentionedUser, result);
}

@Test
void deleteSoftDeletesWhenRequesterOwnsComment() throws Exception {
User postAuthor = user(1L, "post-author");
User commentAuthor = user(2L, "comment-author");
FreePost post = freePost(10L, postAuthor, "제목", "본문");
Comment comment = comment(100L, post, commentAuthor, "댓글");

when(commentRepository.findByIdAndDeletedFalse(100L)).thenReturn(Optional.of(comment));

commentService.delete(100L, 2L);

assertThat(comment.isDeleted()).isTrue();
}

@Test
void deleteThrowsWhenRequesterDoesNotOwnComment() throws Exception {
User postAuthor = user(1L, "post-author");
User commentAuthor = user(2L, "comment-author");
FreePost post = freePost(10L, postAuthor, "제목", "본문");
Comment comment = comment(100L, post, commentAuthor, "댓글");

when(commentRepository.findByIdAndDeletedFalse(100L)).thenReturn(Optional.of(comment));

assertThatThrownBy(() -> commentService.delete(100L, 3L))
.isInstanceOf(GeneralException.class)
.extracting("errorStatus")
.isEqualTo(ErrorStatus.COMMENT_FORBIDDEN);
assertThat(comment.isDeleted()).isFalse();
}

private User user(Long id, String nickname) {
User user = User.createTestUser(nickname, DeviceType.IOS);
ReflectionTestUtils.setField(user, "id", id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,32 @@ void getDetailThrowsWhenViewerBlockedAuthor() throws Exception {
verify(postImageRepository, never()).findByPostOrderBySortOrderAsc(post);
}

@Test
void deleteSoftDeletesWhenRequesterOwnsPost() throws Exception {
User author = user(2L, "author");
FreePost post = freePost(10L, author, "제목", "본문");

when(freePostRepository.findById(10L)).thenReturn(Optional.of(post));

freePostService.delete(10L, 2L);

assertThat(post.isDeleted()).isTrue();
}

@Test
void deleteThrowsWhenRequesterDoesNotOwnPost() throws Exception {
User author = user(2L, "author");
FreePost post = freePost(10L, author, "제목", "본문");

when(freePostRepository.findById(10L)).thenReturn(Optional.of(post));

assertThatThrownBy(() -> freePostService.delete(10L, 3L))
.isInstanceOf(GeneralException.class)
.extracting("errorStatus")
.isEqualTo(ErrorStatus.POST_FORBIDDEN);
assertThat(post.isDeleted()).isFalse();
}

private User user(Long id, String oauthId) {
User user = User.createTestUser(oauthId, DeviceType.IOS);
ReflectionTestUtils.setField(user, "id", id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.semosan.api.domain.community.post.service;

import com.semosan.api.common.exception.GeneralException;
import com.semosan.api.common.status.ErrorStatus;
import com.semosan.api.domain.community.post.entity.RecordPost;
import com.semosan.api.domain.community.post.repository.RecordPostRepository;
import com.semosan.api.domain.hiking.repository.HikingMemberRepository;
import com.semosan.api.domain.hiking.repository.HikingRecordRepository;
import com.semosan.api.domain.user.entity.User;
import com.semosan.api.domain.user.enums.user.DeviceType;
import com.semosan.api.domain.user.service.UserReader;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class RecordPostServiceTest {

@Mock
private RecordPostRepository recordPostRepository;

@Mock
private HikingRecordRepository hikingRecordRepository;

@Mock
private HikingMemberRepository hikingMemberRepository;

@Mock
private UserReader userReader;

@InjectMocks
private RecordPostService recordPostService;

@Test
void deleteSoftDeletesWhenRequesterOwnsPost() {
RecordPost post = recordPost(10L, user(2L, "author"));

when(recordPostRepository.findById(10L)).thenReturn(Optional.of(post));

recordPostService.delete(10L, 2L);

assertThat(post.isDeleted()).isTrue();
}

@Test
void deleteThrowsWhenRequesterDoesNotOwnPost() {
RecordPost post = recordPost(10L, user(2L, "author"));

when(recordPostRepository.findById(10L)).thenReturn(Optional.of(post));

assertThatThrownBy(() -> recordPostService.delete(10L, 3L))
.isInstanceOf(GeneralException.class)
.extracting("errorStatus")
.isEqualTo(ErrorStatus.POST_FORBIDDEN);
assertThat(post.isDeleted()).isFalse();
}

private User user(Long id, String nickname) {
User user = User.createTestUser(nickname, DeviceType.IOS);
ReflectionTestUtils.setField(user, "id", id);
ReflectionTestUtils.setField(user, "nickname", nickname);
return user;
}

private RecordPost recordPost(Long id, User author) {
RecordPost post = RecordPost.create(author, "본문", null);
ReflectionTestUtils.setField(post, "id", id);
return post;
}
}