minauthator/lib/http_server/src/controllers/ui/register.rs

104 lines
2.8 KiB
Rust

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<AppState>
) -> 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<AppState>,
Extension(renderer): Extension<TemplateRenderer>,
Form(register): Form<RegisterForm>
) -> 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
)
)
}