2m2d/src/users.rs

61 lines
1.6 KiB
Rust

use axum::extract::Extension;
use axum::extract::Form;
use axum::response::Html;
use axum::response::Redirect;
use pbkdf2::{
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
Pbkdf2,
};
use serde::Deserialize;
use sqlx::{Pool, Postgres};
use std::sync::Arc;
use tera::Context;
use tera::Tera;
#[derive(Clone, Debug, Deserialize)]
pub struct RawUser {
username: String,
password: String,
}
pub async fn create_user(
Form(data): Form<RawUser>,
Extension(pool): Extension<Arc<Pool<Postgres>>>,
) -> Result<Redirect, String> {
let handle = tokio::task::spawn_blocking(move || {
let salt = SaltString::generate(&mut OsRng);
let password_hash = Pbkdf2.hash_password(data.password.as_bytes(), &salt);
password_hash
.map(|p| p.to_string())
.map_err(|e| e.to_string())
});
let hash = handle.await.map_err(|e| e.to_string())??;
sqlx::query("INSERT INTO users (username, password_hash) VALUES ($1, $2)")
.bind(data.username)
.bind(hash)
.execute(&*pool)
.await
.map_err(|e| e.to_string())?;
Ok(Redirect::to("/login"))
}
pub async fn register_form(Extension(tera): Extension<Arc<Tera>>) -> Result<Html<String>, String> {
let rendered = tera
.render("users/register.html", &Context::new())
.map_err(|e| e.to_string())?;
Ok(Html(rendered))
}
pub async fn login_form(Extension(tera): Extension<Arc<Tera>>) -> Result<Html<String>, String> {
let rendered = tera
.render("users/login.html", &Context::new())
.map_err(|e| e.to_string())?;
Ok(Html(rendered))
}