delete comment

This commit is contained in:
aisensiy 2017-08-15 18:16:06 +08:00
parent f31bcbc6e0
commit 001d4e1eea
9 changed files with 85 additions and 14 deletions

View File

@ -2,7 +2,9 @@ package io.spring.api;
import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.annotation.JsonRootName;
import io.spring.api.exception.InvalidRequestException; import io.spring.api.exception.InvalidRequestException;
import io.spring.api.exception.NoAuthorizationException;
import io.spring.api.exception.ResourceNotFoundException; import io.spring.api.exception.ResourceNotFoundException;
import io.spring.application.AuthorizationService;
import io.spring.application.comment.CommentData; import io.spring.application.comment.CommentData;
import io.spring.application.comment.CommentQueryService; import io.spring.application.comment.CommentQueryService;
import io.spring.core.article.Article; import io.spring.core.article.Article;
@ -22,6 +24,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid; import javax.validation.Valid;
@ -70,6 +73,20 @@ public class CommentsApi {
}}); }});
} }
@RequestMapping(path = "{id}", method = RequestMethod.DELETE)
public ResponseEntity deleteComment(@PathVariable("slug") String slug,
@PathVariable("id") String commentId,
@AuthenticationPrincipal User user) {
Article article = findArticle(slug);
return commentRepository.findById(article.getId(), commentId).map(comment -> {
if (!AuthorizationService.canWriteComment(user, article, comment)) {
throw new NoAuthorizationException();
}
commentRepository.remove(comment);
return ResponseEntity.noContent().build();
}).orElseThrow(ResourceNotFoundException::new);
}
private Article findArticle(String slug) { private Article findArticle(String slug) {
return articleRepository.findBySlug(slug).map(article -> article).orElseThrow(ResourceNotFoundException::new); return articleRepository.findBySlug(slug).map(article -> article).orElseThrow(ResourceNotFoundException::new);
} }

View File

@ -1,10 +1,15 @@
package io.spring.application; package io.spring.application;
import io.spring.core.article.Article; import io.spring.core.article.Article;
import io.spring.core.comment.Comment;
import io.spring.core.user.User; import io.spring.core.user.User;
public class AuthorizationService { public class AuthorizationService {
public static boolean canWriteArticle(User user, Article article) { public static boolean canWriteArticle(User user, Article article) {
return user.getId().equals(article.getUserId()); return user.getId().equals(article.getUserId());
} }
public static boolean canWriteComment(User user, Article article, Comment comment) {
return user.getId().equals(article.getUserId()) || user.getId().equals(comment.getUserId());
}
} }

View File

@ -5,5 +5,7 @@ import java.util.Optional;
public interface CommentRepository { public interface CommentRepository {
void save(Comment comment); void save(Comment comment);
Optional<Comment> findById(String id); Optional<Comment> findById(String articleId, String id);
void remove(Comment comment);
} }

View File

@ -10,5 +10,7 @@ import org.springframework.stereotype.Component;
public interface CommentMapper { public interface CommentMapper {
void insert(@Param("comment") Comment comment); void insert(@Param("comment") Comment comment);
Comment findById(@Param("id") String id); Comment findById(@Param("articleId") String articleId, @Param("id") String id);
void delete(@Param("id") String id);
} }

View File

@ -22,7 +22,12 @@ public class MyBatisCommentRepository implements CommentRepository {
} }
@Override @Override
public Optional<Comment> findById(String id) { public Optional<Comment> findById(String articleId, String id) {
return Optional.ofNullable(commentMapper.findById(id)); return Optional.ofNullable(commentMapper.findById(articleId, id));
}
@Override
public void remove(Comment comment) {
commentMapper.delete(comment.getId());
} }
} }

View File

@ -12,6 +12,9 @@
#{comment.createdAt} #{comment.createdAt}
) )
</insert> </insert>
<delete id="delete">
delete from comments where id = #{id}
</delete>
<select id="findById" resultMap="comment"> <select id="findById" resultMap="comment">
select select
id commentId, id commentId,
@ -20,7 +23,7 @@
article_id commentArticleId, article_id commentArticleId,
created_at commentCreatedAt created_at commentCreatedAt
from comments from comments
where id = #{id} where id = #{id} and article_id = #{articleId}
</select> </select>
<resultMap id="comment" type="io.spring.core.comment.Comment"> <resultMap id="comment" type="io.spring.core.comment.Comment">
<id column="commentId" property="id"/> <id column="commentId" property="id"/>

View File

