mas_handlers/graphql/mutations/
mod.rsmod browser_session;
mod compat_session;
mod matrix;
mod oauth2_session;
mod user;
mod user_email;
use anyhow::Context as _;
use async_graphql::MergedObject;
use mas_data_model::SiteConfig;
use mas_storage::BoxRepository;
use zeroize::Zeroizing;
use super::Requester;
use crate::passwords::PasswordManager;
#[derive(Default, MergedObject)]
pub struct Mutation(
user_email::UserEmailMutations,
user::UserMutations,
oauth2_session::OAuth2SessionMutations,
compat_session::CompatSessionMutations,
browser_session::BrowserSessionMutations,
matrix::MatrixMutations,
);
impl Mutation {
#[must_use]
pub fn new() -> Self {
Self::default()
}
}
async fn verify_password_if_needed(
requester: &Requester,
config: &SiteConfig,
password_manager: &PasswordManager,
password: Option<String>,
user: &mas_data_model::User,
repo: &mut BoxRepository,
) -> Result<bool, async_graphql::Error> {
if requester.is_admin() {
return Ok(true);
}
if !config.password_login_enabled {
return Ok(true);
}
let Some(user_password) = repo
.user_password()
.active(user)
.await
.context("Failed to load user password")?
else {
return Ok(true);
};
let Some(password) = password else {
return Ok(false);
};
let password = Zeroizing::new(password.into_bytes());
let res = password_manager
.verify(
user_password.version,
password,
user_password.hashed_password,
)
.await;
Ok(res.is_ok())
}