feat :add Comment API Implement.

This commit is contained in:
minseokkang
2022-11-01 16:33:19 +09:00
parent 1cb0b2c97f
commit 68df1b6be1
8 changed files with 169 additions and 9 deletions

View File

@@ -1,30 +1,29 @@
package com.io.realworld.domain.aggregate.article.controller;
import com.io.realworld.domain.aggregate.article.dto.ArticleParam;
import com.io.realworld.domain.aggregate.article.dto.ArticleUpdate;
import com.io.realworld.domain.aggregate.article.dto.Articledto;
import com.io.realworld.domain.aggregate.article.dto.ArticleResponse;
import com.io.realworld.domain.aggregate.article.dto.*;
import com.io.realworld.domain.aggregate.article.service.ArticleService;
import com.io.realworld.domain.aggregate.article.service.CommentService;
import com.io.realworld.domain.aggregate.user.dto.UserAuth;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api/articles")
public class ArticleController {
private final ArticleService articleService;
private final CommentService commentService;
public ArticleController(ArticleService articleService) {
public ArticleController(ArticleService articleService, CommentService commentService) {
this.articleService = articleService;
this.commentService = commentService;
}
@GetMapping()
public List<ArticleResponse> getArticles(@AuthenticationPrincipal UserAuth userAuth,@ModelAttribute ArticleParam articleParam){
public List<ArticleResponse> getArticles(@AuthenticationPrincipal UserAuth userAuth, @ModelAttribute ArticleParam articleParam) {
return articleService.getArticles(articleParam);
}
@@ -49,12 +48,17 @@ public class ArticleController {
}
@PostMapping("/{slug}/favorite")
public ArticleResponse favoriteArticle(@AuthenticationPrincipal UserAuth userAuth, @PathVariable("slug") String slug){
public ArticleResponse favoriteArticle(@AuthenticationPrincipal UserAuth userAuth, @PathVariable("slug") String slug) {
return articleService.favoriteArticle(userAuth, slug);
}
@DeleteMapping("/{slug}/favorite")
public ArticleResponse unFavoriteArticle(@AuthenticationPrincipal UserAuth userAuth, @PathVariable("slug") String slug){
public ArticleResponse unFavoriteArticle(@AuthenticationPrincipal UserAuth userAuth, @PathVariable("slug") String slug) {
return articleService.unFavoriteArticle(userAuth, slug);
}
@PostMapping("/{slug}/comments")
public CommentResponse createComment(@AuthenticationPrincipal UserAuth userAuth, @PathVariable("slug") String slug, @Valid @RequestBody Commentdto commentdto) {
return commentService.addComment(userAuth, slug, commentdto);
}
}

View File

@@ -0,0 +1,30 @@
package com.io.realworld.domain.aggregate.article.dto;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.Builder;
import lombok.Getter;
import java.time.LocalDateTime;
@Builder
@Getter
@JsonTypeName("comment")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class CommentResponse {
private Long id;
private LocalDateTime createAt;
private LocalDateTime updateAt;
private String body;
private Author author;
@Builder
@Getter
public static class Author{
private String username;
private String bio;
private String image;
private Boolean following;
}
}

View File

@@ -0,0 +1,18 @@
package com.io.realworld.domain.aggregate.article.dto;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
@JsonTypeName("comment")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class Commentdto {
private String body;
}

View File

@@ -0,0 +1,32 @@
package com.io.realworld.domain.aggregate.article.entity;
import com.io.realworld.base.entity.DateEntity;
import com.io.realworld.domain.aggregate.user.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
@Entity
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "comment")
public class Comment extends DateEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
private String body;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false)
private User author;
}

View File

@@ -0,0 +1,7 @@
package com.io.realworld.domain.aggregate.article.repository;
import com.io.realworld.domain.aggregate.article.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CommentRepository extends JpaRepository<Comment, Long> {
}

View File

@@ -23,4 +23,6 @@ public interface ArticleService {
ArticleResponse favoriteArticle(UserAuth userAuth, String slug);
ArticleResponse unFavoriteArticle(UserAuth userAuth, String slug);
}

View File

@@ -0,0 +1,10 @@
package com.io.realworld.domain.aggregate.article.service;
import com.io.realworld.domain.aggregate.article.dto.CommentResponse;
import com.io.realworld.domain.aggregate.article.dto.Commentdto;
import com.io.realworld.domain.aggregate.user.dto.UserAuth;
public interface CommentService {
CommentResponse addComment(UserAuth userAuth,String slug, Commentdto commentdto);
}

View File

@@ -0,0 +1,57 @@
package com.io.realworld.domain.aggregate.article.service;
import com.io.realworld.domain.aggregate.article.dto.CommentResponse;
import com.io.realworld.domain.aggregate.article.dto.Commentdto;
import com.io.realworld.domain.aggregate.article.entity.Article;
import com.io.realworld.domain.aggregate.article.entity.Comment;
import com.io.realworld.domain.aggregate.article.repository.ArticleRepository;
import com.io.realworld.domain.aggregate.article.repository.CommentRepository;
import com.io.realworld.domain.aggregate.profile.dto.ProfileResponse;
import com.io.realworld.domain.aggregate.profile.service.ProfileService;
import com.io.realworld.domain.aggregate.user.dto.UserAuth;
import com.io.realworld.domain.aggregate.user.entity.User;
import com.io.realworld.domain.aggregate.user.repository.UserRepository;
import com.io.realworld.exception.CustomException;
import com.io.realworld.exception.Error;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class CommentServiceImpl implements CommentService {
private final ArticleRepository articleRepository;
private final ProfileService profileService;
private final UserRepository userRepository;
private final CommentRepository commentRepository;
@Override
public CommentResponse addComment(UserAuth userAuth, String slug, Commentdto commentdto) {
Optional<User> user = userRepository.findById(userAuth.getId());
Optional<Article> article = articleRepository.findAll().stream().filter(findArticle -> findArticle.getSlug().equals(slug)).findAny();
if (article.isEmpty()) {
throw new CustomException(Error.ARTICLE_NOT_FOUND);
}
Comment comment = commentRepository.save(Comment.builder().body(commentdto.getBody()).author(user.get()).build());
return convertComment(userAuth, article.get(), comment);
}
private CommentResponse convertComment(UserAuth userAuth, Article article, Comment comment) {
ProfileResponse profile = profileService.getProfile(userAuth, article.getAuthor().getUsername());
return CommentResponse.builder()
.id(comment.getId())
.createAt(comment.getCreatedDate())
.updateAt(comment.getModifiedDate())
.body(comment.getBody())
.author(CommentResponse.Author.builder()
.username(profile.getUsername())
.bio(profile.getBio())
.image(profile.getImage())
.following(profile.getFollowing()).build()).build();
}
}