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 @@ -127,6 +127,9 @@ public enum SwaggerResponseDescription {
ROOM_PARTICIPANT_NOT_FOUND,
ROOM_HOST_CANNOT_LEAVE
))),
ROOM_REPORT(new LinkedHashSet<>(Set.of(
ROOM_NOT_FOUND
))),


// Record
Expand Down Expand Up @@ -179,6 +182,9 @@ public enum SwaggerResponseDescription {
USER_NOT_FOUND,
ROOM_ACCESS_FORBIDDEN
))),
RECORD_REPORT(new LinkedHashSet<>(Set.of(
RECORD_NOT_FOUND
))),

// Vote
VOTE_CREATE(new LinkedHashSet<>(Set.of(
Expand Down Expand Up @@ -213,6 +219,9 @@ public enum SwaggerResponseDescription {
ROOM_IS_EXPIRED,
ROOM_NOT_IN_PROGRESS
))),
VOTE_REPORT(new LinkedHashSet<>(Set.of(
VOTE_NOT_FOUND
))),


// FEED
Expand Down Expand Up @@ -373,6 +382,10 @@ public enum SwaggerResponseDescription {
ROOM_NOT_IN_PROGRESS
))),

ATTENDANCE_CHECK_REPORT(new LinkedHashSet<>(Set.of(
ATTENDANCE_CHECK_NOT_FOUND
))),

