-
Notifications
You must be signed in to change notification settings - Fork 0
Bug/#66 #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug/#66 #67
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |
| import java.io.IOException; | ||
| import java.nio.charset.StandardCharsets; | ||
| import java.util.List; | ||
| import java.util.UUID; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/assignments") | ||
|
|
@@ -40,12 +41,12 @@ public class AssignmentCommandController { | |
| // 과제 단일 조회 | ||
| @GetMapping("/{assignmentId}") | ||
| public ResponseEntity<AssignmentResponseDto> getAssignment( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long assignmentId | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID assignmentId | ||
| ) { | ||
| AssignmentResponseDto result = assignmentCommandService.findById(assignmentId); | ||
| Assignment assignment = assignmentCommandService.findByIdOrThrow(assignmentId); | ||
| Long classroomId = assignment.getClassRoom().getClassRoomId(); | ||
| UUID classroomId = assignment.getClassRoom().getClassRoomId(); | ||
| if (!classroomUserService.isUserInClassroom(classroomId, userId)) { | ||
| throw new AccessDeniedException("해당 수업실에 속하지 않은 유저입니다."); | ||
| } | ||
|
|
@@ -55,8 +56,8 @@ public ResponseEntity<AssignmentResponseDto> getAssignment( | |
| // 교실 과제 전체 조회 | ||
| @GetMapping("/{classId}/all") | ||
| public ResponseEntity<List<AssignmentResponseDto>> getAllClassroomAssignment( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long classId | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID classId | ||
| ) { | ||
| List<AssignmentResponseDto> result = assignmentCommandService.findAllById(userId,classId); | ||
|
|
||
|
|
@@ -69,23 +70,23 @@ public ResponseEntity<List<AssignmentResponseDto>> getAllClassroomAssignment( | |
|
|
||
| // 메인 페이지 모든 과제 조회 | ||
| @GetMapping("/me") | ||
| public ResponseEntity<List<GetAllAssignmentDto>> getAllAssignments(@CurrentUser Long userId) { | ||
| public ResponseEntity<List<GetAllAssignmentDto>> getAllAssignments(@CurrentUser UUID userId) { | ||
| List<GetAllAssignmentDto> result = assignmentCommandService.findAllAssignmentMe(userId); | ||
| return ResponseEntity.ok(result); | ||
| } | ||
|
|
||
| // 첨부 파일 혹은 링크 전체 조회 (선생, 학생) | ||
| @GetMapping("/{submissionId}/attachment") | ||
| public ResponseEntity<List<SubmissionAttachmentDto>> findAllAssignments(@CurrentUser Long userId, @PathVariable Long submissionId) { | ||
| public ResponseEntity<List<SubmissionAttachmentDto>> findAllAssignments(@CurrentUser UUID userId, @PathVariable UUID submissionId) { | ||
| List<SubmissionAttachmentDto> result = submissionCommandService.findAllAssignment(submissionId); | ||
| return ResponseEntity.ok(result); | ||
| } | ||
|
Comment on lines
78
to
83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제출물 첨부 조회 엔드포인트에 인가 검증이 누락되어 있습니다 현재 사용자 검증 없이 제출물 첨부 목록을 노출합니다. 수업 멤버 또는 적법한 당사자(담당 교사/제출자)만 접근 가능하도록 확인 후 조회하세요. 예시 수정안: @GetMapping("/{submissionId}/attachment")
- public ResponseEntity<List<SubmissionAttachmentDto>> findAllAssignments(@CurrentUser UUID userId, @PathVariable UUID submissionId) {
- List<SubmissionAttachmentDto> result = submissionCommandService.findAllAssignment(submissionId);
+ public ResponseEntity<List<SubmissionAttachmentDto>> findAllAssignments(@CurrentUser UUID userId,
+ @PathVariable UUID submissionId) {
+ var submission = submissionCommandService.findByIdOrThrow(submissionId);
+ UUID classroomId = submission.getAssignment().getClassRoom().getClassRoomId();
+ if (!classroomUserService.isUserInClassroom(classroomId, userId)) {
+ throw new AccessDeniedException("해당 수업실에 속하지 않은 유저입니다.");
+ }
+ List<SubmissionAttachmentDto> result = submissionCommandService.findAllAssignment(submissionId);
return ResponseEntity.ok(result);
}추가 import 필요: import hello.cluebackend.domain.submission.domain.Submission;또한 메서드명 |
||
|
|
||
| // 첨부 파일 다운로드 | ||
| @GetMapping("/{assignmentAttachmentId}/download") | ||
| public ResponseEntity<Resource> assignmentAttachmentDownload( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long assignmentAttachmentId | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID assignmentAttachmentId | ||
| ) throws IOException { | ||
| AssignmentAttachment assignmentAttachment = assignmentCommandService.findAssignmentAttachmentByIdOrderThrow(assignmentAttachmentId); | ||
| Resource resource = assignmentCommandService.downloadAttachment(assignmentAttachment); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
|
|
||
| import java.io.IOException; | ||
| import java.util.List; | ||
| import java.util.UUID; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/assignments") | ||
|
|
@@ -27,8 +28,8 @@ public class AssignmentQueryController { | |
|
|
||
| // 과제 생성 | ||
| @PostMapping | ||
| public ResponseEntity<Long> createAssignment( | ||
| @CurrentUser Long userId, | ||
| public ResponseEntity<UUID> createAssignment( | ||
| @CurrentUser UUID userId, | ||
| @Valid @RequestBody CreateAssignmentDto request | ||
| ) { | ||
| Assignment assignment = assignmentQueryService.save(userId, request); | ||
|
|
@@ -40,29 +41,29 @@ public ResponseEntity<Long> createAssignment( | |
| // 과제 삭제 | ||
| @DeleteMapping("/{assignmentId}") | ||
| public ResponseEntity<?> deleteAssignment( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long assignmentId){ | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID assignmentId){ | ||
| assignmentQueryService.delete(assignmentId); | ||
|
Comment on lines
+44
to
46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain
컨트롤러/서비스/AOP 중 어디서 권한을 검증하는지 확인해주세요. 미검증 시 삭제 권한 취약점이 됩니다. 권한 검증 흔적 점검 스크립트: 🏁 Script executed: #!/bin/bash
# 컨트롤러/서비스의 메서드 보안 적용 여부 점검
rg -nP '@PreAuthorize|@Secured|hasRole|hasAuthority' -C2 src/main/java
# 삭제/수정 서비스 진입점 확인
rg -nP 'delete\s*\(|patchAssignment\s*\(' -C2 src/main/java
# CurrentUser 리졸버와 Security 설정 점검
rg -nP 'CurrentUserArgumentResolver|SecurityConfig|MethodSecurity' -n -C2 src/main/javaLength of output: 9223 삭제 권한 검증 누락: 🤖 Prompt for AI Agents |
||
| return ResponseEntity.ok("과제를 성공적으로 삭제했습니다."); | ||
| } | ||
|
|
||
| // 과제 수정 | ||
| @PatchMapping("/{assignmentId}") | ||
| public ResponseEntity<?> modifyAssignment( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long assignmentId, | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID assignmentId, | ||
| @Valid @RequestBody ModifyAssignmentDto assignmentDto | ||
| ) { | ||
| Long assignment = assignmentQueryService.patchAssignment(assignmentId, assignmentDto); | ||
| UUID assignment = assignmentQueryService.patchAssignment(assignmentId, assignmentDto); | ||
|
|
||
| return ResponseEntity.ok(assignment); | ||
| } | ||
|
|
||
| // 첨부 파일 추가 | ||
| @PostMapping("/{assignmentId}/file") | ||
| public ResponseEntity<?> uploadAttachments( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long assignmentId, | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID assignmentId, | ||
| @RequestParam("files") MultipartFile[] files | ||
| ) throws IOException { | ||
|
|
||
|
|
@@ -76,8 +77,8 @@ public ResponseEntity<?> uploadAttachments( | |
| // 첨부 링크 추가 | ||
| @PostMapping("/{assignmentId}/link") | ||
| public ResponseEntity<?> urlAttachments( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long assignmentId, | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID assignmentId, | ||
| @RequestBody List<AssignmentAttachmentDto> assignmentAttachmentDto | ||
| ){ | ||
| assignmentQueryService.uploadUrlAttachment(assignmentId, assignmentAttachmentDto); | ||
|
|
@@ -87,8 +88,8 @@ public ResponseEntity<?> urlAttachments( | |
| // 첨부파일 혹은 링크 삭제 | ||
| @DeleteMapping("/attachment/{attachmentId}") | ||
| public ResponseEntity<?> deleteAttachment( | ||
| @CurrentUser Long userId, | ||
| @PathVariable Long attachmentId | ||
| @CurrentUser UUID userId, | ||
| @PathVariable UUID attachmentId | ||
| ) { | ||
| assignmentQueryService.deleteAttachment(attachmentId); | ||
| return ResponseEntity.ok("과제를 성공적으로 삭제했습니다."); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,10 +4,11 @@ | |
|
|
||
| import java.time.LocalDateTime; | ||
| import java.util.List; | ||
| import java.util.UUID; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain주의: prod에서 ddl-auto=update 적용 여부 확인 필요 PR 서머리에 따르면 prod 프로필이 validate → update로 바뀐 것으로 보입니다. 운영에서 update는 예상치 못한 스키마 변경/데이터 리스크가 큽니다. 마이그레이션은 Flyway/Liquibase로 관리하고 prod는 validate로 유지하세요. 🏁 Script executed: #!/bin/bash
# prod 프로필에서 ddl-auto 설정 확인
fd -t f 'application-*.yml' | xargs -I{} sh -c "echo '--- {}' && sed -n '1,200p' {} | rg -n 'ddl-auto\s*:\s*(update|create|create-drop)' -n"
fd -t f 'application-*.properties' | xargs -I{} sh -c "echo '--- {}' && rg -n 'spring\.jpa\.hibernate\.ddl-auto\s*=\s*(update|create|create-drop)' {}"Length of output: 329 🏁 Script executed: #!/bin/bash
# 전체 application 설정 파일에서 ddl-auto 설정 검색
rg -n --glob 'application*.yml' 'ddl-auto'
rg -n --glob 'application*.properties' 'spring\.jpa\.hibernate\.ddl-auto'Length of output: 458 prod 프로파일의 ddl-auto를 🤖 Prompt for AI Agents |
||
|
|
||
| @Builder | ||
| public record AssignmentResponseDto( | ||
| Long assignmentId, | ||
| UUID assignmentId, | ||
| String title, | ||
| String content, | ||
| LocalDateTime startDate, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
인가(권한) 검증을 데이터 조회보다 먼저 수행하세요
DTO 조회를 먼저 수행하면 불필요한 DB 접근 및 정보 노출 가능성이 있습니다. 아래처럼 순서를 바꾸세요.
📝 Committable suggestion
🤖 Prompt for AI Agents