Skip to content
Snippets Groups Projects
Commit 35314b1a authored by Martin Mareš's avatar Martin Mareš
Browse files

Zárodek org_submit_list() a košatá kontrola práv

parent 0f9b4979
No related branches found
No related tags found
1 merge request!9WIP: Zárodek uživatelské části webu a submitování
...@@ -13,8 +13,8 @@ class Right(Enum): ...@@ -13,8 +13,8 @@ class Right(Enum):
edit_place = auto() edit_place = auto()
manage_round = auto() manage_round = auto()
manage_contest = auto() manage_contest = auto()
upload_solutions = auto() upload_solutions = auto() # Odevzdávat za účastníka ve stavu "running"
upload_feedback = auto() upload_feedback = auto() # Nahrávat opravené řešení ve stavu "grading"
edit_points = auto() edit_points = auto()
add_users = auto() add_users = auto()
edit_users = auto() edit_users = auto()
...@@ -160,6 +160,9 @@ class Rights: ...@@ -160,6 +160,9 @@ class Rights:
def get_for_contest(self, contest: db.Contest): def get_for_contest(self, contest: db.Contest):
return self.get_for(place=contest.place, year=contest.round.year, cat=contest.round.category, seq=contest.round.seq) return self.get_for(place=contest.place, year=contest.round.year, cat=contest.round.category, seq=contest.round.seq)
def get_for_contest_site(self, contest: db.Contest, place: db.Place):
return self.get_for(place=place, year=contest.round.year, cat=contest.round.category, seq=contest.round.seq)
def have_right(self, right: Right): def have_right(self, right: Right):
if self.user.is_admin: if self.user.is_admin:
return True return True
......
from dataclasses import dataclass
from flask import render_template, g, redirect, url_for, flash, request from flask import render_template, g, redirect, url_for, flash, request
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
import flask_wtf.file import flask_wtf.file
...@@ -445,6 +446,86 @@ def org_contest_solutions(id: int): ...@@ -445,6 +446,86 @@ def org_contest_solutions(id: int):
return table.send_as(format) return table.send_as(format)
@dataclass
class SolutionContext:
contest: db.Contest
round: db.Round
pion: db.Participation
solution: db.Solution
allow_view: bool
allow_upload_solutions: bool
allow_upload_feedback: bool
def get_solution_context(contest_id, user_id, task_id) -> SolutionContext:
sess = db.get_session()
# Nejprve zjistíme, zda existuje soutěž
contest = get_contest(contest_id)
round = contest.round
# Zkontrolujeme, zda se účastník opravdu účastní soutěže
pion = (sess.query(db.Participation)
.filter_by(user_id=user_id, contest_id=contest_id)
.options(joinedload(db.Participation.place))
.one_or_none())
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:
raise werkzeug.exceptions.NotFound()
# Zkontrolujeme, že úloha je součástí soutěže
if sol.round != 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
# 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
# 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)))
if not allow_view:
raise werkzeug.exceptions.Forbidden()
return SolutionContext(
contest=contest,
round=round,
pion=pion,
solution=sol,
allow_view=allow_view,
allow_upload_solutions=allow_upload_solutions,
allow_upload_feedback=allow_upload_feedback,
)
@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)
# FIXME
return render_template('not_implemented.html')
@app.route('/org/contest/c/<int:id>/proctor-import', methods=('GET', 'POST')) @app.route('/org/contest/c/<int:id>/proctor-import', methods=('GET', 'POST'))
def org_proctor_import(id: int): def org_proctor_import(id: int):
contest, rr = get_contest_rr(id, Right.manage_contest) contest, rr = get_contest_rr(id, Right.manage_contest)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment