oauth_provider_rs/providers/
provider_trait.rs1use crate::{client_manager::ClientManager, storage::OAuthStorage};
7use async_trait::async_trait;
8use axum::Router;
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11
12pub type OAuthProviderConfig = crate::http_integration::config::OAuthProviderConfig;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct TokenResponse {
18 pub access_token: String,
19 pub token_type: String,
20 pub scope: String,
21 pub expires_in: Option<u64>,
22 pub refresh_token: Option<String>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct UserInfo {
28 pub user_id: String,
29 pub username: String,
30 pub name: Option<String>,
31 pub email: Option<String>,
32 pub avatar_url: Option<String>,
33 pub provider_specific: Value,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct UserProps {
39 pub user_id: String,
40 pub username: String,
41 pub name: Option<String>,
42 pub email: Option<String>,
43 pub access_token: String,
44 pub provider_specific: Value,
45}
46
47#[async_trait]
49pub trait OAuthProviderTrait<S: OAuthStorage + Clone, CM: ClientManager + Clone>:
50 Send + Sync + Clone
51{
52 fn provider_name(&self) -> &str;
54
55 fn config(&self) -> &OAuthProviderConfig;
57
58 fn router(self) -> Router;
60
61 async fn get_user_info(&self, access_token: &str) -> Result<UserInfo, String>;
63
64 fn user_info_to_props(&self, user_info: &UserInfo, access_token: &str) -> UserProps {
66 UserProps {
67 user_id: user_info.user_id.clone(),
68 username: user_info.username.clone(),
69 name: user_info.name.clone(),
70 email: user_info.email.clone(),
71 access_token: access_token.to_string(),
72 provider_specific: user_info.provider_specific.clone(),
73 }
74 }
75
76 fn storage(&self) -> &S;
78
79 fn client_manager(&self) -> &CM;
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Hash)]
85pub enum ProviderType {
86 GitHub,
87 Cognito,
88 Google,
89 Microsoft,
90 Custom(String),
91}
92
93impl std::fmt::Display for ProviderType {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 match self {
96 ProviderType::GitHub => write!(f, "github"),
97 ProviderType::Cognito => write!(f, "cognito"),
98 ProviderType::Google => write!(f, "google"),
99 ProviderType::Microsoft => write!(f, "microsoft"),
100 ProviderType::Custom(name) => write!(f, "{}", name),
101 }
102 }
103}
104
105impl From<&str> for ProviderType {
106 fn from(s: &str) -> Self {
107 match s.to_lowercase().as_str() {
108 "github" => ProviderType::GitHub,
109 "cognito" => ProviderType::Cognito,
110 "google" => ProviderType::Google,
111 "microsoft" => ProviderType::Microsoft,
112 _ => ProviderType::Custom(s.to_string()),
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_provider_type_display() {
123 assert_eq!(ProviderType::GitHub.to_string(), "github");
124 assert_eq!(ProviderType::Cognito.to_string(), "cognito");
125 assert_eq!(
126 ProviderType::Custom("custom".to_string()).to_string(),
127 "custom"
128 );
129 }
130
131 #[test]
132 fn test_provider_type_from_str() {
133 assert_eq!(ProviderType::from("github"), ProviderType::GitHub);
134 assert_eq!(ProviderType::from("GitHub"), ProviderType::GitHub);
135 assert_eq!(ProviderType::from("cognito"), ProviderType::Cognito);
136 assert_eq!(
137 ProviderType::from("custom"),
138 ProviderType::Custom("custom".to_string())
139 );
140 }
141
142 #[test]
143 fn test_oauth_provider_config() {
144 let config = OAuthProviderConfig::with_oauth_config(
145 "test_client".to_string(),
146 "test_secret".to_string(),
147 "http://localhost:8080/callback".to_string(),
148 "read:user".to_string(),
149 "github".to_string(),
150 );
151
152 assert_eq!(config.provider.client_id.as_ref().unwrap(), "test_client");
153 assert_eq!(config.provider.provider_name.as_ref().unwrap(), "github");
154 }
155
156 #[test]
157 fn test_unified_config_conversion() {
158 let config = OAuthProviderConfig::with_oauth_config(
159 "test_client".to_string(),
160 "test_secret".to_string(),
161 "http://localhost:8080/callback".to_string(),
162 "read:user".to_string(),
163 "github".to_string(),
164 );
165
166 assert_eq!(config.provider.client_id.as_ref().unwrap(), "test_client");
167 assert_eq!(config.provider.client_secret.as_ref().unwrap(), "test_secret");
168 assert_eq!(config.provider.redirect_uri.as_ref().unwrap(), "http://localhost:8080/callback");
169 assert_eq!(config.provider.scope.as_ref().unwrap(), "read:user");
170 assert_eq!(config.provider.provider_name.as_ref().unwrap(), "github");
171 }
172}