Update profile to include all available fields from Google

This commit is contained in:
Chris Jean-Marie 2024-09-25 20:14:50 +00:00
parent 022a138e56
commit 42aba64bc2
7 changed files with 55 additions and 23 deletions

View File

@ -23,7 +23,7 @@ oauth2 = "4.4"
http = "1.1"
tower-http = { version = "0.6.1", features = ["full"] }
chrono = { version = "0.4.38", features = ["serde"] }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio"] }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "macros"] }
uuid = { version = "1.10", features = ["v4"] }
dotenvy = "0.15"
constant_time_eq = "0.3"

View File

@ -56,8 +56,10 @@ pub struct UserData {
#[allow(dead_code)]
pub id: i64,
pub email: String,
/* pub name: String,
pub discriminator: String,
pub name: String,
pub family_name: String,
pub given_name: String,
/* pub discriminator: String,
pub avatar: String,
pub access_token: String,
pub refresh_token: String,

View File

@ -43,18 +43,17 @@ pub async fn inject_user_data(
let id = query.0;
let expires_at = query.1;
if expires_at > Utc::now().timestamp() {
let query: Result<(String,), _> =
sqlx::query_as(r#"SELECT email FROM users WHERE id=?"#)
.bind(id)
.fetch_one(&db_pool)
.await;
if let Ok(query) = query {
let email = query.0;
request.extensions_mut().insert(Some(UserData {
id,
email,
}));
}
let row = sqlx::query_as!(UserData, "SELECT * FROM users WHERE id = ?", id)
.fetch_one(&db_pool)
.await?;
request.extensions_mut().insert(Some(UserData {
id: row.id,
email: row.email,
name: row.name,
family_name: row.family_name,
given_name: row.given_name,
}));
}
}
}

View File

@ -81,6 +81,9 @@ pub async fn login(
.add_scope(Scope::new(
"https://www.googleapis.com/auth/userinfo.email".to_string(),
))
.add_scope(Scope::new(
"https://www.googleapis.com/auth/userinfo.profile".to_string(),
))
.set_pkce_challenge(pkce_code_challenge)
.url();
@ -151,11 +154,27 @@ pub async fn google_auth_return(
.map_err(|_| "OAuth: reqwest received invalid userinfo")?;
let mut body: serde_json::Value =
serde_json::from_str(body.as_str()).map_err(|_| "OAuth: Serde failed to parse userinfo")?;
println!("body: {}", body);
let email = body["email"]
.take()
.as_str()
.ok_or("OAuth: Serde failed to parse email address")?
.to_owned();
let name = body["name"]
.take()
.as_str()
.ok_or("OAuth: Serde failed to parse email address")?
.to_owned();
let family_name = body["family_name"]
.take()
.as_str()
.ok_or("OAuth: Serde failed to parse email address")?
.to_owned();
let given_name = body["given_name"]
.take()
.as_str()
.ok_or("OAuth: Serde failed to parse email address")?
.to_owned();
let verified_email = body["verified_email"]
.take()
.as_bool()
@ -174,8 +193,11 @@ pub async fn google_auth_return(
let user_id = if let Ok(query) = query {
query.0
} else {
let query: (i64,) = sqlx::query_as("INSERT INTO users (email) VALUES (?) RETURNING id")
let query: (i64,) = sqlx::query_as("INSERT INTO users (email, name, family_name, given_name) VALUES (?, ?, ?, ?) RETURNING id")
.bind(email)
.bind(name)
.bind(family_name)
.bind(given_name)
.fetch_one(&db_pool)
.await?;
query.0

View File

@ -10,17 +10,23 @@ use crate::{HtmlTemplate, UserData};
struct ProfileTemplate {
logged_in: bool,
name: String,
family_name: String,
given_name: String,
email: String,
}
pub async fn profile<T>(
Extension(user_data): Extension<Option<UserData>>,
_request: Request<T>,
) -> impl IntoResponse {
let email = user_data.map(|s| s.email);
let logged_in = email.is_some();
let name = email.unwrap_or_default();
let template = ProfileTemplate { logged_in, name};
let Some(UserData {id, email, family_name, given_name, name}) = user_data
else {
return HtmlTemplate(ProfileTemplate { logged_in: false, name: "".to_owned(), given_name: "".to_owned(), family_name: "".to_owned(), email: "".to_owned() });
};
let logged_in = id > 0;
let template = ProfileTemplate { logged_in, name, given_name, family_name, email };
HtmlTemplate(template)
}

View File

@ -44,7 +44,7 @@
<!-- FOOTER -->
<footer>
<p class="pull-right"><a href="#">Back to top</a></p>
<p>© 2022 Jean-Marie family</p>
<p>© 2024 Jean-Marie family</p>
</footer>
</div><!-- /.container -->

View File

@ -1,6 +1,9 @@
{% extends "base.html" %}
{% block title %}User Profile{% endblock %}
{% block content %}
This is your user profile page. <br />
Your email address: {{ name }}.
<h1>User Profile</h1>
Full name: {{ name }}<br/>
Given name: {{ given_name }}<br/>
Family name: {{ family_name }}<br/>
Your email address: {{ email }}<br
{% endblock %}