diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 8d59ffbe..893eb5b0 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -44,6 +44,7 @@ pub fn routes() -> Vec { post_bulk_collections, get_org_details, get_org_domain_sso_details, + get_org_domain_sso_verified, get_members, send_invite, reinvite_member, @@ -979,6 +980,7 @@ struct OrgDomainDetails { // Returning a Domain/Organization here allow to prefill it and prevent prompting the user // So we either return an Org name associated to the user or a dummy value. // The `verifiedDate` is required but the value ATM is ignored. +// DEPRECATED: still present in `v2025.6.0` but appears unused. #[post("/organizations/domain/sso/details", data = "")] async fn get_org_domain_sso_details(data: Json, mut conn: DbConn) -> JsonResult { let data: OrgDomainDetails = data.into_inner(); @@ -995,6 +997,33 @@ async fn get_org_domain_sso_details(data: Json, mut conn: DbCo }))) } +// Returning a Domain/Organization here allow to prefill it and prevent prompting the user +// So we either return an Org name associated to the user or a dummy value. +// In use since `v2025.6.0`, appears to use only the first `organizationIdentifier` +#[post("/organizations/domain/sso/verified", data = "")] +async fn get_org_domain_sso_verified(data: Json, mut conn: DbConn) -> JsonResult { + let data: OrgDomainDetails = data.into_inner(); + + let identifiers = match Organization::find_org_user_email(&data.email, &mut conn) + .await + .into_iter() + .map(|o| o.name) + .collect::>() + { + v if !v.is_empty() => v, + _ => vec![crate::sso::FAKE_IDENTIFIER.to_string()], + }; + + Ok(Json(json!({ + "object": "list", + "data": identifiers.into_iter().map(|identifier| json!({ + "organizationName": identifier, // appear unused + "organizationIdentifier": identifier, + "domainName": CONFIG.domain(), // appear unused + })).collect::>() + }))) +} + #[derive(FromForm)] struct GetOrgUserData { #[field(name = "includeCollections")] diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 42922ffa..77cf91c0 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -422,6 +422,23 @@ impl Organization { .ok().from_db() }} } + + pub async fn find_org_user_email(user_email: &str, conn: &mut DbConn) -> Vec { + let lower_mail = user_email.to_lowercase(); + + db_run! { conn: { + organizations::table + .inner_join(users_organizations::table.on(users_organizations::org_uuid.eq(organizations::uuid))) + .inner_join(users::table.on(users::uuid.eq(users_organizations::user_uuid))) + .filter(users::email.eq(lower_mail)) + .filter(users_organizations::status.ne(MembershipStatus::Revoked as i32)) + .order(users_organizations::atype.asc()) + .select(organizations::all_columns) + .load::(conn) + .expect("Error loading user orgs") + .from_db() + }} + } } impl Membership {