use tokio::sync::RwLock; use std::sync::Arc; use crate::db::error::BoxedError; use crate::db::{DatabaseInterface, Domain, User, UserRef}; #[derive(Clone, Debug)] pub struct Database { pub inner: Arc>>, } impl Database { pub fn new(db: impl DatabaseInterface) -> Self { Self { inner: Arc::new(RwLock::new(Box::new(db))), } } } impl Database { /// Return false if the user doesn't exist, or the password is wrong. /// /// TODO: should we return something else when the account doesn't exist? /// or is it a feature to behave in the same way? /// /// TODO: we may want to make sure the method runs in constant time /// to avoid leaking information about existing users... /// or maybe we do not care. pub async fn check_password(&self, user: &UserRef, password: &str) -> Result { let Some(user) = self.get_user(user).await? else { tracing::debug!("check_password: User not found {user}"); return Ok(false); }; tracing::debug!("Comparing {} and {}", user.password, password); Ok(user.password == password) } pub async fn domains_user_can_see(&self, user: &User) -> Result, BoxedError> { Ok(self .list_all_domains() .await? .into_iter() .filter(|d| user.can_see_domain(&d.name)) .collect()) } }