use anyhow::Result;
use serde::{Deserialize, Serialize};
use crate::{client::post_json, url::URLBuilder};
#[derive(Debug, Serialize, Clone)]
pub struct CreateSessionRequest {
pub identifier: String,
pub password: String,
#[serde(skip_serializing_if = "Option::is_none", rename = "authFactorToken")]
pub auth_factor_token: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct AppPasswordSession {
pub did: String,
pub handle: String,
pub email: String,
#[serde(rename = "accessJwt")]
pub access_jwt: String,
#[serde(rename = "refreshJwt")]
pub refresh_jwt: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct RefreshSessionResponse {
pub did: String,
pub handle: String,
#[serde(rename = "accessJwt")]
pub access_jwt: String,
#[serde(rename = "refreshJwt")]
pub refresh_jwt: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub active: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct AppPasswordResponse {
pub name: String,
pub password: String,
#[serde(rename = "createdAt")]
pub created_at: String,
}
pub async fn create_session(
http_client: &reqwest::Client,
base_url: &str,
identifier: &str,
password: &str,
auth_factor_token: Option<&str>,
) -> Result<AppPasswordSession> {
let mut url_builder = URLBuilder::new(base_url);
url_builder.path("/xrpc/com.atproto.server.createSession");
let url = url_builder.build();
let request = CreateSessionRequest {
identifier: identifier.to_string(),
password: password.to_string(),
auth_factor_token: auth_factor_token.map(|s| s.to_string()),
};
let value = serde_json::to_value(request)?;
post_json(http_client, &url, value)
.await
.and_then(|value| serde_json::from_value(value).map_err(|err| err.into()))
}
pub async fn refresh_session(
http_client: &reqwest::Client,
base_url: &str,
refresh_token: &str,
) -> Result<RefreshSessionResponse> {
let mut url_builder = URLBuilder::new(base_url);
url_builder.path("/xrpc/com.atproto.server.refreshSession");
let url = url_builder.build();
let mut headers = reqwest::header::HeaderMap::new();
headers.insert(
reqwest::header::AUTHORIZATION,
reqwest::header::HeaderValue::from_str(&format!("Bearer {}", refresh_token))?,
);
let response = http_client.post(&url).headers(headers).send().await?;
let value = response.json::<serde_json::Value>().await?;
serde_json::from_value(value).map_err(|err| err.into())
}
pub async fn create_app_password(
http_client: &reqwest::Client,
base_url: &str,
access_token: &str,
name: &str,
) -> Result<AppPasswordResponse> {
let mut url_builder = URLBuilder::new(base_url);
url_builder.path("/xrpc/com.atproto.server.createAppPassword");
let url = url_builder.build();
let request_body = serde_json::json!({
"name": name
});
let mut headers = reqwest::header::HeaderMap::new();
headers.insert(
reqwest::header::AUTHORIZATION,
reqwest::header::HeaderValue::from_str(&format!("Bearer {}", access_token))?,
);
let response = http_client
.post(&url)
.headers(headers)
.json(&request_body)
.send()
.await?;
let value = response.json::<serde_json::Value>().await?;
serde_json::from_value(value).map_err(|err| err.into())
}