1 parent
cfc74d9db6
commit
dacdf9c27d
76 files changed
+5209
-741
No files matched your search
+62
-1
@@ -1,3 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
|
||||
@@ -5,9 +6,10 @@ use base64::Engine;
|
||||
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
|
||||
use dashmap::DashMap;
|
||||
use rand::RngCore;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::session_store::crypto::SessionCrypto;
|
||||
use crate::session_store::{PersistedSession, SessionPersistence};
|
||||
use crate::session_store::{PersistedSession, SessionPersistence, SessionPersistenceDiagnostics};
|
||||
|
||||
pub type SessionId = String;
|
||||
pub type BrowserId = String;
|
||||
@@ -54,6 +56,29 @@ pub struct AccountSession {
|
||||
pub user_agent: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct DiagnosticSession {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub email: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_hash: Option<String>,
|
||||
pub imap_host: String,
|
||||
pub imap_port: u16,
|
||||
pub smtp_host: String,
|
||||
pub smtp_port: u16,
|
||||
pub created_at_unix: u64,
|
||||
pub last_accessed_unix: u64,
|
||||
pub user_agent: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct SessionStoreDiagnostics {
|
||||
pub local_cached_sessions: usize,
|
||||
pub local_cached_browsers: usize,
|
||||
pub local_unique_users: usize,
|
||||
pub sessions: Vec<DiagnosticSession>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SessionStore {
|
||||
sessions: Arc<DashMap<SessionId, AccountSession>>,
|
||||
@@ -480,6 +505,34 @@ impl SessionStore {
|
||||
self.sessions.is_empty()
|
||||
}
|
||||
|
||||
pub fn diagnostics_snapshot(&self, include_user_identifiers: bool) -> SessionStoreDiagnostics {
|
||||
let mut users = HashSet::new();
|
||||
let mut sessions = Vec::new();
|
||||
for entry in self.sessions.iter() {
|
||||
let session = entry.value();
|
||||
users.insert(session.user_hash.clone());
|
||||
sessions.push(DiagnosticSession {
|
||||
email: include_user_identifiers.then(|| session.email.clone()),
|
||||
user_hash: include_user_identifiers.then(|| session.user_hash.clone()),
|
||||
imap_host: session.imap_host.clone(),
|
||||
imap_port: session.imap_port,
|
||||
smtp_host: session.smtp_host.clone(),
|
||||
smtp_port: session.smtp_port,
|
||||
created_at_unix: session.created_at_unix,
|
||||
last_accessed_unix: session.last_accessed_unix,
|
||||
user_agent: session.user_agent.chars().take(256).collect(),
|
||||
});
|
||||
}
|
||||
sessions.sort_by_key(|session| std::cmp::Reverse(session.last_accessed_unix));
|
||||
sessions.truncate(100);
|
||||
SessionStoreDiagnostics {
|
||||
local_cached_sessions: self.sessions.len(),
|
||||
local_cached_browsers: self.browsers.len(),
|
||||
local_unique_users: users.len(),
|
||||
sessions,
|
||||
}
|
||||
}
|
||||
|
||||
fn cache_persisted(&self, record: &PersistedSession) -> Result<AccountSession, String> {
|
||||
let crypto = self
|
||||
.crypto
|
||||
@@ -747,6 +800,14 @@ impl SessionStore {
|
||||
removed
|
||||
}
|
||||
|
||||
pub async fn persistence_diagnostics(&self) -> Result<SessionPersistenceDiagnostics, String> {
|
||||
let persistence = self
|
||||
.persistence
|
||||
.as_ref()
|
||||
.ok_or_else(|| "session persistence is not configured".to_string())?;
|
||||
persistence.diagnostics(Self::unix_now()).await
|
||||
}
|
||||
|
||||
pub async fn purge_expired_shared(&self) {
|
||||
self.purge_expired();
|
||||
if let Some(persistence) = self.persistence.as_ref()
|
||||
|
||||
Reference in new issue
Block a user