#[cfg(feature = "discord")] pub mod discord; pub mod client; pub(crate) mod util; mod error; use api_core::auth::AuthClientConfig; use api_core::models::user::User; pub use error::AuthClientError; use oauth2::{EndpointNotSet, EndpointSet}; type C = oauth2::basic::BasicClient< EndpointSet, EndpointNotSet, EndpointNotSet, EndpointNotSet, EndpointSet, >; #[derive(Clone, Debug)] pub struct BasicClient(C); #[async_trait::async_trait] pub trait OauthDriver: Send + Sync { async fn get_user( &self, client: &client::AuthHttpClient, code: &str, ) -> Result; async fn validate_session(&self, cookie: &str, state: &str) -> Result<(), AuthError>; async fn create_oauth_session(&self) -> Result; async fn save_session(&self, user: &User) -> Result<(), AuthError>; } use oauth2::{AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl}; use std::{convert::TryFrom, ops::Deref}; use url::Url; use crate::error::AuthError; #[allow(dead_code)] static CSRF_TOKEN: &str = "csrf_token"; pub struct SessionResponse { pub cookie_value: String, pub auth_url: Url, } impl Deref for BasicClient { type Target = C; fn deref(&self) -> &Self::Target { &self.0 } } impl TryFrom for BasicClient { type Error = AuthClientError; fn try_from(value: AuthClientConfig) -> Result { let auth_url = AuthUrl::new(value.auth_url).map_err(AuthClientError::InvalidAuthUrl)?; let token_url = TokenUrl::new(value.token_uri).map_err(AuthClientError::InvalidTokenUrl)?; let redirect_url = RedirectUrl::new(value.redirect_uri).map_err(AuthClientError::InvalidRedirectUrl)?; Ok(Self( oauth2::basic::BasicClient::new(ClientId::new(value.client_id)) .set_client_secret(ClientSecret::new(value.client_secret)) .set_auth_uri(auth_url) .set_token_uri(token_url) .set_redirect_uri(redirect_url), )) } }