diff --git a/src/routes/newsletters.rs b/src/routes/newsletters.rs index 50bebf7..242f35c 100644 --- a/src/routes/newsletters.rs +++ b/src/routes/newsletters.rs @@ -84,38 +84,45 @@ fn basic_authentication(headers: &HeaderMap) -> Result Result { - let row: Option<_> = sqlx::query!( +) -> Result, anyhow::Error> { + let row = sqlx::query!( r#" SELECT user_id, password_hash FROM users WHERE username = $1 "#, - credentials.username, + username, ) .fetch_optional(pool) .await - .context("Failed to performed a query to retrieve stored credentials.") - .map_err(PublishError::UnexpectedError)?; + .context("Failed to performed a query to retrieve stored credentials.")? + .map(|row| (row.user_id, row.password_hash)); + Ok(row) +} - let (expected_password_hash, user_id) = match row { - Some(row) => (row.password_hash, row.user_id), - None => { - return Err(PublishError::AuthError(anyhow::anyhow!( - "Unknown username." - ))) - } - }; +#[tracing::instrument(name = "Validate credentials", skip(credentials, pool))] +async fn validate_credentials( + credentials: Credentials, + pool: &PgPool, +) -> Result { + 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) .context("Failed to parse hash in PHC string format.") .map_err(PublishError::UnexpectedError)?; - Argon2::default() - .verify_password(credentials.password.as_bytes(), &expected_password_hash) + tracing::info_span!("Verify password hash") + .in_scope(|| { + Argon2::default() + .verify_password(credentials.password.as_bytes(), &expected_password_hash) + }) .context("Invalid password.") .map_err(PublishError::AuthError)?;