Commit f71fced7 authored by Robert Czechowski's avatar Robert Czechowski
Browse files

Profile: Show and edit

parent a65d6b5d
......@@ -10,12 +10,14 @@ pub trait MedalConnection {
fn get_session(&self, key: String) -> Option<SessionUser>;
fn new_session(&self) -> SessionUser;
fn save_session(&self, session: SessionUser);
fn get_session_or_new(&self, key: String) -> SessionUser;
//fn login(&self, session: &SessionUser, username: String, password: String) -> Result<String,()>;
fn login(&self, session: Option<String>, username: String, password: String) -> Result<String,()>;
fn login_with_code(&self, session: Option<String>, logincode: String) -> Result<SessionUser,()>;
fn login_with_code(&self, session: Option<String>, logincode: String) -> Result<String,()>;
fn create_user_with_groupcode(&self, session: Option<String>, groupcode: String) -> Result<String,()>;
fn logout(&self, session: String);
fn load_submission(&self, session: &SessionUser, task: u32, subtask: Option<String>) -> Option<Submission>;
......
......@@ -74,6 +74,15 @@ impl MedalConnection for Connection {
}
}).unwrap())
}
fn save_session(&self, session: SessionUser) {
self.execute("UPDATE session_user SET
username = ?1,
password = ?2,
logincode = ?3,
firstname = ?4,
lastname = ?5,
grade = ?6 WHERE id = ?", &[&session.username, &session.password, &session.logincode, &session.firstname, &session.lastname, &session.grade, &session.id]).unwrap();
}
fn new_session(&self) -> SessionUser {
let session_token = "123".to_string();
let csrf_token = "123".to_string();
......@@ -115,9 +124,56 @@ impl MedalConnection for Connection {
},
_ => {println!("c"); Err(()) }
}
}
fn login_with_code(&self, session: Option<String>, logincode: String) -> Result<SessionUser,()> {unimplemented!()}
fn login_with_code(&self, session: Option<String>, logincode: String) -> Result<String,()> {
println!("a {}", logincode);
match self.query_row(
"SELECT id FROM session_user WHERE logincode = ?1",
&[&logincode],
|row| -> u32 {
row.get(0)
}) {
Ok(id) => {
// Login okay, update session now!
let session_token: String = thread_rng().gen_ascii_chars().take(10).collect();
let csrf_token: String = thread_rng().gen_ascii_chars().take(10).collect();
let now = time::get_time();
self.execute("UPDATE session_user SET session_token = ?1, csrf_token = ?2, last_login = ?3, last_activity = ?3 WHERE id = ?4", &[&session_token, &csrf_token, &now, &id]).unwrap();
Ok(session_token)
},
_ => {println!("c"); Err(()) }
}
}
fn create_user_with_groupcode(&self, session: Option<String>, groupcode: String) -> Result<String,()> {
println!("a {}", groupcode);
match self.query_row(
"SELECT id FROM usergroup WHERE groupcode = ?1",
&[&groupcode],
|row| -> u32 {
row.get(0)
}) {
Ok(group_id) => {
// Login okay, create session_user!
let session_token: String = thread_rng().gen_ascii_chars().take(10).collect();
let csrf_token: String = thread_rng().gen_ascii_chars().take(10).collect();
let login_code: String = thread_rng().gen_ascii_chars()
.filter(|x| {let x = *x; !(x == 'l' || x == 'I' || x == '1' || x == 'O' || x == 'o' || x == '0')})
.take(7).collect();
let now = time::get_time();
self.execute("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)", &[&session_token, &csrf_token, &now, &false, &login_code, &0, &false, &group_id]).unwrap();
Ok(session_token)
},
_ => {println!("c"); Err(()) }
}
}
fn logout(&self, session: String) {
self.execute("UPDATE session_user SET session_token = NULL WHERE id = ?1", &[&session]).unwrap();
}
......@@ -334,7 +390,56 @@ impl MedalConnection for Connection {
rows
}
fn get_groups_complete(&self, session_id: u32) -> Vec<Group> {unimplemented!();}
fn get_group_complete(&self, group_id: u32) -> Option<Group> {unimplemented!();}
fn get_group_complete(&self, group_id: u32) -> Option<Group> {
let mut group = self.query_row("SELECT name, groupcode, tag, admin FROM usergroup WHERE id = ?1", &[&group_id], |row| {
Group {
id: Some(group_id),
name: row.get(0),
groupcode: row.get(1),
tag: row.get(2),
admin: row.get(3),
members: Vec::new(),
}
}).unwrap(); // TODO handle error
let mut stmt = self.prepare("SELECT id, 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, pms_id, pms_school_id FROM session_user WHERE managed_by = ?1").unwrap();
let rows = stmt.query_map(&[&group_id], |row| {
SessionUser {
id: row.get(0),
session_token: row.get(1),
csrf_token: row.get(2),
last_login: row.get(3),
last_activity: row.get(4),
permanent_login: row.get(5),
username: row.get(6),
password: row.get(7),
salt: None,//"".to_string(),
logincode: row.get(8),
email: row.get(9),
email_unconfirmed: row.get(10),
email_confirmationcode: row.get(11),
firstname: row.get(12),
lastname: row.get(13),
street: row.get(14),
zip: row.get(15),
city: row.get(16),
nation: row.get(17),
grade: row.get(18),
is_teacher: row.get(19),
managed_by: Some(group_id),
pms_id: row.get(20),
pms_school_id: row.get(21),
}
}).unwrap();
for user in rows {
group.members.push(user.unwrap());
}
Some(group)
}
}
......
......@@ -89,12 +89,8 @@ pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: u32, session_token
data.insert("time_left".to_string(), to_json(&format!("{}:{}",left_min,left_sec)));
}
}
("contest".to_owned(), data)
("contest".to_owned(), data)
}
}
}
......@@ -125,6 +121,27 @@ pub fn login<T: MedalConnection>(conn: &T, login_data: (String, String)) -> Resu
}
}
pub fn login_with_code<T: MedalConnection>(conn: &T, code: String) -> Result<Result<String, String>, (String, json_val::Map<String, json_val::Value>)> {
match conn.login_with_code(None, code.clone()) {
Ok(session_token) => {
Ok(Ok(session_token))
},
Err(()) => {
match conn.create_user_with_groupcode(None, code.clone()) {
Ok(session_token) => {
Ok(Err(session_token))
},
Err(()) => {
let mut data = json_val::Map::new();
data.insert("reason".to_string(), to_json(&"Kein gültiger Code".to_string()));
data.insert("code".to_string(), to_json(&code));
Err(("login".to_owned(), data))
}
}
}
}
}
pub fn logout<T: MedalConnection>(conn: &T, session_token: Option<String>) -> () {
match session_token {
......@@ -186,6 +203,7 @@ pub fn show_task<T: MedalConnection>(conn: &T, task_id: u32, session_token: Stri
#[derive(Serialize, Deserialize)]
pub struct GroupInfo {
pub id: u32,
pub name: String,
pub tag: String,
pub code: String,
......@@ -199,6 +217,7 @@ pub fn show_groups<T: MedalConnection>(conn: &T, session_token: String) -> (Str
let mut data = json_val::Map::new();
let v : Vec<GroupInfo> = conn.get_groups(session.id).iter().map(|g| { GroupInfo {
id: g.id.unwrap(),
name: g.name.clone(),
tag: g.tag.clone(),
code: g.groupcode.clone(),
......@@ -209,6 +228,15 @@ pub fn show_groups<T: MedalConnection>(conn: &T, session_token: String) -> (Str
("groups".to_string(), data)
}
#[derive(Serialize, Deserialize)]
pub struct MemberInfo {
pub id: u32,
pub firstname: String,
pub lastname: String,
pub grade: u8,
pub logincode: String,
}
pub fn show_group<T: MedalConnection>(conn: &T, group_id: u32, session_token: String) -> Result<(String, json_val::Map<String, json_val::Value>),(String, json_val::Map<String, json_val::Value>)> {
let session = conn.get_session(session_token).unwrap(); // TODO handle error
let group = conn.get_group_complete(group_id).unwrap(); // TODO handle error
......@@ -219,11 +247,27 @@ pub fn show_group<T: MedalConnection>(conn: &T, group_id: u32, session_token: St
return Err(("error".to_owned(), data));
}
data.insert("groupname".to_string(), to_json(&group.name));
data.insert("grouptag".to_string(), to_json(&group.tag));
let gi = GroupInfo {
id: group.id.unwrap(),
name: group.name.clone(),
tag: group.tag.clone(),
code: group.groupcode.clone(),
};
let v : Vec<MemberInfo> = group.members.iter().map(|m| { MemberInfo {
id: m.id,
firstname: m.firstname.clone().unwrap_or("".to_string()),
lastname: m.lastname.clone().unwrap_or("".to_string()),
grade: m.grade,
logincode: m.logincode.clone().unwrap_or("".to_string()),
}}).collect();
data.insert("group".to_string(), to_json(&gi));
data.insert("member".to_string(), to_json(&v));
Ok(("group".to_string(), data))
}
pub fn modify_group<T: MedalConnection>(conn: &T, group_id: u32, session_token: String) -> Result<(),(String, json_val::Map<String, json_val::Value>)> {
unimplemented!()
}
......@@ -250,3 +294,37 @@ pub fn add_group<T: MedalConnection>(conn: &T, session_token: String, csrf_token
Ok(group.id.unwrap())
}
pub fn show_profile<T: MedalConnection>(conn: &T, session_token: String) -> (String, json_val::Map<String, json_val::Value>) {
let session = conn.get_session(session_token).unwrap(); // TODO handle error
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"));
("profile".to_string(), data)
}
pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, csrf_token: String, firstname: String, lastname: String, grade: u8) -> Result<(),(String, json_val::Map<String, json_val::Value>)> {
let mut session = conn.get_session(session_token).unwrap(); // TODO handle error
if session.csrf_token != csrf_token {
let mut data = json_val::Map::new();
return Err(("error".to_owned(), data));
}
session.firstname = Some(firstname);
session.lastname = Some(lastname);
session.grade = grade;
conn.save_session(session);
Ok(())
}
......@@ -209,6 +209,41 @@ fn login_post(req: &mut Request) -> IronResult<Response> {
}
}
fn login_code_post(req: &mut Request) -> IronResult<Response> {
let code = {
let formdata = itry!(req.get_ref::<UrlEncodedBody>());
iexpect!(formdata.get("code"))[0].to_owned()
};
let loginresult = {
let mutex = req.get::<Write<SharedDatabaseConnection>>().unwrap();
let conn = mutex.lock().unwrap();
// Antwort erstellen und zurücksenden
functions::login_with_code(&*conn, code)
};
println!("aa");
match loginresult {
// Login successful
Ok(Ok(sessionkey)) => {
req.session().set(SessionToken { token: sessionkey }).unwrap();
Ok(Response::with((status::Found, Redirect(url_for!(req, "greet")))))
},
Ok(Err(sessionkey)) => {
req.session().set(SessionToken { token: sessionkey }).unwrap();
Ok(Response::with((status::Found, Redirect(url_for!(req, "profile")))))
},
// Login failed
Err((template, data)) => {
println!("bb");
let mut resp = Response::new();
resp.set_mut(Template::new(&template, data)).set_mut(status::Ok);
Ok(resp)
}
}
}
fn logout(req: &mut Request) -> IronResult<Response> {
let session_token = SessionRequestExt::session(req).get::<SessionToken>().unwrap();
......@@ -406,6 +441,59 @@ fn new_group(req: &mut Request) -> IronResult<Response> {
}
fn profile(req: &mut Request) -> IronResult<Response> {
let session_token = SessionRequestExt::session(req).get::<SessionToken>().unwrap().unwrap();
let (template, data) = {
// hier ggf. Daten aus dem Request holen
let mutex = req.get::<Write<SharedDatabaseConnection>>().unwrap();
let conn = mutex.lock().unwrap();
// Antwort erstellen und zurücksenden
functions::show_profile(&*conn, session_token.token)
/*let mut data = json_val::Map::new();
data.insert("reason".to_string(), to_json(&"Not implemented".to_string()));
("profile", data)*/
};
let mut resp = Response::new();
resp.set_mut(Template::new(&template, data)).set_mut(status::Ok);
Ok(resp)
}
fn profile_post(req: &mut Request) -> IronResult<Response> {
let session_token = SessionRequestExt::session(req).get::<SessionToken>().unwrap().unwrap();
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();
// Antwort erstellen und zurücksenden
functions::edit_profile(&*conn, session_token.token, csrf_token, firstname, lastname, grade)
/*let mut data = json_val::Map::new();
data.insert("reason".to_string(), to_json(&"Not implemented".to_string()));
("profile", data)*/
};
println!("hiiiiii");
match profilechangeresult {
Ok(()) => Ok(Response::with((status::Found, Redirect(url_for!(req, "profile"))))),
Err((template, data)) => {
let mut resp = Response::new();
resp.set_mut(Template::new(&template, data)).set_mut(status::Ok);
Ok(resp)
}
}
}
fn user(req: &mut Request) -> IronResult<Response> {
let (template, data) = {
// hier ggf. Daten aus dem Request holen
let mutex = req.get::<Write<SharedDatabaseConnection>>().unwrap();
......@@ -471,7 +559,8 @@ pub fn start_server(conn: Connection) {
contest_post: post "/contest/:contestid" => contest_post,
login: get "/login" => login,
login_post: post "/login" => login_post,
logout: post "/logout" => logout,
login_code_post: post "/clogin" => login_code_post,
logout: get "/logout" => logout,
subm: get "/submission/:taskid" => submission,
subm_post: post "/submission/:taskid" => submission_post,
subm_load: get "/load/:taskid" => submission,
......@@ -481,6 +570,8 @@ pub fn start_server(conn: Connection) {
group: get "/group/:groupid" => group,
group_post: post "/group" => group_post,
profile: get "/profile" => profile,
profile_post: post "/profile" => profile_post,
user: get "/user/:userid" => user,
/*contest_load_par: get "/load" => task_par,
contest_save_par: post "/save" => task_post_par,*/
task: get "/task/:taskid" => task,
......
......@@ -2,6 +2,10 @@
<p><a href="/login">Login</a>
<p><a href="/logout">Logout</a>
<p><a href="/contest">Wettbewerb</a>
<p><a href="/group">Groups</a>
<p><a href="/group">Gruppenverwaltung</a>
<p><a href="/profile">Profil</a>
\ No newline at end of file
<h1>Gruppe: 3a</h1>
<h1>Gruppe: {{group.name}}</h1>
<p>Gruppencode: r487an48ase<br>
Mitglieder: 1<br>
Marker: 3a</p>
<p>Gruppencode: {{group.code}}<br>
Mitglieder: <br>
Marker: {{group.tag}}</p>
<p><a href="/group">Zurück zur Gruppenübersicht</a></p>
<h2>Mitglieder</h2>
......@@ -13,11 +13,20 @@ Marker: 3a</p>
<th>Jahrgangstufe</th>
</tr>
<tr>
<td><a href="user/1">Robert Czechowski</a></td>
<td><a href="/user/1">Robert Czechowski</a></td>
<td>ag83uten</td>
<td>3</td>
<td><a href="user/1">bearbeiten …</a></td>
<td><a href="/user/1">bearbeiten …</a></td>
</tr>
{{#each member}}
<tr>
<td><a href="/user/{{id}}">{{firstname}} {{lastname}}</a></td>
<td>{{logincode}}</td>
<td>{{grade}}</td>
<td><a href="/user/{{id}}">bearbeiten …</a></td>
</tr>
{{/each}}
</table>
......
......@@ -31,15 +31,16 @@
<td>3a</td>
<td><a href="/group/1">bearbeiten …</a></td>
</tr>
{{#each group}}
<tr>
<td><a href="/group/{{id}}">{{name}}</a></td>
<td>{{code}}</td>
<td></td>
<td>{{tag}}</td>
<td><a href="/group/{{id}}">bearbeiten …</a></td>
</tr>
{{/each}}
</table></p>
<ul>
{{#each group}}
<li><a href="/contest/{{id}}">{{name}}, {{tag}}, {{code}}</li>
{{/each}}
</ul>
<p><a href="/">Zurück zur Startseite</a></p>
......@@ -17,11 +17,11 @@
<form action="clogin" method="post">
Gruppencode / Teilnahmecode:<br>
<input type="text" name="logincode" value="">
<input type="text" name="code" value="{{ code }}">
<br><br>
<input type="submit" value="log in">
</form>
<p>
<a href="https://testpms.bwinf.de/app/PMS/wa/OAuth2/authorize?client_id=bwinf-junior-league&scope=authenticate&response_type=code&state=42&redirect_uri=https%3A%2F%2Fzgtm.de/oauth/">PMS-Login</a>
\ No newline at end of file
<a href="https://testpms.bwinf.de/app/PMS/wa/OAuth2/authorize?client_id=bwinf-junior-league&scope=authenticate&response_type=code&state=42&redirect_uri=https%3A%2F%2Fzgtm.de/oauth/">PMS-Login</a>
<h1>Profil: Robert Czechowski</h1>
<h1>Profil: {{firstname}} {{lastname}}</h1>
<form action="" method="post">
<table>
<tr>
<td>Vorname</td><td><input value="Robert"></td>
<td>Vorname</td><td><input name="firstname" value="{{ firstname }}"></td>
</tr>
<tr>
<td>Nachname</td><td><input value="Czechowski"></td>
<td>Nachname</td><td><input name="lastname" value="{{ lastname }}"></td>
</tr>
<tr>
<td>Jahrgangsstufe</td><td>
<select>
<option value="0">Noch kein Schüler</option>
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11 (G8)</option>
<option value="12">12 (G8)</option>
<option value="111">11 (G9)</option>
<option value="112">12 (G9)</option>
<option value="113">13</option>
<option value="14">Berufsschule</option>
<option value="15">Kein Schüler mehr</option>
<select name="grade">
<option value="0" {{ sel0 }}>Noch kein Schüler</option>
<option value="1" {{ sel1 }}>1</option>
<option value="2" {{ sel2 }}>2</option>
<option value="3" {{ sel3 }}>3</option>
<option value="4" {{ sel4 }}>4</option>
<option value="5" {{ sel5 }}>5</option>
<option value="6" {{ sel6 }}>6</option>
<option value="7" {{ sel7 }}>7</option>
<option value="8" {{ sel8 }}>8</option>
<option value="9" {{ sel9 }}>9</option>
<option value="10" {{ sel10 }}>10</option>
<option value="11" {{ sel11 }}>11 (G8)</option>
<option value="12" {{ sel12 }}>12 (G8)</option>
<option value="111" {{ sel111 }}>11 (G9)</option>
<option value="112" {{ sel112 }}>12 (G9)</option>
<option value="113" {{ sel113 }}>13 (G9)</option>
<option value="114" {{ sel114 }}>Berufsschule</option>
<option value="255" {{ sel255 }}>Kein Schüler mehr</option>
</select>
</td>
</tr>
<tr>
<td></td><td><input type="submit" value="Speichern"></td>
<td></td><td><input type="hidden" name="csrftoken" value="{{ csrftoken }}"><input type="submit" value="Speichern"></td>
</tr>
</table>
</form>
......
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