Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.codeit.todo.common.exception.comment;

import com.codeit.todo.common.exception.EntityNotFoundException;

public class CommentNotFoundException extends EntityNotFoundException {
private static final String ENTITY_TYPE = "comment";

/**
* @param request 엔티티를 찾기 위해 요청한 값
*/
public CommentNotFoundException(String request) {
super(request, ENTITY_TYPE);
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/codeit/todo/domain/Comment.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -28,4 +29,17 @@ public class Comment {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "complete_id", nullable = false)
private Complete complete;

@Builder
public Comment(int commentId, String content, LocalDateTime createdAt, User user, Complete complete) {
this.commentId = commentId;
this.content = content;
this.createdAt = createdAt;
this.user = user;
this.complete = complete;
}

public void update(String content){
this.content = content;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.codeit.todo.repository;


import com.codeit.todo.domain.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CommentRepository extends JpaRepository<Comment, Integer> {

}

15 changes: 15 additions & 0 deletions src/main/java/com/codeit/todo/service/comment/CommentService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.codeit.todo.service.comment;

import com.codeit.todo.web.dto.request.comment.CreateCommentRequest;
import com.codeit.todo.web.dto.request.comment.UpdateCommentRequest;
import com.codeit.todo.web.dto.response.comment.CreateCommentResponse;
import com.codeit.todo.web.dto.response.comment.DeleteCommentResponse;
import com.codeit.todo.web.dto.response.comment.UpdateCommentResponse;

public interface CommentService {
CreateCommentResponse saveComment(int userId, CreateCommentRequest request);

UpdateCommentResponse updateComment(int userId, int commentId, UpdateCommentRequest request);

DeleteCommentResponse deleteComment(int userId, int commentId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.codeit.todo.service.comment.impl;

import com.codeit.todo.common.exception.auth.AuthorizationDeniedException;
import com.codeit.todo.common.exception.comment.CommentNotFoundException;
import com.codeit.todo.common.exception.complete.CompleteNotFoundException;
import com.codeit.todo.domain.Comment;
import com.codeit.todo.domain.Complete;
import com.codeit.todo.domain.User;
import com.codeit.todo.repository.CommentRepository;
import com.codeit.todo.repository.CompleteRepository;
import com.codeit.todo.service.comment.CommentService;
import com.codeit.todo.service.user.UserService;
import com.codeit.todo.service.user.impl.UserServiceImpl;
import com.codeit.todo.web.dto.request.comment.CreateCommentRequest;
import com.codeit.todo.web.dto.request.comment.UpdateCommentRequest;
import com.codeit.todo.web.dto.response.comment.CreateCommentResponse;
import com.codeit.todo.web.dto.response.comment.DeleteCommentResponse;
import com.codeit.todo.web.dto.response.comment.UpdateCommentResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class CommentServiceImpl implements CommentService {

private final UserServiceImpl userServiceImpl;
private final CompleteRepository completeRepository;
private final CommentRepository commentRepository;

@Transactional
@Override
public CreateCommentResponse saveComment(int userId, CreateCommentRequest request) {

User user = userServiceImpl.getUser(userId);
Complete complete = completeRepository.findById(request.completeId())
.orElseThrow(()-> new CompleteNotFoundException(String.valueOf(request.completeId())));

Comment comment = request.toEntity(request.content(), user, complete);
Comment savedComment = commentRepository.save(comment);
return CreateCommentResponse.fromEntity(savedComment);
}

@Transactional
@Override
public UpdateCommentResponse updateComment(int userId, int commentId, UpdateCommentRequest request) {
Comment comment = getComment(userId, commentId);
comment.update(request.content());

return UpdateCommentResponse.fromEntity(comment);
}

@Transactional
@Override
public DeleteCommentResponse deleteComment(int userId, int commentId) {
Comment comment = getComment(userId, commentId);
commentRepository.delete(comment);
return DeleteCommentResponse.from(commentId);
}

private Comment getComment(int userId, int commentId){
Comment comment = commentRepository.findById(commentId)
.orElseThrow(()-> new CommentNotFoundException(String.valueOf(commentId)));

if(comment.getUser().getUserId() != userId){
log.error("댓글 작업 거부됨. 요청 유저 ID : {}", userId);
throw new AuthorizationDeniedException("댓글 작업에 대한 권한이 없습니다.");
}

return comment;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public ReadMyPageResponse findUserInfoAndFollows(int userId) {
return ReadMyPageResponse.from(followerCount, followeeCount);
}

private User getUser(int userId){
public User getUser(int userId){
User user = userRepository.findById(userId)
.orElseThrow(()-> new UserNotFoundException(String.valueOf(userId), "User"));
return user;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.codeit.todo.web.controller;

import com.codeit.todo.repository.CustomUserDetails;
import com.codeit.todo.service.comment.CommentService;
import com.codeit.todo.web.dto.request.comment.CreateCommentRequest;
import com.codeit.todo.web.dto.request.comment.UpdateCommentRequest;
import com.codeit.todo.web.dto.response.Response;
import com.codeit.todo.web.dto.response.comment.CreateCommentResponse;
import com.codeit.todo.web.dto.response.comment.DeleteCommentResponse;
import com.codeit.todo.web.dto.response.comment.UpdateCommentResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/comments")
public class CommentController {

private final CommentService commentService;

@Operation(summary = "댓글 생성", description = "새로운 댓글 생성 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "댓글 생성 성공")
})
@PostMapping
public Response<CreateCommentResponse> createComment(
@AuthenticationPrincipal CustomUserDetails customUserDetails,
@Valid @RequestBody CreateCommentRequest request
){
int userId = customUserDetails.getUserId();
return Response.ok(commentService.saveComment(userId, request));
}

@Operation(summary = "댓글 수정", description = "댓글 내용 수정 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "수정 성공")
})
@PutMapping("{commentId}")
public Response<UpdateCommentResponse> updateComment(
@PathVariable int commentId,
@AuthenticationPrincipal CustomUserDetails customUserDetails,
@Valid @RequestBody UpdateCommentRequest request
){
int userId = customUserDetails.getUserId();
return Response.ok(commentService.updateComment(userId, commentId, request));
}

@Operation(summary = "댓글 삭제", description = "댓글 삭제 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "삭제 성공")
})
@DeleteMapping("{commentId}")
public Response<DeleteCommentResponse> deleteComment(
@PathVariable int commentId,
@AuthenticationPrincipal CustomUserDetails customUserDetails
){
int userId = customUserDetails.getUserId();
return Response.ok(commentService.deleteComment(userId, commentId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.codeit.todo.web.dto.request.comment;

import com.codeit.todo.domain.*;
import jakarta.validation.constraints.NotNull;


import java.time.LocalDateTime;

public record CreateCommentRequest(
int completeId,
@NotNull
String content
) {
public Comment toEntity(String content, User user, Complete complete) {
return Comment.builder()
.content(content)
.createdAt(LocalDateTime.now())
.user(user)
.complete(complete)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.codeit.todo.web.dto.request.comment;

import com.codeit.todo.domain.Comment;
import com.codeit.todo.domain.Complete;
import com.codeit.todo.domain.User;
import jakarta.validation.constraints.NotNull;

import java.time.LocalDateTime;

public record UpdateCommentRequest( @NotNull String content) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.codeit.todo.web.dto.response.comment;

import com.codeit.todo.domain.Comment;
import com.codeit.todo.domain.Goal;
import lombok.Builder;

@Builder
public record CreateCommentResponse(int commentId ) {

public static CreateCommentResponse fromEntity(Comment savedComment) {
return CreateCommentResponse.builder()
.commentId(savedComment.getCommentId())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.codeit.todo.web.dto.response.comment;

import com.codeit.todo.domain.Comment;
import lombok.Builder;

@Builder
public record DeleteCommentResponse(int commentId) {

public static DeleteCommentResponse from(int commentId) {
return DeleteCommentResponse.builder()
.commentId(commentId)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.codeit.todo.web.dto.response.comment;

import com.codeit.todo.domain.Comment;
import lombok.Builder;

@Builder
public record UpdateCommentResponse(int commentId) {

public static UpdateCommentResponse fromEntity(Comment comment) {
return UpdateCommentResponse.builder()
.commentId(comment.getCommentId())
.build();
}

}
Loading