use pubky_common::auth::{grant_session_responses::GrantInfo, jws::GrantId};
use pubky_common::crypto::PublicKey;
use reqwest::Method;
use std::sync::Arc;
use crate::actors::session::credential::SessionCredential;
use crate::client::user_endpoint_url;
use crate::errors::{RequestError, Result};
use crate::util::check_http_status;
use crate::{PubkyHttpClient, PubkySession};
#[derive(Debug, Clone)]
pub struct GrantManager {
client: PubkyHttpClient,
user: PublicKey,
credential: Arc<dyn SessionCredential>,
}
impl GrantManager {
#[must_use]
pub fn new(session: &PubkySession) -> Self {
Self {
client: session.client().clone(),
user: session.info().public_key().clone(),
credential: Arc::clone(session.credential()),
}
}
pub async fn list(&self) -> Result<Vec<GrantInfo>> {
let url = user_endpoint_url(&self.user, "/auth/grant/sessions")?;
let rb = self.client.cross_request(Method::GET, url).await?;
let resp = self
.credential
.attach(rb, &self.client)
.await?
.send()
.await?;
let resp = check_http_status(resp).await?;
let grants: Vec<GrantInfo> = resp.json().await.map_err(|e| RequestError::DecodeJson {
message: format!("decoding /auth/grant/sessions response: {e}"),
})?;
Ok(grants)
}
pub async fn revoke(&self, grant_id: &GrantId) -> Result<()> {
let path = format!("/auth/grant/session/{}", grant_id.as_str());
let url = user_endpoint_url(&self.user, &path)?;
let rb = self.client.cross_request(Method::DELETE, url).await?;
let resp = self
.credential
.attach(rb, &self.client)
.await?
.send()
.await?;
check_http_status(resp).await?;
Ok(())
}
}