115 lines
4.7 KiB
Rust
115 lines
4.7 KiB
Rust
use log::info;
|
|
use maud::{html, PreEscaped};
|
|
use peach_lib::password_utils;
|
|
use rouille::{post_input, try_or_400, Request, Response};
|
|
|
|
use crate::{
|
|
error::PeachWebError,
|
|
templates,
|
|
utils::{
|
|
flash::{FlashRequest, FlashResponse},
|
|
theme,
|
|
},
|
|
};
|
|
|
|
// HELPER AND ROUTES FOR /auth/reset (GET and POST)
|
|
|
|
/// Password reset form template builder.
|
|
pub fn build_template(request: &Request) -> PreEscaped<String> {
|
|
// check for flash cookies; will be (None, None) if no flash cookies are found
|
|
let (flash_name, flash_msg) = request.retrieve_flash();
|
|
|
|
let form_template = html! {
|
|
(PreEscaped("<!-- RESET PASSWORD PAGE -->"))
|
|
div class="card center" {
|
|
form id="resetPassword" class="center" action="/auth/reset" method="post" {
|
|
div style="display: flex; flex-direction: column; margin-bottom: 1rem;" {
|
|
(PreEscaped("<!-- input for temporary password -->"))
|
|
label for="temporaryPassword" class="center label-small font-gray" style="width: 80%;" { "TEMPORARY PASSWORD" }
|
|
input id="temporaryPassword" class="center input" name="temporary_password" type="password" title="Temporary password" autofocus;
|
|
(PreEscaped("<!-- input for new password1 -->"))
|
|
label for="newPassword" class="center label-small font-gray" style="width: 80%;" { "NEW PASSWORD" }
|
|
input id="newPassword" class="center input" name="new_password1" type="password" title="New password";
|
|
(PreEscaped("<!-- input for duplicate new password -->"))
|
|
label for="newPasswordDuplicate" class="center label-small font-gray" style="width: 80%;" { "RE-ENTER NEW PASSWORD" }
|
|
input id="newPasswordDuplicate" class="center input" name="new_password2" type="password" title="New password duplicate";
|
|
(PreEscaped("<!-- save (form submission) button -->"))
|
|
input id="savePassword" class="button button-primary center" title="Add" type="submit" value="Save";
|
|
a class="button button-secondary center" href="/settings/admin" title="Cancel"{ "Cancel" }
|
|
}
|
|
}
|
|
// render flash message if cookies were found in the request
|
|
@if let (Some(name), Some(msg)) = (flash_name, flash_msg) {
|
|
(PreEscaped("<!-- FLASH MESSAGE -->"))
|
|
(templates::flash::build_template(name, msg))
|
|
}
|
|
}
|
|
};
|
|
|
|
// wrap the nav bars around the settings menu template content
|
|
// parameters are template, title and back url
|
|
let body =
|
|
templates::nav::build_template(form_template, "Reset Password", Some("/settings/admin"));
|
|
|
|
// query the current theme so we can pass it into the base template builder
|
|
let theme = theme::get_theme();
|
|
|
|
// render the base template with the provided body
|
|
templates::base::build_template(body, theme)
|
|
}
|
|
|
|
/// Verify, validate and set a new password, overwriting the current password.
|
|
pub fn save_password(
|
|
temporary_password: &str,
|
|
new_password1: &str,
|
|
new_password2: &str,
|
|
) -> Result<(), PeachWebError> {
|
|
info!(
|
|
"Attempting password reset: {} {} {}",
|
|
temporary_password, new_password1, new_password2
|
|
);
|
|
|
|
// check that the supplied value matches the actual temporary password
|
|
password_utils::verify_temporary_password(temporary_password)?;
|
|
|
|
// ensure that both new_password values match
|
|
password_utils::validate_new_passwords(new_password1, new_password2)?;
|
|
|
|
// hash the password and save the hash to file
|
|
password_utils::set_new_password(new_password1)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Parse temporary and new passwords from the submitted form, save the new
|
|
/// password hash to file (`/var/lib/peachcloud/config.yml`) and redirect
|
|
/// to the reset password form URL.
|
|
pub fn handle_form(request: &Request) -> Response {
|
|
// query the request body for form data
|
|
// return a 400 error if the admin_id field is missing
|
|
let data = try_or_400!(post_input!(request, {
|
|
temporary_password: String,
|
|
new_password1: String,
|
|
new_password2: String,
|
|
}));
|
|
|
|
// save submitted admin id to file
|
|
let (flash_name, flash_msg) = match save_password(
|
|
&data.temporary_password,
|
|
&data.new_password1,
|
|
&data.new_password2,
|
|
) {
|
|
Ok(_) => (
|
|
"flash_name=success".to_string(),
|
|
"flash_msg=New password has been saved. Return home to login".to_string(),
|
|
),
|
|
Err(err) => (
|
|
"flash_name=error".to_string(),
|
|
format!("flash_msg=Failed to reset password: {}", err),
|
|
),
|
|
};
|
|
|
|
// redirect to the configure admin page
|
|
Response::redirect_303("/auth/reset").add_flash(flash_name, flash_msg)
|
|
}
|