use async_trait::async_trait; use axum_login::{AuthUser, AuthnBackend, UserId}; use crate::{models::{self, users, DbError}, password, prelude::*}; #[derive(Serialize, Deserialize)] pub struct Credentials { pub username: String, pub password: String, } impl AuthUser for models::users::User { type Id = String; fn id(&self) -> Self::Id { self.id.clone() } fn session_auth_hash(&self) -> &[u8] { self.password_hash.as_bytes() } } #[async_trait] impl AuthnBackend for Context { type User = models::users::User; type Credentials = Credentials; type Error = DbError; async fn authenticate( &self, creds: Self::Credentials, ) -> Result, Self::Error> { let mut db = self.db_pool.get()?; let mut q = users::Query::new(&mut db); let user = q.by_username(&creds.username)?; if password::verify(&user.password_hash, &creds.password) { Ok(Some(user)) } else { Ok(None) } } async fn get_user(&self, user_id: &UserId) -> Result, Self::Error> { let mut db = self.db_pool.get()?; let mut q = users::Query::new(&mut db); let user = q.by_id(&user_id)?; Ok(Some(user)) } }