Commit 2c38e11c authored by Robert Czechowski's avatar Robert Czechowski
Browse files

Format SQL statements more nicely (30%)

parent 3a21d73f
......@@ -74,7 +74,11 @@ impl MedalConnection for Connection {
// fn get_session<T: ToSql>(&self, key: T, keyname: &str) -> Option<SessionUser> {
fn get_session(&self, key: &str) -> Option<SessionUser> {
let query = "SELECT id, csrf_token, last_login, last_activity, permanent_login, username, password, logincode, email, email_unconfirmed, email_confirmationcode, firstname, lastname, street, zip, city, nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt FROM session WHERE session_token = $1";
let query = "SELECT id, csrf_token, last_login, last_activity, permanent_login, username, password, logincode,
email, email_unconfirmed, email_confirmationcode, firstname, lastname, street, zip, city,
nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt
FROM session
WHERE session_token = $1";
let session = self.query_map_one(query, &[&key], |row| SessionUser { id: row.get(0),
session_token: Some(key.to_string()),
csrf_token: row.get(1),
......@@ -110,7 +114,10 @@ impl MedalConnection for Connection {
if let Some(last_activity) = session.last_activity {
if now - last_activity < duration {
self.execute("UPDATE session SET last_activity = $1 WHERE id = $2", &[&now, &session.id]).unwrap();
let query = "UPDATE session
SET last_activity = $1
WHERE id = $2";
self.execute(query, &[&now, &session.id]).unwrap();
return Some(session);
} else {
// Session timed out
......@@ -154,30 +161,33 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
self.execute(
"INSERT INTO session (session_token, csrf_token, last_activity, permanent_login, grade, is_teacher)
VALUES ($1, $2, $3, FALSE, 0, FALSE)",
&[&session_token, &csrf_token, &now],
)
.unwrap();
let query = "INSERT INTO session (session_token, csrf_token, last_activity, permanent_login, grade,
is_teacher)
VALUES ($1, $2, $3, FALSE, 0, FALSE)";
self.execute(query, &[&session_token, &csrf_token, &now]).unwrap();
let id = self.get_last_id().expect("Expected to get last row id");
SessionUser::minimal(id as i32, session_token.to_owned(), csrf_token)
}
fn get_session_or_new(&self, key: &str) -> SessionUser {
let query = "UPDATE session
SET session_token = $1
WHERE session_token = $2";
self.get_session(&key).ensure_alive().unwrap_or_else(|| {
// TODO: Factor this out in own function
// TODO: Should a new session key be generated every time?
self.execute(
"UPDATE session SET session_token = $1 WHERE session_token = $2",
&[&Option::<String>::None, &key]).unwrap();
self.execute(query, &[&Option::<String>::None, &key]).unwrap();
self.new_session(&key)
})
}
fn get_user_by_id(&self, user_id: i32) -> Option<SessionUser> {
let query = "SELECT session_token, csrf_token, last_login, last_activity, permanent_login, username, password, logincode, email, email_unconfirmed, email_confirmationcode, firstname, lastname, street, zip, city, nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt FROM session WHERE id = $1";
let query = "SELECT session_token, csrf_token, last_login, last_activity, permanent_login, username, password,
logincode, email, email_unconfirmed, email_confirmationcode, firstname, lastname, street,
zip, city, nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt
FROM session
WHERE id = $1";
self.query_map_one(query, &[&user_id], |row| SessionUser { id: user_id,
session_token: row.get(0),
csrf_token: row.get(1),
......@@ -217,7 +227,9 @@ impl MedalConnection for Connection {
None => return Some((session, None)),
};
let query = "SELECT name, groupcode, tag, admin FROM usergroup WHERE id = $1";
let query = "SELECT name, groupcode, tag, admin
FROM usergroup
WHERE id = $1";
let res = self.query_map_one(query, &[&group_id], |row| Group { id: Some(group_id),
name: row.get(0),
groupcode: row.get(1),
......@@ -233,11 +245,10 @@ impl MedalConnection for Connection {
//TODO: use session
fn login(&self, _session: Option<&str>, username: &str, password: &str) -> Result<String, ()> {
let query = "SELECT id, password, salt FROM session WHERE username = $1";
self.query_map_one(
query,
&[&username],
|row| {
let query = "SELECT id, password, salt
FROM session
WHERE username = $1";
self.query_map_one(query, &[&username], |row| {
let (id, password_hash, salt): (i32, Option<String>, Option<String>) =
(row.get(0), row.get(1), row.get(2));
......@@ -253,23 +264,26 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
let query = "UPDATE session SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3 WHERE id = $4";
let query = "UPDATE session
SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3
WHERE id = $4";
self.execute(query, &[&session_token, &csrf_token, &now, &id]).unwrap();
Ok(session_token)
} else {
Err(())
}
}).map_err(|_| ())?.ok_or(())?
})
.map_err(|_| ())?
.ok_or(())?
}
//TODO: use session
fn login_with_code(&self, _session: Option<&str>, logincode: &str) -> Result<String, ()> {
let query = "SELECT id FROM session WHERE logincode = $1";
self.query_map_one(
query,
&[&logincode],
|row| {
let query = "SELECT id
FROM session
WHERE logincode = $1";
self.query_map_one(query, &[&logincode], |row| {
// Login okay, update session now!
let id: i32 = row.get(0);
......@@ -277,11 +291,15 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
let query = "UPDATE session SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3 WHERE id = $4";
let query = "UPDATE session
SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3
WHERE id = $4";
self.execute(query, &[&session_token, &csrf_token, &now, &id]).unwrap();
session_token
}).map_err(|_| ())?.ok_or(())
})
.map_err(|_| ())?
.ok_or(())
}
//TODO: use session
......@@ -293,17 +311,24 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
let query = "SELECT id FROM session WHERE oauth_foreign_id = $1";
let query = "SELECT id
FROM session
WHERE oauth_foreign_id = $1";
match self.query_map_one(query, &[&foreign_id], |row| -> i32 { row.get(0) }) {
Ok(Some(id)) => {
let query = "UPDATE session SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3 WHERE id = $4";
let query = "UPDATE session
SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3
WHERE id = $4";
self.execute(query, &[&session_token, &csrf_token, &now, &id]).unwrap();
Ok(session_token)
}
// Add!
_ => {
let query = "INSERT INTO session (session_token, csrf_token, last_login, last_activity, permanent_login, grade, is_teacher, oauth_foreign_id, firstname, lastname) VALUES ($1, $2, $3, $3, $4, $5, $6, $7, $8, $9)";
let query = "INSERT INTO session (session_token, csrf_token, last_login, last_activity,
permanent_login, grade, is_teacher, oauth_foreign_id,
firstname, lastname)
VALUES ($1, $2, $3, $3, $4, $5, $6, $7, $8, $9)";
self.execute(query,
&[&session_token,
&csrf_token,
......@@ -333,7 +358,9 @@ impl MedalConnection for Connection {
let login_code = helpers::make_login_code(); // todo: check for collisions
let now = time::get_time();
let query = "INSERT INTO session (session_token, csrf_token, last_login, last_activity, permanent_login, logincode, grade, is_teacher, managed_by) VALUES ($1, $2, $3, $3, $4, $5, $6, $7, $8)";
let query = "INSERT INTO session (session_token, csrf_token, last_login, last_activity, permanent_login,
logincode, grade, is_teacher, managed_by)
VALUES ($1, $2, $3, $3, $4, $5, $6, $7, $8)";
self.execute(query, &[&session_token, &csrf_token, &now, &false, &login_code, &0, &false, &group_id]).unwrap();
Ok(session_token)
......@@ -347,7 +374,9 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let login_code = helpers::make_login_code(); // TODO: check for collisions
let query = "INSERT INTO session (firstname, lastname, csrf_token, permanent_login, logincode, grade, is_teacher, managed_by) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)";
let query = "INSERT INTO session (firstname, lastname, csrf_token, permanent_login, logincode, grade,
is_teacher, managed_by)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)";
self.execute(query,
&[&user.firstname,
&user.lastname,
......@@ -362,40 +391,55 @@ impl MedalConnection for Connection {
}
fn logout(&self, session: &str) {
let query = "UPDATE session SET session_token = NULL WHERE session_token = $1";
let query = "UPDATE session
SET session_token = NULL
WHERE session_token = $1";
self.execute(query, &[&session]).unwrap();
}
fn load_submission(&self, session: &SessionUser, task: i32, subtask: Option<&str>) -> Option<Submission> {
match subtask {
None => self.query_map_one("SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation FROM submission WHERE task = $1 AND session = $2 ORDER BY id DESC LIMIT 1", &[&task, &session.id], |row| {
Submission {
id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3 ),
subtask_identifier: None,
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6),
}
}).ok()?,
Some(subtask_id) => self.query_map_one("SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation FROM submission WHERE task = $1 AND session = $2 AND subtask_identifier = $3 ORDER BY id DESC LIMIT 1", &[&task, &session.id, &subtask_id], |row| {
Submission {
id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3),
subtask_identifier: Some(subtask_id.to_string()),
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6),
}
}).ok()?,
None => {
let query = "SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation
FROM submission
WHERE task = $1
AND session = $2
ORDER BY id DESC
LIMIT 1";
self.query_map_one(query, &[&task, &session.id], |row| Submission { id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3),
subtask_identifier: None,
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6) })
.ok()?
}
Some(subtask_id) => {
let query = "SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation
FROM submission
WHERE task = $1
AND session = $2
AND subtask_identifier = $3
ORDER BY id DESC
LIMIT 1";
self.query_map_one(query, &[&task, &session.id, &subtask_id], |row| {
Submission { id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3),
subtask_identifier: Some(subtask_id.to_string()),
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6) }
})
.ok()?
}
}
}
fn submit_submission(&self, mut submission: Submission) {
......
......@@ -74,7 +74,11 @@ impl MedalConnection for Connection {
// fn get_session<T: ToSql>(&self, key: T, keyname: &str) -> Option<SessionUser> {
fn get_session(&self, key: &str) -> Option<SessionUser> {
let query = "SELECT id, csrf_token, last_login, last_activity, permanent_login, username, password, logincode, email, email_unconfirmed, email_confirmationcode, firstname, lastname, street, zip, city, nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt FROM session_user WHERE session_token = ?1";
let query = "SELECT id, csrf_token, last_login, last_activity, permanent_login, username, password, logincode,
email, email_unconfirmed, email_confirmationcode, firstname, lastname, street, zip, city,
nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt
FROM session_user
WHERE session_token = ?1";
let session = self.query_map_one(query, &[&key], |row| SessionUser { id: row.get(0),
session_token: Some(key.to_string()),
csrf_token: row.get(1),
......@@ -110,7 +114,10 @@ impl MedalConnection for Connection {
if let Some(last_activity) = session.last_activity {
if now - last_activity < duration {
self.execute("UPDATE session_user SET last_activity = ?1 WHERE id = ?2", &[&now, &session.id]).unwrap();
let query = "UPDATE session_user
SET last_activity = ?1
WHERE id = ?2";
self.execute(query, &[&now, &session.id]).unwrap();
return Some(session);
} else {
// Session timed out
......@@ -154,30 +161,33 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
self.execute(
"INSERT INTO session_user (session_token, csrf_token, last_activity, permanent_login, grade, is_teacher)
VALUES (?1, ?2, ?3, 0, 0, 0)",
&[&session_token, &csrf_token, &now],
)
.unwrap();
let query = "INSERT INTO session_user (session_token, csrf_token, last_activity, permanent_login, grade,
is_teacher)
VALUES (?1, ?2, ?3, 0, 0, 0)";
self.execute(query, &[&session_token, &csrf_token, &now]).unwrap();
let id = self.get_last_id().expect("Expected to get last row id");
SessionUser::minimal(id, session_token.to_owned(), csrf_token)
}
fn get_session_or_new(&self, key: &str) -> SessionUser {
let query = "UPDATE session_user
SET session_token = ?1
WHERE session_token = ?2";
self.get_session(&key).ensure_alive().unwrap_or_else(|| {
// TODO: Factor this out in own function
// TODO: Should a new session key be generated every time?
self.execute(
"UPDATE session_user SET session_token = ?1 WHERE session_token = ?2",
&[&Option::<String>::None, &key]).unwrap();
self.execute(query, &[&Option::<String>::None, &key]).unwrap();
self.new_session(&key)
})
}
fn get_user_by_id(&self, user_id: i32) -> Option<SessionUser> {
let query = "SELECT session_token, csrf_token, last_login, last_activity, permanent_login, username, password, logincode, email, email_unconfirmed, email_confirmationcode, firstname, lastname, street, zip, city, nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt FROM session_user WHERE id = ?1";
let query = "SELECT session_token, csrf_token, last_login, last_activity, permanent_login, username, password,
logincode, email, email_unconfirmed, email_confirmationcode, firstname, lastname, street,
zip, city, nation, grade, is_teacher, managed_by, oauth_provider, oauth_foreign_id, salt
FROM session_user
WHERE id = ?1";
self.query_map_one(query, &[&user_id], |row| SessionUser { id: user_id,
session_token: row.get(0),
csrf_token: row.get(1),
......@@ -217,7 +227,9 @@ impl MedalConnection for Connection {
None => return Some((session, None)),
};
let query = "SELECT name, groupcode, tag, admin FROM usergroup WHERE id = ?1";
let query = "SELECT name, groupcode, tag, admin
FROM usergroup
WHERE id = ?1";
let res = self.query_map_one(query, &[&group_id], |row| Group { id: Some(group_id),
name: row.get(0),
groupcode: row.get(1),
......@@ -233,11 +245,10 @@ impl MedalConnection for Connection {
//TODO: use session
fn login(&self, _session: Option<&str>, username: &str, password: &str) -> Result<String, ()> {
let query = "SELECT id, password, salt FROM session_user WHERE username = ?1";
self.query_map_one(
query,
&[&username],
|row| {
let query = "SELECT id, password, salt
FROM session_user
WHERE username = ?1";
self.query_map_one(query, &[&username], |row| {
let (id, password_hash, salt): (i32, Option<String>, Option<String>) =
(row.get(0), row.get(1), row.get(2));
......@@ -253,23 +264,24 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_session_token();
let now = time::get_time();
let query = "UPDATE session_user SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3 WHERE id = ?4";
let query = "UPDATE session_user
SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3
WHERE id = ?4";
self.execute(query, &[&session_token, &csrf_token, &now, &id]).unwrap();
Ok(session_token)
} else {
Err(())
}
}).map_err(|_| ())?.ok_or(())?
})
.map_err(|_| ())?
.ok_or(())?
}
//TODO: use session
fn login_with_code(&self, _session: Option<&str>, logincode: &str) -> Result<String, ()> {
let query = "SELECT id FROM session_user WHERE logincode = ?1";
self.query_map_one(
query,
&[&logincode],
|row| {
self.query_map_one(query, &[&logincode], |row| {
// Login okay, update session now!
let id: i32 = row.get(0);
......@@ -277,11 +289,15 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
let query = "UPDATE session_user SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3 WHERE id = ?4";
let query = "UPDATE session_user
SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3
WHERE id = ?4";
self.execute(query, &[&session_token, &csrf_token, &now, &id]).unwrap();
session_token
}).map_err(|_| ())?.ok_or(())
})
.map_err(|_| ())?
.ok_or(())
}
//TODO: use session
......@@ -293,17 +309,24 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let now = time::get_time();
let query = "SELECT id FROM session_user WHERE oauth_foreign_id = ?1";
let query = "SELECT id
FROM session_user
WHERE oauth_foreign_id = ?1";
match self.query_map_one(query, &[&foreign_id], |row| -> i32 { row.get(0) }) {
Ok(Some(id)) => {
let query = "UPDATE session_user SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3 WHERE id = ?4";
let query = "UPDATE session_user
SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3
WHERE id = ?4";
self.execute(query, &[&session_token, &csrf_token, &now, &id]).unwrap();
Ok(session_token)
}
// Add!
_ => {
let query = "INSERT INTO session_user (session_token, csrf_token, last_login, last_activity, permanent_login, grade, is_teacher, oauth_foreign_id, firstname, lastname) VALUES (?1, ?2, ?3, ?3, ?4, ?5, ?6, ?7, ?8, ?9)";
let query = "INSERT INTO session_user (session_token, csrf_token, last_login, last_activity,
permanent_login, grade, is_teacher, oauth_foreign_id,
firstname, lastname)
VALUES (?1, ?2, ?3, ?3, ?4, ?5, ?6, ?7, ?8, ?9)";
self.execute(query,
&[&session_token,
&csrf_token,
......@@ -323,7 +346,9 @@ impl MedalConnection for Connection {
//TODO: use session
fn create_user_with_groupcode(&self, _session: Option<&str>, groupcode: &str) -> Result<String, ()> {
let query = "SELECT id FROM usergroup WHERE groupcode = ?1";
let query = "SELECT id
FROM usergroup
WHERE groupcode = ?1";
let group_id =
self.query_map_one(query, &[&groupcode], |row| -> i32 { row.get(0) }).map_err(|_| ())?.ok_or(())?;
......@@ -333,7 +358,9 @@ impl MedalConnection for Connection {
let login_code = helpers::make_login_code(); // TODO: check for collisions
let now = time::get_time();
let query = "INSERT INTO session_user (session_token, csrf_token, last_login, last_activity, permanent_login, logincode, grade, is_teacher, managed_by) VALUES (?1, ?2, ?3, ?3, ?4, ?5, ?6, ?7, ?8)";
let query = "INSERT INTO session_user (session_token, csrf_token, last_login, last_activity, permanent_login,
logincode, grade, is_teacher, managed_by)
VALUES (?1, ?2, ?3, ?3, ?4, ?5, ?6, ?7, ?8)";
self.execute(query, &[&session_token, &csrf_token, &now, &false, &login_code, &0, &false, &group_id]).unwrap();
Ok(session_token)
......@@ -347,7 +374,9 @@ impl MedalConnection for Connection {
let csrf_token = helpers::make_csrf_token();
let login_code = helpers::make_login_code(); // TODO: check for collisions
let query = "INSERT INTO session_user (firstname, lastname, csrf_token, permanent_login, logincode, grade, is_teacher, managed_by) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)";
let query = "INSERT INTO session_user (firstname, lastname, csrf_token, permanent_login, logincode, grade,
is_teacher, managed_by)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)";
self.execute(query,
&[&user.firstname,
&user.lastname,
......@@ -362,40 +391,55 @@ impl MedalConnection for Connection {
}
fn logout(&self, session: &str) {
let query = "UPDATE session_user SET session_token = NULL WHERE session_token = ?1";
let query = "UPDATE session_user
SET session_token = NULL
WHERE session_token = ?1";
self.execute(query, &[&session]).unwrap();
}
fn load_submission(&self, session: &SessionUser, task: i32, subtask: Option<&str>) -> Option<Submission> {
match subtask {
None => self.query_map_one("SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation FROM submission WHERE task = ?1 AND session_user = ?2 ORDER BY id DESC LIMIT 1", &[&task, &session.id], |row| {
Submission {
id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3 ),
subtask_identifier: None,
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6),
}
}).ok()?,
Some(subtask_id) => self.query_map_one("SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation FROM submission WHERE task = ?1 AND session_user = ?2 AND subtask_identifier = ?3 ORDER BY id DESC LIMIT 1", &[&task, &session.id, &subtask_id], |row| {
Submission {
id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3),
subtask_identifier: Some(subtask_id.to_string()),
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6),
}
}).ok()?
None => {
let query = "SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation
FROM submission
WHERE task = ?1
AND session_user = ?2
ORDER BY id DESC
LIMIT 1";
self.query_map_one(query, &[&task, &session.id], |row| Submission { id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3),
subtask_identifier: None,
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6) })
.ok()?
}
Some(subtask_id) => {
let query = "SELECT id, grade, validated, nonvalidated_grade, value, date, needs_validation
FROM submission
WHERE task = ?1
AND session_user = ?2
AND subtask_identifier = ?3
ORDER BY id DESC
LIMIT 1";
self.query_map_one(query, &[&task, &session.id, &subtask_id], |row| {
Submission { id: Some(row.get(0)),
task: task,
session_user: session.id,
grade: row.get(1),
validated: row.get(2),
nonvalidated_grade: row.get(3),
subtask_identifier: Some(subtask_id.to_string()),
value: row.get(4),
date: row.get(5),
needs_validation: row.get(6) }
})
.ok()?
}
}
}
fn submit_submission(&self, mut submission: Submission) {
......
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