Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Article CRUD and Comment CRUD #13

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e313192
Add: article create
thelight0804 Jul 5, 2023
fe9b97e
Add: find by title in article
thelight0804 Jul 5, 2023
d85b433
Add: like search by title or content in article
thelight0804 Jul 5, 2023
5a563f8
Add: Update article feature in test code
thelight0804 Jul 5, 2023
71c21fb
Add: Delete article feature in test code
thelight0804 Jul 5, 2023
10e249c
Add: Create comment
thelight0804 Jul 8, 2023
67e0277
Add: Read comment
thelight0804 Jul 8, 2023
247011c
Fix: test get comment
thelight0804 Jul 8, 2023
c305540
Add: update comment
thelight0804 Jul 8, 2023
bdc530d
Add: delete comment
thelight0804 Jul 8, 2023
e76bd33
Add save login user in comment
thelight0804 Jul 9, 2023
e33831b
Add save login user in Article
thelight0804 Jul 9, 2023
55fa8a2
Add method article controller and service
thelight0804 Jul 9, 2023
3d14903
Add Principal in article and comment controller method
thelight0804 Jul 10, 2023
ea9c945
Add Swagger annotation
thelight0804 Jul 11, 2023
6630e49
Fix DI to Article controller of UserService
thelight0804 Jul 12, 2023
8a8d54a
Fix sendError() when create Article
thelight0804 Jul 12, 2023
3d08cfe
Add dto in article
thelight0804 Jul 12, 2023
877e468
Fix http 400, 500 error of Article CRUD
thelight0804 Jul 12, 2023
a72394c
Fix add @controller in ArticleController
thelight0804 Jul 12, 2023
5d5be0a
Add comment DTO
thelight0804 Jul 12, 2023
9c66e7c
Add feature of Comment Create and Read
thelight0804 Jul 12, 2023
dd1ba9b
Fix typo postID -> commentID
thelight0804 Jul 12, 2023
48c9199
Add feature of comment update and delete
thelight0804 Jul 12, 2023
d2f4145
Update: apply mapping path as HTTP Method of REST API
thelight0804 Jul 14, 2023
7c153c1
Update: HttpServletRequest Swagger parameter to hidden
thelight0804 Jul 14, 2023
2073414
Update: add @Parameter to @PathVariable
thelight0804 Jul 14, 2023
ac9ac26
Remove Swagger documentation in service
thelight0804 Jul 14, 2023
3b99ccf
Add: get article by title
thelight0804 Jul 14, 2023
6fd13b0
Update: use orElseThrow() instead of if-else
thelight0804 Jul 14, 2023
a8d6e2f
Fix typo: 게시글 id instead of 댓글 id in swagger parameter annotation
thelight0804 Jul 14, 2023
66e9e2c
Remove findByArticleIdx method
thelight0804 Jul 14, 2023
122bb7b
Refactor: improve responsibility distribution by create Article, Comm…
thelight0804 Jul 14, 2023
d39ccfd
Add: Base Entity to remove Duplicate code in entity
thelight0804 Jul 14, 2023
c510964
Add: Transactional annotation
thelight0804 Jul 14, 2023
79683bd
Remove: save() method in update
thelight0804 Jul 14, 2023
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
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules/blog.main.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/main/java/com/gdsc/blog/BlogApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing //자동으로 시간을 매핑
public class BlogApplication {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 스타일 관련 변경점은 새로운 PR을 통해 작성하는게 좋아요!

다른 사람과 작업을 할 때, 이 부분을 예를 들자면, 어플리케이션 실행 전 로그를 남기는 등의 동작을 추가하게 된다면 Conflict가 나게 되겠죠?


public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}

public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
}
137 changes: 137 additions & 0 deletions src/main/java/com/gdsc/blog/article/controller/ArticleController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.gdsc.blog.article.controller;

