use std::sync::Arc; use async_trait::async_trait; use config::AppConfig; use export::{AppDatabase, AppRedis, AppState}; use session::SessionError; use session::share::guard::{SessionGuard, SessionWithUser}; use crate::errors::AuthError; pub mod access_keys; pub mod agreements; pub mod deletion; pub mod devices; pub mod email; pub mod jwt; pub mod login; pub mod logout; pub mod notifications; pub mod password; pub mod pow; pub mod preferences; pub mod profile; pub mod register; pub mod reports; pub mod sessions; pub mod ssh_keys; pub mod suspensions; pub mod two_factor; pub mod users; #[derive(Clone)] pub struct AuthService { pub state: AppState, } impl AuthService { pub fn new(state: AppState) -> Self { Self { state } } pub fn config(&self) -> &AppConfig { &self.state.config } pub fn db(&self) -> &Arc { &self.state.database } pub fn redis(&self) -> &AppRedis { &self.state.redis } /// Pick the mail language for one recipient. /// /// Order: the recipient's own `users.language`/`users.locale`, then the /// request's `Accept-Language`, then `[email].default_locale`. Account /// preference wins because a single request can notify several recipients. pub async fn mail_locale( &self, uid: Option, accept_language: Option<&str>, ) -> i18n::UiLocale { let fallback = i18n::UiLocale::parse(self.config().email.default_locale()) .unwrap_or(i18n::UiLocale::En); match uid { Some(uid) => { i18n::resolve_user_locale(self.db().read(), uid, fallback).await } None => i18n::negotiate_accept_language(accept_language, fallback), } } pub async fn send_email( &self, to: &str, subject: &str, text: &str, html: &str, ) -> Result<(), AuthError> { self.state .email .send_mail(to, subject, text, html) .await .map_err(|error| AuthError::Internal(format!("email send failed: {error}"))) } } #[async_trait] impl SessionGuard for AuthService { async fn lookup_session_with_user( &self, token_hash: &str, ) -> Result, SessionError> { session::lookup_session_with_user(self.db().read(), token_hash).await } }