use crate::http_client::HttpClientExt;
use std::fmt;
#[cfg(not(target_family = "wasm"))]
pub use crate::providers::internal::auth::FileTokenStore;
pub use crate::providers::internal::auth::{
DeviceCodeHandler, DeviceCodePrompt, MemoryTokenStore, StoreLock, TokenStore,
};
#[cfg(not(target_family = "wasm"))]
mod native;
#[cfg(not(target_family = "wasm"))]
const STORE_KEY: &str = super::PROVIDER_NAME;
#[derive(Debug, Clone)]
pub struct BrowserSignInPrompt {
pub authorize_url: String,
pub browser_launched: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SignInMethod {
Browser,
DeviceCode,
}
#[derive(Debug, Clone)]
pub enum SignInPrompt {
Browser(BrowserSignInPrompt),
BrowserUnavailable(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SignedOut {
NotSignedIn,
Forgotten {
revoked: Result<(), String>,
},
}
#[derive(Clone)]
pub enum AuthSource {
AccessToken {
access_token: String,
account_id: Option<String>,
},
OAuth,
}
impl fmt::Debug for AuthSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AccessToken { .. } => f.write_str("AccessToken(<redacted>)"),
Self::OAuth => f.write_str("OAuth"),
}
}
}
#[derive(Clone)]
pub struct Authenticator(Shell<AuthSource>);
impl fmt::Debug for Authenticator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
use crate::providers::internal::auth::Shell;
pub use crate::providers::internal::auth::{AuthContext, AuthError};
impl Authenticator {
pub fn new(
source: AuthSource,
store: impl TokenStore + 'static,
device_code_handler: DeviceCodeHandler,
allow_device_flow: bool,
) -> Self {
Self(Shell::new(
source,
store,
device_code_handler,
allow_device_flow,
))
}
pub fn forget(&self) {
self.0.remembered.forget();
}
#[must_use]
pub fn with_device_code_handler(mut self, handler: DeviceCodeHandler) -> Self {
self.0.device_code_handler = handler;
self
}
#[cfg_attr(target_family = "wasm", allow(unused_variables))]
pub async fn auth_context<H>(&self, http: &H) -> Result<AuthContext, AuthError>
where
H: HttpClientExt,
{
match &self.0.source {
AuthSource::AccessToken {
access_token,
account_id,
} => Ok(AuthContext {
api_key: access_token.clone().into(),
account_id: account_id.clone(),
api_base: None,
}),
#[cfg(not(target_family = "wasm"))]
AuthSource::OAuth => self.auth_context_oauth(http).await,
#[cfg(target_family = "wasm")]
AuthSource::OAuth => Err(AuthError::Message(
"ChatGPT OAuth is not supported on wasm targets".into(),
)),
}
}
}