[Fix] 모집 여부 카테고리에 정보, 자유 카테고리 글이 포함되는 오류 수정 #117
Conversation
개요이 PR은 API 엔드포인트에 변경 사항
예상 코드 리뷰 난이도🎯 2 (Simple) | ⏱️ ~12 분 관련 가능성 있는 PR
추천 리뷰어
시 🐰
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/main/java/com/devsong/server/chat/controller/ChatController.java (1)
46-50:⚠️ Potential issue | 🟡 Minor일관성을 위해
@AuthenticationPrincipal사용으로 변경하세요.현재 코드는 다른 컨트롤러(UserController 등)에서 광범위하게 사용 중인
@AuthenticationPrincipal Long userId패턴과 달리 수동으로Long.valueOf(authentication.getName())로 추출합니다. null 체크도 불필요합니다. SecurityConfig에서 해당 엔드포인트는.authenticated()을 요구하므로 인증되지 않은 요청은 컨트롤러에 도달하기 전에 Spring Security에서 거부됩니다.제안 수정안
+import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ `@GetMapping`("/chat/rooms/{roomId}/messages") public List<ChatMessageResponseDto> getMessages( `@PathVariable` Long roomId, - Authentication authentication + `@AuthenticationPrincipal` Long userId ) { - if (authentication == null) { + if (userId == null) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Authentication required"); } - Long me = Long.valueOf(authentication.getName()); - return chatService.getMessages(roomId, me); + return chatService.getMessages(roomId, userId); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/devsong/server/chat/controller/ChatController.java` around lines 46 - 50, Replace the manual Authentication handling in ChatController (the method that currently uses Authentication authentication and Long.valueOf(authentication.getName())) with the `@AuthenticationPrincipal` Long userId parameter; remove the null check and the Long.valueOf conversion, and call chatService.getMessages(roomId, userId) (or pass userId as the "me" value) directly since the endpoint is already protected by .authenticated().src/main/java/com/devsong/server/post/service/PostService.java (1)
125-145:⚠️ Potential issue | 🟠 Major모집 여부 필터에서
category가 명시되면 정보/자유가 다시 포함될 수 있습니다.현재는
category가 비어있을 때만recruitCategories를 강제합니다. 그래서closed와 함께INFO/FREE가 들어오면 기존findAllByCategoryAndClosed...경로로 조회되어 요구사항이 다시 깨질 수 있습니다.closed != null일 때는 명시 카테고리도 모집 카테고리 집합에 포함되는지 검사해 주세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/devsong/server/post/service/PostService.java` around lines 125 - 145, The category-specific branches in PostService incorrectly use findAllByCategoryAndClosed... whenever a category string is provided, allowing INFO/FREE to bypass the recruitCategories filter; update the logic where Category categoryEnum = Category.from(category) is created (both in the closed branch and the open branch) to check if closed != null and recruitCategories.contains(categoryEnum) — if the categoryEnum is NOT in recruitCategories, call the corresponding findAllByCategoryInAndClosed... (or findAllByCategoryInAndClosedOrderByCreatedAtDesc / OrderByLikeCountDesc as per sortByLike) using recruitCategories and closed; otherwise keep the current findAllByCategoryAndClosed... path so explicit categories are only used when they belong to recruitCategories.
🧹 Nitpick comments (3)
src/main/java/com/devsong/server/security/SecurityConfig.java (1)
50-50:setAllowCredentials(true)중복 호출은 제거해도 됩니다.동일 설정이 두 번 호출되고 있어 가독성만 떨어집니다. 한 번만 남기세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/devsong/server/security/SecurityConfig.java` at line 50, SecurityConfig contains a duplicated call to configuration.setAllowCredentials(true); remove the redundant invocation so the method is only called once; locate the duplicate calls to configuration.setAllowCredentials(true) inside the SecurityConfig class (e.g., in any CORS or HttpSecurity configuration methods) and delete the extra occurrence, leaving a single call to preserve behavior and improve readability.src/main/java/com/devsong/server/chat/config/WebSocketConfig.java (1)
29-31: 허용 Origin을 하드코딩하지 말고 설정값으로 분리해 주세요.현재 값은 로컬 환경에는 맞지만, 스테이징/운영 프론트 도메인이 추가되면 WebSocket 연결이 바로 실패할 수 있습니다. 환경변수/프로퍼티 기반 목록으로 분리하는 게 안전합니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/devsong/server/chat/config/WebSocketConfig.java` around lines 29 - 31, The WebSocketConfig currently hardcodes the allowed origin in the call to setAllowedOriginPatterns("http://localhost:5173"); change this to read a configurable list from application properties or environment variables (e.g., via `@Value`("${websocket.allowed-origins}") or a `@ConfigurationProperties` bean), provide a sensible default that includes localhost for dev, parse the property into a String[] or List<String>, and pass that variable into setAllowedOriginPatterns(...) inside the same method that registers the endpoint (the method using setAllowedOriginPatterns and .addInterceptors(jwtHandshakeInterceptor). Ensure the property is documented in application.yml/properties for staging/production use.src/main/java/com/devsong/server/post/service/PostService.java (1)
104-109:recruitCategories는 상수로 올려 재사용하는 편이 좋습니다.요청마다 리스트를 새로 만들기보다
private static final상수로 두면 의도도 더 명확해집니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/devsong/server/post/service/PostService.java` around lines 104 - 109, Extract the local List<Category> recruitCategories into a class-level constant to avoid recreating it per request: declare a private static final List<Category> RECRUIT_CATEGORIES = List.of(Category.PROJECT, Category.STUDY, Category.EXTRA) in the PostService class (or a shared constants holder if preferred) and replace occurrences of the local variable recruitCategories with RECRUIT_CATEGORIES (ensure imports and immutability are preserved).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docker-compose.yml`:
- Around line 10-11: Replace the use of the `root` DB user for the application
by adding MySQL user creation env vars and wiring them into the app config: add
`MYSQL_USER` and `MYSQL_PASSWORD` environment variables (and ensure
`MYSQL_ROOT_PASSWORD` remains set for root), then change
`SPRING_DATASOURCE_USERNAME` from `root` to `MYSQL_USER` and keep
`SPRING_DATASOURCE_PASSWORD` mapped to `MYSQL_PASSWORD`; ensure the MySQL
service/container will create that user (via these env vars) so the app runs
with a least-privilege DB account instead of root.
In `@src/main/java/com/devsong/server/security/SecurityConfig.java`:
- Around line 46-50: The CORS config uses setAllowedOriginPatterns(List.of("*"))
together with setAllowCredentials(true), which violates CORS rules; replace the
wildcard origin pattern with an explicit origin list (e.g., build origins like
"http://localhost:3000" or load allowed origins from an environment/property and
pass that list into setAllowedOrigins or setAllowedOriginPatterns) and remove
the duplicate setAllowCredentials(true) call so setAllowCredentials is only
invoked once; locate these calls on the configuration object
(setAllowedOriginPatterns, setAllowedOrigins, setAllowCredentials) and update
them to use a concrete origin list sourced from config/env and eliminate the
redundant setAllowCredentials invocation.
---
Outside diff comments:
In `@src/main/java/com/devsong/server/chat/controller/ChatController.java`:
- Around line 46-50: Replace the manual Authentication handling in
ChatController (the method that currently uses Authentication authentication and
Long.valueOf(authentication.getName())) with the `@AuthenticationPrincipal` Long
userId parameter; remove the null check and the Long.valueOf conversion, and
call chatService.getMessages(roomId, userId) (or pass userId as the "me" value)
directly since the endpoint is already protected by .authenticated().
In `@src/main/java/com/devsong/server/post/service/PostService.java`:
- Around line 125-145: The category-specific branches in PostService incorrectly
use findAllByCategoryAndClosed... whenever a category string is provided,
allowing INFO/FREE to bypass the recruitCategories filter; update the logic
where Category categoryEnum = Category.from(category) is created (both in the
closed branch and the open branch) to check if closed != null and
recruitCategories.contains(categoryEnum) — if the categoryEnum is NOT in
recruitCategories, call the corresponding findAllByCategoryInAndClosed... (or
findAllByCategoryInAndClosedOrderByCreatedAtDesc / OrderByLikeCountDesc as per
sortByLike) using recruitCategories and closed; otherwise keep the current
findAllByCategoryAndClosed... path so explicit categories are only used when
they belong to recruitCategories.
---
Nitpick comments:
In `@src/main/java/com/devsong/server/chat/config/WebSocketConfig.java`:
- Around line 29-31: The WebSocketConfig currently hardcodes the allowed origin
in the call to setAllowedOriginPatterns("http://localhost:5173"); change this to
read a configurable list from application properties or environment variables
(e.g., via `@Value`("${websocket.allowed-origins}") or a `@ConfigurationProperties`
bean), provide a sensible default that includes localhost for dev, parse the
property into a String[] or List<String>, and pass that variable into
setAllowedOriginPatterns(...) inside the same method that registers the endpoint
(the method using setAllowedOriginPatterns and
.addInterceptors(jwtHandshakeInterceptor). Ensure the property is documented in
application.yml/properties for staging/production use.
In `@src/main/java/com/devsong/server/post/service/PostService.java`:
- Around line 104-109: Extract the local List<Category> recruitCategories into a
class-level constant to avoid recreating it per request: declare a private
static final List<Category> RECRUIT_CATEGORIES = List.of(Category.PROJECT,
Category.STUDY, Category.EXTRA) in the PostService class (or a shared constants
holder if preferred) and replace occurrences of the local variable
recruitCategories with RECRUIT_CATEGORIES (ensure imports and immutability are
preserved).
In `@src/main/java/com/devsong/server/security/SecurityConfig.java`:
- Line 50: SecurityConfig contains a duplicated call to
configuration.setAllowCredentials(true); remove the redundant invocation so the
method is only called once; locate the duplicate calls to
configuration.setAllowCredentials(true) inside the SecurityConfig class (e.g.,
in any CORS or HttpSecurity configuration methods) and delete the extra
occurrence, leaving a single call to preserve behavior and improve readability.
ℹ️ Review info
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
.gitignoreDockerfiledocker-compose.ymlsrc/main/java/com/devsong/server/chat/config/WebSocketConfig.javasrc/main/java/com/devsong/server/chat/controller/ChatController.javasrc/main/java/com/devsong/server/post/controller/PostController.javasrc/main/java/com/devsong/server/post/repository/PostRepository.javasrc/main/java/com/devsong/server/post/service/PostService.javasrc/main/java/com/devsong/server/ranking/controller/RankingController.javasrc/main/java/com/devsong/server/security/SecurityConfig.javasrc/main/java/com/devsong/server/user/controller/UserController.java
| SPRING_DATASOURCE_USERNAME: root | ||
| SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the docker-compose.yml file structure
cat -n docker-compose.yml | head -40Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 1194
🏁 Script executed:
# Search for DB-related environment variables
rg -n 'SPRING_DATASOURCE_USERNAME|MYSQL_ROOT_PASSWORD|MYSQL_USER|MYSQL_PASSWORD|DB_PASSWORD' docker-compose.ymlRepository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 216
🏁 Script executed:
# Look for .env files and SQL initialization scripts
fd -HI '(^\.env(\..*)?$|\.sql$)' | head -20Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 60
🏁 Script executed:
# Search for any DB user/permission initialization patterns
rg -n 'MYSQL_USER|MYSQL_PASSWORD|CREATE USER|GRANT|PRIVILEGES' --type-listRepository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 467
🏁 Script executed:
# Search for any entrypoint scripts or initialization files
fd -HI '(init|entrypoint|setup|schema)' --type f | grep -E '\.(sh|sql|env)$'Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 60
🏁 Script executed:
# Check if there's any documentation about DB setup
fd -HI '(README|SETUP|INSTALL|DATABASE)' --type f | head -10Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 87
🏁 Script executed:
# Look for any scripts or configs in root directory
ls -la | grep -E '\.(sh|sql|env)'Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 60
🏁 Script executed:
# Search entire codebase for CREATE USER or GRANT statements
rg -i 'CREATE USER|GRANT.*PRIVILEGES|mysql_user' --type-list --filesRepository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 465
🏁 Script executed:
# Search entire codebase for any CREATE USER or GRANT patterns
rg 'CREATE USER|GRANT' -iRepository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 60
🏁 Script executed:
# Check README.md for database setup documentation
cat README.md | head -100Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 1617
🏁 Script executed:
# Search for any docker-related init scripts
fd -type f -name '*.sh' -o -name '*.sql'Repository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 248
애플리케이션 DB 접속 계정으로 root를 사용하는 구성은 보안 위험입니다.
최소권한 원칙(least-privilege) 위반으로, 운영 사고 시 영향 범위가 과도하게 커집니다. MySQL 서비스에 MYSQL_USER와 MYSQL_PASSWORD를 추가하여 앱 전용 제한된 권한 계정을 생성하고, SPRING_DATASOURCE_USERNAME도 해당 계정으로 변경해야 합니다.
MYSQL_ROOT_PASSWORD는 보안을 위해 별도로 설정하되, 애플리케이션은 제한된 권한의 전용 계정만 접근하도록 분리하세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docker-compose.yml` around lines 10 - 11, Replace the use of the `root` DB
user for the application by adding MySQL user creation env vars and wiring them
into the app config: add `MYSQL_USER` and `MYSQL_PASSWORD` environment variables
(and ensure `MYSQL_ROOT_PASSWORD` remains set for root), then change
`SPRING_DATASOURCE_USERNAME` from `root` to `MYSQL_USER` and keep
`SPRING_DATASOURCE_PASSWORD` mapped to `MYSQL_PASSWORD`; ensure the MySQL
service/container will create that user (via these env vars) so the app runs
with a least-privilege DB account instead of root.
| configuration.setAllowedOriginPatterns(List.of("*")); | ||
| configuration.setAllowCredentials(true); | ||
| configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); | ||
| configuration.setAllowedHeaders(List.of("*")); | ||
| configuration.setAllowCredentials(true); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Examine the specific file and lines
echo "=== Examining SecurityConfig.java ==="
cat -n src/main/java/com/devsong/server/security/SecurityConfig.java | sed -n '40,55p'
echo -e "\n=== Searching for all CORS-related configurations in the codebase ==="
rg -n --type=java 'setAllowedOriginPatterns|setAllowCredentials|@CrossOrigin|CorsConfiguration' src/main/javaRepository: APPS-sookmyung/2025-DEVSONG-Server
Length of output: 2594
CORS 설정에서 와일드카드와 자격증명을 함께 사용하면 안 됩니다.
setAllowedOriginPatterns(List.of("*"))와 setAllowCredentials(true) 조합은 CORS 표준 위반입니다. 브라우저가 이 설정을 거부합니다. 코드 41-44줄의 주석 처리된 코드처럼 명시적인 Origin 목록(예: "http://localhost:*")으로 제한하거나, 환경 변수로 관리하도록 변경해 주세요. 또한 47번 줄과 50번 줄의 setAllowCredentials(true) 호출이 중복되어 있으니 제거해 주세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/devsong/server/security/SecurityConfig.java` around lines
46 - 50, The CORS config uses setAllowedOriginPatterns(List.of("*")) together
with setAllowCredentials(true), which violates CORS rules; replace the wildcard
origin pattern with an explicit origin list (e.g., build origins like
"http://localhost:3000" or load allowed origins from an environment/property and
pass that list into setAllowedOrigins or setAllowedOriginPatterns) and remove
the duplicate setAllowCredentials(true) call so setAllowCredentials is only
invoked once; locate these calls on the configuration object
(setAllowedOriginPatterns, setAllowedOrigins, setAllowCredentials) and update
them to use a concrete origin list sourced from config/env and eliminate the
redundant setAllowCredentials invocation.
⚙️ Related ISSUE Number
closed #116
📄 Work Description
📷 Screenshot
💬 To Reviewers
🔗 Reference
<!— 문제를 해결하면서 도움이 되었거나, 참고했던 사이트 (코드링크) —>
Summary by CodeRabbit
릴리스 노트
API 변경
보안
배포
리팩터링