-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 어드민 일정 관리 API 추가 #139
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
Conversation
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.
Pull request overview
이 PR은 어드민 사용자가 자신이 속한 대학교의 일정을 관리할 수 있는 API를 추가하고, 역할 기반 접근 제어를 위한 @Auth 어노테이션을 도입합니다.
Changes:
@Auth어노테이션과AuthorizationInterceptor를 추가하여 역할 기반 접근 제어 기능 구현- 어드민 일정 관리 API 추가: 일정 생성, 일괄 생성/수정, 삭제 기능
- Swagger 설정에 Public API와 Admin API 그룹 분리 추가
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
WebConfig.java |
AuthorizationInterceptor를 인터셉터 체인에 추가하여 역할 기반 인증 활성화 |
SwaggerConfig.java |
Admin API와 Public API를 분리한 Swagger 그룹 추가 |
ApiResponseCode.java |
역할 접근 권한 에러와 일정 미존재 에러 코드 추가 |
LoginCheckInterceptor.java |
인증된 사용자 ID와 공개 엔드포인트 정보를 request attribute로 저장 |
AuthorizationInterceptor.java |
@Auth 어노테이션 기반 역할 검증 인터셉터 구현 |
Auth.java |
메서드 레벨 역할 기반 접근 제어를 위한 새 어노테이션 |
UniversityScheduleRepository.java |
대학교와 일정 ID로 일정 조회 기능 추가 |
ScheduleRepository.java |
일정 저장 및 삭제 메서드 추가 |
UniversitySchedule.java |
정적 팩토리 메서드 of() 추가 |
Schedule.java |
일정 생성을 위한 of() 메서드와 수정을 위한 update() 메서드 추가 |
AdminScheduleService.java |
어드민 일정 생성, 일괄 생성/수정, 삭제 비즈니스 로직 구현 |
AdminScheduleUpsertRequest.java |
일괄 일정 생성/수정 요청 DTO |
AdminScheduleUpsertItemRequest.java |
개별 일정 생성/수정 항목 DTO |
AdminScheduleCreateRequest.java |
일정 생성 요청 DTO |
AdminScheduleController.java |
어드민 일정 API 컨트롤러 구현 |
AdminScheduleApi.java |
어드민 일정 API 인터페이스 정의 및 Swagger 문서화 |
src/main/java/gg/agit/konect/admin/schedule/dto/AdminScheduleUpsertRequest.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/admin/schedule/dto/AdminScheduleUpsertItemRequest.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/admin/schedule/dto/AdminScheduleCreateRequest.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/admin/schedule/service/AdminScheduleService.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/admin/schedule/service/AdminScheduleService.java
Show resolved
Hide resolved
src/main/java/gg/agit/konect/admin/schedule/controller/AdminScheduleController.java
Outdated
Show resolved
Hide resolved
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.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.
| universityScheduleRepository.delete(universitySchedule); | ||
| scheduleRepository.delete(universitySchedule.getSchedule()); |
Copilot
AI
Jan 23, 2026
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.
일정을 삭제할 때 UniversitySchedule만 삭제하고 Schedule도 함께 삭제하고 있습니다. 그러나 Schedule은 다른 타입(CLUB, COUNCIL, DORM)의 일정과도 연결될 수 있는데, 현재 구조에서는 UniversitySchedule이 삭제되면 Schedule도 무조건 삭제됩니다. 만약 하나의 Schedule이 여러 엔티티(예: ClubSchedule, CouncilSchedule 등)와 연결될 수 있다면, 다른 곳에서 참조하고 있는 Schedule을 삭제하여 데이터 무결성 문제가 발생할 수 있습니다. Schedule과 UniversitySchedule의 관계가 1:1이 확실하다면 문제없지만, 아키텍처를 확인해야 합니다.
src/main/java/gg/agit/konect/admin/schedule/service/AdminScheduleService.java
Show resolved
Hide resolved
| Object userId = request.getAttribute(LoginCheckInterceptor.AUTHENTICATED_USER_ID_ATTRIBUTE); | ||
|
|
||
| if (!(userId instanceof Integer id)) { | ||
| throw CustomException.of(ApiResponseCode.INVALID_SESSION); |
Copilot
AI
Jan 23, 2026
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.
AuthorizationInterceptor에서 사용자 ID가 Integer가 아닌 경우 INVALID_SESSION 에러를 반환하고 있습니다. 그러나 이 시점에서는 이미 LoginCheckInterceptor를 통과한 상태이므로, userId는 항상 Integer여야 합니다. 만약 userId가 Integer가 아니라면 이는 시스템 내부 오류이므로, INVALID_SESSION보다는 내부 서버 오류를 나타내는 더 적절한 에러 코드를 사용하거나 IllegalStateException을 던지는 것이 더 적절합니다.
| throw CustomException.of(ApiResponseCode.INVALID_SESSION); | |
| throw new IllegalStateException("Authenticated user id is not an Integer: " + userId); |
src/main/java/gg/agit/konect/admin/schedule/service/AdminScheduleService.java
Show resolved
Hide resolved
| @Auth(roles = {UserRole.ADMIN}) | ||
| ResponseEntity<Void> createSchedule( | ||
| @Valid @RequestBody AdminScheduleCreateRequest request, | ||
| @UserId Integer userId | ||
| ); | ||
|
|
||
| @Operation(summary = "일정을 일괄 생성/수정한다.", description = """ | ||
| scheduleId가 없으면 신규 생성, 있으면 해당 일정 수정입니다. | ||
| **scheduleType (일정 구분):** | ||
| - `UNIVERSITY`: 대학교 일정 | ||
| - `CLUB`: 동아리 일정 | ||
| - `COUNCIL`: 총동아리연합회 일정 | ||
| - `DORM`: 기숙사 일정 | ||
| """) | ||
| @PutMapping("/batch") | ||
| @Auth(roles = {UserRole.ADMIN}) | ||
| ResponseEntity<Void> upsertSchedules( | ||
| @Valid @RequestBody AdminScheduleUpsertRequest request, | ||
| @UserId Integer userId | ||
| ); | ||
|
|
||
| @Operation(summary = "일정을 삭제한다.") | ||
| @DeleteMapping("/{scheduleId}") | ||
| @Auth(roles = {UserRole.ADMIN}) |
Copilot
AI
Jan 23, 2026
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.
모든 메서드에 동일한 @Auth(roles = {UserRole.ADMIN}) 어노테이션이 반복되고 있습니다. DRY(Don't Repeat Yourself) 원칙에 따라 인터페이스 레벨에 @Auth 어노테이션을 한 번만 적용하는 것을 고려해보세요. AuthorizationInterceptor는 이미 클래스 레벨 어노테이션을 지원하도록 구현되어 있습니다(line 61: handlerMethod.getBeanType().getAnnotation(Auth.class)).
🔍 개요
🚀 주요 변경 내용
@Auth어노테이션을 추가하여 API의 접근 권한을 제한할 수 있습니다.어드민 기능으로 일정 관리 API를 추가했습니다.
POST /admin/schedules를 통해 새로운 일정을 추가 합니다.PUT /admin/schedules/batch를 통해 일괄적으로 일정을 추가/수정 합니다.DELETE /admin/schedules/{scheduleId}를 통해 일정을 삭제 합니다.💬 참고 사항
✅ Checklist (완료 조건)