use axum::{extract::State, http::StatusCode, response::{Html, IntoResponse}, Extension, Form}; use chrono::{SecondsFormat, Utc}; use log::{error, info, warn}; use serde::Deserialize; use minijinja::context; use fully_pub::fully_pub; use sqlx::types::Json; use uuid::Uuid; use crate::{renderer::TemplateRenderer, AppState}; use kernel::models::user::{User, UserStatus}; use utils::get_password_hash; pub async fn register_form( State(app_state): State ) -> impl IntoResponse { Html( app_state.templating_env.get_template("pages/register.html").unwrap() .render(context!()) .unwrap() ) } #[derive(Debug, Deserialize)] #[fully_pub] struct RegisterForm { handle: String, email: String, password: String, } pub async fn perform_register( State(app_state): State, Extension(renderer): Extension, Form(register): Form ) -> impl IntoResponse { let password_hash = Some( get_password_hash(register.password) .expect("To process password").1 ); let user = User { id: Uuid::new_v4().to_string(), email: Some(register.email), handle: register.handle, full_name: None, avatar_asset_id: None, password_hash, status: UserStatus::Active, roles: Json(Vec::new()), // take the default role in the config reset_password_token: None, created_at: Utc::now(), website: None, last_login_at: None }; // save in DB let res = sqlx::query(" INSERT INTO users (id, handle, email, status, roles, password_hash, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7) ") .bind(user.id) .bind(user.handle) .bind(user.email) .bind(user.status.to_string()) .bind(user.roles) .bind(user.password_hash) .bind(user.created_at.to_rfc3339_opts(SecondsFormat::Millis, true)) .execute(&app_state.db.0) .await; match res { Err(err) => { let err_code = err.as_database_error().unwrap().code().unwrap(); if err_code == "2067" { warn!("Cannot register user because email or handle is not unique. Failing silently."); } else { error!("Cannot register user: {}", err); return renderer.render_with_status( StatusCode::INTERNAL_SERVER_ERROR, "pages/register", context!( error => true ) ) } }, Ok(_v) => { info!("Registered user successfully"); } }; renderer.render_with_status( StatusCode::OK, "pages/register", context!( success => true ) ) }