use pubky_common::auth::{grant_session_responses::GrantSessionInfo, jws::GrantId};
use super::{DelegatedGrantCredentialState, GrantCredential};
use crate::actors::session::core::PubkySession;
use crate::errors::Result;
#[derive(Debug)]
pub struct GrantSessionView<'a> {
session: &'a PubkySession,
credential: &'a GrantCredential,
}
impl PubkySession {
#[must_use]
pub fn as_grant(&self) -> Option<GrantSessionView<'_>> {
self.try_downcast_credential::<GrantCredential>()
.map(|c| GrantSessionView::new(self, c))
}
}
impl<'a> GrantSessionView<'a> {
pub(crate) const fn new(session: &'a PubkySession, credential: &'a GrantCredential) -> Self {
Self {
session,
credential,
}
}
pub async fn session_info(&self) -> GrantSessionInfo {
self.credential.state.lock().await.session.clone()
}
pub async fn export_local_secret(&self) -> Option<String> {
self.credential.export_local_secret().await
}
pub async fn export_delegated_restore_state(&self) -> Option<DelegatedGrantCredentialState> {
self.credential.export_delegated_restore_state().await
}
pub async fn current_bearer(&self) -> String {
self.credential.current_bearer().await
}
pub async fn grant_id(&self) -> GrantId {
self.credential.state.lock().await.grant_claims.jti.clone()
}
#[doc(hidden)]
pub async fn refresh_if_needed(&self) -> Result<()> {
self.credential.refresh(self.session.client()).await
}
#[doc(hidden)]
pub async fn coordinate(
&self,
coordinator: std::sync::Arc<dyn crate::GrantSessionCoordinator>,
lease: &dyn crate::GrantSessionLease,
) -> Result<()> {
self.credential.coordinate(coordinator, lease).await
}
#[doc(hidden)]
pub async fn force_refresh(&self) -> Result<String> {
if let Some(coordinator) = self.credential.coordinator().await {
let bearer = self.credential.current_bearer().await;
self.credential
.refresh_shared(self.session.client(), coordinator.as_ref(), Some(&bearer))
.await?;
return Ok(self.credential.current_bearer().await);
}
self.credential.state.lock().await.session.token_expires_at = 0;
self.credential.refresh(self.session.client()).await?;
Ok(self.credential.state.lock().await.bearer.clone())
}
}