From d55b49afe66593ba7567669b6267061108a17287 Mon Sep 17 00:00:00 2001
From: Martin Mares <mj@ucw.cz>
Date: Sat, 9 Jan 2021 17:09:47 +0100
Subject: [PATCH] =?UTF-8?q?Opravy=20vyhodnocov=C3=A1n=C3=AD=20pr=C3=A1v=20?=
 =?UTF-8?q?k=20=C5=99e=C5=A1en=C3=ADm?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 mo/web/org_contest.py | 55 ++++++++++++++++++++++---------------------
 1 file changed, 28 insertions(+), 27 deletions(-)

diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py
index c1a3836f..9f9bd888 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
 
-- 
GitLab