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 @@ -4,10 +4,7 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import moadong.club.payload.request.ClubApplicantEditRequest;
import moadong.club.payload.request.ClubApplicationCreateRequest;
import moadong.club.payload.request.ClubApplicationEditRequest;
import moadong.club.payload.request.ClubApplyRequest;
import moadong.club.payload.request.*;
import moadong.club.service.ClubApplyService;
import moadong.global.payload.Response;
import moadong.user.annotation.CurrentUser;
Expand Down Expand Up @@ -71,7 +68,7 @@ public ResponseEntity<?> getApplyInfo(@PathVariable String clubId,
}

@PutMapping("/apply/{appId}")
@Operation(summary = "지원서 변경",
@Operation(summary = "지원자의 지원서 정보 변경",
description = "클럽 지원자의 지원서 정보를 수정합니다.<br>"
+ "appId - 지원서 아이디"
)
Expand All @@ -85,17 +82,16 @@ public ResponseEntity<?> editApplicantDetail(@PathVariable String clubId,
return Response.ok("success edit applicant");
}

@DeleteMapping("/apply/{appId}")
@Operation(summary = "지원서 삭제",
description = "클럽 지원자의 지원서를 삭제합니다.<br>"
+ "appId - 지원서 아이디"
@DeleteMapping("/applicant")
@Operation(summary = "지원자 삭제",
description = "클럽 지원자의 지원서를 삭제합니다"
)
@PreAuthorize("isAuthenticated()")
@SecurityRequirement(name = "BearerAuth")
public ResponseEntity<?> removeApplicant(@PathVariable String clubId,
@PathVariable String appId,
@RequestBody @Validated ClubApplicantDeleteRequest request,
@CurrentUser CustomUserDetails user) {
clubApplyService.deleteApplicant(clubId, appId, user);
clubApplyService.deleteApplicant(clubId, request, user);
return Response.ok("success delete applicant");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package moadong.club.payload.request;

import jakarta.validation.constraints.NotEmpty;

import java.util.List;

public record ClubApplicantDeleteRequest(
@NotEmpty
List<String> applicantIds
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ public interface ClubApplicationRepository extends MongoRepository<ClubApplicati
List<ClubApplication> findAllByQuestionId(String questionId);

Optional<ClubApplication> findByIdAndQuestionId(String id, String questionId);

List<ClubApplication> findAllByIdInAndQuestionId(List<String> ids, String clubId);
}
16 changes: 8 additions & 8 deletions backend/src/main/java/moadong/club/service/ClubApplyService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import moadong.club.entity.*;
import moadong.club.enums.ClubApplicationQuestionType;
import moadong.club.payload.dto.ClubApplicantsResult;
import moadong.club.payload.request.ClubApplicantEditRequest;
import moadong.club.payload.request.ClubApplicationCreateRequest;
import moadong.club.payload.request.ClubApplicationEditRequest;
import moadong.club.payload.request.ClubApplyRequest;
import moadong.club.payload.request.*;
import moadong.club.payload.response.ClubApplicationResponse;
import moadong.club.payload.response.ClubApplyInfoResponse;
import moadong.club.repository.ClubApplicationRepository;
Expand Down Expand Up @@ -160,18 +157,21 @@ public void editApplicantDetail(String clubId, String appId, ClubApplicantEditRe
}

@Transactional
public void deleteApplicant(String clubId, String appId, CustomUserDetails user) {
public void deleteApplicant(String clubId, ClubApplicantDeleteRequest request, CustomUserDetails user) {
Club club = clubRepository.findById(clubId)
.orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));

if (!user.getId().equals(club.getUserId())) {
throw new RestApiException(ErrorCode.USER_UNAUTHORIZED);
}

ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId)
.orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND));
List<ClubApplication> applicants = clubApplicationRepository.findAllByIdInAndQuestionId(request.applicantIds(), clubId);

if (applicants.size() != request.applicantIds().size()) {
throw new RestApiException(ErrorCode.APPLICANT_NOT_FOUND);
}

clubApplicationRepository.delete(application);
clubApplicationRepository.deleteAll(applicants);
}
Comment on lines +168 to 175
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

중복 ID 요청 시 오탐 404 발생 — 존재 확인 로직의 크리티컬 버그

applicants.size()request.applicantIds().size()를 직접 비교하면, 요청에 중복 ID가 포함될 때 실제 전부 존재해도 사이즈가 달라져 APPLICANT_NOT_FOUND가 잘못 발생합니다. 중복 제거 후 비교가 필요합니다.

최소 수정안:

-        List<ClubApplication> applicants = clubApplicationRepository.findAllByIdInAndQuestionId(request.applicantIds(), clubId);
-
-        if (applicants.size() != request.applicantIds().size()) {
+        List<String> uniqueIds = request.applicantIds().stream().distinct().toList();
+        List<ClubApplication> applicants = clubApplicationRepository.findAllByIdInAndQuestionId(uniqueIds, clubId);
+
+        if (applicants.size() != uniqueIds.size()) {
             throw new RestApiException(ErrorCode.APPLICANT_NOT_FOUND);
         }
 
         clubApplicationRepository.deleteAll(applicants);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
List<ClubApplication> applicants = clubApplicationRepository.findAllByIdInAndQuestionId(request.applicantIds(), clubId);
if (applicants.size() != request.applicantIds().size()) {
throw new RestApiException(ErrorCode.APPLICANT_NOT_FOUND);
}
clubApplicationRepository.delete(application);
clubApplicationRepository.deleteAll(applicants);
}
// Deduplicate incoming applicant IDs to avoid false negatives when duplicates are present
List<String> uniqueIds = request.applicantIds().stream()
.distinct()
.toList();
List<ClubApplication> applicants = clubApplicationRepository
.findAllByIdInAndQuestionId(uniqueIds, clubId);
if (applicants.size() != uniqueIds.size()) {
throw new RestApiException(ErrorCode.APPLICANT_NOT_FOUND);
}
clubApplicationRepository.deleteAll(applicants);
🤖 Prompt for AI Agents
In backend/src/main/java/moadong/club/service/ClubApplyService.java around lines
168 to 175, the existence check wrongly compares applicants.size() to
request.applicantIds().size(), causing false 404s when the request contains
duplicate IDs; fix by deduplicating the requested IDs before querying and
comparing: compute a collection of distinct applicant IDs (e.g.,
stream().distinct() or a Set), use that distinct collection in the repository
call, and then compare applicants.size() against the distinct collection size
(or validate all distinct IDs were found) before deleting.


private void validateAnswers(List<ClubApplyRequest.Answer> answers, ClubQuestion clubQuestion) {
Expand Down
Loading