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

Password changing: Clean up code, harmonise some variable naming, show bold...

Password changing: Clean up code, harmonise some variable naming, show bold messages to users, append ProfileStatus directly to URL via derive(Debug) and forward directly into template
parent 40ebad9c
......@@ -483,19 +483,10 @@ pub fn show_profile<T: MedalConnection>(conn: &T, session_token: String, user_id
data.insert("csrftoken".to_string(), to_json(&session.csrf_token));
let status = query_string.unwrap();
if status == "status=password_not_matched" {
data.insert("password_not_matched".to_string(), to_json(&true));
}
else if status == "status=password_changed" {
data.insert("password_changed".to_string(), to_json(&true));
}
else if status == "status=personal_data_changed" {
data.insert("personal_data_changed".to_string(), to_json(&true));
}
else if status == "status=nothing_changed" {
data.insert("nothing_changed".to_string(), to_json(&true));
}
query_string.map(|query| {
if query.starts_with("status=") {
data.insert((&query[7..]).to_string(), to_json(&true));
}});
},
Some(user_id) => {
// TODO: Add test to check if this access restriction works
......@@ -533,26 +524,48 @@ fn hash_password(password: &str, salt: &str) -> Result<String, BcryptError> {
}
}
pub enum ChangeData {
data_changed,
pw_changed_success,
pw_changed_failed,
#[derive(Debug)]
pub enum ProfileStatus {
nothing_changed,
data_changed,
password_changed,
password_missmatch,
}
impl std::convert::Into<String> for ProfileStatus {
fn into(self) -> String {
format!("{:?}", self)
}
}
pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, user_id: Option<u32>, csrf_token: String, firstname: String, lastname: String, new_password_1: String, new_password_2: String, grade: u8) -> MedalResult<ChangeData> {
pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, user_id: Option<u32>, csrf_token: String, firstname: String, lastname: String, password: String, password_repeat: String, grade: u8) -> MedalResult<ProfileStatus> {
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
}
let mut result = ChangeData::data_changed;
if session.firstname.as_ref() == Some(&firstname)
&& session.lastname.as_ref() == Some(&lastname)
&& session.grade == grade
&& password == ""
&& password_repeat == "" {
return Ok(ProfileStatus::nothing_changed);
}
let mut result = ProfileStatus::data_changed;
let mut password_salt = None;
let firstname_for_check: String = firstname.to_owned();
let lastname_for_check: String = lastname.to_owned();
if session.firstname == Some(firstname_for_check) && session.lastname == Some(lastname_for_check) && session.grade == grade && new_password_1 == "" && new_password_2 == "" {
result = ChangeData::nothing_changed;
if password != "" || password_repeat != "" {
if password == password_repeat {
let salt: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
let hash = hash_password(&password, &salt).ok()?;
password_salt = Some((hash, salt));
result = ProfileStatus::password_changed;
} else {
result = ProfileStatus::password_missmatch;
}
}
match user_id {
......@@ -561,18 +574,11 @@ pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, user_id
session.lastname = Some(lastname);
session.grade = grade;
if new_password_1 != "" && new_password_2 != "" && new_password_1 == new_password_2 {
let salt: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
let hash = hash_password(&new_password_1, &salt).ok()?;
session.password = Some(hash);
session.salt = Some(salt.into());
result = ChangeData::pw_changed_success;
}
else if (new_password_1 != "" && new_password_2 != "" && new_password_1 != new_password_2) || ((new_password_1 != "" || new_password_2 != "") && new_password_1 != new_password_2) {
result = ChangeData::pw_changed_failed;
if let Some((password, salt)) = password_salt {
session.password = Some(password);
session.salt = Some(salt);
}
conn.save_session(session);
}
Some(user_id) => {
......@@ -587,18 +593,11 @@ pub fn edit_profile<T: MedalConnection>(conn: &T, session_token: String, user_id
user.lastname = Some(lastname);
user.grade = grade;
if new_password_1 != "" && new_password_2 != "" && new_password_1 == new_password_2 {
let salt: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
let hash = hash_password(&new_password_1, &salt).ok()?;
user.password = Some(hash);
user.salt = Some(salt.into());
result = ChangeData::pw_changed_success;
if let Some((password, salt)) = password_salt {
user.password = Some(password);
user.salt = Some(salt);
}
else if (new_password_1 != "" && new_password_2 != "" && new_password_1 != new_password_2) || ((new_password_1 != "" || new_password_2 != "") && new_password_1 != new_password_2) {
result = ChangeData::pw_changed_failed;
}
conn.save_session(user);
}
}
......
......@@ -590,10 +590,7 @@ fn new_group(req: &mut Request) -> IronResult<Response> {
fn profile(req: &mut Request) -> IronResult<Response> {
let session_token = req.require_session_token()?;
let query_string :String = match req.url.query() {
Some(t) => t,
None => "",
}.to_string();
let query_string = req.url.query().map(|s| s.to_string());
let (template, data) = {
// hier ggf. Daten aus dem Request holen
......@@ -601,7 +598,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, None, Some(query_string)).aug(req)?
functions::show_profile(&*conn, session_token, None, query_string).aug(req)?
};
let mut resp = Response::new();
......@@ -611,32 +608,26 @@ fn profile(req: &mut Request) -> IronResult<Response> {
fn profile_post(req: &mut Request) -> IronResult<Response> {
let session_token = req.expect_session_token()?;
let (csrf_token, firstname, lastname, new_password_1, new_password_2, grade) = {
let (csrf_token, firstname, lastname, password, password_repeat, 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("new_password_1"))[0].to_owned(),
iexpect!(formdata.get("new_password_2"))[0].to_owned(),
iexpect!(formdata.get("password"))[0].to_owned(),
iexpect!(formdata.get("password_repeat"))[0].to_owned(),
iexpect!(formdata.get("grade"))[0].parse::<u8>().unwrap_or(0)
)
};
// 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
let ans ={ functions::edit_profile(&*conn, session_token, None, csrf_token, firstname, lastname, new_password_1, new_password_2, grade)};
match ans {
Ok(functions::ChangeData::pw_changed_failed) => Ok(Response::with((status::Found, Redirect(iron::Url::parse(&format!("{}{}", &url_for!(req, "profile"),"?status=password_not_matched")).unwrap())))),
Ok(functions::ChangeData::pw_changed_success) => Ok(Response::with((status::Found, Redirect(iron::Url::parse(&format!("{}{}", &url_for!(req, "profile"),"?status=password_changed")).unwrap())))),
Ok(functions::ChangeData::data_changed) => Ok(Response::with((status::Found, Redirect(iron::Url::parse(&format!("{}{}", &url_for!(req, "profile"),"?status=personal_data_changed")).unwrap())))),
Ok(functions::ChangeData::nothing_changed) => Ok(Response::with((status::Found, Redirect(iron::Url::parse(&format!("{}{}", &url_for!(req, "profile"),"?status=nothing_changed")).unwrap())))),
Err(_) => Ok(Response::with((status::Found, Redirect(url_for!(req, "profile"))))),
}
let changestatus = {
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, None, csrf_token, firstname, lastname, password, password_repeat, grade).aug(req)?
};
Ok(Response::with((status::Found, Redirect(iron::Url::parse(&format!("{}?status={:?}", &url_for!(req, "profile"), changestatus)).unwrap()))))
}
fn user(req: &mut Request) -> IronResult<Response> {
......@@ -660,14 +651,14 @@ fn user(req: &mut Request) -> IronResult<Response> {
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, new_password_1, new_password_2, grade) = {
let (csrf_token, firstname, lastname, pwd, pwd_repeat, 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("new_password_1"))[0].to_owned(),
iexpect!(formdata.get("new_password_2"))[0].to_owned(),
iexpect!(formdata.get("password"))[0].to_owned(),
iexpect!(formdata.get("password_repeat"))[0].to_owned(),
iexpect!(formdata.get("grade"))[0].parse::<u8>().unwrap_or(0),
)
......@@ -679,7 +670,7 @@ fn user_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, Some(user_id), csrf_token, firstname, lastname, new_password_1, new_password_2, grade).aug(req)?
functions::edit_profile(&*conn, session_token, Some(user_id), csrf_token, firstname, lastname, pwd, pwd_repeat, grade).aug(req)?
};
Ok(Response::with((status::Found, Redirect(url_for!(req, "user", "userid" => format!("{}",user_id))))))
......
......@@ -15,13 +15,13 @@
<form action="" method="post">
<table>
<tr>
<td>Vorname</td><td><input name="firstname" value="{{ firstname }}"></td>
<td>Vorname:</td><td><input name="firstname" value="{{ firstname }}"></td>
</tr>
<tr>
<td>Nachname</td><td><input name="lastname" value="{{ lastname }}"></td>
<td>Nachname:</td><td><input name="lastname" value="{{ lastname }}"></td>
</tr>
<tr>
<td>Jahrgangsstufe</td><td>
<td>Jahrgangsstufe:</td><td>
<select name="grade">
<option value="0" {{ sel0 }}>Noch kein Schüler</option>
<option value="1" {{ sel1 }}>1</option>
......@@ -45,10 +45,10 @@
</td>
</tr>
<tr>
<td>Neues Passwort:</td><td><input type="password" name="new_password_1" value=""></td>
<td>Neues Passwort:</td><td><input type="password" name="password" value=""></td>
</tr>
<tr>
<td>Neues Passwort wiederholen:</td><td><input type="password" name="new_password_2" value=""></td>
<td>Neues Passwort (wdh):</td><td><input type="password" name="password_repeat" value=""></td>
</tr>
<tr>
<td></td><td><input type="hidden" name="csrftoken" value="{{ csrftoken }}"><input type="submit" value="Speichern"></td>
......@@ -56,21 +56,23 @@
</table>
</form>
{{#if password_not_matched}}
<p>Die eingegebenen Paswörter stimmen nicht überein. Bitte versuche es nochmal.</p>
{{/if}}
<div style="color:green; font-weight:bold">
{{#if nothing_changed}}
<p>Keine Änderungen.</p>
{{/if}}
{{#if password_changed}}
<p>Dein Passwort wurde erfolgreich geändert.</p>
{{/if}}
{{#if data_changed}}
<p>Daten wurden erfolgreich geändert.</p>
{{/if}}
{{#if personal_data_changed}}
<p>Deine Daten wurden erfolgreich geändert.</p>
{{/if}}
{{#if password_changed}}
<p>Passwort wurde erfolgreich geändert.</p>
{{/if}}
{{#if nothing_changed}}
<p>Bitte ändere deine Daten, bevor du auf "Speichern" klickst.</p>
{{/if}}
{{#if password_missmatch}}
<p style="color:red;">Die eingegebenen Paswörter stimmen nicht überein. Passwort wurde nicht geändert.</p>
{{/if}}
<div>
<a href="/">Zur Startseite</a>
......
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