Replace Rocket and Tera with Rouille and Maud #88
|
@ -86,7 +86,7 @@ pub fn send_password_reset() -> Result<(), PeachError> {
|
|||
"Your new temporary password is: {}
|
||||
|
||||
If you are on the same WiFi network as your PeachCloud device you can reset your password \
|
||||
using this link: http://peach.local/reset_password",
|
||||
using this link: http://peach.local/auth/reset",
|
||||
temporary_password
|
||||
);
|
||||
// if there is an external domain, then include remote link in message
|
||||
|
@ -95,7 +95,7 @@ using this link: http://peach.local/reset_password",
|
|||
Some(domain) => {
|
||||
format!(
|
||||
"\n\nOr if you are on a different WiFi network, you can reset your password \
|
||||
using the the following link: {}/reset_password",
|
||||
using the the following link: {}/auth/reset",
|
||||
domain
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use log::{error, info};
|
||||
use rouille::{router, Request, Response};
|
||||
|
||||
use crate::{
|
||||
|
@ -6,8 +7,11 @@ use crate::{
|
|||
SessionData,
|
||||
};
|
||||
|
||||
/// Receive an incoming request, mount the fileservers for static assets and
|
||||
/// define the publically-accessible routes.
|
||||
/// Request handler.
|
||||
///
|
||||
/// Mount the fileservers for static assets and define the
|
||||
/// publically-accessible routes (including per-route handlers). Includes
|
||||
/// logging of all incoming requests.
|
||||
///
|
||||
/// If the request is for a private route (ie. a route requiring successful
|
||||
/// authentication to view), check the authentication status of the user
|
||||
|
@ -32,42 +36,68 @@ pub fn handle_route(request: &Request, session_data: &mut Option<SessionData>) -
|
|||
return rouille::match_assets(&request, &blobstore);
|
||||
}
|
||||
|
||||
// handle the routes which are always accessible (ie. whether logged-in
|
||||
// or not)
|
||||
router!(request,
|
||||
(GET) (/auth/forgot) => {
|
||||
Response::html(routes::authentication::forgot::build_template())
|
||||
},
|
||||
// get the current time (for logging purposes)
|
||||
let now = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S%.6f");
|
||||
|
||||
(GET) (/auth/login) => {
|
||||
Response::html(routes::authentication::login::build_template(request))
|
||||
.reset_flash()
|
||||
},
|
||||
// define the success logger for incoming requests
|
||||
let log_ok = |req: &Request, _resp: &Response, _elap: std::time::Duration| {
|
||||
info!("{} {} {}", now, req.method(), req.raw_url());
|
||||
};
|
||||
|
||||
(POST) (/auth/login) => {
|
||||
routes::authentication::login::handle_form(request, session_data)
|
||||
},
|
||||
// define the error logger for incoming requests
|
||||
let log_err = |req: &Request, _elap: std::time::Duration| {
|
||||
error!(
|
||||
"{} Handler panicked: {} {}",
|
||||
now,
|
||||
req.method(),
|
||||
req.raw_url()
|
||||
);
|
||||
};
|
||||
|
||||
(GET) (/auth/reset) => {
|
||||
Response::html(routes::authentication::reset::build_template(request))
|
||||
.reset_flash()
|
||||
},
|
||||
// instantiate request logging
|
||||
rouille::log_custom(request, log_ok, log_err, || {
|
||||
// handle the routes which are always accessible (ie. whether logged-in
|
||||
// or not)
|
||||
router!(request,
|
||||
(GET) (/auth/forgot) => {
|
||||
Response::html(routes::authentication::forgot::build_template(request))
|
||||
.reset_flash()
|
||||
},
|
||||
|
||||
(POST) (/auth/reset) => {
|
||||
routes::authentication::reset::handle_form(request)
|
||||
},
|
||||
(GET) (/auth/login) => {
|
||||
Response::html(routes::authentication::login::build_template(request))
|
||||
.reset_flash()
|
||||
},
|
||||
|
||||
_ => {
|
||||
// now that we handled all the routes that are accessible in all
|
||||
// circumstances, we check that the user is logged in before proceeding
|
||||
if let Some(_session) = session_data.as_ref() {
|
||||
// logged in:
|
||||
// mount the routes which require authentication to view
|
||||
private_router::mount_peachpub_routes(request, session_data)
|
||||
} else {
|
||||
// not logged in:
|
||||
Response::redirect_303("/auth/login")
|
||||
(POST) (/auth/login) => {
|
||||
routes::authentication::login::handle_form(request, session_data)
|
||||
},
|
||||
|
||||
(GET) (/auth/reset) => {
|
||||
Response::html(routes::authentication::reset::build_template(request))
|
||||
.reset_flash()
|
||||
},
|
||||
|
||||
(POST) (/auth/reset) => {
|
||||
routes::authentication::reset::handle_form(request)
|
||||
},
|
||||
|
||||
(POST) (/auth/temporary) => {
|
||||
routes::authentication::temporary::handle_form()
|
||||
},
|
||||
|
||||
_ => {
|
||||
// now that we handled all the routes that are accessible in all
|
||||
// circumstances, we check that the user is logged in before proceeding
|
||||
if let Some(_session) = session_data.as_ref() {
|
||||
// logged in:
|
||||
// mount the routes which require authentication to view
|
||||
private_router::mount_peachpub_routes(request, session_data)
|
||||
} else {
|
||||
// not logged in:
|
||||
Response::redirect_303("/auth/login")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
use maud::{html, PreEscaped};
|
||||
use rouille::Request;
|
||||
|
||||
use crate::{templates, utils::theme};
|
||||
use crate::{
|
||||
templates,
|
||||
utils::{flash::FlashRequest, theme},
|
||||
};
|
||||
|
||||
// ROUTE: /auth/forgot
|
||||
|
||||
/// Forgot password template builder.
|
||||
pub fn build_template() -> PreEscaped<String> {
|
||||
let form_template = html! {
|
||||
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 password_reset_template = html! {
|
||||
(PreEscaped("<!-- PASSWORD RESET REQUEST CARD -->"))
|
||||
div class="card center" {
|
||||
div class="capsule capsule-container border-info" {
|
||||
|
@ -20,20 +27,26 @@ pub fn build_template() -> PreEscaped<String> {
|
|||
"Once you have the temporary password, click the 'Set New Password' button to reach the password reset page."
|
||||
}
|
||||
}
|
||||
form id="sendPasswordReset" action="/auth/send_password_reset" method="post" {
|
||||
form id="sendPasswordReset" action="/auth/temporary" method="post" {
|
||||
div id="buttonDiv" {
|
||||
input class="button button-primary center" style="margin-top: 1rem;" type="submit" value="Send Temporary Password" title="Send temporary password to Scuttlebutt admin";
|
||||
input class="button button-primary center" style="margin-top: 1rem;" type="submit" value="Send Temporary Password" title="Send temporary password to Scuttlebutt admin(s)";
|
||||
a href="/auth/reset_password" class="button button-primary center" title="Set a new password using the temporary password" {
|
||||
"Set New Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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, "Send Password Reset", Some("/"));
|
||||
let body =
|
||||
templates::nav::build_template(password_reset_template, "Send Password Reset", Some("/"));
|
||||
|
||||
// query the current theme so we can pass it into the base template builder
|
||||
let theme = theme::get_theme();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use log::info;
|
||||
use log::debug;
|
||||
use maud::{html, PreEscaped};
|
||||
use peach_lib::password_utils;
|
||||
use rouille::{post_input, try_or_400, Request, Response};
|
||||
|
@ -63,17 +63,17 @@ pub fn handle_form(request: &Request, session_data: &mut Option<SessionData>) ->
|
|||
|
||||
match password_utils::verify_password(&data.password) {
|
||||
Ok(_) => {
|
||||
info!("Successful login attempt");
|
||||
debug!("Successful login attempt");
|
||||
// if password verification is successful, write to `session_data`
|
||||
// to authenticate the user
|
||||
*session_data = Some(SessionData {
|
||||
_login: data.password,
|
||||
_login: "success".to_string(),
|
||||
});
|
||||
|
||||
Response::redirect_303("/")
|
||||
}
|
||||
Err(err) => {
|
||||
info!("Unsuccessful login attempt");
|
||||
debug!("Unsuccessful login attempt");
|
||||
let err_msg = format!("Invalid password: {}", err);
|
||||
let (flash_name, flash_msg) = (
|
||||
"flash_name=error".to_string(),
|
||||
|
|
|
@ -3,3 +3,4 @@ pub mod forgot;
|
|||
pub mod login;
|
||||
pub mod logout;
|
||||
pub mod reset;
|
||||
pub mod temporary;
|
||||
|
|
|
@ -100,7 +100,6 @@ pub fn handle_form(request: &Request) -> Response {
|
|||
&data.new_password2,
|
||||
) {
|
||||
Ok(_) => (
|
||||
// <cookie-name>=<cookie-value>
|
||||
"flash_name=success".to_string(),
|
||||
"flash_msg=New password has been saved. Return home to login".to_string(),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
use log::debug;
|
||||
use peach_lib::password_utils;
|
||||
use rouille::Response;
|
||||
|
||||
use crate::utils::flash::FlashResponse;
|
||||
|
||||
// ROUTE: /auth/temporary (POST)
|
||||
|
||||
/// Send a temporary password as a Scuttlebutt private message to the admin(s).
|
||||
///
|
||||
/// This route is used by a user who is not logged in and is specifically for
|
||||
/// users who have forgotten their password. A successful request results
|
||||
/// in a Scuttlebutt private message being sent to the account of the device
|
||||
/// admin.
|
||||
///
|
||||
/// Redirects to the Send Password Reset page a flash message describing the
|
||||
/// outcome of the action (may be successful or unsuccessful).
|
||||
pub fn handle_form() -> Response {
|
||||
// save submitted admin id to file
|
||||
let (flash_name, flash_msg) = match password_utils::send_password_reset() {
|
||||
Ok(_) => {
|
||||
debug!("Sent temporary password to device admin(s)");
|
||||
(
|
||||
"flash_name=success".to_string(),
|
||||
"flash_msg=A temporary password has been sent to the admin(s) of this device"
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
Err(err) => {
|
||||
debug!(
|
||||
"Received an error while trying to send temporary password to device admin(s): {}",
|
||||
err
|
||||
);
|
||||
(
|
||||
"error".to_string(),
|
||||
format!("Failed to send temporary password: {}", err),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
Response::redirect_303("/auth/forgot").add_flash(flash_name, flash_msg)
|
||||
}
|
Loading…
Reference in New Issue