use std::collections::HashMap;
use futures::future::BoxFuture;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OAuth2UserInfo {
pub provider: String,
pub provider_id: String,
pub email: Option<String>,
pub name: Option<String>,
pub avatar_url: Option<String>,
pub raw: serde_json::Value,
}
pub trait OAuth2Provider: Send + Sync + 'static {
fn name(&self) -> &'static str;
fn authorize_url(&self) -> (String, String, String);
fn exchange_code<'a>(
&'a self,
code: &'a str,
pkce_verifier: &'a str,
) -> BoxFuture<'a, Result<String, String>>;
fn fetch_user_info<'a>(
&'a self,
access_token: &'a str,
) -> BoxFuture<'a, Result<OAuth2UserInfo, String>>;
}
pub struct OAuth2Service {
providers: HashMap<String, Box<dyn OAuth2Provider>>,
}
impl Default for OAuth2Service {
fn default() -> Self {
Self::new()
}
}
impl OAuth2Service {
pub fn new() -> Self {
Self {
providers: HashMap::new(),
}
}
pub fn register(&mut self, p: impl OAuth2Provider) -> &mut Self {
self.providers.insert(p.name().to_owned(), Box::new(p));
self
}
pub fn get(&self, name: &str) -> Option<&dyn OAuth2Provider> {
self.providers.get(name).map(|b| b.as_ref())
}
}