Contest community#740
Conversation
|
@codex review |
There was a problem hiding this comment.
Pull request overview
대회 진행 중 질문을 나눌 수 있는 대회 전용 커뮤니티(게시글/질문) 기능을 추가하고, 게시글 열람 범위(대회 참여자 전체 / 주최자만) 및 주최자 댓글 배지 표시를 지원하도록 프론트/백엔드를 확장한 PR입니다.
Changes:
- Contest 영역에 커뮤니티 페이지/라우트를 추가하고 목록 UI(잠금 표시, 내 질문 필터, 작성 모달)를 구현
- 게시글
visibility필드 추가 및 목록/상세에서 열람 가능 여부(can_view)와 접근 제한 로직 반영 (DB migration 포함) - 게시글 상세에서 대회 운영자(주최자) 댓글/대댓글에 “운영자” 배지 표시
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/pages/oj/views/contest/SideNavBar.vue | 대회 사이드바에 커뮤니티 진입 메뉴 추가 |
| frontend/src/pages/oj/views/contest/index.js | ContestCommunity lazy import/export 추가 |
| frontend/src/pages/oj/views/contest/children/ContestCommunity.vue | 대회 커뮤니티 목록/작성 모달 UI 및 잠금/필터 로직 추가 |
| frontend/src/pages/oj/views/community/PostDetail.vue | 댓글/대댓글에 운영자 배지 UI 추가 |
| frontend/src/pages/oj/views/community/CreatePostPage.vue | 대회 컨텍스트(contestID) 처리 및 작성 후 라우팅 분기 추가 |
| frontend/src/pages/oj/router/routes.js | contest-community / contest-community-create 라우트 추가 |
| frontend/src/pages/admin/views/contest/Contest.vue | (현재) 머지 충돌 마커가 남아 있어 빌드 불가 상태 |
| frontend/src/i18n/oj/en-US.js | Contest 커뮤니티 관련 i18n 키 추가 |
| backend/community/views/oj.py | visibility 저장/기본값 처리, 목록 can_view/is_mine 주석, 상세 열람 제한 추가 |
| backend/community/tests.py | visibility 목록/상세 제한 및 운영자 배지 응답 테스트 추가 |
| backend/community/serializers.py | visibility/is_mine/can_view 및 is_contest_host 필드 직렬화 추가 |
| backend/community/models.py | Post.visibility 필드 및 enum 추가 |
| backend/community/migrations/0004_post_visibility.py | visibility 필드 추가 마이그레이션 |
| backend/account/decorators.py | contest_id 추론(기존 self.contest 재사용) 개선 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1264fe8cbe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if not getattr(self, "contest", None): | ||
| try: | ||
| # use self.contest to avoid query contest again in view. | ||
| self.contest = Contest.objects.select_related("created_by").get(id=contest_id, visible=True) |
There was a problem hiding this comment.
Re-check visibility for preloaded contests
When a view preloads self.contest, this branch skips the only lookup that enforces visible=True. PostDetailAPIView now sets self.contest = post.contest, so posts belonging to a contest later hidden/deleted in admin can still be read by any user who otherwise passes the public/password/status checks; please either validate self.contest.visible here or reload by id with visible=True.
Useful? React with 👍 / 👎.
| if (post.visibility == Post.Visibility.CONTEST_HOSTS and | ||
| post.author != request.user and | ||
| not request.user.is_contest_admin(post.contest)): |
There was a problem hiding this comment.
Enforce host-only access on comment endpoints
This only blocks the post detail response for CONTEST_HOSTS; the /community/posts/<id>/comments endpoints still fetch by post_id without the same visibility check, and the list response exposes locked post ids. A non-host contest participant can therefore call the comments API directly to read or add comments on a host-only question, so the same author/host/super-admin guard should be applied to comment list/create/update/delete.
Useful? React with 👍 / 👎.
| "contest", | ||
| "comment_count", | ||
| "is_mine", | ||
| "can_view", |
There was a problem hiding this comment.
Suppress previews for locked posts
Adding can_view does not prevent the list serializer from still returning content_preview for rows where can_view is false. The UI hides that preview, but any contest participant can inspect the API response and read the first 100 characters of a host-only question despite being denied detail access; the server should blank or omit preview/content fields for non-viewable posts.
Useful? React with 👍 / 👎.
| visiblePosts() { | ||
| if (this.activeTab === "my") { | ||
| return this.posts.filter( | ||
| (post) => post.is_mine && post.post_type === "QUESTION", | ||
| ) |
There was a problem hiding this comment.
Filter my questions before paginating
The “내 질문 보기” tab filters only the current already-paginated page of all contest posts, while fetchPosts and total still come from the unfiltered server query. Once a contest has more than one page, a user's own question on a later page can make this tab show empty on page 1 and pagination counts all posts instead of their questions; request a server-side “mine/question” filter or otherwise paginate the filtered dataset.
Useful? React with 👍 / 👎.
Changelog
대회 내 질문 사항을 나눌 수 있는 대회 내 커뮤니티 기능을 생성하였습니다.
대회 글 작성 시 열람 범위를 선택할 수 있도록 추가했습니다.
제한글은 목록에서 숨기지 않고 회색 톤 카드와 자물쇠 아이콘으로 표시되도록 변경했습니다.
주최자가 답변할 시 주최자임을 사용자 아이디 옆에 표시해두었습니다.
Testing
위와 같이 접근 불가 게시글을 상세히 보려고 시도 시 우측 상단 메세지가 뜹니다.
Ops Impact
DB migration 필요
Version Compatibility
N/A