bios_iam/basic/serv/oauth2_spi/
iam_cert_oauth2_spi_github.rs

1use crate::basic::serv::iam_cert_oauth2_serv::{IamCertOAuth2Spi, IamCertOAuth2TokenInfo};
2use async_trait::async_trait;
3use ldap3::log::trace;
4use tardis::basic::result::TardisResult;
5use tardis::serde_json::Value;
6use tardis::{TardisFuns, TardisFunsInst};
7
8pub struct IamCertOAuth2SpiGithub;
9const OAUTH2_GITHUB_USER_INFO_CACHE_KEY: &str = "OAUTH2_GITHUB_USER_INFO_CACHE_KEY:";
10#[async_trait]
11impl IamCertOAuth2Spi for IamCertOAuth2SpiGithub {
12    async fn get_access_token(&self, code: &str, ak: &str, sk: &str, funs: &TardisFunsInst) -> TardisResult<IamCertOAuth2TokenInfo> {
13        //https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps
14        let headers = vec![("Accept".to_string(), "application/json".to_string())];
15        let result = funs
16            .web_client()
17            .post_to_obj::<Value>(
18                &format!("https://github.com/login/oauth/access_token?client_id={ak}&client_secret={sk}&code={code}"),
19                "",
20                headers,
21            )
22            .await?;
23        if result.code != 200 {
24            return Err(funs.err().not_found(
25                "oauth_spi_github",
26                "get_access_token",
27                "oauth get access token error",
28                "500-iam-cert-oauth-get-access-token-error",
29            ));
30        }
31        let result = result.body.unwrap_or_default();
32        trace!("iam oauth2 spi [Github] get access token response: {}", result);
33        if let Some(access_token) = result.get("access_token") {
34            let access_token = access_token.as_str().unwrap_or("");
35            let headers = vec![
36                ("Authorization".to_string(), format!("Bearer {access_token}")),
37                ("Accept".to_string(), "application/json".to_string()),
38                ("User-Agent".to_string(), "BIOS".to_string()),
39            ];
40            //get user info
41            let result = funs.web_client().get_to_str("https://api.github.com/user", headers).await?;
42            trace!("iam oauth2 spi [Github] get user info response: {:?}", result);
43            if result.code != 200 {
44                return Err(funs.err().not_found(
45                    "oauth_spi_github",
46                    "get_access_token",
47                    "oauth get user info error",
48                    "500-iam-cert-oauth-get-user-info-error",
49                ));
50            }
51            let user_info = result.body.unwrap_or_default();
52            let user_info = TardisFuns::json.str_to_obj::<Value>(&user_info)?;
53            funs.cache().set_ex(&format!("{OAUTH2_GITHUB_USER_INFO_CACHE_KEY}{access_token}"), &user_info.to_string(), 5).await?;
54            if let Some(id) = user_info.get("id") {
55                Ok(IamCertOAuth2TokenInfo {
56                    open_id: id.to_string(),
57                    access_token: access_token.to_string(),
58                    refresh_token: None,
59                    token_expires_ms: None,
60                    union_id: None,
61                })
62            } else {
63                Err(funs.err().not_found(
64                    "oauth_spi_github",
65                    "get_access_token",
66                    "oauth get user info error",
67                    "500-iam-cert-oauth-get-user-info-error",
68                ))
69            }
70        } else {
71            let mut v_error = "";
72            if let Some(error) = result.get("error") {
73                v_error = error.as_str().unwrap_or("");
74            }
75            Err(funs.err().not_found(
76                "oauth_spi_github",
77                "get_access_token",
78                &format!("oauth get access token error:{v_error}"),
79                "500-iam-cert-oauth-get-access-token-error",
80            ))
81        }
82    }
83
84    async fn get_account_name(&self, oauth2_info: IamCertOAuth2TokenInfo, funs: &TardisFunsInst) -> TardisResult<String> {
85        let user_info = funs.cache().get(&format!("{}{}", OAUTH2_GITHUB_USER_INFO_CACHE_KEY, oauth2_info.access_token.clone())).await?;
86        if let Some(user_info) = user_info {
87            let result = TardisFuns::json.str_to_obj::<Value>(&user_info)?;
88            Ok(result.get("name").unwrap_or(&Value::Null).as_str().unwrap_or("").to_string())
89        } else {
90            Err(funs.err().not_found(
91                "oauth_spi_github",
92                "get_account_name",
93                "oauth get account name error",
94                "500-iam-cert-oauth-get-account-name-error",
95            ))
96        }
97    }
98}