diff --git a/mo/imports.py b/mo/imports.py index 72c7b7b3dc98fdff4878118727dd51225f15254a..7cedac5decae24c86d4af3dbaf16d567b72a802f 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 019b907402a1c5ebe48b257dd9603eaed06a68ae..8bc74947ccb0858dbc50d78a4897c76bb548a091 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 4925de52983b4623069b642da1d8207bc0d6bc4a..ed0b0dccfde0bc57b1dae33486a8eb21607d0662 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 dcb73a6f713c7b2386521b024525a0d7ee0ba0d6..6ca24602703e717c46bddc3298458820bb7db747 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 63c9051133f7b3fe15ce6c9eae04241ddef24790..d6f4f2454e17d777f42534956cba595d8354b482 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 150d77ecb0f50d4af978c31b7e65e4557fa9c949..a91f604c954c09770807f7ffda2af7c238e32862 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 f4ac0297b3e72e73939b74ce80e9676319ac14bf..a0b79284f121092e75ac3b034973828efb11eafa 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 56dc2e9b494bbeb79f825932bde89c7c98d6f397..31ffd6d2b028566f087d063bb2667581097916e0 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: