diff options
author | Cara Salter <cara@devcara.com> | 2022-07-19 19:49:39 -0400 |
---|---|---|
committer | Cara Salter <cara@devcara.com> | 2022-07-19 19:49:39 -0400 |
commit | c742b752140ab0eee6e353c779bd897042ba6739 (patch) | |
tree | 58953fdcaedb7e6c458a29dd980b8f97fb1af2a7 /src/handlers/auth.rs | |
parent | 1bd04149f8f6133b817a37a37a91397750c76c1b (diff) | |
download | nccd-c742b752140ab0eee6e353c779bd897042ba6739.tar.gz nccd-c742b752140ab0eee6e353c779bd897042ba6739.zip |
Big login system
Still needs cookies, but those are coming! (and should be set anyways!)
Diffstat (limited to 'src/handlers/auth.rs')
-rw-r--r-- | src/handlers/auth.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/handlers/auth.rs b/src/handlers/auth.rs new file mode 100644 index 0000000..c4672aa --- /dev/null +++ b/src/handlers/auth.rs @@ -0,0 +1,79 @@ +use std::sync::Arc; + +use axum::{response::{IntoResponse, Html, Redirect}, Form, Extension}; +use axum_extra::extract::{PrivateCookieJar, cookie::Cookie}; +use serde::Deserialize; +use sqlx::{query, query_as}; +use tracing::debug; +use crate::{errors::ServiceError, State, models::DbUser}; +use chrono::prelude::*; + +#[derive(Deserialize, Debug)] +pub struct RegisterForm { + pub email: String, + pub prefname: String, + pub password: String, + #[serde(rename="password-confirm")] + pub password_confirm: String +} + +#[derive(Deserialize)] +pub struct LoginForm { + pub email: String, + pub password: String, +} + +pub async fn login() -> impl IntoResponse { + let mut buf = Vec::new(); + crate::templates::login_html(&mut buf).unwrap(); + + Html(buf) +} + +pub async fn login_post(Form(login): Form<LoginForm>, state: Extension<Arc<State>>, jar: PrivateCookieJar) -> Result<(PrivateCookieJar, Redirect), ServiceError> { + let mut conn = state.conn.acquire().await?; + + let user: DbUser = query_as("SELECT * FROM users WHERE email=$1").bind(login.email) + .fetch_one(&mut conn) + .await?; + + if bcrypt::verify(login.password, &user.pw_hash)? { + debug!("Logged in ID {} (email {})", user.id, user.email); + query("UPDATE users SET last_login=$1 WHERE id=$2").bind(Utc::now()).bind(user.id) + .execute(&mut conn) + .await?; + + let updated_jar = jar.add(Cookie::new("user-id", user.id.clone())); + } else { + + } + Ok((updated_jar, Redirect::to("/"))) +} + +pub async fn register() -> impl IntoResponse { + let mut buf = Vec::new(); + crate::templates::register_html(&mut buf).unwrap(); + + Html(buf) +} + +pub async fn register_post(Form(reg): Form<RegisterForm>, state: Extension<Arc<State>>) -> impl IntoResponse { + if reg.password_confirm == reg.password { + let hash = match bcrypt::hash(reg.password, bcrypt::DEFAULT_COST) { + Ok(h) => h, + Err(e) => { + return Err(ServiceError::NotAuthorized); + } + }; + + let mut conn = state.conn.acquire().await?; + let ulid = ulid::Ulid::new(); + + query("INSERT INTO users (id, email, pref_name, pw_hash, last_login) VALUES ($1, $2, $3, $4, $5)").bind(ulid.to_string()).bind(reg.email.clone()).bind(reg.prefname).bind(hash).bind(Utc::now()) + .execute(&mut conn) + .await?; + + } + + Ok(Redirect::to("/dash/auth/login")) +} |