142 lines
3.9 KiB
Rust
142 lines
3.9 KiB
Rust
use crate::db::{Dao, TenebrousDbConn};
|
|
use crate::models::users::{self, NewUser, User};
|
|
use log::error;
|
|
use rocket::http::{Cookie, CookieJar};
|
|
use rocket::request::{FlashMessage, Form};
|
|
use rocket::response::{Flash, Redirect};
|
|
use rocket_contrib::templates::Template;
|
|
use std::collections::HashMap;
|
|
|
|
pub(crate) fn routes() -> Vec<rocket::Route> {
|
|
routes![
|
|
login,
|
|
logout,
|
|
logged_in_user,
|
|
login_page,
|
|
register_page,
|
|
register
|
|
]
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct Login {
|
|
username: String,
|
|
password: String,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct Registration {
|
|
username: String,
|
|
password: String,
|
|
}
|
|
|
|
fn add_login_cookie(cookies: &CookieJar<'_>, user: &User) {
|
|
cookies.add_private(Cookie::new("user_id", user.id.to_string()));
|
|
}
|
|
|
|
fn remove_login_cookie(cookies: &CookieJar<'_>) {
|
|
cookies.remove_private(Cookie::named("user_id"));
|
|
}
|
|
|
|
fn login_error_redirect<S: AsRef<str>>(message: S) -> Flash<Redirect> {
|
|
Flash::error(Redirect::to(uri!(login_page)), message.as_ref())
|
|
}
|
|
|
|
fn registration_error_redirect<S: AsRef<str>>(message: S) -> Flash<Redirect> {
|
|
Flash::error(Redirect::to(uri!(register_page)), message.as_ref())
|
|
}
|
|
|
|
#[post("/login", data = "<login>")]
|
|
async fn login(
|
|
cookies: &CookieJar<'_>,
|
|
login: Form<Login>,
|
|
conn: TenebrousDbConn,
|
|
) -> Result<Redirect, Flash<Redirect>> {
|
|
let user = conn
|
|
.load_user(login.username.clone())
|
|
.await
|
|
.map_err(|e| {
|
|
error!("login - error loading user user: {}", e);
|
|
login_error_redirect("Internal error.")
|
|
})?
|
|
.ok_or_else(|| login_error_redirect("Invalid username or password."))?;
|
|
|
|
if user.verify_password(&login.password) {
|
|
add_login_cookie(cookies, &user);
|
|
Ok(Redirect::to(uri!(super::root::index)))
|
|
} else {
|
|
Err(login_error_redirect("Invalid username or password."))
|
|
}
|
|
}
|
|
|
|
#[post("/logout")]
|
|
fn logout(cookies: &CookieJar<'_>) -> Flash<Redirect> {
|
|
remove_login_cookie(cookies);
|
|
Flash::success(Redirect::to(uri!(login_page)), "Successfully logged out.")
|
|
}
|
|
|
|
#[get("/login")]
|
|
fn logged_in_user(_user: &User) -> Redirect {
|
|
Redirect::to(uri!(super::root::index))
|
|
}
|
|
|
|
#[get("/login", rank = 2)]
|
|
fn login_page(flash: Option<FlashMessage>) -> Template {
|
|
let mut context = HashMap::new();
|
|
if let Some(ref msg) = flash {
|
|
context.insert("flash", msg.msg());
|
|
}
|
|
|
|
Template::render("login", &context)
|
|
}
|
|
|
|
#[get("/register")]
|
|
fn register_page(flash: Option<FlashMessage>) -> Template {
|
|
let mut context = HashMap::new();
|
|
if let Some(ref msg) = flash {
|
|
context.insert("flash", msg.msg());
|
|
}
|
|
|
|
Template::render("registration", &context)
|
|
}
|
|
|
|
#[post("/register", data = "<registration>")]
|
|
async fn register(
|
|
mut cookies: &CookieJar<'_>,
|
|
registration: Form<Registration>,
|
|
conn: TenebrousDbConn,
|
|
) -> Result<Redirect, Flash<Redirect>> {
|
|
let existing_user = conn
|
|
.load_user(registration.username.clone())
|
|
.await
|
|
.map_err(|e| {
|
|
error!("registration - error loading existing user: {}", e);
|
|
registration_error_redirect("There was an error attempting to register.")
|
|
})?;
|
|
|
|
if existing_user.is_some() {
|
|
return Err(registration_error_redirect(format!(
|
|
"The username {} is already taken.",
|
|
registration.username
|
|
)));
|
|
}
|
|
|
|
let hashed_pw = users::hash_password(®istration.password).map_err(|e| {
|
|
error!("registration - password hashing error: {}", e);
|
|
registration_error_redirect("There was an error attempting to register.")
|
|
})?;
|
|
|
|
let user = NewUser {
|
|
username: registration.username.clone(),
|
|
password: hashed_pw,
|
|
};
|
|
|
|
let user = conn.insert_user(user).await.map_err(|e| {
|
|
error!("registration - could not insert user: {}", e);
|
|
registration_error_redirect("There was an error completing registration.")
|
|
})?;
|
|
|
|
add_login_cookie(&mut cookies, &user);
|
|
Ok(Redirect::to(uri!(super::root::index)))
|
|
}
|