2024-11-08 23:38:54 +01:00
|
|
|
use axum::{extract::State, http::StatusCode, response::{Html, IntoResponse}, Extension, Form};
|
2024-10-21 00:05:20 +02:00
|
|
|
use chrono::{SecondsFormat, Utc};
|
2024-11-08 23:38:54 +01:00
|
|
|
use log::{error, info, warn};
|
|
|
|
|
use serde::Deserialize;
|
2024-10-21 00:05:20 +02:00
|
|
|
use minijinja::context;
|
|
|
|
|
use fully_pub::fully_pub;
|
2024-11-08 23:38:54 +01:00
|
|
|
use sqlx::types::Json;
|
2024-10-21 00:05:20 +02:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
2024-11-28 12:47:00 +01:00
|
|
|
use crate::{renderer::TemplateRenderer, AppState};
|
|
|
|
|
|
|
|
|
|
use kernel::models::user::{User, UserStatus};
|
|
|
|
|
use utils::get_password_hash;
|
2024-10-21 00:05:20 +02:00
|
|
|
|
|
|
|
|
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>,
|
2024-11-08 23:38:54 +01:00
|
|
|
Extension(renderer): Extension<TemplateRenderer>,
|
2024-10-21 00:05:20 +02:00
|
|
|
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,
|
2024-12-04 18:25:56 +01:00
|
|
|
avatar_asset_id: None,
|
2024-10-21 00:05:20 +02:00
|
|
|
|
|
|
|
|
password_hash,
|
|
|
|
|
status: UserStatus::Active,
|
2024-11-08 23:38:54 +01:00
|
|
|
roles: Json(Vec::new()), // take the default role in the config
|
2024-12-02 18:39:00 +01:00
|
|
|
reset_password_token: None,
|
2024-10-21 00:05:20 +02:00
|
|
|
created_at: Utc::now(),
|
|
|
|
|
website: None,
|
|
|
|
|
last_login_at: None
|
|
|
|
|
};
|
|
|
|
|
// save in DB
|
2024-11-08 23:38:54 +01:00
|
|
|
let res = sqlx::query("
|
|
|
|
|
INSERT INTO users
|
|
|
|
|
(id, handle, email, status, roles, password_hash, created_at)
|
|
|
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
|
|
|
")
|
2024-10-21 00:05:20 +02:00
|
|
|
.bind(user.id)
|
|
|
|
|
.bind(user.handle)
|
|
|
|
|
.bind(user.email)
|
|
|
|
|
.bind(user.status.to_string())
|
2024-11-08 23:38:54 +01:00
|
|
|
.bind(user.roles)
|
2024-10-21 00:05:20 +02:00
|
|
|
.bind(user.password_hash)
|
|
|
|
|
.bind(user.created_at.to_rfc3339_opts(SecondsFormat::Millis, true))
|
2024-11-28 12:47:00 +01:00
|
|
|
.execute(&app_state.db.0)
|
2024-11-08 23:38:54 +01:00
|
|
|
.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");
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-10-21 00:05:20 +02:00
|
|
|
|
2024-11-08 23:38:54 +01:00
|
|
|
renderer.render_with_status(
|
|
|
|
|
StatusCode::OK,
|
|
|
|
|
"pages/register",
|
|
|
|
|
context!(
|
2024-11-28 12:47:00 +01:00
|
|
|
success => true
|
2024-11-08 23:38:54 +01:00
|
|
|
)
|
2024-10-21 00:05:20 +02:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|