use oauth2::reqwest::async_http_client;
use oauth2::{AuthorizationCode, TokenResponse};
use crate::Result;
use crate::{Config, Database};
use super::UserInfo;
pub const AUTH_URL: &str = "https://accounts.google.com/o/oauth2/v2/auth";
pub const TOKEN_URL: &str = "https://www.googleapis.com/oauth2/v4/token";
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, rename_all = "camelCase")]
struct GoogleUserInfo {
names: Vec<GoogleName>,
email_addresses: Vec<GoogleEmail>,
photos: Vec<GooglePhoto>,
}
impl Into<UserInfo> for GoogleUserInfo {
fn into(self) -> UserInfo {
UserInfo {
email: self.email_addresses.first().unwrap().value.clone(),
full_name: Some(format!(
"{} {}",
self.names.first().unwrap().given_name,
self.names.first().unwrap().family_name,
)),
avatar_url: self.photos.first().map(|p| p.url.clone()),
..Default::default()
}
}
}
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, rename_all = "camelCase")]
struct GoogleMetadata {
pub primary: bool,
pub verified: bool,
}
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, rename_all = "camelCase")]
struct GoogleName {
pub metadata: GoogleMetadata,
pub display_name: String,
pub given_name: String,
pub family_name: String,
}
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, rename_all = "camelCase")]
struct GoogleEmail {
pub metadata: GoogleMetadata,
pub value: String,
pub r#type: String,
}
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, rename_all = "camelCase")]
struct GooglePhoto {
pub metadata: GoogleMetadata,
pub url: String,
pub default: bool,
}
pub async fn get_user_info<'c>(
auth_code: String,
config: &Config,
db: &Database,
) -> Result<UserInfo> {
let client = crate::oauth::client(
&config.oauth.google,
config.domain.clone(),
"google".to_string(),
AUTH_URL.to_string(),
TOKEN_URL.to_string(),
)?;
let token = client
.exchange_code(AuthorizationCode::new(auth_code.clone()))
.request_async(async_http_client)
.await
.unwrap();
let client = reqwest::Client::new();
let user_info: GoogleUserInfo = client
.get("https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,photos")
.bearer_auth(token.access_token().secret())
.send()
.await
.unwrap()
.json::<GoogleUserInfo>()
.await
.unwrap();
println!("user_info: {:?}", user_info);
Ok(user_info.into())
}