use std::sync::Arc; use config::AppConfig; use export::{AppDatabase, AppRedis, AppState}; use models::users::access_scope::AccessKeyScope; use crate::errors::AuthError; pub mod agreements; pub mod notifications; pub mod preferences; pub mod profile; pub mod reports; pub mod suspensions; pub mod users; pub struct VerifiedAccessKey { pub user_id: i64, pub scope: AccessKeyScope, } #[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. 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 verify_access_token( &self, token: &str, ) -> Result, AuthError> { let Some(client) = self.state.kenauth.as_ref() else { return Ok(None); }; let principal = match client.verify_access_key(token, Vec::new()).await { Ok(Some(principal)) => principal, Ok(None) => return Ok(None), Err(error) => return Err(AuthError::Internal(error.to_string())), }; let write = principal.scopes.iter().any(|scope| *scope == 12); Ok(Some(VerifiedAccessKey { user_id: principal.user_id, scope: if write { AccessKeyScope::Write } else { AccessKeyScope::Read }, })) } }