Add post and comment deletion

This commit is contained in:
Tim
2025-07-11 17:24:48 +08:00
parent 216faeb496
commit f4af7a48c7
7 changed files with 139 additions and 3 deletions

View File

@@ -65,6 +65,11 @@ public class CommentController {
return dto;
}
@DeleteMapping("/comments/{id}")
public void deleteComment(@PathVariable Long id, Authentication auth) {
commentService.deleteComment(auth.getName(), id);
}
private CommentDto toDto(Comment comment) {
CommentDto dto = new CommentDto();
dto.setId(comment.getId());

View File

@@ -48,6 +48,11 @@ public class PostController {
return ResponseEntity.ok(toDto(post));
}
@DeleteMapping("/{id}")
public void deletePost(@PathVariable Long id, Authentication auth) {
postService.deletePost(id, auth.getName());
}
@GetMapping("/{id}")
public ResponseEntity<PostDto> getPost(@PathVariable Long id, Authentication auth) {
String viewer = auth != null ? auth.getName() : null;

View File

@@ -2,6 +2,8 @@ package com.openisle.repository;
import com.openisle.model.Notification;
import com.openisle.model.User;
import com.openisle.model.Post;
import com.openisle.model.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
@@ -11,4 +13,6 @@ public interface NotificationRepository extends JpaRepository<Notification, Long
List<Notification> findByUserOrderByCreatedAtDesc(User user);
List<Notification> findByUserAndReadOrderByCreatedAtDesc(User user, boolean read);
long countByUserAndRead(User user, boolean read);
List<Notification> findByPost(Post post);
List<Notification> findByComment(Comment comment);
}

View File

@@ -7,8 +7,12 @@ import com.openisle.model.NotificationType;
import com.openisle.repository.CommentRepository;
import com.openisle.repository.PostRepository;
import com.openisle.repository.UserRepository;
import com.openisle.repository.ReactionRepository;
import com.openisle.repository.CommentSubscriptionRepository;
import com.openisle.repository.NotificationRepository;
import com.openisle.service.NotificationService;
import com.openisle.service.SubscriptionService;
import com.openisle.model.Role;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -24,6 +28,9 @@ public class CommentService {
private final UserRepository userRepository;
private final NotificationService notificationService;
private final SubscriptionService subscriptionService;
private final ReactionRepository reactionRepository;
private final CommentSubscriptionRepository commentSubscriptionRepository;
private final NotificationRepository notificationRepository;
public Comment addComment(String username, Long postId, String content) {
User author = userRepository.findByUsername(username)
@@ -115,4 +122,28 @@ public class CommentService {
public java.util.List<Comment> getCommentsByIds(java.util.List<Long> ids) {
return commentRepository.findAllById(ids);
}
@org.springframework.transaction.annotation.Transactional
public void deleteComment(String username, Long id) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new IllegalArgumentException("User not found"));
Comment comment = commentRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Comment not found"));
if (!user.getId().equals(comment.getAuthor().getId()) && user.getRole() != Role.ADMIN) {
throw new IllegalArgumentException("Unauthorized");
}
deleteCommentCascade(comment);
}
@org.springframework.transaction.annotation.Transactional
public void deleteCommentCascade(Comment comment) {
List<Comment> replies = commentRepository.findByParentOrderByCreatedAtAsc(comment);
for (Comment c : replies) {
deleteCommentCascade(c);
}
reactionRepository.findByComment(comment).forEach(reactionRepository::delete);
commentSubscriptionRepository.findByComment(comment).forEach(commentSubscriptionRepository::delete);
notificationRepository.findByComment(comment).forEach(n -> { n.setComment(null); notificationRepository.save(n); });
commentRepository.delete(comment);
}
}

View File

@@ -5,12 +5,19 @@ import com.openisle.model.PostStatus;
import com.openisle.model.PublishMode;
import com.openisle.model.User;
import com.openisle.model.Category;
import com.openisle.model.Comment;
import com.openisle.model.NotificationType;
import com.openisle.repository.PostRepository;
import com.openisle.repository.UserRepository;
import com.openisle.repository.CategoryRepository;
import com.openisle.repository.TagRepository;
import com.openisle.service.SubscriptionService;
import com.openisle.service.CommentService;
import com.openisle.repository.CommentRepository;
import com.openisle.repository.ReactionRepository;
import com.openisle.repository.PostSubscriptionRepository;
import com.openisle.repository.NotificationRepository;
import com.openisle.model.Role;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -27,6 +34,11 @@ public class PostService {
private PublishMode publishMode;
private final NotificationService notificationService;
private final SubscriptionService subscriptionService;
private final CommentService commentService;
private final CommentRepository commentRepository;
private final ReactionRepository reactionRepository;
private final PostSubscriptionRepository postSubscriptionRepository;
private final NotificationRepository notificationRepository;
@org.springframework.beans.factory.annotation.Autowired
public PostService(PostRepository postRepository,
@@ -35,6 +47,11 @@ public class PostService {
TagRepository tagRepository,
NotificationService notificationService,
SubscriptionService subscriptionService,
CommentService commentService,
CommentRepository commentRepository,
ReactionRepository reactionRepository,
PostSubscriptionRepository postSubscriptionRepository,
NotificationRepository notificationRepository,
@Value("${app.post.publish-mode:DIRECT}") PublishMode publishMode) {
this.postRepository = postRepository;
this.userRepository = userRepository;
@@ -42,6 +59,11 @@ public class PostService {
this.tagRepository = tagRepository;
this.notificationService = notificationService;
this.subscriptionService = subscriptionService;
this.commentService = commentService;
this.commentRepository = commentRepository;
this.reactionRepository = reactionRepository;
this.postSubscriptionRepository = postSubscriptionRepository;
this.notificationRepository = notificationRepository;
this.publishMode = publishMode;
}
@@ -317,6 +339,24 @@ public class PostService {
return post;
}
@org.springframework.transaction.annotation.Transactional
public void deletePost(Long id, String username) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Post not found"));
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new IllegalArgumentException("User not found"));
if (!user.getId().equals(post.getAuthor().getId()) && user.getRole() != Role.ADMIN) {
throw new IllegalArgumentException("Unauthorized");
}
for (Comment c : commentRepository.findByPostAndParentIsNullOrderByCreatedAtAsc(post)) {
commentService.deleteCommentCascade(c);
}
reactionRepository.findByPost(post).forEach(reactionRepository::delete);
postSubscriptionRepository.findByPost(post).forEach(postSubscriptionRepository::delete);
notificationRepository.findByPost(post).forEach(n -> { n.setPost(null); notificationRepository.save(n); });
postRepository.delete(post);
}
public java.util.List<Post> getPostsByIds(java.util.List<Long> ids) {
return postRepository.findAllById(ids);
}