diff --git a/mo/rights.py b/mo/rights.py index 1bc0b58d0602362d5b64b247209d6e3c309b13a4..0cc4e4e0cb17374b72b136fdbcf43116f1436d30 100644 --- a/mo/rights.py +++ b/mo/rights.py @@ -2,7 +2,7 @@ from enum import Enum, auto from dataclasses import dataclass -from sqlalchemy import or_ +from sqlalchemy import or_, and_ from sqlalchemy.orm.query import Query from typing import Set, List, Dict, Tuple, Optional @@ -321,7 +321,7 @@ class RoundRights(Rights): def can_create_solutions(self) -> bool: return self.can_upload_solutions() or self.can_upload_feedback() - def can_view_statement(self): + def can_view_statement(self, _offer: bool = False) -> bool: round = self.round if round.tasks_file is None: return False @@ -335,16 +335,34 @@ class RoundRights(Rights): if round.state in [db.RoundState.grading, db.RoundState.closed]: return True - # Od stanoveného času vidí zadání orgové s právem view_statement. - if (self.have_right(Right.view_statement) - and round.state != db.RoundState.preparing + # Od stanoveného času vidí zadání orgové s právem view_statement, + # ale pozor na to, že ho mohou mít omezené na soutěžní místo. + if (round.state != db.RoundState.preparing and round.pr_tasks_start is not None and mo.now >= round.pr_tasks_start): - return True + round_rights = self.gatekeeper.rights_for_round(self.round, any_place=True) + if round_rights.have_right(Right.view_statement): + # Teď víme, že org má právo view_statement pro toto kolo na nějakém místě, + # což nám stačí na zobrazení tlačítka. + if _offer: + return True + # Pro skutečné zobrazení zadání ale chceme testovat konkrétní + # soutěžní místa. To může být pomalé, ale zadáni se stahuje zřídka. + place_ids = set(ur.place_id for ur in round_rights.user_roles if Right.view_statement in roles_by_type[ur.role].rights) + if place_ids: + pion = (db.get_session().query(db.Participation) + .join(db.Contest, and_(db.Contest.round == self.round, db.Contest.contest_id == db.Participation.contest_id)) + .filter(db.Participation.place_id.in_(place_ids)) + .one_or_none()) + if pion: + return True # Ve zbylých případech jsme konzervativní a zadání neukazujeme return False + def offer_view_statement(self) -> bool: + return self.can_view_statement(_offer=True) + class ContestRights(RoundRights): """Práva k soutěži.""" diff --git a/mo/web/templates/org_contest.html b/mo/web/templates/org_contest.html index 198997bac804a1f68257c4ef3eacc0446f1472fa..0f2e8c0efebcfc9fe67512612b69a732f366a675 100644 --- a/mo/web/templates/org_contest.html +++ b/mo/web/templates/org_contest.html @@ -6,7 +6,7 @@ {% set can_upload = rights.can_upload_feedback() %} {% set can_edit_points = not site and rights.can_edit_points() %} {% set can_create_solutions = rights.can_upload_feedback() or rights.can_upload_solutions() %} -{% set can_view_statement = rights.can_view_statement() %} +{% set offer_view_statement = rights.offer_view_statement() %} {% set can_view_contestants = rights.have_right(Right.view_contestants) %} {% set can_view_submits = rights.have_right(Right.view_submits) %} @@ -40,7 +40,7 @@ {% endif %} <tr><td>Zadání<td> {% if round.tasks_file %} - {% if can_view_statement %} + {% if offer_view_statement %} <a href='{{ ctx.url_for('org_task_statement', ct_id=None) }}'>stáhnout</a> {% else %} není dostupné diff --git a/mo/web/templates/org_round.html b/mo/web/templates/org_round.html index 055c5759630b3bdd580128e437bfbfb4dbb6c2d8..13c3934eff0c1e65b7cfde135f980db7f4bdcc99 100644 --- a/mo/web/templates/org_round.html +++ b/mo/web/templates/org_round.html @@ -6,7 +6,7 @@ {% set can_view_contestants = rights.have_right(Right.view_contestants) %} {% set can_handle_submits = rights.have_right(Right.view_submits) %} {% set can_upload = rights.can_upload_feedback() %} -{% set can_view_statement = rights.can_view_statement() %} +{% set offer_view_statement = rights.offer_view_statement() %} {% set can_add_contest = g.gatekeeper.rights_generic().have_right(Right.add_contest) %} {% block title %} @@ -63,7 +63,7 @@ {% if round.tasks_file %} {% if not statement_exists %} <span class=error>soubor neexistuje</span> - {% elif can_view_statement %} + {% elif offer_view_statement %} <a href='{{ ctx.url_for('org_task_statement') }}'>stáhnout</a> {% else %} není dostupné