// Notiification
FCM_TOKEN_REGISTER(new LinkedHashSet<>(Set.of(
USER_NOT_FOUND,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class FeedJpaEntity extends PostJpaEntity {
@Column(name = "is_public")
private Boolean isPublic;

@Column(name = "report_count")
@Column(name = "report_count", nullable = false)
private int reportCount = 0;

@ManyToOne(fetch = FetchType.LAZY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
import konkuk.thip.room.adapter.in.web.response.RoomJoinResponse;
import konkuk.thip.room.adapter.in.web.response.RoomPostIsLikeResponse;
import konkuk.thip.room.adapter.in.web.response.RoomRecruitCloseResponse;
import konkuk.thip.room.adapter.in.web.response.RoomReportResponse;
import konkuk.thip.room.application.port.in.RoomCreateUseCase;
import konkuk.thip.room.application.port.in.RoomJoinUseCase;
import konkuk.thip.room.application.port.in.RoomParticipantDeleteUseCase;
import konkuk.thip.room.application.port.in.RoomRecruitCloseUseCase;
import konkuk.thip.room.application.port.in.RoomReportUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

Expand All @@ -34,6 +36,7 @@ public class RoomCommandController {
private final RoomRecruitCloseUseCase roomRecruitCloseUsecase;
private final RoomParticipantDeleteUseCase roomParticipantDeleteUseCase;
private final PostLikeUseCase postLikeUseCase;
private final RoomReportUseCase roomReportUseCase;

/**
* 방 생성 요청
Expand Down Expand Up @@ -113,4 +116,15 @@ public BaseResponse<Void> deleteRoomParticipant(
@Parameter(description = "나갈 방의 ID", example = "1") @PathVariable final Long roomId) {
return BaseResponse.ok(roomParticipantDeleteUseCase.leaveRoom(userId, roomId));
}

@Operation(
summary = "모임방 신고",
description = "사용자가 모임방을 신고합니다. 신고 횟수만 증가하며 별도의 처리는 이루어지지 않습니다."
)
@ExceptionDescription(ROOM_REPORT)
@PostMapping("/rooms/{roomId}/report")
public BaseResponse<RoomReportResponse> reportRoom(
@Parameter(description = "신고하려는 방 ID", example = "1") @PathVariable("roomId") final Long roomId) {
return BaseResponse.ok(RoomReportResponse.of(roomReportUseCase.reportRoom(roomId)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package konkuk.thip.room.adapter.in.web.response;

import konkuk.thip.room.application.port.in.dto.RoomReportResult;

public record RoomReportResponse(
Long roomId,
int reportCount
) {
public static RoomReportResponse of(RoomReportResult roomReportResult) {
return new RoomReportResponse(roomReportResult.roomId(), roomReportResult.reportCount());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ public class RoomJpaEntity extends BaseJpaEntity {
@Column(nullable = false)
private Category category;

@Builder.Default
@Column(name = "report_count", nullable = false)
private int reportCount = 0;

public RoomJpaEntity updateFrom(Room room) {
this.title = room.getTitle();
this.description = room.getDescription();
Expand All @@ -80,6 +84,7 @@ public RoomJpaEntity updateFrom(Room room) {
this.recruitCount = room.getRecruitCount();
this.memberCount = room.getMemberCount();
this.roomStatus = room.getRoomStatus();
this.reportCount = room.getReportCount();
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public Room toDomainEntity(RoomJpaEntity roomJpaEntity) {
.roomStatus(roomJpaEntity.getRoomStatus())
.bookId(roomJpaEntity.getBookJpaEntity().getBookId())
.category(roomJpaEntity.getCategory())
.reportCount(roomJpaEntity.getReportCount())
.createdAt(roomJpaEntity.getCreatedAt())
.modifiedAt(roomJpaEntity.getModifiedAt())
.status(roomJpaEntity.getStatus())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package konkuk.thip.room.application.port.in;

import konkuk.thip.room.application.port.in.dto.RoomReportResult;

public interface RoomReportUseCase {
RoomReportResult reportRoom(Long roomId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package konkuk.thip.room.application.port.in.dto;

public record RoomReportResult(
Long roomId,
int reportCount
) {
public static RoomReportResult of(Long roomId, int reportCount) {
return new RoomReportResult(roomId, reportCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package konkuk.thip.room.application.service;

import konkuk.thip.room.application.port.in.RoomReportUseCase;
import konkuk.thip.room.application.port.in.dto.RoomReportResult;
import konkuk.thip.room.application.port.out.RoomCommandPort;
import konkuk.thip.room.domain.Room;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class RoomReportService implements RoomReportUseCase {

private final RoomCommandPort roomCommandPort;

@Override
@Transactional
public RoomReportResult reportRoom(Long roomId) {
Room room = roomCommandPort.getByIdOrThrow(roomId);
room.increaseReportCount();
roomCommandPort.update(room);

return RoomReportResult.of(room.getId(), room.getReportCount());
}
}
8 changes: 8 additions & 0 deletions src/main/java/konkuk/thip/room/domain/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import konkuk.thip.common.exception.code.ErrorCode;
import konkuk.thip.room.domain.value.Category;
import konkuk.thip.room.domain.value.RoomStatus;
import lombok.Builder;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
Expand Down Expand Up @@ -46,6 +47,9 @@ public class Room extends BaseDomainEntity {

private Category category;

@Builder.Default
private int reportCount = 0;

public static Room withoutId(String title, String description, boolean isPublic, String password, LocalDate startDate, LocalDate endDate, int recruitCount, Long bookId, Category category) {
validateVisibilityPasswordRule(isPublic, password);
validateDates(startDate, endDate);
Expand Down Expand Up @@ -182,4 +186,8 @@ public void validateRoomInProgress() {
}
}

public void increaseReportCount() {
reportCount++;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@ public class RoomPostCommandController {

private final AttendanceCheckCreateUseCase attendanceCheckCreateUseCase;
private final AttendanceCheckDeleteUseCase attendanceCheckDeleteUseCase;
private final AttendanceCheckReportUseCase attendanceCheckReportUseCase;

private final RecordReviewCreateUseCase recordReviewCreateUseCase;

private final RecordReportUseCase recordReportUseCase;
private final VoteReportUseCase voteReportUseCase;

/**
* 기록 관련
*/
Expand Down Expand Up @@ -85,6 +89,18 @@ public BaseResponse<RecordUpdateResponse> updateRecord(
));
}

@Operation(
summary = "기록 신고",
description = "사용자가 기록을 신고합니다. 신고 횟수만 증가하며 별도의 처리는 이루어지지 않습니다."
)
@ExceptionDescription(RECORD_REPORT)
@PostMapping("/rooms/{roomId}/record/{recordId}/report")
public BaseResponse<RecordReportResponse> reportRecord(
@Parameter(description = "신고할 방 ID", example = "1") @PathVariable("roomId") final Long roomId,
@Parameter(description = "신고하려는 기록 ID", example = "1") @PathVariable("recordId") final Long recordId) {
return BaseResponse.ok(RecordReportResponse.of(recordReportUseCase.reportRecord(recordId)));
}
Comment on lines +92 to +102

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

중첩 경로의 roomId 소속을 검증하십시오.

세 엔드포인트는 {roomId}를 받지만 use case에는 하위 리소스 ID만 전달합니다. 따라서 POST /rooms/A/record/B/report에서 기록 B가 방 A에 속하지 않아도 B의 신고 횟수가 증가합니다. 하위 리소스의 방 ID가 경로의 roomId와 다르면 대상 없음 오류를 반환하도록 use case 계약과 서비스를 변경하십시오.

  • src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L92-L102: roomIdrecordId를 함께 use case에 전달하십시오.
  • src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L168-L178: roomIdvoteId를 함께 use case에 전달하십시오.
  • src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L213-L225: roomIdattendanceCheckId를 함께 use case에 전달하십시오.
  • src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java#L106-L118: 다른 방에 속한 기록을 신고하면 404를 반환하고 신고 횟수를 변경하지 않는 테스트를 추가하십시오.
📍 Affects 2 files
  • src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L92-L102 (this comment)
  • src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L168-L178
  • src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L213-L225
  • src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java#L106-L118
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java`
around lines 92 - 102, 중첩 경로의 방 소속 검증이 누락되어 하위 리소스만으로 처리되는 문제를 수정하십시오.
RoomPostCommandController의 92-102행에서는 roomId와 recordId를 함께 recordReportUseCase에
전달하고, 168-178행과 213-225행에서도 각각 roomId와 voteId, roomId와 attendanceCheckId를 함께
전달하도록 관련 use case 계약과 서비스를 변경해 소속이 다르면 대상 없음 오류를 반환하십시오.
src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java
106-118행에는 다른 방의 기록 신고 시 404를 반환하고 신고 횟수가 변경되지 않는 테스트를 추가하십시오.


/**
* 투표 관련
*/
Expand Down Expand Up @@ -149,6 +165,18 @@ public BaseResponse<VoteUpdateResponse> updateVote(
));
}

@Operation(
summary = "투표 신고",
description = "사용자가 투표를 신고합니다. 신고 횟수만 증가하며 별도의 처리는 이루어지지 않습니다."
)
@ExceptionDescription(VOTE_REPORT)
@PostMapping("/rooms/{roomId}/vote/{voteId}/report")
public BaseResponse<VoteReportResponse> reportVote(
@Parameter(description = "신고할 방 ID", example = "1") @PathVariable("roomId") final Long roomId,
@Parameter(description = "신고하려는 투표 ID", example = "1") @PathVariable("voteId") final Long voteId) {
return BaseResponse.ok(VoteReportResponse.of(voteReportUseCase.reportVote(voteId)));
}

/**
* 오늘의 한마디 관련
*/
Expand Down Expand Up @@ -182,6 +210,20 @@ public BaseResponse<AttendanceCheckDeleteResponse> deleteAttendanceCheck(
));
}

@Operation(
summary = "오늘의 한마디 신고",
description = "사용자가 오늘의 한마디를 신고합니다. 신고 횟수만 증가하며 별도의 처리는 이루어지지 않습니다."
)
@ExceptionDescription(ATTENDANCE_CHECK_REPORT)
@PostMapping("/rooms/{roomId}/daily-greeting/{attendanceCheckId}/report")
public BaseResponse<AttendanceCheckReportResponse> reportAttendanceCheck(
@Parameter(description = "신고할 방 ID", example = "1") @PathVariable("roomId") final Long roomId,
@Parameter(description = "신고하려는 오늘의 한마디 ID", example = "1") @PathVariable("attendanceCheckId") final Long attendanceCheckId) {
return BaseResponse.ok(AttendanceCheckReportResponse.of(
attendanceCheckReportUseCase.reportAttendanceCheck(attendanceCheckId)
));
}

@Operation(
summary = "AI 기반 기록 독후감 생성",
description = "AI를 활용하여 사용자가 작성한 기록을 바탕으로 독후감을 생성합니다."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package konkuk.thip.roompost.adapter.in.web.response;

import konkuk.thip.roompost.application.port.in.dto.attendancecheck.AttendanceCheckReportResult;

public record AttendanceCheckReportResponse(
Long attendanceCheckId,
int reportCount
) {
public static AttendanceCheckReportResponse of(AttendanceCheckReportResult attendanceCheckReportResult) {
return new AttendanceCheckReportResponse(attendanceCheckReportResult.attendanceCheckId(), attendanceCheckReportResult.reportCount());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package konkuk.thip.roompost.adapter.in.web.response;

import konkuk.thip.roompost.application.port.in.dto.record.RecordReportResult;

public record RecordReportResponse(
Long recordId,
int reportCount
) {
public static RecordReportResponse of(RecordReportResult recordReportResult) {
return new RecordReportResponse(recordReportResult.recordId(), recordReportResult.reportCount());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package konkuk.thip.roompost.adapter.in.web.response;

import konkuk.thip.roompost.application.port.in.dto.vote.VoteReportResult;

public record VoteReportResponse(
Long voteId,
int reportCount
) {
public static VoteReportResponse of(VoteReportResult voteReportResult) {
return new VoteReportResponse(voteReportResult.voteId(), voteReportResult.reportCount());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import konkuk.thip.common.entity.BaseJpaEntity;
import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity;
import konkuk.thip.roompost.domain.AttendanceCheck;
import konkuk.thip.user.adapter.out.jpa.UserJpaEntity;
import lombok.*;
import org.hibernate.annotations.SQLDelete;
Expand Down Expand Up @@ -32,4 +33,13 @@ public class AttendanceCheckJpaEntity extends BaseJpaEntity {
@JoinColumn(name = "user_id", nullable = false)
private UserJpaEntity userJpaEntity;

@Builder.Default
@Column(name = "report_count", nullable = false)
private int reportCount = 0;

public AttendanceCheckJpaEntity updateFrom(AttendanceCheck attendanceCheck) {
this.reportCount = attendanceCheck.getReportCount();
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ public class RecordJpaEntity extends PostJpaEntity {
@JoinColumn(name = "room_id") // FEED 로 인해 nullable = true로 설정
private RoomJpaEntity roomJpaEntity;

@Column(name = "report_count", nullable = false)
private int reportCount;

@Builder
public RecordJpaEntity(String content, Integer likeCount, Integer commentCount, UserJpaEntity userJpaEntity, Integer page, boolean isOverview, RoomJpaEntity roomJpaEntity) {
public RecordJpaEntity(String content, Integer likeCount, Integer commentCount, UserJpaEntity userJpaEntity, Integer page, boolean isOverview, RoomJpaEntity roomJpaEntity, int reportCount) {
super(content, likeCount, commentCount, userJpaEntity);
this.page = page;
this.isOverview = isOverview;
this.roomJpaEntity = roomJpaEntity;
this.reportCount = reportCount;
}

public RecordJpaEntity updateFrom(Record record) {
Expand All @@ -41,6 +45,7 @@ public RecordJpaEntity updateFrom(Record record) {
this.commentCount = record.getCommentCount();
this.page = record.getPage();
this.isOverview = record.isOverview();
this.reportCount = record.getReportCount();
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ public class VoteJpaEntity extends PostJpaEntity {
@JoinColumn(name = "room_id") // FEED 로 인해 nullable = true로 설정
private RoomJpaEntity roomJpaEntity;

@Column(name = "report_count", nullable = false)
private int reportCount;

@Builder
public VoteJpaEntity(String content, Integer likeCount, Integer commentCount, UserJpaEntity userJpaEntity, Integer page, boolean isOverview, RoomJpaEntity roomJpaEntity) {
public VoteJpaEntity(String content, Integer likeCount, Integer commentCount, UserJpaEntity userJpaEntity, Integer page, boolean isOverview, RoomJpaEntity roomJpaEntity, int reportCount) {
super(content, likeCount, commentCount, userJpaEntity);
this.page = page;
this.isOverview = isOverview;
this.roomJpaEntity = roomJpaEntity;
this.reportCount = reportCount;
}

public VoteJpaEntity updateFrom(Vote vote) {
Expand All @@ -41,6 +45,7 @@ public VoteJpaEntity updateFrom(Vote vote) {
this.commentCount = vote.getCommentCount();
this.page = vote.getPage();
this.isOverview = vote.isOverview();
this.reportCount = vote.getReportCount();
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public AttendanceCheck toDomainEntity(AttendanceCheckJpaEntity attendanceCheckJp
.todayComment(attendanceCheckJpaEntity.getTodayComment())
.roomId(attendanceCheckJpaEntity.getRoomJpaEntity().getRoomId())
.creatorId(attendanceCheckJpaEntity.getUserJpaEntity().getUserId())
.reportCount(attendanceCheckJpaEntity.getReportCount())
.createdAt(attendanceCheckJpaEntity.getCreatedAt())
.modifiedAt(attendanceCheckJpaEntity.getModifiedAt())
.status(attendanceCheckJpaEntity.getStatus())
Expand Down
Loading
Loading