mirror of
https://github.com/LukeMathWalker/zero-to-production.git
synced 2024-12-21 23:46:37 +00:00
Extract db query into its own function.
This commit is contained in:
parent
4695dfebf4
commit
db0ebb4828
1 changed files with 24 additions and 17 deletions
|
@ -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)?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue