From f7f4fd2813340cb7be40356b4d7f185a41c1db7b Mon Sep 17 00:00:00 2001 From: Ethan Girouard Date: Sat, 27 Jun 2026 17:23:02 -0400 Subject: [PATCH] Add password check function --- src/models/user.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/models/user.rs b/src/models/user.rs index f14c121..ed99050 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -28,7 +28,12 @@ use diesel::{ serialize::ToSql, sql_types, }; -use pbkdf2::{PasswordHasher, Pbkdf2}; +use pbkdf2::{ + PasswordHasher, PasswordVerifier, Pbkdf2, password_hash::Error::PasswordInvalid, + phc::PasswordHash, +}; + +use crate::util::error::{Error, Result}; /// Newtype for a `String`-represented hashed password #[derive(Clone, Debug, AsExpression, FromSqlRow)] @@ -36,6 +41,26 @@ use pbkdf2::{PasswordHasher, Pbkdf2}; pub struct HashedPassword(String); impl HashedPassword { + /// Check a password attempt against this hashed password + /// + /// # Returns + /// + /// `Ok(true)` for a correct password + /// `Ok(false)` for an incorrect password + /// `Err` for a hashing error + pub fn check(&self, password_attempt: String) -> Result { + let pw_hash = PasswordHash::new(&self.0) + .map_err(|e| Error::message_here(format!("Error parsing `HashedPassword`: {e}")))?; + + match Pbkdf2::default().verify_password(password_attempt.as_bytes(), &pw_hash) { + Ok(()) => Ok(true), + Err(PasswordInvalid) => Ok(false), + Err(e) => Err(Error::message_here(format!( + "Error comparing password attempt against hash: {e}" + ))), + } + } + /// Returns the "session auth hash" for `axum-login`, just the hashed password as bytes pub fn auth_hash(&self) -> &[u8] { self.0.as_bytes()