diff --git a/services/headless-lms/models/.sqlx/query-375b467ba026680d07ba6fa844de91afd942e86b2715431e41b6788df0d2b3c0.json b/services/headless-lms/models/.sqlx/query-3ad1dd4e432eba7a681e55b02ca8db9f4f52c921431259b90dd9bd3c79a6aa76.json similarity index 91% rename from services/headless-lms/models/.sqlx/query-375b467ba026680d07ba6fa844de91afd942e86b2715431e41b6788df0d2b3c0.json rename to services/headless-lms/models/.sqlx/query-3ad1dd4e432eba7a681e55b02ca8db9f4f52c921431259b90dd9bd3c79a6aa76.json index 5b8c573eaeae..835f2088c1f7 100644 --- a/services/headless-lms/models/.sqlx/query-375b467ba026680d07ba6fa844de91afd942e86b2715431e41b6788df0d2b3c0.json +++ b/services/headless-lms/models/.sqlx/query-3ad1dd4e432eba7a681e55b02ca8db9f4f52c921431259b90dd9bd3c79a6aa76.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT * FROM users WHERE upstream_id = $1", + "query": "SELECT * FROM users WHERE upstream_id = $1 AND deleted_at IS NULL", "describe": { "columns": [ { @@ -84,5 +84,5 @@ true ] }, - "hash": "375b467ba026680d07ba6fa844de91afd942e86b2715431e41b6788df0d2b3c0" + "hash": "3ad1dd4e432eba7a681e55b02ca8db9f4f52c921431259b90dd9bd3c79a6aa76" } diff --git a/services/headless-lms/models/src/users.rs b/services/headless-lms/models/src/users.rs index ba8f8a262199..802b7265f9c5 100644 --- a/services/headless-lms/models/src/users.rs +++ b/services/headless-lms/models/src/users.rs @@ -128,7 +128,7 @@ pub async fn find_by_upstream_id( ) -> ModelResult> { let user = sqlx::query_as!( User, - "SELECT * FROM users WHERE upstream_id = $1", + "SELECT * FROM users WHERE upstream_id = $1 AND deleted_at IS NULL", upstream_id ) .fetch_optional(conn) @@ -209,7 +209,7 @@ pub async fn update_email_for_user( let user = sqlx::query_as!( User, - "SELECT * FROM users WHERE upstream_id = $1", + "SELECT * FROM users WHERE upstream_id = $1 AND deleted_at IS NULL", upstream_id ) .fetch_one(&mut *tx) diff --git a/services/headless-lms/server/src/controllers/auth.rs b/services/headless-lms/server/src/controllers/auth.rs index 735e391b7993..70456306626e 100644 --- a/services/headless-lms/server/src/controllers/auth.rs +++ b/services/headless-lms/server/src/controllers/auth.rs @@ -218,24 +218,37 @@ pub async fn signup( .await; let user = match user { Ok(user) => user, - Err(error) => match error.error_type() { - ModelErrorType::DatabaseConstraint { constraint, .. } - if constraint == "users_email" - || constraint == "users_upstream_id_active_uniq_idx" => - { - // Either the email or the upstream_id already belongs to an existing account, - // so the caller already has a courses.mooc.fi user. - let token = skip_authorize(); - return token.authorized_ok(web::Json(SignupResponse::EmailAlreadyExists)); - } - _ => { - return Err(controller_err!( - InternalServerError, - "Failed to insert user.".to_string(), - anyhow!(error) - )); - } - }, + Err(error) + if matches!( + error.error_type(), + ModelErrorType::DatabaseConstraint { constraint, .. } + if constraint == "users_email" + ) => + { + let token = skip_authorize(); + return token.authorized_ok(web::Json(SignupResponse::EmailAlreadyExists)); + } + // TMC synchronously posts the new user back to /api/v0/tmc-server/users/create + // while post_new_user_to_tmc is still in flight, so that callback has usually + // already created the user; continue with the existing row. + Err(error) + if matches!( + error.error_type(), + ModelErrorType::DatabaseConstraint { constraint, .. } + if constraint == "users_upstream_id_active_uniq_idx" + ) => + { + models::users::find_by_upstream_id(&mut conn, upstream_id) + .await? + .ok_or(error)? + } + Err(error) => { + return Err(controller_err!( + InternalServerError, + "Failed to insert user.".to_string(), + anyhow!(error) + )); + } }; let country = user_details.country.clone();