Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.stream.Collectors;

Expand All @@ -35,13 +36,13 @@ public Video createVideo(String transcodingStatus, String originalPath, String o

public Video getNewsByUuid(String uuid) {
return videoRepository.findByUuid(uuid)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 비디오입니다."));
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 비디오입니다."));
}

//HeadObjectRequest 고려
public URL generateUploadUrl(String bucket, String objectKey) {
if(!isExist(bucket, objectKey)){
throw new RuntimeException("요청한 파일이 존재하지 않습니다: " + objectKey);
throw new NoSuchElementException("요청한 파일이 존재하지 않습니다: " + objectKey);
}

PutObjectRequest request = PutObjectRequest.builder()
Expand All @@ -64,7 +65,7 @@ public URL generateUploadUrl(String bucket, String objectKey) {

public URL generateDownloadUrl(String bucket, String objectKey) {
if(!isExist(bucket, objectKey)){
throw new RuntimeException("요청한 파일이 존재하지 않습니다: " + objectKey);
throw new NoSuchElementException("요청한 파일이 존재하지 않습니다: " + objectKey);
}

GetObjectRequest request = GetObjectRequest.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import com.back.domain.news.news.service.NewsService;
import com.back.global.rq.Rq;
import com.back.global.rsData.RsData;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand All @@ -25,6 +27,7 @@ public class CommentController {
private final Rq rq;

@GetMapping
@Operation(summary = "댓글 목록 조회", description = "특정 뉴스의 댓글 목록을 불러옵니다.")
public RsData<List<CommentResponse>> getComments(@PathVariable Long newsId) {
News news = newsService.getNewsById(newsId);
List<Comment> comments = commentService.getComments(news);
Expand All @@ -35,6 +38,7 @@ public RsData<List<CommentResponse>> getComments(@PathVariable Long newsId) {
}

@PostMapping
@Operation(summary = "댓글 생성", description = "특정 뉴스에 댓글을 생성합니다. 로그인한 사용자만 접근할 수 있습니다.")
public RsData<CommentResponse> createComment(@PathVariable Long newsId, @RequestBody CommentCreateRequest request) {
Member member = rq.getActor();
if (member == null) {
Expand All @@ -47,25 +51,39 @@ public RsData<CommentResponse> createComment(@PathVariable Long newsId, @Request
}

@PutMapping("/{commentId}")
@Operation(summary = "댓글 수정", description = "특정 뉴스의 댓글을 수정합니다. 댓글 작성자만 접근할 수 있습니다.")
public RsData<CommentResponse> updateComment(@PathVariable Long newsId, @PathVariable Long commentId, @RequestBody CommentUpdateRequest request) {
Member member = rq.getActor();
if (member == null) {
return new RsData<>("401", "로그인이 필요합니다.");
}
News news = newsService.getNewsById(newsId);
Comment updatedComment = commentService.updateComment(member, news, commentId, request.content());
CommentResponse commentResponse = new CommentResponse(updatedComment);
return new RsData<>("200", "댓글 수정 완료", commentResponse);
try {
News news = newsService.getNewsById(newsId);
Comment updatedComment = commentService.updateComment(member, news, commentId, request.content());
CommentResponse commentResponse = new CommentResponse(updatedComment);
return new RsData<>("200", "댓글 수정 완료", commentResponse);
} catch (AccessDeniedException e) {
return new RsData<>("403", e.getMessage());
} catch (IllegalArgumentException e) {
return new RsData<>("400", e.getMessage());
}
}

@DeleteMapping("/{commentId}")
@Operation(summary = "댓글 삭제", description = "특정 뉴스의 댓글을 삭제합니다. 댓글 작성자만 접근할 수 있습니다.")
public RsData<Void> deleteComment(@PathVariable Long newsId, @PathVariable Long commentId) {
Member member = rq.getActor();
if (member == null) {
return new RsData<>("401", "로그인이 필요합니다.");
}
News news = newsService.getNewsById(newsId);
commentService.deleteComment(member, news, commentId);
return new RsData<>("200", "댓글 삭제 완료");
try {
News news = newsService.getNewsById(newsId);
commentService.deleteComment(member, news, commentId);
return new RsData<>("200", "댓글 삭제 완료");
} catch (AccessDeniedException e) {
return new RsData<>("403", e.getMessage());
} catch (IllegalArgumentException e) {
return new RsData<>("400", e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
import com.back.domain.news.comment.repository.CommentRepository;
import com.back.domain.news.news.entity.News;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.NoSuchElementException;

@Service
@RequiredArgsConstructor
Expand All @@ -26,14 +27,16 @@ public List<Comment> getComments(News news) {
return commentRepository.findByNews(news);
}

public Optional<Comment> getCommentById(Long commentId) {
return commentRepository.findById(commentId);
public Comment getCommentById(Long commentId) {
return commentRepository.findById(commentId)
.orElseThrow(() -> new NoSuchElementException("Comment not found: " + commentId));
}

public Comment updateComment(Member member, News news, Long commentId, String content) {
Comment comment = getCommentById(commentId).orElseThrow(() -> new IllegalArgumentException("Comment not found"));
Comment comment = getCommentById(commentId);

if (!comment.getMember().equals(member)) {
throw new IllegalArgumentException("You do not have permission to update this comment.");
throw new AccessDeniedException("You do not have permission to update this comment.");
}
if (!comment.getNews().equals(news)) {
throw new IllegalArgumentException("This comment does not belong to the given news.");
Expand All @@ -43,9 +46,10 @@ public Comment updateComment(Member member, News news, Long commentId, String co
}

public void deleteComment(Member member, News news, Long commentId) {
Comment comment = getCommentById(commentId).orElseThrow(() -> new IllegalArgumentException("Comment not found"));
Comment comment = getCommentById(commentId);

if (!comment.getMember().equals(member)) {
throw new IllegalArgumentException("You do not have permission to delete this comment.");
throw new AccessDeniedException("You do not have permission to delete this comment.");
}
if (!comment.getNews().equals(news)) {
throw new IllegalArgumentException("This comment does not belong to the given news.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.back.domain.news.news.service.NewsService;
import com.back.global.rq.Rq;
import com.back.global.rsData.RsData;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
Expand All @@ -25,22 +26,31 @@ public class NewsController {
private final Rq rq;

@PostMapping
@Operation(summary = "뉴스 생성", description = "뉴스를 생성합니다. ADMIN 사용자만 접근할 수 있습니다.")
public RsData<NewsCreateResponse> createNews(@RequestBody NewsCreateRequest request) {
Member member = rq.getActor();
Member member = rq.getActorFromDb().get();
if (member == null) {
return new RsData<>("401", "로그인 후 이용해주세요.", null);
}
if (member.getRole() != Member.Role.ADMIN) {
return new RsData<>("403", "권한이 없습니다.", null);
}
Video video = videoService.getNewsByUuid(request.videoUuid());
News news = newsService.createNews(member, request.title(), video, request.content());
NewsCreateResponse response = new NewsCreateResponse(news.getTitle(), news.getVideo().getUuid(), news.getContent(), member.getName());
return new RsData<>("201", "뉴스가 생성되었습니다.", response);
}

@GetMapping("{newsId}")
public RsData<NewsGetResponse> getNews(@PathVariable Long newsId) {
@Operation(summary = "뉴스 단건 조회", description = "특정 ID의 뉴스를 읽어옵니다.")
public RsData<NewsGetResponse> getNews(@PathVariable("newsId") Long newsId) {
News news = newsService.getNewsById(newsId);
NewsGetResponse response = new NewsGetResponse(news);
return new RsData<>("200", "뉴스 읽어오기 완료", response);
}

@GetMapping
@Operation(summary = "뉴스 목록 조회", description = "뉴스 목록을 페이지 단위로 불러옵니다. 기본 페이지 크기는 10입니다.")
public RsData<List<NewsGetResponse>> getNewsList(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Expand All @@ -55,8 +65,12 @@ public RsData<List<NewsGetResponse>> getNewsList(
}

@PutMapping("{newsId}/likes")
public RsData<NewsLikeResponse> likeNews(@PathVariable Long newsId) {
Member member = rq.getActor();
@Operation(summary = "뉴스 좋아요", description = "특정 ID의 뉴스를 좋아요 합니다. 로그인한 사용자만 접근할 수 있습니다.")
public RsData<NewsLikeResponse> likeNews(@PathVariable("newsId") Long newsId) {
Member member = rq.getActorFromDb().get();
if (member == null) {
return new RsData<>("401", "로그인 후 이용해주세요.", null);
}
try {
likeService.likeNews(member, newsId);
NewsLikeResponse response = new NewsLikeResponse(member.getId(), newsId, likeService.getLikeCount(newsId));
Expand All @@ -67,10 +81,17 @@ public RsData<NewsLikeResponse> likeNews(@PathVariable Long newsId) {
}

@PutMapping("{newsId}")
public RsData<NewsUpdateResponse> modifyNews(@RequestBody NewsUpdateRequest request) {
Member member = rq.getActor();
@Operation(summary = "뉴스 수정", description = "특정 ID의 뉴스를 수정합니다. ADMIN 사용자만 접근할 수 있습니다.")
public RsData<NewsUpdateResponse> modifyNews(@PathVariable("newsId") Long newsId, @RequestBody NewsUpdateRequest request) {
Member member = rq.getActorFromDb().get();
if (member == null) {
return new RsData<>("401", "로그인 후 이용해주세요.", null);
}
if (member.getRole() != Member.Role.ADMIN) {
return new RsData<>("403", "권한이 없습니다.", null);
}
try {
News news = newsService.getNewsById(request.newsId());
News news = newsService.getNewsById(newsId);
Video video = videoService.getNewsByUuid(request.videoUuid());
News updatedNews = newsService.updateNews(member, news, request.title(), video, request.content());
NewsUpdateResponse response = new NewsUpdateResponse(updatedNews);
Expand All @@ -81,10 +102,17 @@ public RsData<NewsUpdateResponse> modifyNews(@RequestBody NewsUpdateRequest requ
}

@DeleteMapping("{newsId}")
public RsData<?> deleteNews(@PathVariable Long newsId) {
Member member = rq.getActor();
@Operation(summary = "뉴스 삭제", description = "특정 ID의 뉴스를 삭제합니다. ADMIN 사용자만 접근할 수 있습니다.")
public RsData<?> deleteNews(@PathVariable("newsId") Long newsId) {
Member member = rq.getActorFromDb().get();
if (member == null){
return new RsData<>("401", "로그인 후 이용해주세요.", null);
}
if (member.getRole() != Member.Role.ADMIN) {
return new RsData<>("403", "권한이 없습니다.", null);
}
News news = newsService.getNewsById(newsId);
newsService.deleteNews(member, news);
return new RsData<>("200", news.getId()+"번 뉴스가 삭제되었습니다.", null);
return new RsData<>("200", newsId + "번 뉴스가 삭제되었습니다.", null);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.back.domain.news.news.dto;

public record NewsUpdateRequest(
Long newsId,
String title,
String content,
String videoUuid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class News extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne
private Member member;
private String title;
@OneToOne
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.NoSuchElementException;

@Service
@RequiredArgsConstructor
public class NewsService {
Expand All @@ -28,7 +30,7 @@ public Page<News> getNewsByPage(int page, int size) {
}

public News getNewsById(Long id) {
return newsRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("뉴스를 찾을 수 없습니다."));
return newsRepository.findById(id).orElseThrow(() -> new NoSuchElementException("뉴스를 찾을 수 없습니다."));
}

public News updateNews(Member member, News news, String title, Video video, String content) {
Expand Down