use crate::auth::credentials::REDACTED;
use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum LoadState {
Fresh,
Loaded,
Unreadable,
Unparseable,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct OAuth1Token {
pub access_token: String,
pub token_secret: String,
pub consumer_key: String,
pub consumer_secret: String,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct OAuth2Token {
pub access_token: String,
pub refresh_token: String,
pub expiration_time: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum TokenType {
Bearer,
Oauth2,
Oauth1,
}
#[allow(clippy::struct_field_names)]
#[derive(Clone, Serialize, Deserialize)]
pub struct Token {
#[serde(rename = "type")]
pub token_type: TokenType,
#[serde(skip_serializing_if = "Option::is_none")]
pub bearer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oauth2: Option<OAuth2Token>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oauth1: Option<OAuth1Token>,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct App {
pub client_id: String,
pub client_secret: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub default_user: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub redirect_uri: String,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub oauth2_tokens: BTreeMap<String, Token>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub oauth1_token: Option<Token>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bearer_token: Option<Token>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub unnamed_oauth2_token: Option<Token>,
}
impl std::fmt::Debug for OAuth1Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OAuth1Token")
.field("access_token", &REDACTED)
.field("token_secret", &REDACTED)
.field("consumer_key", &self.consumer_key)
.field("consumer_secret", &REDACTED)
.finish()
}
}
impl std::fmt::Debug for OAuth2Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OAuth2Token")
.field("access_token", &REDACTED)
.field("refresh_token", &REDACTED)
.field("expiration_time", &self.expiration_time)
.finish()
}
}
impl std::fmt::Debug for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Token")
.field("token_type", &self.token_type)
.field("bearer", &self.bearer.as_ref().map(|_| REDACTED))
.field("oauth2", &self.oauth2)
.field("oauth1", &self.oauth1)
.finish()
}
}
impl std::fmt::Debug for App {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("App")
.field("client_id", &self.client_id)
.field("client_secret", &REDACTED)
.field("default_user", &self.default_user)
.field("redirect_uri", &self.redirect_uri)
.field("oauth2_tokens", &self.oauth2_tokens)
.field("oauth1_token", &self.oauth1_token)
.field("bearer_token", &self.bearer_token)
.field("unnamed_oauth2_token", &self.unnamed_oauth2_token)
.finish()
}
}
impl App {
pub(crate) fn new() -> Self {
Self {
client_id: String::new(),
client_secret: String::new(),
default_user: String::new(),
redirect_uri: String::new(),
oauth2_tokens: BTreeMap::new(),
oauth1_token: None,
bearer_token: None,
unnamed_oauth2_token: None,
}
}
pub(crate) fn with_credentials(client_id: &str, client_secret: &str) -> Self {
Self {
client_id: client_id.to_string(),
client_secret: client_secret.to_string(),
..Self::new()
}
}
pub(crate) fn has_tokens(&self) -> bool {
!self.oauth2_tokens.is_empty()
|| self.oauth1_token.is_some()
|| self.bearer_token.is_some()
|| self.unnamed_oauth2_token.is_some()
}
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct StoreFile {
pub apps: BTreeMap<String, App>,
pub default_app: String,
}