-
Notifications
You must be signed in to change notification settings - Fork 3
#601 대회 생성 페이지에 AI 조교 사용 여부 설정 기능 추가 #616
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
base: develop
Are you sure you want to change the base?
Changes from all commits
1a4a299
eabb6c5
cf2564b
bb93622
07257b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Generated by Django 3.2.25 on 2026-04-23 05:36 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('contest', '0002_contest_allow_paste'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AddField( | ||
| model_name='contest', | ||
| name='ai_assistant_enabled', | ||
| field=models.BooleanField(default=True), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,9 +7,10 @@ | |
| from django.http import HttpResponseBadRequest, HttpResponseNotFound, StreamingHttpResponse | ||
| from django.contrib.auth import get_user_model | ||
|
|
||
| from account.decorators import (check_contest_permission, scheduler_only) | ||
| from account.decorators import (check_contest_permission, check_contest_password, scheduler_only) | ||
| from utils.constants import CONTEST_PASSWORD_SESSION_KEY | ||
| from account.models import UserProfile, UserScore | ||
| from contest.models import ContestRuleType | ||
| from contest.models import Contest, ContestRuleType, ContestStatus, ContestType | ||
| from submission.models import JudgeStatus, Submission | ||
| from utils.api import APIView | ||
| from utils.constants import Difficulty, ProblemField, Tier | ||
|
|
@@ -143,13 +144,38 @@ def get(self, request): | |
| return self._error_response("로그인이 필요합니다.", err="permission-denied") | ||
|
|
||
| problem_id = request.GET.get("problem_id") | ||
| contest_id = request.GET.get("contest_id") | ||
| if not problem_id: | ||
| return self._error_response("문제 번호가 필요합니다.") | ||
|
|
||
| try: | ||
| problem = Problem.objects.get(_id=problem_id, contest_id__isnull=True, visible=True) | ||
| except Problem.DoesNotExist: | ||
| return self._error_response("문제를 찾을 수 없습니다.") | ||
| if contest_id: | ||
| try: | ||
| contest = Contest.objects.select_related("created_by").get(id=contest_id, visible=True) | ||
| except Contest.DoesNotExist: | ||
| return self._error_response("대회를 찾을 수 없습니다.", err="permission-denied") | ||
|
|
||
| if not request.user.is_contest_admin(contest): | ||
| if contest.contest_type == ContestType.PASSWORD_PROTECTED_CONTEST: | ||
| if not check_contest_password( | ||
| request.session.get(CONTEST_PASSWORD_SESSION_KEY, {}).get(contest.id), | ||
| contest.password, | ||
| ): | ||
| return self._error_response("비밀번호가 올바르지 않거나 만료되었습니다.", err="permission-denied") | ||
|
|
||
| if contest.status == ContestStatus.CONTEST_NOT_START: | ||
| return self._error_response("아직 시작하지 않은 대회입니다.", err="permission-denied") | ||
|
|
||
| if not contest.ai_assistant_enabled: | ||
| return self._error_response("이 대회에서는 AI 조교를 사용할 수 없습니다.") | ||
| try: | ||
| problem = Problem.objects.get(_id=problem_id, contest_id=contest_id, visible=True) | ||
| except Problem.DoesNotExist: | ||
| return self._error_response("문제를 찾을 수 없습니다.") | ||
|
Comment on lines
+151
to
+173
|
||
| else: | ||
| try: | ||
| problem = Problem.objects.get(_id=problem_id, contest_id__isnull=True, visible=True) | ||
| except Problem.DoesNotExist: | ||
| return self._error_response("문제를 찾을 수 없습니다.") | ||
|
Comment on lines
146
to
+178
|
||
|
|
||
| hint_log = None | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -275,7 +275,7 @@ export const m = { | |
| Allowed_IP_Ranges: "허용된 IP 범위", | ||
| CIDR_Network: "CIDR 네트워크", | ||
| Allow_Paste: "붙여넣기 허용", | ||
| Contest_Visible: "활성화하면 참가자에게 대회가 노출됩니다.", | ||
| AIAssistant_allow: "AI힌트 기능 허용", | ||
|
Comment on lines
275
to
+278
|
||
|
|
||
|
Comment on lines
275
to
279
|
||
| // ContestList.vue | ||
| Contest_List_Page_Title: "대회 목록", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -124,6 +124,7 @@ | |
| ></span> | ||
| </label> | ||
| </div> | ||
|
|
||
| <div class="toggle-item"> | ||
| <span id="allow_paste_label" class="toggle-label"> | ||
| {{ $t("m.Allow_Paste") }} | ||
|
|
@@ -146,6 +147,30 @@ | |
| ></span> | ||
| </label> | ||
| </div> | ||
|
|
||
| <div class="toggle-item"> | ||
| <span id="allow_ai_label" class="toggle-label"> | ||
| {{ $t("m.AIAssistant_allow") }} | ||
| <el-tooltip | ||
| content="대회 진행 중 AI힌트 기능을 허용합니다." | ||
| placement="top" | ||
| > | ||
| <i class="el-icon-question help-icon"></i> | ||
| </el-tooltip> | ||
| </span> | ||
|
Comment on lines
+151
to
+160
|
||
|
|
||
| <label class="spj-toggle"> | ||
| <input | ||
| type="checkbox" | ||
| v-model="contest.ai_assistant_enabled" | ||
| aria-labelledby="allow_ai_label" | ||
| /> | ||
| <span | ||
| class="spj-toggle-track" | ||
| :class="{ 'is-on': contest.ai_assistant_enabled }" | ||
| ></span> | ||
| </label> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
|
|
@@ -216,6 +241,7 @@ export default { | |
| real_time_rank: true, | ||
| visible: true, | ||
| allow_paste: true, | ||
| ai_assistant_enabled: true, | ||
| allowed_ip_ranges: [{ value: "" }], | ||
| }, | ||
| } | ||
|
|
||
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.
contest_id가 주어졌을 때 대회 접근 권한 검증이 빠져 있습니다. 현재 구현은Contest.objects.get(id=contest_id)로 대회를 가져온 뒤ai_assistant_enabled만 확인하므로, 로그인한 사용자가contest_id/problem_id를 추측하기만 하면 비공개(비밀번호) 대회/시작 전 대회/visible=False 대회 및 visible=False 문제에 대해서도 AI 힌트를 요청할 수 있습니다.ContestProblemAPI가 사용하는check_contest_permission(check_type="problems")와 동일한 기준(visible=True, 비밀번호 세션, 시작 전 차단 등)으로 검증하고, 문제 조회도visible=True조건을 포함하도록 수정해 주세요.