본문 바로가기

카테고리 없음

댓글

소셜 로그인은 가장 마지막에 하는걸로 하고, 댓글 기능부터 만들기로 했다.

@Entity
@Table(name = "comments")
class Comment(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    @Column(nullable = false)
    var content: String,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id", nullable = false)
    var post: Post,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "admin_id")
    var admin: Admin? = null,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    var user: Users? = null,

    @Column(nullable = false)
    var createdAt: LocalDateTime = LocalDateTime.now()
)

이렇게 유저, 어드민, 게시글과 연결하고

 

interface CommentRepository : JpaRepository<Comment, Long> {
    fun findByPostId(postId: Long): List<Comment>
}

이걸로 댓글 작성시 게시글의 아이디를 찾을수 있게 하고 

interface CommentService {
    fun createComment(postId: Long, commentRequest: CommentRequest, userPrincipal: UserPrincipal): CommentResponse
    fun updateComment(id: Long, commentRequest: CommentRequest, userPrincipal: UserPrincipal): CommentResponse
    fun deleteComment(id: Long, userPrincipal: UserPrincipal)
    fun getCommentsByPostId(postId: Long): List<CommentResponse>
    fun getAllComments(): List<CommentResponse>
    fun getCommentById(id: Long): CommentResponse
}

 

 

이렇게 생성, 삭제, 수정, 조회를 만들고

 

@Service
@Transactional
class CommentServiceImpl(
    private val commentRepository: CommentRepository,
    private val adminRepository: AdminRepository,
    private val userRepository: UserRepository,
    private val postRepository: PostRepository
) : CommentService {

    @Transactional
    override fun createComment(postId: Long, commentRequest: CommentRequest, userPrincipal: UserPrincipal): CommentResponse {
        val userId = userPrincipal.id

        // 각자의 Repository에서 사용자가 존재하는지 확인
        val user = userRepository.findById(userId).orElse(null)
        val admin = adminRepository.findById(userId).orElse(null)

        // 사용자가 존재하지 않으면 예외
        if (user == null && admin == null) {
            throw ModelNotFoundException("User or Admin not found or deleted", userId)
        }

        // Post가 존재하는지 확인
        val post = postRepository.findById(postId).orElseThrow {
            ModelNotFoundException("Post not found or deleted", postId)
        }

        // Comment 객체를 생성하고 저장
        val comment = Comment(
            content = commentRequest.content,
            post = post,
            user = user,
            admin = admin
        )
        val savedComment = commentRepository.save(comment)

        return CommentResponse.toResponse(savedComment)
    }

    @Transactional
    override fun updateComment(id: Long, commentRequest: CommentRequest, userPrincipal: UserPrincipal): CommentResponse {
        val userId = userPrincipal.id

        // 각자의 Repository에서 사용자가 존재하는지 확인
        val user = userRepository.findById(userId).orElse(null)
        val admin = adminRepository.findById(userId).orElse(null)

        // 사용자가 존재하지 않으면 예외
        if (user == null && admin == null) {
            throw ModelNotFoundException("User or Admin not found or deleted", userId)
        }

        val comment = commentRepository.findById(id).orElseThrow {
            ModelNotFoundException("Comment not found or deleted", id)
        }

        // 댓글 작성자 또는 어드민 여부 확인
        if (comment.user?.id != userId && comment.admin?.id != userId) {
            throw IllegalStateException("User does not have permission to update this comment")
        }

        comment.content = commentRequest.content
        comment.updatedAt = LocalDateTime.now()

        val updatedComment = commentRepository.save(comment)

        return CommentResponse.toResponse(updatedComment)
    }

    @Transactional
    override fun deleteComment(id: Long, userPrincipal: UserPrincipal) {
        val userId = userPrincipal.id

        // 각자의 Repository에서 사용자가 존재하는지 확인
        val user = userRepository.findById(userId).orElse(null)
        val admin = adminRepository.findById(userId).orElse(null)

        // 사용자가 존재하지 않으면 예외
        if (user == null && admin == null) {
            throw ModelNotFoundException("User or Admin not found or deleted", userId)
        }

        val comment = commentRepository.findById(id).orElseThrow {
            ModelNotFoundException("Comment not found or deleted", id)
        }

        // 댓글 작성자 또는 어드민 여부 확인
        if (comment.user?.id != userId && comment.admin?.id != userId) {
            throw IllegalStateException("User does not have permission to delete this comment")
        }

        commentRepository.delete(comment)
    }

    override fun getAllComments(): List<CommentResponse> {
        return commentRepository.findAll().map(CommentResponse::toResponse)
    }

    @Transactional
    override fun getCommentById(id: Long): CommentResponse {
        val comment = commentRepository.findById(id).orElseThrow { ModelNotFoundException("Comment not found or deleted", id) }
        return CommentResponse.toResponse(comment)
    }

    @Transactional
    override fun getCommentsByPostId(postId: Long): List<CommentResponse> {
        val comments = commentRepository.findByPostId(postId)
        return comments.map(CommentResponse::toResponse)
    }
}

 

 

이렇게 유저 프린시팔로 유저, 어드민을 각각 감지해서 로그인을 해야 댓글을 생성하고, 글을 작성한 사람만 수정, 삭제를 할수 있게 한다.

 

@RestController
@RequestMapping("/comments")
class CommentController(val commentService: CommentService) {

    @PostMapping("/post/{postId}")
    fun createComment(
        @PathVariable postId: Long,
        @RequestBody commentRequest: CommentRequest,
        @AuthenticationPrincipal userPrincipal: UserPrincipal
    ): ResponseEntity<CommentResponse> {
        val response = commentService.createComment(postId, commentRequest, userPrincipal)
        return ResponseEntity.ok(response)
    }

    @PutMapping("/{id}")
    fun updateComment(
        @PathVariable id: Long,
        @RequestBody commentRequest: CommentRequest,
        @AuthenticationPrincipal userPrincipal: UserPrincipal
    ): ResponseEntity<CommentResponse> {
        val response = commentService.updateComment(id, commentRequest, userPrincipal)
        return ResponseEntity.ok(response)
    }

    @DeleteMapping("/{id}")
    fun deleteComment(
        @PathVariable id: Long,
        @AuthenticationPrincipal userPrincipal: UserPrincipal
    ): ResponseEntity<Void> {
        commentService.deleteComment(id, userPrincipal)
        return ResponseEntity.noContent().build()
    }

    @GetMapping("/post/{postId}")
    fun getCommentsByPostId(@PathVariable postId: Long): ResponseEntity<List<CommentResponse>> {
        val comments = commentService.getCommentsByPostId(postId)
        return ResponseEntity.ok(comments)
    }

    @GetMapping
    fun getAllComments(): ResponseEntity<List<CommentResponse>> {
        val comments = commentService.getAllComments()
        return ResponseEntity.ok(comments)
    }

    @GetMapping("/{id}")
    fun getCommentById(@PathVariable id: Long): ResponseEntity<CommentResponse> {
        val comment = commentService.getCommentById(id)
        return ResponseEntity.ok(comment)
    }
}

 

그리고 이렇게 댓글 생성시에만 포스트 아이디를 입력 하도록 한다.