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
Expand Up @@ -15,6 +15,7 @@
import com.devkor.ifive.nadab.global.exception.ConflictException;
import com.devkor.ifive.nadab.global.exception.ForbiddenException;
import com.devkor.ifive.nadab.global.exception.NotFoundException;
import com.devkor.ifive.nadab.global.shared.util.TodayDateTimeProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -103,7 +104,7 @@ private void checkNotSuspended(Long userId) {

private void checkCommentWriteAccess(Long dailyReportId, Long reportOwnerId, Long currentUserId) {
if (currentUserId.equals(reportOwnerId)) return;
if (!dailyReportRepository.existsByIdAndIsSharedTrue(dailyReportId)) {
if (!dailyReportRepository.existsByIdAndIsSharedTrueAndDate(dailyReportId, TodayDateTimeProvider.getTodayDate())) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
long smallerId = Math.min(currentUserId, reportOwnerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.devkor.ifive.nadab.global.exception.ConflictException;
import com.devkor.ifive.nadab.global.exception.ForbiddenException;
import com.devkor.ifive.nadab.global.exception.NotFoundException;
import com.devkor.ifive.nadab.global.shared.util.TodayDateTimeProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -187,7 +188,7 @@ private Map<Long, Long> buildSubCountMap(List<Comment> comments, List<Long> excl

private void checkCommentViewAccess(Long dailyReportId, Long reportOwnerId, Long currentUserId) {
if (currentUserId.equals(reportOwnerId)) return;
if (!dailyReportRepository.existsByIdAndIsSharedTrue(dailyReportId)) {
if (!dailyReportRepository.existsByIdAndIsSharedTrueAndDate(dailyReportId, TodayDateTimeProvider.getTodayDate())) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
long smallerId = Math.min(currentUserId, reportOwnerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Optional<DailyReport> findByUserIdAndDate(
@Query("select ae.user.id from DailyReport dr join dr.answerEntry ae where dr.id = :reportId")
Optional<Long> findReportOwnerIdById(@Param("reportId") Long reportId);

boolean existsByIdAndIsSharedTrue(Long id);
boolean existsByIdAndIsSharedTrueAndDate(Long id, LocalDate date);

@Query("""
select new com.devkor.ifive.nadab.domain.dailyreport.core.dto.FeedDto(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.devkor.ifive.nadab.global.exception.ConflictException;
import com.devkor.ifive.nadab.global.exception.ForbiddenException;
import com.devkor.ifive.nadab.global.exception.NotFoundException;
import com.devkor.ifive.nadab.global.shared.util.TodayDateTimeProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -112,7 +113,7 @@ private void checkNotSuspended(Long userId) {
}

private void checkReportLikeAccess(Long dailyReportId, Long reportOwnerId, Long currentUserId) {
if (!dailyReportRepository.existsByIdAndIsSharedTrue(dailyReportId)) {
if (!dailyReportRepository.existsByIdAndIsSharedTrueAndDate(dailyReportId, TodayDateTimeProvider.getTodayDate())) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
long smallerId = Math.min(currentUserId, reportOwnerId);
Expand All @@ -124,7 +125,7 @@ private void checkReportLikeAccess(Long dailyReportId, Long reportOwnerId, Long

private void checkCommentLikeAccess(Long dailyReportId, Long reportOwnerId, Long currentUserId) {
if (currentUserId.equals(reportOwnerId)) return;
if (!dailyReportRepository.existsByIdAndIsSharedTrue(dailyReportId)) {
if (!dailyReportRepository.existsByIdAndIsSharedTrueAndDate(dailyReportId, TodayDateTimeProvider.getTodayDate())) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
long smallerId = Math.min(currentUserId, reportOwnerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.devkor.ifive.nadab.global.exception.ConflictException;
import com.devkor.ifive.nadab.global.exception.ForbiddenException;
import com.devkor.ifive.nadab.global.exception.NotFoundException;
import com.devkor.ifive.nadab.global.shared.util.TodayDateTimeProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -100,7 +101,7 @@ public LikeListResponse getCommentLikers(Long commentId, Long currentUserId) {

private void checkCommentViewAccess(Long dailyReportId, Long reportOwnerId, Long currentUserId) {
if (currentUserId.equals(reportOwnerId)) return;
if (!dailyReportRepository.existsByIdAndIsSharedTrue(dailyReportId)) {
if (!dailyReportRepository.existsByIdAndIsSharedTrueAndDate(dailyReportId, TodayDateTimeProvider.getTodayDate())) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
long smallerId = Math.min(currentUserId, reportOwnerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ public class ModerationController {
content = @Content
),
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
@ApiResponse(
responseCode = "403",
description = """
- ErrorCode: AUTH_ACCESS_DENIED - 신고 권한 없음 (친구가 아니거나, 오늘 공유된 게시글이 아님, 비밀 댓글 열람 권한 없음)
""",
content = @Content
),
@ApiResponse(
responseCode = "404",
description = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.devkor.ifive.nadab.domain.comment.core.repository.CommentRepository;
import com.devkor.ifive.nadab.domain.dailyreport.core.entity.DailyReport;
import com.devkor.ifive.nadab.domain.dailyreport.core.repository.DailyReportRepository;
import com.devkor.ifive.nadab.domain.friend.core.repository.FriendshipRepository;
import com.devkor.ifive.nadab.domain.moderation.core.entity.ContentReport;
import com.devkor.ifive.nadab.domain.moderation.core.entity.ReportReason;
import com.devkor.ifive.nadab.domain.moderation.core.repository.ContentReportRepository;
Expand All @@ -12,7 +13,9 @@
import com.devkor.ifive.nadab.global.core.response.ErrorCode;
import com.devkor.ifive.nadab.global.exception.BadRequestException;
import com.devkor.ifive.nadab.global.exception.ConflictException;
import com.devkor.ifive.nadab.global.exception.ForbiddenException;
import com.devkor.ifive.nadab.global.exception.NotFoundException;
import com.devkor.ifive.nadab.global.shared.util.TodayDateTimeProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
Expand All @@ -27,6 +30,7 @@ public class ContentReportCommandService {
private final DailyReportRepository dailyReportRepository;
private final CommentRepository commentRepository;
private final UserRepository userRepository;
private final FriendshipRepository friendshipRepository;
private final SharingSuspensionService sharingSuspensionService;

public void reportContent(Long reporterId, Long dailyReportId, Long commentId,
Expand Down Expand Up @@ -74,6 +78,10 @@ private ContentReport buildDailyReportReport(User reporter, Long reporterId, Lon
if (reporterId.equals(reportedUser.getId())) {
throw new BadRequestException(ErrorCode.CONTENT_REPORT_SELF_REPORT_FORBIDDEN);
}

// 접근 권한 검증 (오늘 공유된 친구 리포트만 신고 가능, 본인 글은 early return)
checkReportAccess(dailyReportId, reportedUser.getId(), reporterId);

return ContentReport.createForDailyReport(reporter, dailyReport, reportedUser, reason, customReason);
}

Expand All @@ -95,9 +103,40 @@ private ContentReport buildCommentReport(User reporter, Long reporterId, Long co
if (reporterId.equals(reportedUser.getId())) {
throw new BadRequestException(ErrorCode.CONTENT_REPORT_SELF_REPORT_FORBIDDEN);
}

// 게시글 접근 권한 검증 (오늘 공유된 친구 리포트만 신고 가능, 본인 글은 early return)
Long dailyReportId = comment.getDailyReport().getId();
Long reportOwnerId = dailyReportRepository.findReportOwnerIdById(dailyReportId)
.orElseThrow(() -> new NotFoundException(ErrorCode.DAILY_REPORT_NOT_FOUND));
checkReportAccess(dailyReportId, reportOwnerId, reporterId);

// 비밀 댓글은 열람 권한자만 신고 가능 (작성자는 자기 신고 방지로 이미 차단됨)
if (comment.isSecret()) {
boolean isParentAuthor = !comment.isTopLevel() &&
commentRepository.findParentAuthorIdById(commentId)
.map(id -> id.equals(reporterId))
.orElse(false);
boolean canView = reportOwnerId.equals(reporterId) || isParentAuthor;
if (!canView) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
}

return ContentReport.createForComment(reporter, comment, reportedUser, reason, customReason);
}

private void checkReportAccess(Long dailyReportId, Long reportOwnerId, Long reporterId) {
if (reporterId.equals(reportOwnerId)) return;
if (!dailyReportRepository.existsByIdAndIsSharedTrueAndDate(dailyReportId, TodayDateTimeProvider.getTodayDate())) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
long smallerId = Math.min(reporterId, reportOwnerId);
long largerId = Math.max(reporterId, reportOwnerId);
if (!friendshipRepository.existsAcceptedByUserIds(smallerId, largerId)) {
throw new ForbiddenException(ErrorCode.AUTH_ACCESS_DENIED);
}
}

private void validateTarget(Long dailyReportId, Long commentId) {
if (dailyReportId == null && commentId == null) {
throw new BadRequestException(ErrorCode.CONTENT_REPORT_INVALID);
Expand Down
Loading