diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py index c1a3836fee73738e599f5d2732f5bea677648109..9f9bd888faf48b019524fd8f5a8c4e8c0391b070 100644 --- a/mo/web/org_contest.py +++ b/mo/web/org_contest.py @@ -451,13 +451,14 @@ class SolutionContext: contest: db.Contest round: db.Round pion: db.Participation - solution: db.Solution + task: db.Task + solution: Optional[db.Solution] allow_view: bool allow_upload_solutions: bool allow_upload_feedback: bool -def get_solution_context(contest_id, user_id, task_id) -> SolutionContext: +def get_solution_context(contest_id: int, site_id: Optional[int], user_id: int, task_id: int) -> SolutionContext: sess = db.get_session() # Nejprve zjistíme, zda existuje soutěž @@ -472,37 +473,36 @@ def get_solution_context(contest_id, user_id, task_id) -> SolutionContext: if not pion: raise werkzeug.exceptions.NotFound() - # Najdeme jeho řešení úlohy - sol = (sess.query(db.Solution) - .filter_by(user_id=user_id, task_id=task_id) - .options(joinedload(db.Solution.task)) - .one_or_none()) - if not sol: + # A zda soutěží na zadaném soutěžním místě, je-li určeno + if site_id is not None and site_id != pion.site_id: raise werkzeug.exceptions.NotFound() - # Zkontrolujeme, že úloha je součástí soutěže - if sol.round != round: + # Najdeme úlohu a ověříme, že je součástí soutěže + task = sess.query(db.Task).get(task_id) + if not task or task.round_id != round: raise werkzeug.exceptions.NotFound() - # Má uživatel práva skrz contest? - rr = Rights(g.user) - rr.get_for_contest(contest) - all_rights = rr.current_rights + # Najdeme řešení úlohy (nemusí existovat) + sol = (sess.query(db.Solution) + .filter_by(user_id=user_id, task_id=task_id) + .one_or_none()) - # Má práva skrz soutěžní místo? - if pion.place != contest.place: - rr.get_for_contest_site(contest, pion.place) - all_rights = all_rights | rr.current_rights + # Pokud je uvedeno soutěžní místo, hledáme práva k němu, jinak k soutěži + if site_id is not None: + site = pion.place + else: + site = contest.place + rr = Rights(g.user) + rr.get_for_contest_site(contest, site) # Kdo má právo na jaké operace - allow_upload_solutions = (Right.manage_contest in all_rights - or (Right.upload_solutions in all_rights and round.state == db.RoundState.running)) - allow_upload_feedback = (Right.manage_contest in all_rights - or (Right.upload_feedback in all_rights and round.state == db.RoundState.grading)) - allow_view = (Right.manage_contest in all_rights - or (Right.upload_solutions in all_rights and round.state != db.RoundState.preparing) - or (Right.upload_feedback in all_rights and round.state in (db.RoundState.preparing, db.RoundState.running, db.RoundState.closed))) - + allow_upload_solutions = (rr.have_right(Right.manage_contest) + or (rr.have_right(Right.upload_solutions) and round.state == db.RoundState.running)) + allow_upload_feedback = (rr.have_right(Right.manage_contest) + or (rr.have_right(Right.upload_feedback) and round.state == db.RoundState.grading)) + allow_view = (rr.have_right(Right.manage_contest) + or (rr.have_right(Right.upload_solutions) and round.state in (db.RoundState.running, db.RoundState.grading, db.RoundState.closed)) + or (rr.have_right(Right.upload_feedback) and round.state in (db.RoundState.grading, db.RoundState.closed))) if not allow_view: raise werkzeug.exceptions.Forbidden() @@ -510,6 +510,7 @@ def get_solution_context(contest_id, user_id, task_id) -> SolutionContext: contest=contest, round=round, pion=pion, + task=task, solution=sol, allow_view=allow_view, allow_upload_solutions=allow_upload_solutions, @@ -519,7 +520,7 @@ def get_solution_context(contest_id, user_id, task_id) -> SolutionContext: @app.route('/org/contest/c/<int:contest_id>/submit/<int:user_id>/<int:task_id>/') def org_submit_list(contest_id, user_id, task_id): - sc = get_solution_context(contest_id, user_id, task_id) + sc = get_solution_context(contest_id, None, user_id, task_id) # FIXME