Commit 83f9a8a1 authored by Robert Czechowski's avatar Robert Czechowski

Admin interface: Add stub for admin export download page

parent 06a852a8
......@@ -1277,6 +1277,24 @@ pub fn admin_delete_participation<T: MedalConnection>(conn: &T, user_id: i32, co
Ok(("profile".to_string(), data))
}
pub fn admin_contest_export<T: MedalConnection>(conn: &T, contest_id: i32, session_token: &str)
-> MedalResult<String> {
conn.get_session(&session_token)
.ensure_logged_in()
.ok_or(MedalError::NotLoggedIn)?
.ensure_admin()
.ok_or(MedalError::AccessDenied)?;
let contest = conn.get_contest_by_id_complete(contest_id);
let taskgroup_ids : Vec<i32> = contest.taskgroups.iter().map(|tg| tg.id.unwrap()).collect();
let filename = "./export/blub.csv";
let contest = conn.export_contest_results_to_file(contest_id, &taskgroup_ids, filename);
Ok("blub".to_string())
}
#[derive(PartialEq)]
pub enum UserType {
User,
......
......@@ -796,6 +796,15 @@ impl MedalConnection for Connection {
.unwrap_or_default()
}
fn export_contest_results_to_file(&self, contest_id: i32, taskgroups_ids: &[i32], filename: &str) {
let query = "COPY (
SELECT * from contest
)
TO '/tmp/output.csv'
WITH CSV DELIMITER ',' HEADER;";
self.execute(query, &[]).unwrap();
}
fn get_contest_list(&self) -> Vec<Contest> {
let query = "SELECT id, location, filename, name, duration, public, start_date, end_date, min_grade, max_grade,
positionalnumber, requires_login, secret
......
......@@ -47,6 +47,7 @@ pub trait MedalConnection {
-> (Vec<String>, Vec<(Group, Vec<(UserInfo, Vec<Grade>)>)>);
fn get_taskgroup_user_grade(&self, session: &str, taskgroup_id: i32) -> Grade;
fn get_contest_user_grades(&self, session: &str, contest_id: i32) -> Vec<Grade>;
fn export_contest_results_to_file(&self, contest_id: i32, taskgroups_ids: &[i32], filename: &str);
fn get_contest_list(&self) -> Vec<Contest>;
fn get_contest_by_id(&self, contest_id: i32) -> Contest;
......
......@@ -551,8 +551,8 @@ impl MedalConnection for Connection {
}
//TODO: use session
fn login_foreign(&self, _session: Option<&str>, provider_id: &str, foreign_id: &str,
(is_teacher, is_admin, firstname, lastname, sex): (bool, bool, &str, &str, Option<i32>))
fn login_foreign(&self, _session: Option<&str>, provider_id: &str, foreign_id: &str, (is_teacher, is_admin,
firstname, lastname, sex): (bool, bool, &str, &str, Option<i32>))
-> Result<String, ()>
{
let session_token = helpers::make_session_token();
......@@ -569,17 +569,7 @@ impl MedalConnection for Connection {
SET session_token = $1, csrf_token = $2, last_login = $3, last_activity = $3,
is_teacher = $4, is_admin = $5, firstname = $6, lastname = $7, sex = $8
WHERE id = $9";
self.execute(query,
&[&session_token,
&csrf_token,
&now,
&is_teacher,
&is_admin,
&firstname,
&lastname,
&sex,
&id])
.unwrap();
self.execute(query, &[&session_token, &csrf_token, &now, &is_teacher, &is_admin, &firstname, &lastname, &sex, &id]).unwrap();
Ok(session_token)
}
......@@ -727,18 +717,18 @@ impl MedalConnection for Connection {
WHERE task = $1
AND session = $2";
self.query_map_many(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),
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) })
.unwrap()
}
_ => unimplemented!(),
_ => unimplemented!()
}
}
fn submit_submission(&self, mut submission: Submission) {
......@@ -916,6 +906,15 @@ impl MedalConnection for Connection {
.unwrap_or_default()
}
fn export_contest_results_to_file(&self, contest_id: i32, taskgroups_ids: &[i32], filename: &str) {
let query = "COPY (
SELECT * from contest
)
TO '/tmp/output.csv'
WITH CSV DELIMITER ',' HEADER;";
self.execute(query, &[]).unwrap();
}
fn get_contest_list(&self) -> Vec<Contest> {
let query = "SELECT id, location, filename, name, duration, public, start_date, end_date, min_grade, max_grade,
positionalnumber, requires_login, secret
......@@ -1074,25 +1073,29 @@ impl MedalConnection for Connection {
JOIN contest ON participation.contest = contest.id
WHERE participation.session = $1";
self.query_map_many(query, &[&session_id], |row| {
(Participation { contest: row.get(1), user: session_id, start: row.get(0) },
Contest { id: Some(row.get(1)),
location: row.get(2),
filename: row.get(3),
name: row.get(4),
duration: row.get(5),
public: row.get(6),
start: row.get(7),
end: row.get(8),
min_grade: row.get(9),
max_grade: row.get(10),
positionalnumber: None,
requires_login: row.get(11),
secret: row.get(12),
taskgroups: Vec::new() })
})
.unwrap()
( Participation { contest: row.get(1),
user: session_id,
start: row.get(0) },
Contest { id: Some(row.get(1)),
location: row.get(2),
filename: row.get(3),
name: row.get(4),
duration: row.get(5),
public: row.get(6),
start: row.get(7),
end: row.get(8),
min_grade: row.get(9),
max_grade: row.get(10),
positionalnumber: None,
requires_login: row.get(11),
secret: row.get(12),
taskgroups: Vec::new() },
)
})
.unwrap()
}
fn new_participation(&self, session: &str, contest_id: i32) -> Result<Participation, ()> {
let query = "SELECT session, start_date
FROM participation
......
......@@ -551,8 +551,8 @@ impl MedalConnection for Connection {
}
//TODO: use session
fn login_foreign(&self, _session: Option<&str>, provider_id: &str, foreign_id: &str,
(is_teacher, is_admin, firstname, lastname, sex): (bool, bool, &str, &str, Option<i32>))
fn login_foreign(&self, _session: Option<&str>, provider_id: &str, foreign_id: &str, (is_teacher, is_admin,
firstname, lastname, sex): (bool, bool, &str, &str, Option<i32>))
-> Result<String, ()>
{
let session_token = helpers::make_session_token();
......@@ -569,17 +569,7 @@ impl MedalConnection for Connection {
SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3,
is_teacher = ?4, is_admin = ?5, firstname = ?6, lastname = ?7, sex = ?8
WHERE id = ?9";
self.execute(query,
&[&session_token,
&csrf_token,
&now,
&is_teacher,
&is_admin,
&firstname,
&lastname,
&sex,
&id])
.unwrap();
self.execute(query, &[&session_token, &csrf_token, &now, &is_teacher, &is_admin, &firstname, &lastname, &sex, &id]).unwrap();
Ok(session_token)
}
......@@ -727,18 +717,18 @@ impl MedalConnection for Connection {
WHERE task = ?1
AND session = ?2";
self.query_map_many(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),
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) })
.unwrap()
}
_ => unimplemented!(),
_ => unimplemented!()
}
}
fn submit_submission(&self, mut submission: Submission) {
......@@ -916,6 +906,15 @@ impl MedalConnection for Connection {
.unwrap_or_default()
}
fn export_contest_results_to_file(&self, contest_id: i32, taskgroups_ids: &[i32], filename: &str) {
let query = "COPY (
SELECT * from contest
)
TO '/tmp/output.csv'
WITH CSV DELIMITER ',' HEADER;";
self.execute(query, &[]).unwrap();
}
fn get_contest_list(&self) -> Vec<Contest> {
let query = "SELECT id, location, filename, name, duration, public, start_date, end_date, min_grade, max_grade,
positionalnumber, requires_login, secret
......@@ -1074,25 +1073,29 @@ impl MedalConnection for Connection {
JOIN contest ON participation.contest = contest.id
WHERE participation.session = ?1";
self.query_map_many(query, &[&session_id], |row| {
(Participation { contest: row.get(1), user: session_id, start: row.get(0) },
Contest { id: Some(row.get(1)),
location: row.get(2),
filename: row.get(3),
name: row.get(4),
duration: row.get(5),
public: row.get(6),
start: row.get(7),
end: row.get(8),
min_grade: row.get(9),
max_grade: row.get(10),
positionalnumber: None,
requires_login: row.get(11),
secret: row.get(12),
taskgroups: Vec::new() })
})
.unwrap()
( Participation { contest: row.get(1),
user: session_id,
start: row.get(0) },
Contest { id: Some(row.get(1)),
location: row.get(2),
filename: row.get(3),
name: row.get(4),
duration: row.get(5),
public: row.get(6),
start: row.get(7),
end: row.get(8),
min_grade: row.get(9),
max_grade: row.get(10),
positionalnumber: None,
requires_login: row.get(11),
secret: row.get(12),
taskgroups: Vec::new() },
)
})
.unwrap()
}
fn new_participation(&self, session: &str, contest_id: i32) -> Result<Participation, ()> {
let query = "SELECT session, start_date
FROM participation
......
......@@ -1004,6 +1004,17 @@ fn admin_participation<C>(req: &mut Request) -> IronResult<Response>
Ok(resp)
}
fn admin_export_contest<C>(req: &mut Request) -> IronResult<Response>
where C: MedalConnection + std::marker::Send + 'static {
let contest_id = req.expect_int::<i32>("contestid")?;
let session_token = req.expect_session_token()?;
let filename = with_conn![core::admin_contest_export, C, req, contest_id, &session_token].aug(req)?;
Ok(Response::with((status::Found, RedirectRaw(format!("/export/{}", filename)))))
}
#[derive(Deserialize, Debug)]
struct OAuthAccess {
access_token: String,
......@@ -1239,6 +1250,7 @@ pub fn start_server<C>(conn: C, config: Config) -> iron::error::HttpResult<iron:
admin_group_post: post "/admin/group/:groupid" => admin_group::<C>,
admin_participation: get "/admin/user/:userid/:contestid" => admin_participation::<C>,
admin_participation_post: post "/admin/user/:userid/:contestid" => admin_participation::<C>,
admin_export_contest: get "/admin/contest/:contestid/export" => admin_export_contest::<C>,
oauth: get "/oauth/:oauthid" => oauth::<C>,
check_cookie: get "/cookie" => cookie_warning,
dbstatus: get "/dbstatus" => dbstatus::<C>,
......@@ -1252,6 +1264,7 @@ pub fn start_server<C>(conn: C, config: Config) -> iron::error::HttpResult<iron:
// Serve the shared JS/CSS at /
mount.mount("/static/", Static::new(Path::new("static")));
mount.mount("/export/", Static::new(Path::new("export")));
mount.mount("/tasks/", Static::new(Path::new(TASK_DIR)));
mount.mount("/", router);
......
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