mahjong_service/auth/
github.rs1use actix_web::web::Query;
2use serde::{Deserialize, Serialize};
3use service_contracts::UserPostSetAuthResponse;
4
5use crate::{
6 auth::{GetAuthInfo, UserRole},
7 env::{ENV_GITHUB_CLIENT_ID, ENV_GITHUB_SECRET},
8 http_server::DataStorage,
9};
10
11use super::AuthHandler;
12
13#[derive(Deserialize, Debug)]
14pub struct GithubCallbackQuery {
15 code: String,
16}
17
18pub struct GithubAuth {}
19
20impl GithubAuth {
21 pub async fn handle_callback(
22 query: Query<GithubCallbackQuery>,
23 storage: &DataStorage,
24 auth_handler: &mut AuthHandler<'_>,
25 ) -> Option<UserPostSetAuthResponse> {
26 #[derive(Serialize, Debug)]
27 struct GithubAccessBody {
28 client_id: String,
29 client_secret: String,
30 code: String,
31 }
32
33 let body = GithubAccessBody {
34 client_id: std::env::var(ENV_GITHUB_CLIENT_ID).unwrap(),
35 client_secret: std::env::var(ENV_GITHUB_SECRET).unwrap(),
36 code: query.code.clone(),
37 };
38
39 let url = "https://github.com/login/oauth/access_token";
40 let json_data = serde_json::to_string(&body).unwrap();
41
42 let client = reqwest::Client::new();
43
44 let response2 = client
45 .post(url)
46 .header("Content-Type", "application/json")
47 .body(json_data.to_owned())
48 .send()
49 .await
50 .unwrap();
51
52 let response_body_text2 = response2.text().await.unwrap();
53
54 #[derive(Deserialize, Debug)]
55 struct GithubAccessResponse {
56 access_token: String,
57 }
58
59 let response_body2 =
60 serde_qs::from_str::<GithubAccessResponse>(&response_body_text2).unwrap();
61
62 let access_token = response_body2.access_token.clone();
63 let response = client
64 .get("https://api.github.com/user")
65 .header("Content-Type", "application/json")
66 .header("User-Agent", "Rust Server")
67 .header("Authorization", format!("Bearer {}", access_token))
68 .send()
69 .await
70 .unwrap();
71 let response_body_text = response.text().await.unwrap();
72
73 #[derive(Deserialize, Debug)]
74 struct GithubUserResponse {
75 login: String,
76 }
77
78 let response_body3 =
79 serde_json::from_str::<GithubUserResponse>(&response_body_text).unwrap();
80
81 let existing_user = storage
82 .get_auth_info(GetAuthInfo::GithubUsername(response_body3.login.clone()))
83 .await
84 .unwrap();
85
86 if existing_user.is_none() {
87 let result = auth_handler
88 .create_github_user(&response_body3.login, &access_token, UserRole::Player)
89 .await;
90
91 if result.is_err() {
92 return None;
93 }
94 } else {
95 auth_handler.auth_info = existing_user;
96 }
97
98 let data = auth_handler.generate_token();
99
100 if data.is_err() {
101 return None;
102 }
103
104 Some(data.unwrap())
105 }
106}