Conversation
refactor: 프론트 새 도메인 CORS 설정 추가
Refactor: 프론트 새 도메인 CORS 설정 추가
refactor: 프론트 새 도메인 CORS 설정 추가
refactor: 프론트 새 도메인 CORS 설정 추가
refactor: 프론트 새 도메인 CORS 설정 추가
refactor: 프론트 새 도메인 CORS 설정 추가
refactor: 프론트 새 CORS 설정 추가
[Release] main 서버 배포 (dev → main 병합)
- validateMembership, validateExecutive 메서드를 구현해 일정 관련 api 실행 시 권한 검증 로직을 모듈화 했습니다. - addParticipants 메서드를 구현해 일정 참가자 추가 시 (일정 생성 및 수정) 활용할 수 있도록 했습니다.
- 경로 : POST /api/events
- 경로 : POST /api/events/{eventId}
- 경로 : GET /api/events/monthly?orgId=1&year=2026&&month=2
- 경로 : GET /api/events/upcoming?orgId=1
- 경로 : DELETE /api/events/{eventId}
- 경로 : GET /api/events/{eventId}
Summary of ChangesHello @tishakong, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the application's core architecture by introducing a robust multi-profile and organization management system. This foundational change allows users to operate within different organizational contexts, each with its own specific roles and data. Building upon this, a new calendar event feature has been integrated, enabling streamlined event planning and viewing for organization members. The changes required extensive refactoring across various modules, including board services, controllers, and authentication mechanisms, to ensure a cohesive and context-aware user experience. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a multi-profile system, refactoring user and organization-related logic across the application. Key changes include replacing direct Member entity references with MemberOrg for actions tied to specific organizations, and updating many service and controller methods to accept a Long orgId or ProfileContext instead of a String organization.
New DTOs (ActiveProfile, ProfileContext, MultiProfileDto, SignInResponse) and a ProfileContextResolver with WebConfig are added to support the new multi-profile authentication flow, where users can select a specific organizational profile after login. The TokenProvider is updated to generate tokens with an orgId claim, and CustomUserDetails is simplified by removing organization-specific fields.
Several repositories (FreeMemberJPARepository, QnAMemberRepository, TipMemberRepository) have been simplified by removing findByEmailAndOrganization methods, as MemberOrgRepository now handles organization-specific member lookups. Entity fields like status are consistently renamed to accountStatus across various entities and services. Initializer classes for tags are commented out, and the CommonDataInitializer now sets up a default admin email and a school, removing previous member-specific initializations.
Review comments highlight issues with access control logic in FreePostService where organization ID comparisons were inverted or type-mismatched, and suggest refactoring repetitive userDetails == null checks in controllers using Spring Security annotations or filters for better code organization and maintainability. A potential NullPointerException in ProfileContextResolver when idStr is null is also noted.
| if (post.getOrganization().getId().equals(currProfile.getOrganization().getId()) ) { | ||
| throw new AccessDeniedCustomException(ErrorCode.ACCESS_DENIED_ORGANIZATION); | ||
| } |
There was a problem hiding this comment.
조직 ID가 일치할 경우 접근을 거부하고 있어 로직이 반대로 구현된 것 같습니다. !를 추가하여 조직 ID가 일치하지 않을 때 예외를 던지도록 수정해야 합니다.
| if (post.getOrganization().getId().equals(currProfile.getOrganization().getId()) ) { | |
| throw new AccessDeniedCustomException(ErrorCode.ACCESS_DENIED_ORGANIZATION); | |
| } | |
| if (!post.getOrganization().getId().equals(currProfile.getOrganization().getId())) { | |
| throw new AccessDeniedCustomException(ErrorCode.ACCESS_DENIED_ORGANIZATION); | |
| } |
| if (!post.getOrganization().equals(orgId)) { | ||
| throw new AccessDeniedCustomException(ErrorCode.ACCESS_DENIED_ORGANIZATION); | ||
| } |
There was a problem hiding this comment.
post.getOrganization()은 Organization 객체를 반환하고, orgId는 Long 타입의 프로필 ID이므로 타입이 맞지 않아 비교가 올바르게 동작하지 않습니다. 현재 프로필의 조직 ID와 게시글의 조직 ID를 비교해야 합니다.
| if (!post.getOrganization().equals(orgId)) { | |
| throw new AccessDeniedCustomException(ErrorCode.ACCESS_DENIED_ORGANIZATION); | |
| } | |
| if (!post.getOrganization().getId().equals(member.getOrganization().getId())) { | |
| throw new AccessDeniedCustomException(ErrorCode.ACCESS_DENIED_ORGANIZATION); | |
| } |
| log.warn("멀티 프로필 헤더가 누락되었습니다. ID: {}", idStr); | ||
| throw new IllegalArgumentException("Required 'Active-Profile-Id' header is not present."); |
There was a problem hiding this comment.
idStr이 null일 때 log.warn 문에서 NullPointerException이 발생할 수 있습니다. idStr이 null인 경우를 로깅 메시지에서 안전하게 처리해야 합니다.
| log.warn("멀티 프로필 헤더가 누락되었습니다. ID: {}", idStr); | |
| throw new IllegalArgumentException("Required 'Active-Profile-Id' header is not present."); | |
| log.warn("멀티 프로필 헤더가 누락되었습니다."); | |
| throw new IllegalArgumentException("Required 'Active-Profile-Id' header is not present."); |
| if (!post.getWriter().getId().equals(orgId)) { | ||
| throw new AccessDeniedException("해당 조직의 게시글만 조회할 수 있습니다."); | ||
| } |
There was a problem hiding this comment.
현재 로직은 게시글 작성자의 프로필 ID(post.getWriter().getId())와 현재 사용자의 프로필 ID(orgId)를 비교하고 있습니다. "해당 조직의 게시글만 조회할 수 있습니다"라는 접근 제어 목적에 맞게, 현재 사용자의 조직과 게시글의 조직이 일치하는지 확인하는 로직으로 수정해야 합니다.
MemberOrg currentProfile = memberOrgRepository.findById(orgId)
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 프로필입니다."));
if (!post.getOrganization().getId().equals(currentProfile.getOrganization().getId())) {
throw new AccessDeniedException("해당 조직의 게시글만 조회할 수 있습니다.");
}| public ResponseEntity<?> createEvent( | ||
| @RequestBody EventCreateReqDto reqDto, | ||
| @AuthenticationPrincipal CustomUserDetails userDetails | ||
| ) { | ||
| // TODO 인증 정보가 없습니다 코드 공통 로직 처리 | ||
| if (userDetails == null) { | ||
| return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("인증 정보가 없습니다."); | ||
| } | ||
|
|
||
| Long eventId = eventService.createEvent(reqDto, userDetails.getId()); | ||
|
|
||
| // TODO ResponseEntity 커스텀 공통 양식 추가 | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(eventId); | ||
| } |
There was a problem hiding this comment.
|
캘린더 API 관련한 high priority 없는 거 확인했습니다 ! |
이슈 번호
작업 내용