more refactor on backend

This commit is contained in:
wt committed 2025-11-28 01:38:59 +07:00
1 parent 941afa2485
commit 7f7936d37f
20 files changed
+1603 -1527

No files matched your search

+117
View File
@@ -0,0 +1,117 @@
use crate::model;
use crate::state;
use crate::utils;
use axum::extract::{Json, State};
use bcrypt::{DEFAULT_COST, hash};
use chrono::{Duration, Utc};
use std::sync::Arc;
pub async fn register_handler(
State(state): State<Arc<state::AppState>>,
Json(payload): Json<model::RegisterRequest>,
) -> Json<model::AuthResponse> {
// Validate input
if payload.phone.len() < 5 {
return Json(model::AuthResponse {
success: false,
message: "Phone number is too short".to_string(),
username: None,
token: None,
});
}
if payload.username.len() < 3
|| payload.username.len() > state.config.limits.max_username_length
{
return Json(model::AuthResponse {
success: false,
message: format!(
"Username must be between 3 and {} characters",
state.config.limits.max_username_length
),
username: None,
token: None,
});
}
if payload.password.len() < state.config.limits.min_password_length {
return Json(model::AuthResponse {
success: false,
message: format!(
"Password must be at least {} characters",
state.config.limits.min_password_length
),
username: None,
token: None,
});
}
// Hash password
let password_hash = match hash(&payload.password, DEFAULT_COST) {
Ok(hash) => hash,
Err(_) => {
return Json(model::AuthResponse {
success: false,
message: "Error hashing password".to_string(),
username: None,
token: None,
});
}
};
// Insert user into database
let result = sqlx::query("INSERT INTO users (phone, username, password_hash) VALUES (?, ?, ?)")
.bind(&payload.phone)
.bind(&payload.username)
.bind(&password_hash)
.execute(&state.db_pool)
.await;
match result {
Ok(_) => {
// Generate session token
let token = utils::generate_token();
let expires_at = Utc::now() + Duration::days(30);
// Store session
let _ = sqlx::query(
"INSERT INTO sessions (token, username, phone, expires_at) VALUES (?, ?, ?, ?)",
)
.bind(&token)
.bind(&payload.username)
.bind(&payload.phone)
.bind(expires_at.naive_utc())
.execute(&state.db_pool)
.await;
Json(model::AuthResponse {
success: true,
message: "Registration successful".to_string(),
username: Some(payload.username),
token: Some(token),
})
}
Err(e) => {
let error_message = if e
.to_string()
.contains("UNIQUE constraint failed: users.phone")
{
"Phone number already registered".to_string()
} else if e
.to_string()
.contains("UNIQUE constraint failed: users.username")
{
"Username already taken".to_string()
} else {
"Registration failed".to_string()
};
Json(model::AuthResponse {
success: false,
message: error_message,
username: None,
token: None,
})
}
}
}