use crate::prelude2::*;
use sqlx::MySql;
use sqlx::Pool;
use actix_web::http::header::HeaderMap;
use crate::commons;
use commons::verify_password;
use crate::services::user_service::get_stored_credentials;
use super::UserId;
pub struct Credentials {
pub username: String,
pub password: String,
}
impl Credentials {
pub fn password(&self) -> String {
self.password.to_string()
}
}
pub fn basic_auth0(headers: &HeaderMap) -> Result<Credentials> {
let header_value = headers
.get("Authorization")
.ok_or_else(|| Error::invalid_request("The 'Authorization' header was missing."))?
.to_str()
.map_err(|_| {
Error::invalid_request("The 'Authorization' header was not a valid UTF8 string.")
})?;
let base64encoded_segment = header_value
.strip_prefix("Basic ")
.ok_or_else(|| Error::invalid_request("The authorization scheme was not 'Basic'."))?;
let decoded_credentials = commons::base64decode(base64encoded_segment)
.map_err(|_| Error::invalid_request("Failed to base64-decode 'Basic' credentials."))?;
let mut credentials = decoded_credentials.splitn(2, ':');
let username = credentials
.next()
.ok_or_else(|| Error::invalid_request("A username must be provided in 'Basic' auth."))?
.to_string();
let password = credentials
.next()
.ok_or_else(|| Error::invalid_request("A password must be provided in 'Basic' auth."))?
.to_string();
Ok(Credentials { username, password })
}
pub async fn validate_credentials(credentials: &Credentials, pool: &Pool<MySql>) -> Option<UserId> {
let mut user_id = None;
let mut expected_password_hash: String = "".to_string();
match get_stored_credentials(&credentials.username, pool).await {
Ok(credentials) => {
if let Some((stored_user_id, stored_password_hash, _resource_id)) = credentials {
user_id = Some(stored_user_id);
expected_password_hash = stored_password_hash.clone().unwrap().to_string();
}
}
Err(e) => {
log::error!("validate_credentials-failed: error={:?}", e);
}
};
if let Some(user_id) = user_id {
let verifyed =
verify_password(credentials.password(), expected_password_hash).unwrap_or(false);
if verifyed {
return Some(UserId(user_id));
}
}
None
}