61 lines
1.6 KiB
Rust
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))
|
|
}
|