Something went wrong. Try again.
Rust CLI for tangled
Something went wrong. Try again.
2.6 kB · 93 lines
Rust
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394use anyhow::Result;use chrono::{DateTime, Utc};use serde::{Deserialize, Serialize};
use crate::keychain::Keychain;
#[derive(Debug, Clone, Serialize, Deserialize)]pub struct Session { pub access_jwt: String, pub refresh_jwt: String, pub did: String, pub handle: String, #[serde(default)] pub pds: Option<String>, #[serde(default)] pub created_at: DateTime<Utc>, /// Present when the session was created via OAuth instead of an app /// password. OAuth access tokens are DPoP-bound: requests to the PDS /// must carry a proof signed with `dpop_key`. #[serde(default, skip_serializing_if = "Option::is_none")] pub oauth: Option<OAuthTokens>,}
#[derive(Debug, Clone, Serialize, Deserialize)]pub struct OAuthTokens { pub access_token: String, pub refresh_token: String, /// Authorization server issuer URL. pub issuer: String, pub token_endpoint: String, /// The (loopback) client_id used for the grant; needed for refresh. pub client_id: String, /// base64url-encoded P-256 secret key scalar for DPoP proofs. pub dpop_key: String, /// Unix timestamp when the access token expires. pub expires_at: i64,}
impl Default for Session { fn default() -> Self { Self { access_jwt: String::new(), refresh_jwt: String::new(), did: String::new(), handle: String::new(), pds: None, created_at: Utc::now(), oauth: None, } }}
pub struct SessionManager { service: String, account: String,}
impl Default for SessionManager { fn default() -> Self { Self { service: "tangled-cli".into(), account: "default".into(), } }}
impl SessionManager { pub fn new(service: &str, account: &str) -> Self { Self { service: service.into(), account: account.into(), } }
pub fn save(&self, session: &Session) -> Result<()> { let keychain = Keychain::new(&self.service, &self.account); let json = serde_json::to_string(session)?; keychain.set_password(&json) }
pub fn load(&self) -> Result<Option<Session>> { let keychain = Keychain::new(&self.service, &self.account); match keychain.get_password() { Ok(json) => Ok(Some(serde_json::from_str(&json)?)), Err(_) => Ok(None), } }
pub fn clear(&self) -> Result<()> { let keychain = Keychain::new(&self.service, &self.account); keychain.delete_password() }}