@ -4,10 +4,12 @@ import io.restassured.RestAssured;
import io.spring.application.comment.CommentData; import io.spring.application.comment.CommentData;
import io.spring.application.comment.CommentQueryService; import io.spring.application.comment.CommentQueryService;
import io.spring.application.profile.ProfileData; import io.spring.application.profile.ProfileData;
import io.spring.application.user.UserData;
import io.spring.core.article.Article; import io.spring.core.article.Article;
import io.spring.core.article.ArticleRepository; import io.spring.core.article.ArticleRepository;
import io.spring.core.comment.Comment;
import io.spring.core.comment.CommentRepository; import io.spring.core.comment.CommentRepository;
import org.joda.time.DateTime; import io.spring.core.user.User;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -22,7 +24,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import static io.restassured.RestAssured.given; import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.any;
import static org.hamcrest.core.IsEqual.equalTo; import static org.hamcrest.core.IsEqual.equalTo;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
@ -49,6 +50,7 @@ public class CommentsApiTest extends TestWithCurrentUser {
private Article article; private Article article;
private CommentData commentData; private CommentData commentData;
private Comment comment;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -60,12 +62,13 @@ public class CommentsApiTest extends TestWithCurrentUser {
article = new Article("title", "desc", "body", new String[]{"test", "java"}, user.getId()); article = new Article("title", "desc", "body", new String[]{"test", "java"}, user.getId());
when(articleRepository.findBySlug(eq(article.getSlug()))).thenReturn(Optional.of(article)); when(articleRepository.findBySlug(eq(article.getSlug()))).thenReturn(Optional.of(article));
comment = new Comment("comment", user.getId(), article.getId());
commentData = new CommentData( commentData = new CommentData(
"123", comment.getId(),
"comment", comment.getBody(),
article.getId(), comment.getArticleId(),
new DateTime(), comment.getCreatedAt(),
new DateTime(), comment.getCreatedAt(),
new ProfileData(user.getId(), user.getUsername(), user.getBio(), user.getImage(), false)); new ProfileData(user.getId(), user.getUsername(), user.getBio(), user.getImage(), false));
} }
@ -120,4 +123,38 @@ public class CommentsApiTest extends TestWithCurrentUser {
.statusCode(200) .statusCode(200)
.body("comments[0].id", equalTo(commentData.getId())); .body("comments[0].id", equalTo(commentData.getId()));
} }
@Test
public void should_delete_comment_success() throws Exception {
when(commentRepository.findById(article.getId(), eq(comment.getId()))).thenReturn(Optional.of(comment));
given()
.header("Authorization", "Token " + token)
.when()
.delete("/articles/{slug}/comments/{id}", article.getSlug(), comment.getId())
.then()
.statusCode(204);
}
@Test
public void should_get_403_if_not_author_of_article_or_author_of_comment_when_delete_comment() throws Exception {
User anotherUser = new User("other@example.com", "other", "123", "", "");
when(userRepository.findByUsername(eq(anotherUser.getUsername()))).thenReturn(Optional.of(anotherUser));
when(commentRepository.findById(eq(article.getId()), eq(comment.getId()))).thenReturn(Optional.of(comment));
String token = jwtService.toToken(
new UserData(
anotherUser.getId(),
anotherUser.getEmail(),
anotherUser.getUsername(),
anotherUser.getBio(),
anotherUser.getImage()));
given()
.header("Authorization", "Token " + token)
.when()
.delete("/articles/{slug}/comments/{id}", article.getSlug(), comment.getId())
.then()
.statusCode(403);
}
} }

View File

@ -25,7 +25,7 @@ class TestWithCurrentUser {
protected String token; protected String token;
@Autowired @Autowired
private JwtService jwtService; protected JwtService jwtService;
protected void userFixture(String email, String username, String defaultAvatar) { protected void userFixture(String email, String username, String defaultAvatar) {
user = new User(email, username, "123", "", defaultAvatar); user = new User(email, username, "123", "", defaultAvatar);

View File

@ -26,7 +26,7 @@ public class MyBatisCommentRepositoryTest {
Comment comment = new Comment("content", "123", "456"); Comment comment = new Comment("content", "123", "456");
commentRepository.save(comment); commentRepository.save(comment);
Optional<Comment> optional = commentRepository.findById(comment.getId()); Optional<Comment> optional = commentRepository.findById("456", comment.getId());
assertThat(optional.isPresent(), is(true)); assertThat(optional.isPresent(), is(true));
assertThat(optional.get(), is(comment)); assertThat(optional.get(), is(comment));
} }