1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::api::github::{
self,
users::authenticated_user::{
authenticated_user::{AuthenticatedUserViewer, Variables},
AuthenticatedUser,
},
};
use crate::api::rcos::users::accounts::reverse_lookup::ReverseLookup;
use crate::api::rcos::users::UserAccountType;
use crate::env::global_config;
use crate::error::TelescopeError;
use crate::web::services::auth::identity::{AuthenticationCookie, RootIdentity};
use crate::web::services::auth::oauth2_providers::{Oauth2Identity, Oauth2IdentityProvider};
use futures::future::LocalBoxFuture;
use oauth2::basic::{BasicClient, BasicTokenResponse};
use oauth2::{AccessToken, AuthUrl, Scope, TokenResponse, TokenUrl};
use std::sync::Arc;
use uuid::Uuid;
pub struct GitHubOauth;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GitHubIdentity {
pub access_token: AccessToken,
}
lazy_static! {
static ref GITHUB_CLIENT: Arc<BasicClient> = {
let config = global_config();
let github_client = BasicClient::new(
config.github_credentials.client_id.clone(),
Some(config.github_credentials.client_secret.clone()),
AuthUrl::new("https://github.com/login/oauth/authorize".into())
.expect("Invalid GitHub Auth URL"),
Some(TokenUrl::new("https://github.com/login/oauth/access_token".into())
.expect("Invalid GitHub Token URL")));
Arc::new(github_client)
};
}
impl Oauth2IdentityProvider for GitHubOauth {
type IdentityType = GitHubIdentity;
const SERVICE_NAME: &'static str = "github";
fn get_client() -> Arc<BasicClient> {
GITHUB_CLIENT.clone()
}
fn scopes() -> Vec<Scope> {
vec![
Scope::new("read:user".into()),
]
}
}
impl Oauth2Identity for GitHubIdentity {
const USER_ACCOUNT_TY: UserAccountType = UserAccountType::GitHub;
fn from_basic_token(token: &BasicTokenResponse) -> Self {
Self {
access_token: token.access_token().clone(),
}
}
fn platform_user_id(&self) -> LocalBoxFuture<Result<String, TelescopeError>> {
Box::pin(async move { self.get_github_id().await })
}
fn into_root(self) -> RootIdentity {
RootIdentity::GitHub(self)
}
fn add_to_cookie(self, cookie: &mut AuthenticationCookie) {
cookie.github = Some(self);
}
}
impl GitHubIdentity {
pub async fn get_github_id(&self) -> Result<String, TelescopeError> {
self.get_authenticated_user()
.await
.map(|u| u.id.to_string())
}
pub async fn get_authenticated_user(&self) -> Result<AuthenticatedUserViewer, TelescopeError> {
github::send_query::<AuthenticatedUser>(&self.access_token, Variables {})
.await
.map(|response| response.viewer)
}
pub async fn get_rcos_user_id(&self) -> Result<Option<Uuid>, TelescopeError> {
let platform_id: String = self.get_github_id().await?;
ReverseLookup::execute(UserAccountType::GitHub, platform_id).await
}
}