use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceAccountCredentials {
#[serde(rename = "type")]
pub account_type: String,
pub project_id: String,
pub private_key_id: String,
pub private_key: String,
pub client_email: String,
pub client_id: String,
pub auth_uri: String,
pub token_uri: String,
pub auth_provider_x509_cert_url: String,
pub client_x509_cert_url: String,
#[serde(default = "default_universe_domain")]
pub universe_domain: String,
}
fn default_universe_domain() -> String {
"googleapis.com".to_string()
}
impl ServiceAccountCredentials {
pub async fn from_file(path: &str) -> crate::Result<Self> {
let content = tokio::fs::read_to_string(path).await?;
Self::from_json(&content)
}
pub fn from_json(json: &str) -> crate::Result<Self> {
let creds: Self = serde_json::from_str(json)?;
if creds.account_type != "service_account" {
return Err(crate::Error::InvalidCredentials(format!(
"Expected type 'service_account', got '{}'",
creds.account_type
)));
}
Ok(creds)
}
}
#[derive(Debug, Clone)]
pub enum Credentials {
ApiKey(String),
ServiceAccount(ServiceAccountCredentials),
OAuth2 {
client_id: String,
client_secret: String,
refresh_token: Option<String>,
},
}
impl Credentials {
pub fn api_key(key: impl Into<String>) -> Self {
Self::ApiKey(key.into())
}
pub fn service_account(creds: ServiceAccountCredentials) -> Self {
Self::ServiceAccount(creds)
}
pub fn oauth2(client_id: impl Into<String>, client_secret: impl Into<String>) -> Self {
Self::OAuth2 {
client_id: client_id.into(),
client_secret: client_secret.into(),
refresh_token: None,
}
}
pub fn oauth2_with_refresh(
client_id: impl Into<String>,
client_secret: impl Into<String>,
refresh_token: impl Into<String>,
) -> Self {
Self::OAuth2 {
client_id: client_id.into(),
client_secret: client_secret.into(),
refresh_token: Some(refresh_token.into()),
}
}
}