Commit 2f7b4f73 authored by Robert Czechowski's avatar Robert Czechowski Committed by Robert Czechowski
Browse files

Check if user is qualified before allowing to start contest

parent 5be71da1
......@@ -286,6 +286,18 @@ pub struct ContestStartConstraints {
pub grade_matching: bool,
}
fn check_contest_qualification<T: MedalConnection>(conn: &T, session: &SessionUser, contest: &Contest) -> Option<bool> {
let required_contests = contest.requires_contest.as_ref()?.split(",");
for req_contest in required_contests {
if conn.has_participation_by_contest_file(session.id, &contest.location, req_contest) {
return Some(true);
}
}
Some(false)
}
fn check_contest_constraints(session: &SessionUser, contest: &Contest) -> ContestStartConstraints {
let now = time::get_time();
let student_grade = session.grade % 100 - if session.grade / 100 == 1 { 1 } else { 0 };
......@@ -305,7 +317,8 @@ fn check_contest_constraints(session: &SessionUser, contest: &Contest) -> Contes
contest_running,
grade_too_low,
grade_too_high,
grade_matching }
grade_matching,
}
}
pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token: &str,
......@@ -333,11 +346,13 @@ pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token
fill_oauth_data(login_info, &mut data);
let constraints = check_contest_constraints(&session, &contest);
let is_qualified = check_contest_qualification(conn, &session, &contest).unwrap_or(true);
let can_start = session.is_logged_in() && constraints.contest_running && constraints.grade_matching;
let can_start = session.is_logged_in() && constraints.contest_running && constraints.grade_matching && is_qualified;
let has_duration = contest.duration > 0;
data.insert("constraints".to_string(), to_json(&constraints));
data.insert("is_qualified".to_string(), to_json(&is_qualified));
data.insert("has_duration".to_string(), to_json(&has_duration));
data.insert("can_start".to_string(), to_json(&can_start));
......@@ -516,6 +531,12 @@ pub fn start_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_toke
return Err(MedalError::AccessDenied);
}
let is_qualified = check_contest_qualification(conn, &session, &contest);
if is_qualified == Some(false) {
return Err(MedalError::AccessDenied);
}
// Start contest
match conn.new_participation(&session_token, contest_id) {
Ok(_) => Ok(()),
......
......@@ -1203,6 +1203,16 @@ impl MedalConnection for Connection {
.unwrap()
}
fn has_participation_by_contest_file(&self, session_id: i32, location: &str, filename: &str) -> bool {
let query = "SELECT participation.contest
FROM participation
JOIN contest ON participation.contest = contest.id
WHERE participation.session = $1
AND contest.location = $2
AND contest.filename = $3";
self.exists(query, &[&session_id, &location, &filename])
}
fn new_participation(&self, session: &str, contest_id: i32) -> Result<Participation, ()> {
let query = "SELECT session, start_date
FROM participation
......
......@@ -123,6 +123,8 @@ pub trait MedalConnection {
/// Returns an `Vec` that contains pairs of all participations with their associated contests.
fn get_all_participations_complete(&self, session_id: i32) -> Vec<(Participation, Contest)>;
fn has_participation_by_contest_file(&self, session_id: i32, location: &str, filename: &str) -> bool;
/// Start a new participation of the session identified by the session token `session` for the contest with the
/// contest id `contest_id`. It checks whether the session is allowed to start the participation.
///
......
......@@ -1322,6 +1322,16 @@ impl MedalConnection for Connection {
.unwrap()
}
fn has_participation_by_contest_file(&self, session_id: i32, location: &str, filename: &str) -> bool {
let query = "SELECT participation.contest
FROM participation
JOIN contest ON participation.contest = contest.id
WHERE participation.session = $1
AND contest.location = $2
AND contest.filename = $3";
self.exists(query, &[&session_id, &location, &filename])
}
fn new_participation(&self, session: &str, contest_id: i32) -> Result<Participation, ()> {
let query = "SELECT session, start_date
FROM participation
......
......@@ -1322,6 +1322,16 @@ impl MedalConnection for Connection {
.unwrap()
}
fn has_participation_by_contest_file(&self, session_id: i32, location: &str, filename: &str) -> bool {
let query = "SELECT participation.contest
FROM participation
JOIN contest ON participation.contest = contest.id
WHERE participation.session = ?1
AND contest.location = ?2
AND contest.filename = ?3";
self.exists(query, &[&session_id, &location, &filename])
}
fn new_participation(&self, session: &str, contest_id: i32) -> Result<Participation, ()> {
let query = "SELECT session, start_date
FROM participation
......
......@@ -134,11 +134,16 @@
{{/if}}
{{else}}
{{#if logged_in}}
{{#if constraints.grade_too_low}}
<p>Deine angegebene Jahrgangsstufe entspricht nicht den für diesen Wettbewerb vorgesehenen Altersgruppen.</p>
{{/if}}
{{#if constraints.grade_too_high}}
<p>Deine angegebene Jahrgangsstufe entspricht nicht den für diesen Wettbewerb vorgesehenen Altersgruppen.</p>
{{#if is_qualified}}
{{#if constraints.grade_too_low}}
<p>Deine angegebene Jahrgangsstufe entspricht nicht den für diesen Wettbewerb vorgesehenen Altersgruppen.</p>
{{/if}}
{{#if constraints.grade_too_high}}
<p>Deine angegebene Jahrgangsstufe entspricht nicht den für diesen Wettbewerb vorgesehenen Altersgruppen.</p>
{{/if}}
{{else}}
<p>Du bist für diesen Wettbewerb nicht qualifiziert.</p>
<p>Du hast nicht an der vorhergehenden Wettbewerbsrunde teilgenommen, die Voraussetzung für diesen Wettbewerb ist oder nicht die vorhergehenden Aufgaben bearbeitet, die Voraussetzung für diese Aufgaben sind.</p>
{{/if}}
{{else}}
<p>Möglicherweise musst du dich zunächst <a href="/login">einloggen</a>.</p>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment