From 889f70fac2239808dec734e6acf198ca44338881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Setni=C4=8Dka?= <setnicka@seznam.cz> Date: Thu, 4 Mar 2021 22:30:24 +0100 Subject: [PATCH] =?UTF-8?q?Drobn=C3=A9=20zm=C4=9Bny=20v=20org=20=C4=8D?= =?UTF-8?q?=C3=A1sti=20webu=20souvisej=C3=ADc=C3=AD=20se=20zaveden=C3=AD?= =?UTF-8?q?=20=C4=8D=C3=A1st=C3=AD=20kol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * importy kontrolují práva podle stavu u RoundPart namísto Round * job na upload feedbacku bere stav pro kontrolu práv podle round_part_id dané úlohy * soubory se zadáním jsou určeny kombinací Round + RoundPart --- mo/imports.py | 6 +++--- mo/jobs/submit.py | 8 +++++--- mo/web/org_score.py | 2 +- mo/web/templates/org_contest_solutions.html | 2 +- mo/web/templates/org_submit_list.html | 2 +- mo/web/templates/parts/org_solution_table.html | 2 +- mo/web/user.py | 12 ++++++++---- mo/web/util.py | 6 +++--- 8 files changed, 23 insertions(+), 17 deletions(-) diff --git a/mo/imports.py b/mo/imports.py index 72c7b7b3..7cedac5d 100644 --- a/mo/imports.py +++ b/mo/imports.py @@ -670,7 +670,7 @@ class PointsImport(Import): return self.error('Soutěžící nesoutěží v této oblasti') rights = self.gatekeeper.rights_for_contest(pion.contest) - if not rights.can_edit_points(self.round): + if not rights.can_edit_points(self.task.round_part): return self.error('Nemáte právo na úpravu bodů') user = pion.user @@ -682,7 +682,7 @@ class PointsImport(Import): return if not self.allow_add_del: return self.error('Tento soutěžící úlohu neodevzdal') - if not rights.can_upload_solutions(round): + if not rights.can_upload_solutions(self.task.round_part): return self.error('Nemáte právo na zakládání nových řešení') sol = db.Solution(user_id=user_id, task_id=task_id) sess.add(sol) @@ -698,7 +698,7 @@ class PointsImport(Import): return self.error('Tento soutěžící úlohu odevzdal') if sol.final_submit is not None or sol.final_feedback is not None: return self.error('Nelze smazat řešení, ke kterému existují odevzdané soubory') - if not rights.can_upload_solutions(round): + if not rights.can_upload_solutions(self.task.round_part): return self.error('Nemáte právo na mazání řešení') logger.info(f'Import: Smazáno řešení user=#{user_id} task=#{task_id}') mo.util.log( diff --git a/mo/jobs/submit.py b/mo/jobs/submit.py index 019b9074..8bc74947 100644 --- a/mo/jobs/submit.py +++ b/mo/jobs/submit.py @@ -227,7 +227,9 @@ def handle_upload_feedback(the_job: TheJob): contest_dict[user.user_id] = contest site_id_dict[user.user_id] = pion.place_id rr = the_job.gatekeeper.rights_for_contest(contest) - user_rights[user.user_id] = rr.can_upload_feedback(round) + user_rights[user.user_id] = { + part.round_part_id: rr.can_upload_feedback(part) for part in round.parts + } for f in files: f.user = user_dict[f.user_id] @@ -237,8 +239,8 @@ def handle_upload_feedback(the_job: TheJob): the_job.error(f'{f.file_name}: Účastník leží mimo vybranou soutěž') elif only_site_id is not None and site_id_dict[f.user_id] != only_site_id: the_job.error(f'{f.file_name}: Účastník leží mimo vybrané soutěžní místo') - elif not user_rights[f.user_id]: - the_job.error(f'{f.file_name}: K tomuto účastníkovi nemáte dostatečná oprávnění') + elif not user_rights[f.user_id][f.task.round_part_id]: + the_job.error(f'{f.file_name}: K tomuto účastníkovi a úloze nemáte dostatečná oprávnění') def process_file(fb: UploadFeedback) -> bool: assert fb.user and fb.task diff --git a/mo/web/org_score.py b/mo/web/org_score.py index 4925de52..ed0b0dcc 100644 --- a/mo/web/org_score.py +++ b/mo/web/org_score.py @@ -127,7 +127,7 @@ def org_score(round_id: Optional[int] = None, contest_id: Optional[int] = None): url_for('org_contest_task', contest_id=contest_id, task_id=task.task_id), task.code ) - if rr.can_edit_points(round): + if rr.can_edit_points(task.round_part): title += ' <a href="{}" title="Editovat body" class="icon">✎</a>'.format( url_for('org_contest_task_points', contest_id=contest_id, task_id=task.task_id), ) diff --git a/mo/web/templates/org_contest_solutions.html b/mo/web/templates/org_contest_solutions.html index dcb73a6f..6ca24602 100644 --- a/mo/web/templates/org_contest_solutions.html +++ b/mo/web/templates/org_contest_solutions.html @@ -69,7 +69,7 @@ konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje {% set sol = tasks_sols[task.task_id][u.user_id] %} {% if sol.final_submit_obj %} {% set p = sol.final_submit_obj %} - {% set late = p.check_deadline(round) %} + {% set late = p.check_deadline(task.round_part) %} <td class="sol{% if late or p.broken %} sol-warn{% endif %}"> <a href="{{ paper_link(u, p) }}" title="{{ p.uploaded_at|timeformat }}{% if p.broken %} - nekorektní PDF{% endif %}{% if p.pages != None %} - {{ p.pages|inflected('stránka', 'stránky', 'stránek') }}{% endif %}{% if late %} - {{ late }}{% endif %}">🖺</a> {% set key = (u.user_id, task.task_id, "solution") %} diff --git a/mo/web/templates/org_submit_list.html b/mo/web/templates/org_submit_list.html index 63c90511..d6f4f245 100644 --- a/mo/web/templates/org_submit_list.html +++ b/mo/web/templates/org_submit_list.html @@ -61,7 +61,7 @@ Existuje více než jedna verze řešení, finální je podbarvená. {% set active_sol_id = None %} {% endif %} {% for p in sol_papers %} - {% set late = p.check_deadline(sc.round) %} + {% set late = p.check_deadline(sc.task.round_part) %} <tr{% if p.paper_id == active_sol_id %} class='sol-active'{% endif %}> <td{% if late %} class='sol-warn'{% endif %}>{{ p.uploaded_at|timeformat }} <td>{% if p.broken %}nekorektní PDF{% else %}{{ p.pages|or_dash }}{% endif %} diff --git a/mo/web/templates/parts/org_solution_table.html b/mo/web/templates/parts/org_solution_table.html index 150d77ec..a91f604c 100644 --- a/mo/web/templates/parts/org_solution_table.html +++ b/mo/web/templates/parts/org_solution_table.html @@ -47,7 +47,7 @@ finální (ve výchozím stavu poslední nahrané).{% elif sc.allow_upload_solut {% if sol %} <td>{% if sol.final_submit_obj %} {% set p = sol.final_submit_obj %} - {% set late = p.check_deadline(round) %} + {% set late = p.check_deadline(task.round_part) %} {% if late %}<span class='sol-warn icon' title="{{ late }}">⚠</span>{% endif %} <a href='{{ paper_link(u, p) }}'> {{- p.uploaded_at|timeformat }} diff --git a/mo/web/user.py b/mo/web/user.py index f4ac0297..a0b79284 100644 --- a/mo/web/user.py +++ b/mo/web/user.py @@ -85,15 +85,19 @@ def user_contest(id: int): ) -@app.route('/user/contest/<int:id>/task-statement/zadani.pdf') -def user_task_statement(id: int): +@app.route('/user/contest/<int:id>/part/<int:part_id>/task-statement/zadani.pdf') +def user_task_statement(id: int, part_id: int): contest = get_contest(id) - if not contest.round.task_statement_available(): + round_part = db.get_session().query(db.RoundPart).get(part_id) + if not round_part or round_part.round_id != contest.round_id: + raise werkzeug.exceptions.NotFound() + + if not round_part.task_statement_available(): logger.warn(f'Účastník #{g.user.user_id} chce zadání, na které nemá právo') raise werkzeug.exceptions.Forbidden() - return mo.web.util.send_task_statement(contest.round) + return mo.web.util.send_task_statement(round_part) class SubmitForm(FlaskForm): diff --git a/mo/web/util.py b/mo/web/util.py index 56dc2e9b..31ffd6d2 100644 --- a/mo/web/util.py +++ b/mo/web/util.py @@ -40,9 +40,9 @@ class PagerForm(FlaskForm): return (count, query) -def send_task_statement(round: db.Round) -> Response: - assert round.tasks_file is not None - file = os.path.join(mo.util.data_dir('statements'), round.tasks_file) +def send_task_statement(round_part: db.RoundPart) -> Response: + assert round_part.tasks_file is not None + file = os.path.join(mo.util.data_dir('statements'), round_part.tasks_file) if os.path.isfile(file): return send_file(file, mimetype='application/pdf') else: -- GitLab