Commit 5ddf9711 authored by Robert Czechowski's avatar Robert Czechowski
Browse files

Allow group admin to edit profiles of group members

parent 36023199
......@@ -14,6 +14,8 @@ pub trait MedalConnection {
fn save_session(&self, session: SessionUser);
fn get_session_or_new(&self, key: String) -> SessionUser;
fn get_user_and_group_by_id(&self, user_id: u32) -> Option<(SessionUser, Option<Group>)>;
//fn login(&self, session: &SessionUser, username: String, password: String) -> Result<String,()>;
fn login(&self, session: Option<String>, username: String, password: String) -> Result<String,()>;
......
......@@ -48,6 +48,7 @@ impl MedalConnection for Connection {
println!("OK.");
}
// fn get_session<T: ToSql>(&self, key: T, keyname: &str) -> Option<SessionUser> {
fn get_session(&self, key: String) -> Option<SessionUser> {
let res = self.query_row("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, pms_id, pms_school_id FROM session_user WHERE session_token = ?1", &[&key], |row| {
SessionUser {
......@@ -108,6 +109,67 @@ impl MedalConnection for Connection {
fn get_session_or_new(&self, key: String) -> SessionUser {
self.get_session(key).unwrap_or_else(|| self.new_session())
}
fn get_user_and_group_by_id(&self, user_id: u32) -> Option<(SessionUser, Option<Group>)> {
let res = self.query_row("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, pms_id, pms_school_id FROM session_user WHERE id = ?1", &[&user_id], |row| {
SessionUser {
id: user_id,
session_token: row.get(0),
csrf_token: row.get(1),
last_login: row.get(2),
last_activity: row.get(3),
permanent_login: row.get(4),
username: row.get(5),
password: row.get(6),
salt: None,//"".to_string(),
logincode: row.get(7),
email: row.get(8),
email_unconfirmed: row.get(9),
email_confirmationcode: row.get(10),
firstname: row.get(11),
lastname: row.get(12),
street: row.get(13),
zip: row.get(14),
city: row.get(15),
nation: row.get(16),
grade: row.get(17),
is_teacher: row.get(18),
managed_by: row.get(19),
pms_id: row.get(20),
pms_school_id: row.get(21),
}
});
let session = match res {
Ok(session) => session,
_ => return None
};
println!("A");
let group_id = match session.managed_by {
Some(id) => id,
None => return Some((session, None))
};
println!("B");
let res = self.query_row("SELECT name, groupcode, tag, admin FROM usergroup WHERE id = ?1", &[&group_id], |row| {
println!("D");
Group {
id: Some(group_id),
name: row.get(0),
groupcode: row.get(1),
tag: row.get(2),
admin: row.get(3),
members: Vec::new(),
}
});
println!("C");
match res {
Ok(group) => Some((session, Some(group))),
_ => Some((session, None))
}
}
fn login(&self, session: Option<String>, username: String, password: String) -> Result<String,()> {
println!("a {} {}", username, password);
......
......@@ -385,34 +385,83 @@ pub fn show_groups_results<T: MedalConnection>(conn: &T, contest_id: u32, sessio
Ok(("groupresults".into(), data))
}
pub fn show_profile<T: MedalConnection>(conn: &T, session_token: String) -> MedalValueResult {
pub fn show_profile<T: MedalConnection>(conn: &T, session_token: String, user_id: Option<u32>) -> MedalValueResult {
let session = conn.get_session_or_new(session_token).ensure_alive().ok_or(MedalError::AccessDenied)?; // TODO SessionTimeout
let mut data = json_val::Map::new();
data.insert("firstname".to_string(), to_json(&session.firstname));
data.insert("lastname".to_string(), to_json(&session.lastname));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token));
data.insert("username".to_string(), to_json(&session.username));
data.insert(format!("sel{}", session.grade), to_json(&"selected"));
match user_id {
None => {
data.insert("firstname".to_string(), to_json(&session.firstname));
data.insert("lastname".to_string(), to_json(&session.lastname));
data.insert(format!("sel{}", session.grade), to_json(&"selected"));
data.insert("logincode".to_string(), to_json(&session.logincode));
if session.password.is_some() {
data.insert("username".to_string(), to_json(&session.username));
}
data.insert("ownprofile".into(), to_json(&true));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token));
},
Some(user_id) => {
// TODO: Add test to check if this access restriction works
let (user, opt_group) = conn.get_user_and_group_by_id(user_id).ok_or(MedalError::AccessDenied)?;
let group = opt_group.ok_or(MedalError::AccessDenied)?;
if group.admin != session.id {
return Err(MedalError::AccessDenied);
}
data.insert("firstname".to_string(), to_json(&user.firstname));
data.insert("lastname".to_string(), to_json(&user.lastname));
data.insert(format!("sel{}", user.grade), to_json(&"selected"));
data.insert("logincode".to_string(), to_json(&user.logincode));
if user.password.is_some() {
data.insert("username".to_string(), to_json(&user.username));
}
data.insert("ownprofile".into(), to_json(&false));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token));
}
}
Ok(("profile".to_string(), data))
}
pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, csrf_token: String, firstname: String, lastname: String, grade: u8) -> MedalResult<()> {
pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, user_id: Option<u32>, csrf_token: String, firstname: String, lastname: String, grade: u8) -> MedalResult<()> {
let mut session = conn.get_session(session_token).ok_or(MedalError::AccessDenied)?.ensure_alive().ok_or(MedalError::AccessDenied)?; // TODO SessionTimeout
if session.csrf_token != csrf_token {
return Err(MedalError::AccessDenied); // CsrfError
}
session.firstname = Some(firstname);
session.lastname = Some(lastname);
session.grade = grade;
conn.save_session(session);
match user_id {
None => {
session.firstname = Some(firstname);
session.lastname = Some(lastname);
session.grade = grade;
conn.save_session(session);
}
Some(user_id) => {
// TODO: Add test to check if this access restriction works
let (mut user, opt_group) = conn.get_user_and_group_by_id(user_id).ok_or(MedalError::AccessDenied)?;
let group = opt_group.ok_or(MedalError::AccessDenied)?;
if group.admin != session.id {
return Err(MedalError::AccessDenied);
}
user.firstname = Some(firstname);
user.lastname = Some(lastname);
user.grade = grade;
conn.save_session(user);
}
}
Ok(())
}
......
......@@ -545,7 +545,7 @@ fn profile(req: &mut Request) -> IronResult<Response> {
let conn = mutex.lock().unwrap_or_else(|e| e.into_inner());
// Antwort erstellen und zurücksenden
functions::show_profile(&*conn, session_token).aug(req)?
functions::show_profile(&*conn, session_token, None).aug(req)?
};
let mut resp = Response::new();
......@@ -570,23 +570,23 @@ fn profile_post(req: &mut Request) -> IronResult<Response> {
let conn = mutex.lock().unwrap_or_else(|e| e.into_inner());
// Antwort erstellen und zurücksenden
functions::edit_profile(&*conn, session_token, csrf_token, firstname, lastname, grade).aug(req)?
functions::edit_profile(&*conn, session_token, None, csrf_token, firstname, lastname, grade).aug(req)?
};
Ok(Response::with((status::Found, Redirect(url_for!(req, "profile")))))
}
fn user(req: &mut Request) -> IronResult<Response> {
let user_id = req.expect_int::<u32>("userid")?;
let session_token = req.expect_session_token()?;
let (template, data) = {
// hier ggf. Daten aus dem Request holen
let mutex = req.get::<Write<SharedDatabaseConnection>>().unwrap();
let _conn = mutex.lock().unwrap_or_else(|e| e.into_inner());
let conn = mutex.lock().unwrap_or_else(|e| e.into_inner());
// Antwort erstellen und zurücksenden
//functions::show_contests(&*conn)
let mut data = json_val::Map::new();
data.insert("reason".to_string(), to_json(&"Not implemented".to_string()));
("profile", data)
functions::show_profile(&*conn, session_token, Some(user_id)).aug(req)?
};
let mut resp = Response::new();
......@@ -594,6 +594,31 @@ fn user(req: &mut Request) -> IronResult<Response> {
Ok(resp)
}
fn user_post(req: &mut Request) -> IronResult<Response> {
let user_id = req.expect_int::<u32>("userid")?;
let session_token = req.expect_session_token()?;
let (csrf_token, firstname, lastname, grade) = {
let formdata = itry!(req.get_ref::<UrlEncodedBody>());
(iexpect!(formdata.get("csrftoken"))[0].to_owned(),
iexpect!(formdata.get("firstname"))[0].to_owned(),
iexpect!(formdata.get("lastname"))[0].to_owned(),
iexpect!(formdata.get("grade"))[0].parse::<u8>().unwrap_or(0))
};
let profilechangeresult = {
// hier ggf. Daten aus dem Request holen
let mutex = req.get::<Write<SharedDatabaseConnection>>().unwrap();
let conn = mutex.lock().unwrap_or_else(|e| e.into_inner());
// Antwort erstellen und zurücksenden
functions::edit_profile(&*conn, session_token, Some(user_id), csrf_token, firstname, lastname, grade).aug(req)?
};
Ok(Response::with((status::Found, Redirect(url_for!(req, "user", "userid" => format!("{}",user_id))))))
}
#[derive(Deserialize, Debug)]
struct OAuthAccess {
access_token: String,
......@@ -795,6 +820,7 @@ pub fn start_server(conn: Connection, config: ::Config) -> iron::error::HttpResu
profile: get "/profile" => profile,
profile_post: post "/profile" => profile_post,
user: get "/user/:userid" => user,
user_post: post "/user/:userid" => user_post,
/*contest_load_par: get "/load" => task_par,
contest_save_par: post "/save" => task_post_par,*/
task: get "/task/:taskid" => task,
......
<h1>Profil: {{firstname}} {{lastname}}</h1>
{{#if ownprofile}}
<h1>Mein Profil: {{firstname}} {{lastname}}</h1>
{{else}}
<h1>Benutzerdaten bearbeiten: {{firstname}} {{lastname}}</h1>
{{/if}}
{{#if username}}
<p>Benutzername: {{username}}</p>
{{/if}}
{{#if logincode}}
<p>Login-Code: {{logincode}}</p>
{{/if}}
<form action="" method="post">
<table>
......
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