Files
CRM_backup/backend/src/services/auth_service.rs
T

87 lines
2.3 KiB
Rust

use axum::http::StatusCode;
use sha2::{Digest, Sha256};
use sqlx::PgPool;
use uuid::Uuid;
use crate::auth::{create_token, Claims};
use crate::repositories;
use crate::repositories::session_repo;
pub struct LoginResponse {
pub token: String,
pub user_id: Uuid,
pub username: String,
pub role: String,
}
pub async fn login(
pool: &PgPool,
username: &str,
password: &str,
ip_address: Option<&str>,
user_agent: Option<&str>,
jwt_secret: &str,
jwt_expiry_hours: i64,
) -> Result<LoginResponse, StatusCode> {
let user = repositories::user_repo::find_by_username(pool, username)
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.ok_or(StatusCode::UNAUTHORIZED)?;
if !user.is_active {
return Err(StatusCode::FORBIDDEN);
}
if user.is_locked {
return Err(StatusCode::LOCKED);
}
let password_valid = bcrypt::verify(password, &user.password_hash)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
if !password_valid {
let _ = repositories::user_repo::increment_failed_login(pool, username).await;
return Err(StatusCode::UNAUTHORIZED);
}
let _ = repositories::user_repo::update_last_login(pool, user.id, ip_address.unwrap_or("")).await;
let role = "USER";
let token = create_token(user.id, &user.username, role, jwt_secret, jwt_expiry_hours)?;
let token_hash = hex::encode(Sha256::digest(token.as_bytes()));
let expires_at = chrono::Utc::now()
.checked_add_signed(chrono::Duration::hours(jwt_expiry_hours))
.ok_or(StatusCode::INTERNAL_SERVER_ERROR)?;
let _ = session_repo::create_session(
pool,
user.id,
&token_hash,
ip_address,
user_agent,
&expires_at,
)
.await;
Ok(LoginResponse {
token,
user_id: user.id,
username: user.username,
role: role.to_string(),
})
}
pub async fn logout(pool: &PgPool, token: &str) -> Result<(), StatusCode> {
let token_hash = hex::encode(Sha256::digest(token.as_bytes()));
session_repo::invalidate_session(pool, &token_hash)
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
pub fn validate_token(token: &str, jwt_secret: &str) -> Result<Claims, StatusCode> {
crate::auth::validate_token(token, jwt_secret)
}