use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GitHubOAuthConfig {
pub client_id: String,
pub client_secret: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoogleOAuthConfig {
pub client_id: String,
pub client_secret: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOAuthConfig {
pub app_id: String,
pub app_secret: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct OAuthConfig {
pub enabled: bool,
pub redirect_url: String,
pub github: Option<GitHubOAuthConfig>,
pub google: Option<GoogleOAuthConfig>,
pub wechat: Option<WechatOAuthConfig>,
}
impl OAuthConfig {
pub fn from_env() -> Self {
let enabled = std::env::var("OAUTH_ENABLED")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(false);
let redirect_url = std::env::var("OAUTH_REDIRECT_URL")
.unwrap_or_else(|_| "http://localhost:3000/auth/callback".into());
let github = {
let client_id = std::env::var("OAUTH_GITHUB_CLIENT_ID").ok();
let client_secret = std::env::var("OAUTH_GITHUB_CLIENT_SECRET").ok();
match (client_id, client_secret) {
(Some(id), Some(secret)) if !id.is_empty() && !secret.is_empty() => {
Some(GitHubOAuthConfig {
client_id: id,
client_secret: secret,
})
}
_ => None,
}
};
let google = {
let client_id = std::env::var("OAUTH_GOOGLE_CLIENT_ID").ok();
let client_secret = std::env::var("OAUTH_GOOGLE_CLIENT_SECRET").ok();
match (client_id, client_secret) {
(Some(id), Some(secret)) if !id.is_empty() && !secret.is_empty() => {
Some(GoogleOAuthConfig {
client_id: id,
client_secret: secret,
})
}
_ => None,
}
};
let wechat = {
let app_id = std::env::var("OAUTH_WECHAT_APP_ID").ok();
let app_secret = std::env::var("OAUTH_WECHAT_APP_SECRET").ok();
match (app_id, app_secret) {
(Some(id), Some(secret)) if !id.is_empty() && !secret.is_empty() => {
Some(WechatOAuthConfig {
app_id: id,
app_secret: secret,
})
}
_ => None,
}
};
Self {
enabled,
redirect_url,
github,
google,
wechat,
}
}
pub fn is_provider_configured(&self, provider: &str) -> bool {
match provider {
"github" => self.github.is_some(),
"google" => self.google.is_some(),
"wechat" => self.wechat.is_some(),
_ => false,
}
}
pub fn configured_providers(&self) -> Vec<&str> {
let mut providers = Vec::new();
if self.github.is_some() {
providers.push("github");
}
if self.google.is_some() {
providers.push("google");
}
if self.wechat.is_some() {
providers.push("wechat");
}
providers
}
}