Skip to content

Commit 1e175b3

Browse files
committed
user: Implement backend part of google accoutn linking
When reaching the /oauth/google endpoint fully authenticated, and the provided google credentials are valid, link the authenticated pointercrate account with the google account. Only do so it the google account is not already linked to another pointercrate account, and if the pointercrate account is not already linked to a google account (e.g. re-linking from one google account to a different one is not possible right now). Signed-off-by: stadust <[email protected]>
1 parent 6ca1410 commit 1e175b3

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

pointercrate-user-api/src/pages.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ pub async fn logout(_auth: Auth<NonMutating>, cookies: &CookieJar<'_>) -> Redire
117117
#[cfg(feature = "oauth2")]
118118
#[rocket::post("/oauth/google", data = "<payload>")]
119119
pub async fn google_oauth_login(
120-
payload: Json<GoogleOauthPayload>, key_store: &State<GoogleCertificateStore>, pool: &State<PointercratePool>,
121-
cookies: &rocket::http::CookieJar<'_>,
120+
payload: Json<GoogleOauthPayload>, auth: Option<Auth<PasswordOrBrowser>>, key_store: &State<GoogleCertificateStore>,
121+
pool: &State<PointercratePool>, cookies: &rocket::http::CookieJar<'_>,
122122
) -> pointercrate_core_api::error::Result<Status> {
123123
if key_store.needs_refresh().await {
124124
key_store
@@ -132,7 +132,25 @@ pub async fn google_oauth_login(
132132
.await
133133
.ok_or(CoreError::Unauthorized)?;
134134

135-
let authenticated_user = AuthenticatedUser::by_validated_google_creds(&validated_credentials, &mut *pool.connection().await?).await?;
135+
let maybe_linked_user = AuthenticatedUser::by_validated_google_creds(&validated_credentials, &mut *pool.connection().await?).await;
136+
137+
let authenticated_user = match auth {
138+
None => maybe_linked_user?,
139+
Some(mut signed_in_user) => {
140+
// Unauthorized = No linked account found. But in the flow that is supposed to establish the link,
141+
// that is exactly what we need.
142+
if !matches!(maybe_linked_user, Err(UserError::Core(CoreError::Unauthorized))) {
143+
return Err(CoreError::Unauthorized.into());
144+
}
145+
146+
signed_in_user
147+
.user
148+
.link_google_account(&validated_credentials, &mut signed_in_user.connection)
149+
.await?;
150+
signed_in_user.connection.commit().await.map_err(UserError::from)?;
151+
signed_in_user.user
152+
},
153+
};
136154

137155
build_cookies(&authenticated_user, cookies)?;
138156

pointercrate-user-pages/static/js/account/profile.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,21 @@ function setupInvalidateToken() {
155155
});
156156
}
157157

158+
function googleOauthCallback (response) {
159+
let error = document.getElementById("g-signin-error");
160+
161+
post("/api/v1/auth/oauth/google", {}, response)
162+
.then(() => window.location.reload())
163+
.catch(response => {
164+
error.innerText = response.data.message;
165+
error.style.display = "block";
166+
});
167+
}
168+
158169
export function initialize() {
159170
setupGetAccessToken();
160171
setupEditAccount();
161172
setupInvalidateToken();
173+
174+
window.googleOauthCallback = googleOauthCallback;
162175
}

pointercrate-user/src/auth/oauth/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#[cfg(feature = "oauth2")]
22
mod get;
33
#[cfg(feature = "oauth2")]
4+
mod patch;
5+
#[cfg(feature = "oauth2")]
46
mod post;
57

68
#[cfg(feature = "oauth2")]

pointercrate-user/src/auth/oauth/patch.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use sqlx::PgConnection;
33
use crate::auth::legacy::LegacyAuthenticatedUser;
44
use crate::Result;
55

6-
use super::{ValidatedGoogleCredentials};
6+
use super::ValidatedGoogleCredentials;
77

88
impl LegacyAuthenticatedUser {
99
pub async fn set_linked_google_account(&mut self, creds: &ValidatedGoogleCredentials, connection: &mut PgConnection) -> Result<()> {
@@ -17,4 +17,4 @@ impl LegacyAuthenticatedUser {
1717

1818
Ok(())
1919
}
20-
}
20+
}

pointercrate-user/src/auth/patch.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ impl AuthenticatedUser<PasswordOrBrowser> {
8686

8787
Ok(())
8888
}
89+
90+
#[cfg(feature = "oauth2")]
91+
pub async fn link_google_account(
92+
&mut self, creds: &super::oauth::ValidatedGoogleCredentials, connection: &mut PgConnection,
93+
) -> Result<()> {
94+
match &mut self.auth_type {
95+
AuthenticationType::Legacy(legacy) => legacy.set_linked_google_account(creds, connection).await?,
96+
_ => return Err(CoreError::Unauthorized.into()),
97+
}
98+
99+
self.increment_generation_id(connection).await
100+
}
89101
}
90102

91103
#[cfg(test)]

0 commit comments

Comments
 (0)