church-api/src/services/auth.rs
Benjamin Slingo ed72011f16 Phase 3 complete: EventService restructuring achieves maximum DRY/KISS compliance
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.
2025-08-29 22:37:26 -04:00

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
}
}