Skip to content

Commit 1f603bf

Browse files
authored
Merge pull request #10 from prgrms-web-devcourse-final-project/feature/comment-CRD
댓글 생성/삭제 기능 구현
2 parents adb0836 + a9cdfa2 commit 1f603bf

File tree

13 files changed

+352
-53
lines changed

13 files changed

+352
-53
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.example.log4u.domain.comment.controller;
2+
3+
import org.springframework.http.ResponseEntity;
4+
import org.springframework.web.bind.annotation.DeleteMapping;
5+
import org.springframework.web.bind.annotation.PathVariable;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestBody;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
import com.example.log4u.domain.comment.dto.request.CommentCreateRequestDto;
12+
import com.example.log4u.domain.comment.dto.response.CommentCreateResponseDto;
13+
import com.example.log4u.domain.comment.service.CommentService;
14+
15+
import io.swagger.v3.oas.annotations.tags.Tag;
16+
import jakarta.validation.Valid;
17+
import lombok.RequiredArgsConstructor;
18+
19+
@Tag(name = "댓글 API")
20+
@RestController
21+
@RequiredArgsConstructor
22+
@RequestMapping("/comments")
23+
public class CommentController {
24+
25+
private final CommentService commentService;
26+
27+
@PostMapping
28+
public ResponseEntity<CommentCreateResponseDto> addComment(@RequestBody @Valid CommentCreateRequestDto requestDto) {
29+
Long userId = 1L; //임시 처리
30+
31+
CommentCreateResponseDto response = commentService.addComment(userId, requestDto);
32+
return ResponseEntity.ok(response);
33+
}
34+
35+
@DeleteMapping("/{commentId}")
36+
public ResponseEntity<Void> deleteComment(@PathVariable Long commentId) {
37+
Long userId = 1L; //임시 처리
38+
39+
commentService.deleteComment(userId, commentId);
40+
return ResponseEntity.noContent().build();
41+
}
42+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.example.log4u.domain.comment.dto.request;
2+
3+
import com.example.log4u.domain.comment.entity.Comment;
4+
5+
import jakarta.validation.constraints.Max;
6+
import jakarta.validation.constraints.NotBlank;
7+
import jakarta.validation.constraints.NotNull;
8+
import jakarta.validation.constraints.Size;
9+
10+
public record CommentCreateRequestDto(
11+
12+
@NotNull
13+
Long diaryId,
14+
15+
@NotBlank
16+
@Size(max = 1000)
17+
String content
18+
) {
19+
public Comment toEntity(Long userId) {
20+
return Comment.builder()
21+
.userId(userId)
22+
.diaryId(diaryId)
23+
.content(content)
24+
.build();
25+
}
26+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.example.log4u.domain.comment.dto.response;
2+
3+
import com.example.log4u.domain.comment.entity.Comment;
4+
5+
public record CommentCreateResponseDto(
6+
Long commentId,
7+
String content
8+
) {
9+
public static CommentCreateResponseDto of(Comment comment) {
10+
return new CommentCreateResponseDto(
11+
comment.getCommentId(),
12+
comment.getContent());
13+
}
14+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.example.log4u.domain.comment.entity;
2+
3+
import com.example.log4u.common.entity.BaseEntity;
4+
5+
import jakarta.persistence.Column;
6+
import jakarta.persistence.Entity;
7+
import jakarta.persistence.GeneratedValue;
8+
import jakarta.persistence.GenerationType;
9+
import jakarta.persistence.Id;
10+
import lombok.AccessLevel;
11+
import lombok.AllArgsConstructor;
12+
import lombok.Builder;
13+
import lombok.Getter;
14+
import lombok.NoArgsConstructor;
15+
16+
@Entity
17+
@Getter
18+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
19+
@AllArgsConstructor
20+
@Builder
21+
public class Comment extends BaseEntity {
22+
23+
@Id
24+
@GeneratedValue(strategy = GenerationType.IDENTITY)
25+
private Long commentId;
26+
27+
@Column(nullable = false)
28+
private Long userId;
29+
30+
@Column(nullable = false)
31+
private Long diaryId;
32+
33+
private String content;
34+
}

src/main/java/com/example/log4u/domain/comment/exception/CommentErrorCode.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
@RequiredArgsConstructor
1212
public enum CommentErrorCode implements ErrorCode {
1313

14-
NOT_FOUND_COMMENT(HttpStatus.NOT_FOUND, "댓글을 찾을 수 없습니다.");
14+
NOT_FOUND_COMMENT(HttpStatus.NOT_FOUND, "댓글을 찾을 수 없습니다."),
15+
UNAUTHORIZED_COMMENT_ACCESS(HttpStatus.FORBIDDEN, "댓글에 대한 삭제 권한이 없습니다.");
16+
;
1517

1618
private final HttpStatus httpStatus;
1719
private final String message;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.example.log4u.domain.comment.exception;
2+
3+
public class UnauthorizedAccessException extends CommentException {
4+
public UnauthorizedAccessException() {
5+
super(CommentErrorCode.UNAUTHORIZED_COMMENT_ACCESS);
6+
}
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example.log4u.domain.comment.repository;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
5+
import com.example.log4u.domain.comment.entity.Comment;
6+
7+
public interface CommentRepository extends JpaRepository<Comment, Long> {
8+
9+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.example.log4u.domain.comment.service;
2+
3+
import org.springframework.stereotype.Service;
4+
import org.springframework.transaction.annotation.Transactional;
5+
6+
import com.example.log4u.domain.comment.dto.request.CommentCreateRequestDto;
7+
import com.example.log4u.domain.comment.dto.response.CommentCreateResponseDto;
8+
import com.example.log4u.domain.comment.entity.Comment;
9+
import com.example.log4u.domain.comment.exception.NotFoundCommentException;
10+
import com.example.log4u.domain.comment.exception.UnauthorizedAccessException;
11+
import com.example.log4u.domain.comment.repository.CommentRepository;
12+
import com.example.log4u.domain.diary.service.DiaryService;
13+
14+
import lombok.RequiredArgsConstructor;
15+
16+
@Service
17+
@RequiredArgsConstructor
18+
public class CommentService {
19+
20+
private final CommentRepository commentRepository;
21+
private final DiaryService diaryService;
22+
23+
@Transactional
24+
public CommentCreateResponseDto addComment(Long userId, CommentCreateRequestDto requestDto) {
25+
checkDiaryExists(requestDto);
26+
Comment comment = requestDto.toEntity(userId);
27+
commentRepository.save(comment);
28+
return CommentCreateResponseDto.of(comment);
29+
}
30+
31+
@Transactional
32+
public void deleteComment(Long userId, Long commentId) {
33+
Comment comment = getComment(commentId);
34+
validateCommentOwner(userId, comment);
35+
commentRepository.delete(comment);
36+
}
37+
38+
private void checkDiaryExists(CommentCreateRequestDto requestDto) {
39+
diaryService.checkDiaryExists(requestDto.diaryId());
40+
}
41+
42+
private void validateCommentOwner(Long userId, Comment comment) {
43+
if (!comment.getUserId().equals(userId)) {
44+
throw new UnauthorizedAccessException();
45+
}
46+
}
47+
48+
private Comment getComment(Long commentId) {
49+
return commentRepository.findById(commentId)
50+
.orElseThrow(NotFoundCommentException::new);
51+
}
52+
}

src/main/java/com/example/log4u/domain/comment/testController/TestController.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/com/example/log4u/domain/comment/testDto/TestRequest.java

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)