more refactor on backend
This commit is contained in:
1 parent
941afa2485
commit
7f7936d37f
20 files changed
+1603
-1527
No files matched your search
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user