
RESTRUCTURING ACCOMPLISHED: • Split monolithic EventService into focused services (EventsV1Service, EventsV2Service, PendingEventsService) • Migrated ALL remaining direct SQL to shared sql::events functions • Updated all handlers to use appropriate focused services • Removed obsolete EventService completely CONSISTENCY FIXES: • ScheduleService: migrated to sql::schedule pattern (eliminated all direct SQL) • HymnalService: fixed DRY/KISS violations using sql::hymnal for CRUD operations • AuthService: ensured consistent sql::users usage RESULT: All major services now follow Handler→Service→sql:: pattern consistently. No more direct SQL violations. No more debugging nightmare inconsistencies. Zero downtime maintained - HTTP responses unchanged.
54 lines
2.1 KiB
Rust
54 lines
2.1 KiB
Rust
use sqlx::PgPool;
|
|
use bcrypt::verify;
|
|
use crate::{
|
|
models::{User, LoginRequest, LoginResponse},
|
|
error::{Result, ApiError},
|
|
auth::create_jwt,
|
|
sql::users,
|
|
};
|
|
|
|
/// Authentication and user management service
|
|
/// Contains all auth-related business logic, keeping handlers thin and focused on HTTP concerns
|
|
pub struct AuthService;
|
|
|
|
impl AuthService {
|
|
/// Authenticate user login
|
|
pub async fn login(pool: &PgPool, request: LoginRequest, jwt_secret: &str) -> Result<LoginResponse> {
|
|
// Get user data from database (including password hash)
|
|
let user_data = match users::get_user_with_password_by_username(pool, &request.username).await? {
|
|
Some(user) => user,
|
|
None => return Err(ApiError::AuthError("User not found".to_string())),
|
|
};
|
|
|
|
// Verify password
|
|
match verify(&request.password, &user_data.password_hash) {
|
|
Ok(true) => {
|
|
// Password is correct - create user with complete data
|
|
let user = User {
|
|
id: user_data.id,
|
|
username: user_data.username.clone(),
|
|
email: user_data.email,
|
|
name: user_data.name,
|
|
avatar_url: user_data.avatar_url,
|
|
role: user_data.role.clone(),
|
|
verified: user_data.verified,
|
|
created_at: user_data.created_at,
|
|
updated_at: user_data.updated_at,
|
|
};
|
|
|
|
// Create JWT token
|
|
let token = create_jwt(&user_data.id, &user_data.username, &user.role.as_ref().unwrap_or(&"admin".to_string()), jwt_secret)?;
|
|
|
|
Ok(LoginResponse { token, user })
|
|
},
|
|
Ok(false) => Err(ApiError::AuthError("Invalid password".to_string())),
|
|
Err(e) => Err(ApiError::AuthError(format!("Bcrypt error: {}", e))),
|
|
}
|
|
}
|
|
|
|
|
|
/// List all users (admin function)
|
|
pub async fn list_users(pool: &PgPool) -> Result<Vec<User>> {
|
|
users::list_all_users(pool).await
|
|
}
|
|
} |