feat(auth): add username sign-in mode and recovery kits (#3215)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-05 14:10:07 +02:00
1 parent bf3d73a5f7
commit e1eecc3b6c
355 files changed
+52138 -24097

No files matched your search

+46 -1
View File
@@ -3,7 +3,7 @@
use crate::{
api::{
client::{AdminApiClient, ApiResultExt},
types::PremiumBranding,
types::{AccountIdentityMode, AccountIdentitySettings, PremiumBranding},
},
config::AdminConfig,
};
@@ -13,6 +13,8 @@ use std::{
};
const PREMIUM_BRANDING_TTL: Duration = Duration::from_secs(60);
const ACCOUNT_IDENTITY_TTL: Duration = Duration::from_secs(60);
const ACCOUNT_IDENTITY_RETRY_TTL: Duration = Duration::from_secs(10);
#[derive(Clone)]
pub struct AppState {
@@ -23,6 +25,7 @@ struct AppStateInner {
pub config: AdminConfig,
pub http_client: reqwest::Client,
premium_branding: Mutex<Option<(Instant, PremiumBranding)>>,
account_identity: Mutex<Option<(Instant, AccountIdentitySettings)>>,
}
impl AppState {
@@ -36,6 +39,7 @@ impl AppState {
config,
http_client,
premium_branding: Mutex::new(None),
account_identity: Mutex::new(None),
}),
}
}
@@ -81,6 +85,47 @@ impl AppState {
self.remember_premium_branding(branding.clone());
Some(branding)
}
pub async fn account_identity(&self, client: &AdminApiClient) -> AccountIdentityMode {
self.account_identity_settings(client).await.mode
}
pub async fn account_identity_settings(
&self,
client: &AdminApiClient,
) -> AccountIdentitySettings {
if !self.config().self_hosted {
return AccountIdentitySettings::default();
}
let previous = *self
.inner
.account_identity
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
if let Some((expires_at, settings)) = previous
&& Instant::now() < expires_at
{
return settings;
}
let (settings, ttl) = match client
.get_instance_account_identity()
.await
.log_error("load account identity mode")
{
Some(settings) => (settings, ACCOUNT_IDENTITY_TTL),
None => (
previous.map_or(AccountIdentitySettings::default(), |(_, settings)| settings),
ACCOUNT_IDENTITY_RETRY_TTL,
),
};
*self
.inner
.account_identity
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner()) =
Some((Instant::now() + ttl, settings));
settings
}
}
impl axum::extract::FromRef<AppState> for AdminConfig {