delete comment
This commit is contained in:
parent
f31bcbc6e0
commit
001d4e1eea
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"/>
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user