Extract db query into its own function.

This commit is contained in:
Luca Palmieri 2021-08-30 13:56:34 +02:00
parent 4695dfebf4
commit db0ebb4828

View file

@ -84,38 +84,45 @@ fn basic_authentication(headers: &HeaderMap) -> Result<Credentials, anyhow::Erro
Ok(Credentials { username, password }) Ok(Credentials { username, password })
} }
async fn validate_credentials( #[tracing::instrument(name = "Get stored credentials", skip(username, pool))]
credentials: Credentials, async fn get_stored_credentials(
username: &str,
pool: &PgPool, pool: &PgPool,
) -> Result<uuid::Uuid, PublishError> { ) -> Result<Option<(uuid::Uuid, String)>, anyhow::Error> {
let row: Option<_> = sqlx::query!( let row = sqlx::query!(
r#" r#"
SELECT user_id, password_hash SELECT user_id, password_hash
FROM users FROM users
WHERE username = $1 WHERE username = $1
"#, "#,
credentials.username, username,
) )
.fetch_optional(pool) .fetch_optional(pool)
.await .await
.context("Failed to performed a query to retrieve stored credentials.") .context("Failed to performed a query to retrieve stored credentials.")?
.map_err(PublishError::UnexpectedError)?; .map(|row| (row.user_id, row.password_hash));
Ok(row)
}
let (expected_password_hash, user_id) = match row { #[tracing::instrument(name = "Validate credentials", skip(credentials, pool))]
Some(row) => (row.password_hash, row.user_id), async fn validate_credentials(
None => { credentials: Credentials,
return Err(PublishError::AuthError(anyhow::anyhow!( pool: &PgPool,
"Unknown username." ) -> Result<uuid::Uuid, PublishError> {
))) let (user_id, expected_password_hash) = get_stored_credentials(&credentials.username, &pool)
} .await
}; .map_err(PublishError::UnexpectedError)?
.ok_or_else(|| PublishError::AuthError(anyhow::anyhow!("Unknown username.")))?;
let expected_password_hash = PasswordHash::new(&expected_password_hash) let expected_password_hash = PasswordHash::new(&expected_password_hash)
.context("Failed to parse hash in PHC string format.") .context("Failed to parse hash in PHC string format.")
.map_err(PublishError::UnexpectedError)?; .map_err(PublishError::UnexpectedError)?;
tracing::info_span!("Verify password hash")
.in_scope(|| {
Argon2::default() Argon2::default()
.verify_password(credentials.password.as_bytes(), &expected_password_hash) .verify_password(credentials.password.as_bytes(), &expected_password_hash)
})
.context("Invalid password.") .context("Invalid password.")
.map_err(PublishError::AuthError)?; .map_err(PublishError::AuthError)?;