use std::sync::Arc;
use pubky_common::crypto::PublicKey;
use super::SessionInfo;
use super::credential::SessionCredential;
use crate::errors::Error;
use crate::{PubkyHttpClient, Result, SessionStorage, cross_log};
#[derive(Clone)]
pub struct PubkySession {
pub(crate) client: PubkyHttpClient,
pub(crate) credential: Arc<dyn SessionCredential>,
}
impl PubkySession {
pub(crate) fn from_credential(
client: PubkyHttpClient,
credential: Arc<dyn SessionCredential>,
) -> Self {
Self { client, credential }
}
#[must_use]
pub fn info(&self) -> SessionInfo {
self.credential.info()
}
#[must_use]
pub const fn client(&self) -> &PubkyHttpClient {
&self.client
}
pub(crate) fn credential(&self) -> &Arc<dyn SessionCredential> {
&self.credential
}
pub(crate) fn try_downcast_credential<T: SessionCredential + 'static>(&self) -> Option<&T> {
self.credential.as_any().downcast_ref::<T>()
}
#[must_use]
pub fn public_key(&self) -> PublicKey {
self.info().public_key().clone()
}
pub async fn revalidate(&self) -> Result<Option<SessionInfo>> {
let user = self.info().public_key().clone();
cross_log!(info, "Revalidating session for {}", user);
self.credential.revalidate(&self.client, &user).await
}
pub async fn signout(self) -> std::result::Result<(), (Error, Self)> {
cross_log!(info, "Signing out session for {}", self.info().public_key());
if let Err(e) = self.credential.signout(&self.client).await {
cross_log!(error, "Signout failed: {}", e);
return Err((e, self));
}
cross_log!(info, "Session signed out");
Ok(())
}
#[must_use]
pub fn storage(&self) -> SessionStorage {
SessionStorage::new(self)
}
}
impl std::fmt::Debug for PubkySession {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("PubkySession");
ds.field("client", &self.client);
ds.field("credential", &self.credential);
ds.field("info", &self.info());
ds.finish()
}
}