Initial commit - current CRM state
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user