From a8f3aa4a0d36c7c79f43b35c5c7307d1d80509b1 Mon Sep 17 00:00:00 2001 From: Timshel Date: Mon, 7 Oct 2024 15:38:45 +0200 Subject: [PATCH] Ensure result order when searching for sso_user --- src/db/models/user.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/db/models/user.rs b/src/db/models/user.rs index c553fd0e..917ea61e 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -1,6 +1,7 @@ use crate::util::{format_date, get_uuid, retry}; use chrono::{NaiveDateTime, TimeDelta, Utc}; use serde_json::Value; +use std::cmp::Ordering; use crate::crypto; use crate::CONFIG; @@ -487,7 +488,8 @@ impl SsoUser { } // Written as an union to make the query more lisible than using an `or_filter`. - // But `first()` does not appear to work with `union()` so we use `load()`. + // If there is a match on identifier and email we want the identifier match. + // We sort results in code since UNION does not garanty order and DBs order NULL differently. pub async fn find_by_identifier_or_email( identifier: &str, mail: &str, @@ -496,7 +498,7 @@ impl SsoUser { let lower_mail = mail.to_lowercase(); db_run! {conn: { - users::table + let mut res = users::table .inner_join(sso_users::table) .select(<(UserDb, Option)>::as_select()) .filter(sso_users::identifier.eq(identifier)) @@ -509,8 +511,17 @@ impl SsoUser { .load(conn) .expect("Error searching user by SSO identifier and email") .into_iter() - .next() .map(|(user, sso_user)| { (user.from_db(), sso_user.from_db()) }) + .collect::)>>(); + + res.sort_by(|(_, sso_user), _| { + match sso_user { + Some(db_sso_user) if db_sso_user.identifier == identifier => Ordering::Less, + _ => Ordering::Greater, + } + }); + + res.into_iter().next() }} } }