✨ 지원자 현황 조회에 소속 대학 파라미터 추가 - #626
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
Walkthrough
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/apis/applications/api.ts`:
- Around line 48-57: The comment above getApplicationsList incorrectly describes
homeUniversityId as exclusively derived from the authenticated user and raises a
server authorization concern. Remove or revise that client-side assertion to
match the API contract, and ensure the server-side applications endpoint
validates the token-derived university scope before using homeUniversityId only
as a permitted filter; document the required authorization contract if server
validation is outside this diff.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9a7c033c-c685-4469-bbe0-91daf9d3409c
📒 Files selected for processing (2)
apps/web/src/apis/applications/api.tsapps/web/src/apis/applications/getApplicants.ts
| * | ||
| * homeUniversityId 는 클라이언트가 임의로 정하는 값이 아니라, | ||
| * access token 에서 파싱된 로그인 사용자의 소속 대학(useAuthStore.homeUniversityId)을 그대로 전달한다. | ||
| */ | ||
| getApplicationsList: async (): Promise<AxiosResponse<ApplicationListResponse>> => { | ||
| return axiosInstance.get("/applications"); | ||
| getApplicationsList: async (params?: { | ||
| homeUniversityId?: number | null; | ||
| }): Promise<AxiosResponse<ApplicationListResponse>> => { | ||
| return axiosInstance.get("/applications", { | ||
| params: { homeUniversityId: normalizePositiveInt(params?.homeUniversityId) }, | ||
| }); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 대학 식별자와 애플리케이션 조회의 서버 처리 위치를 찾는다.
rg -n -C 8 'homeUniversityId|home_university|/applications' .Repository: solid-connection/solid-connect-web
Length of output: 50397
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== apps/web/src/apis/applications/api.ts =="
cat -n apps/web/src/apis/applications/api.ts
echo
echo "== token parsing and store =="
cat -n apps/web/src/lib/zustand/useAuthStore.ts | sed -n '1,120p'
echo
echo "== application calls/usages in apps/web =="
rg -n 'getApplicationsList|ApplicationsList|applicationsList|homeUniversityId' apps/web --glob '*.{ts,tsx}'Repository: solid-connection/solid-connect-web
Length of output: 16914
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== GET /applications and competitors fixtures =="
for f in \
packages/bruno-api-typescript/tests/fixtures/bruno-v2/applications/get-applicants.bru-1-meta \
packages/bruno-api-typescript/tests/fixtures/bruno-v2/applications/get-applicants.bru \
packages/bruno-api-typescript/tests/fixtures/bruno-v2/applications/get-competitors.bru \
packages/bruno-api-typescript/tests/fixtures/bruno/applications/get-applicants.bru-1-meta \
packages/bruno-api-typescript/tests/fixtures/bruno/applications/get-applicants.bru \
packages/bruno-api-typescript/tests/fixtures/bruno/applications/get-competitors.bru
do
if [ -f "$f" ]; then
echo "--- $f"
cat -n "$f" | sed -n '1,220p'
fi
done
echo "== API definitions for /applications =="
rg -n -C 12 '"path": "\{\{URL\}\}/applications"|"/applications"|applicants|homeUniversityId' packages/api-schema src apps packages/bruno-api-typescript/tests/fixtures/bruno packages/bruno-api-typescript/tests/fixtures/bruno-v2 | sed -n '1,260p'
echo "== generated schema paths containing applications =="
python3 - <<'PY'
import json, pathlib
for p in pathlib.Path('packages/api-schema').rglob('*.json'):
try:
data=json.loads(p.read_text())
except Exception: continue
k='/applications'
ks='/applications/competitors'
ks2='/applications/applicants'
hits=[]
for path, methods in data.get('paths',{}).items():
if path == k or path == ks or path == ks2:
hits.append((str(p),path,methods))
if hits:
for hit in hits:
print('---',hit[0])
print(hit[1], list(hit[2]))
for m,v in hit[2].items():
print(m,v)
PYRepository: solid-connection/solid-connect-web
Length of output: 22682
1. homeUniversityId가 클라이언트 임의 값임을 문서에 포함하지 마세요.
- `GET /applications`는 현재 accept header와 query params만 명시되어 있어, client가 token에서 읽은 값을 그대로 query string으로 바꿀 수 있습니다.
- `"homeUniversityId 는 클라이언트가 임의로 정하는 값이 아니라"`라는 주석은 서버 계약과 다릅니다.
2. 서버는 token 기반으로 접근 범위를 검증하세요.
- 서버가 `homeUniversityId`를 사용한다면 서버 내부 인증 정보에서 파손되지 않은 값으로 권한 경계를 확인한 후 필터로만 사용하세요.
- request가 단순 필터처럼 보이거나 서버 검증이 보이지 않으면 권한 bypass 위험을 문서화해 서버 쪽 보안 검증 계약과 맞추세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/apis/applications/api.ts` around lines 48 - 57, The comment
above getApplicationsList incorrectly describes homeUniversityId as exclusively
derived from the authenticated user and raises a server authorization concern.
Remove or revise that client-side assertion to match the API contract, and
ensure the server-side applications endpoint validates the token-derived
university scope before using homeUniversityId only as a permitted filter;
document the required authorization contract if server validation is outside
this diff.
요약
GET /applications(지원자 현황) 호출 시homeUniversityId를 쿼리 파라미터로 함께 보냅니다. 대학 검색 API(/univ-apply-infos/search/text)가homeUniversityId를 받는 것과 같은 방식입니다.값의 출처
클라이언트가 임의로 정하는 값이 아니라, access token에서 파싱된 로그인 사용자의 소속 대학을 그대로 보냅니다.
useAuthStore가 이미 JWT의home_university클레임을homeUniversityId로 파싱해 두고 있어(parseAuthToken), 그 값을 그대로 사용했습니다. 별도 파싱 로직을 추가하지 않았습니다.변경 내용
apis/applications/api.ts—getApplicationsList가{ homeUniversityId }를 받아 쿼리 파라미터로 전달.universities/api.ts와 동일한normalizePositiveInt규칙을 적용해 유효한 양의 정수만 내보냅니다(소속 대학이 없으면 파라미터 자체가 빠짐).apis/applications/getApplicants.ts—useAuthStore에서homeUniversityId를 읽어 전달하고,queryKey에도 포함했습니다. 포함하지 않으면 계정 전환 시 다른 소속 대학의 응답이 캐시에서 그대로 재사용됩니다.호출부(
ApplicationUniversityDetailContent,ApprovedApplicationStatusPage) 수정은 필요 없습니다. 훅 내부에서 처리합니다.확인 필요: 서버가 아직 이 파라미터를 받지 않습니다
현재
ApplicationController.getApplicants는region,keyword만@RequestParam으로 선언되어 있습니다.Spring은 선언되지 않은 쿼리 파라미터를 조용히 무시하므로, 이 PR만으로는 응답이 달라지지 않습니다. 서버에서
homeUniversityId를 받아 필터에 반영하는 작업이 함께 배포되어야 실제 범위 제한이 동작합니다.서버 작업이 이미 진행 중이라면 그대로 두시면 되고, 아직이라면 이 PR은 그때까지 무해한 상태로 대기합니다(파라미터만 추가로 전송).
검증
pnpm --filter @solid-connect/web run lint:check— 통과pnpm --filter @solid-connect/web run typecheck— 통과3 → 3,null/undefined/0/-1 → 미전송🤖 Generated with Claude Code