48 lines
1.5 KiB
Rust
48 lines
1.5 KiB
Rust
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<D: DatabaseInterface> {
|
|
pub inner: Arc<RwLock<D>>,
|
|
}
|
|
|
|
impl<D: DatabaseInterface> Database<D> {
|
|
pub fn new(db: D) -> Self {
|
|
Self {
|
|
inner: Arc::new(RwLock::new(db)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<D: DatabaseInterface> Database<D> {
|
|
/// 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<bool, BoxedError> {
|
|
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<Vec<Domain>, BoxedError> {
|
|
Ok(self
|
|
.list_all_domains()
|
|
.await?
|
|
.into_iter()
|
|
.filter(|d| user.role.can_see_domain(&d.name))
|
|
.collect())
|
|
}
|
|
}
|