import com.gdsc.blog.article.dto.ArticleCreateDto;
import com.gdsc.blog.article.dto.ArticleUpdateDto;
import com.gdsc.blog.article.entity.Article;
import com.gdsc.blog.article.service.ArticleService;
import com.gdsc.blog.user.entity.User;
import com.gdsc.blog.user.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
@RequestMapping("/api/article")
@RestController
@RequiredArgsConstructor
@Tag(name = "게시글 Controller", description = "Article controller API")
@Slf4j
public class ArticleController {

private final ArticleService articleService;
private final UserService userService;

/**
* 게시글 생성
* @param dto 게시글 생성 정보
* @return 생성된 게시글
*/
@PostMapping //컨트롤러 메핑
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')") //권한 설정
@Operation(summary = "게시글 생성") //swagger 설명
public Article createArticle(
@Parameter(name="게시글 생성 DTO") @RequestBody ArticleCreateDto dto){
//로그인 유저 정보 가져오기
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String userName = authentication.getName();
User user = userService.getUserByName(userName); //유저 이름 가져오기

return articleService.createArticle(dto, user);
}

/**
* 모든 게시글 조회
* @param req HTTP 파싱 객체
* @return 게시글 목록
*/
@GetMapping("/get")
@Operation(summary = "모든 게시글 조회")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
public List<Article> getUserArticle(
@Parameter(hidden = true) HttpServletRequest req
) {
User user = userService.whoami(req); //로그인 유저 정보 가져오기

return articleService.getUserArticle(user);
}

/**
* id로 게시글 조회
* @param id 게시글 id
* @param req HTTP 파싱 객체
* @return 게시글
*/
@GetMapping("/get/id/{id}")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
@Operation(summary = "id로 게시글 조회")
public Article getArticleById(
@Parameter(description = "게시글 id") @PathVariable("id") Long id,
@Parameter(hidden = true) HttpServletRequest req){
return articleService.getArticleById(id);
}

/**
* 제목으로 게시글 조회
* @param title 게시글 제목
* @param req HTTP 파싱 객체
* @return 게시글
*/
@GetMapping("/get/title/{title}")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
@Operation(summary = "제목으로 게시글 조회")
public Article getArticleByTitle(
@Parameter(description = "게시글 제목") @PathVariable(value = "title") String title,
@Parameter(hidden = true) HttpServletRequest req){
return articleService.getArticleByTitle(title);
}

/**
* 게시글 수정
* @param id 게시글 id
* @param dto 게시글 수정 정보
* @param req HTTP 파싱 객체
*/
@PostMapping("/patch/{id}") //생성 & 수정은 PostMapping
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
@Operation(summary = "게시글 수정")
public void updateArticle(
@Parameter(description = "게시글 id") @PathVariable(value = "id") Long id,
@Parameter(name="게시글 수정 DTO") @RequestBody ArticleUpdateDto dto,
@Parameter(hidden = true) HttpServletRequest req) {
User user = userService.whoami(req);

articleService.updateArticle(id, dto);
}

/**
* 게시글 삭제
* @param id 게시글 id
* @param req HTTP 파싱 객체
*/
@GetMapping("/delete/{id}")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
@Operation(summary = "게시글 삭제")
public void deleteArticle(
@Parameter(description = "게시글 id") @PathVariable(value = "id") Long id,
@Parameter(hidden = true) HttpServletRequest req) {
User user = userService.whoami(req);

Article article = articleService.getArticleById(id);

articleService.deleteArticle(article);
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/gdsc/blog/article/dto/ArticleCreateDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.gdsc.blog.article.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Setter
public class ArticleCreateDto {
@Schema(description = "제목", example = "게시글 제목")
public String title;

@Schema(description = "내용", example = "게시글 내용")
public String content;
}
21 changes: 21 additions & 0 deletions src/main/java/com/gdsc/blog/article/dto/ArticleUpdateDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.gdsc.blog.article.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Setter
public class ArticleUpdateDto {
@Schema(description = "수정할 제목", example = "수정된 게시글 제목")
public String title;

@Schema(description = "수정할 내용", example = "수정된 게시글 내용")
public String content;
}
37 changes: 37 additions & 0 deletions src/main/java/com/gdsc/blog/article/entity/Article.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.gdsc.blog.article.entity;

import com.gdsc.blog.base.entity.Base;
import com.gdsc.blog.comment.entity.Comment;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;

@Entity
@NoArgsConstructor
@AllArgsConstructor //생성자 자동 생성
@Getter
@Setter
@SuperBuilder
@Table(name = "articles")
public class Article extends Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; //id

@Column(length = 200)
private String title; //제목

@OneToMany(mappedBy = "article", cascade = CascadeType.REMOVE)
private List<Comment> comments;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gdsc.blog.article.repository;

import com.gdsc.blog.article.entity.Article;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {
Optional<Article> findByTitle(String title);
List<Article> findByTitleLikeOrContentLike(String title, String content);
}
Loading