diff --git a/src/identity/backends/error.rs b/src/identity/backends/error.rs index 5a1c7cb5..9d48ec3f 100644 --- a/src/identity/backends/error.rs +++ b/src/identity/backends/error.rs @@ -35,6 +35,12 @@ pub enum IdentityDatabaseError { source: serde_json::Error, }, + #[error(transparent)] + Join { + #[from] + source: tokio::task::JoinError, + }, + #[error("building user response data")] UserBuilderError { #[from] diff --git a/src/identity/backends/sql.rs b/src/identity/backends/sql.rs index 33bbf900..672c68c9 100644 --- a/src/identity/backends/sql.rs +++ b/src/identity/backends/sql.rs @@ -366,31 +366,28 @@ async fn list_users( let db_users: Vec = user_select.all(db).await?; - let user_opts: Vec> = db_users.load_many(UserOption, db).await?; + let (user_opts, local_users, nonlocal_users, federated_users) = tokio::join!( + db_users.load_many(UserOption, db), + db_users.load_one(local_user_select, db), + db_users.load_one(nonlocal_user_select, db), + db_users.load_many(federated_user_select, db) + ); - let local_users: Vec> = - db_users.load_one(local_user_select, db).await?; - - let nonlocal_users: Vec> = - db_users.load_one(nonlocal_user_select, db).await?; - - let federated_users: Vec> = - db_users.load_many(federated_user_select, db).await?; + let locals = local_users?; let local_users_passwords: Vec>> = - local_user::load_local_users_passwords( - db, - local_users.iter().cloned().map(|u| u.map(|x| x.id)), - ) - .await?; + local_user::load_local_users_passwords(db, locals.iter().cloned().map(|u| u.map(|x| x.id))) + .await?; let mut results: Vec = Vec::new(); for (u, (o, (l, (p, (n, f))))) in db_users.into_iter().zip( - user_opts.into_iter().zip( - local_users.into_iter().zip( - local_users_passwords - .into_iter() - .zip(nonlocal_users.into_iter().zip(federated_users.into_iter())), + user_opts?.into_iter().zip( + locals.into_iter().zip( + local_users_passwords.into_iter().zip( + nonlocal_users? + .into_iter() + .zip(federated_users?.into_iter()), + ), ), ), ) { @@ -435,32 +432,33 @@ pub async fn get_user( let user_entry: Option = user_select.one(db).await?; - if let Some(user) = &user_entry { - let user_opts: Vec = user.find_related(UserOption).all(db).await?; + if let Some(user) = user_entry { + let (user_opts, local_user_with_passwords) = tokio::join!( + user.find_related(UserOption).all(db), + local_user::load_local_user_with_passwords( + db, + Some(&user_id), + None::<&str>, + None::<&str>, + ) + ); - let user_builder: UserResponseBuilder = match local_user::load_local_user_with_passwords( - db, - Some(&user_id), - None::<&str>, - None::<&str>, - ) - .await? - { + let user_builder: UserResponseBuilder = match local_user_with_passwords? { Some(local_user_with_passwords) => common::get_local_user_builder( conf, - user, + &user, local_user_with_passwords.0, Some(local_user_with_passwords.1), - user_opts, + user_opts?, ), _ => match user.find_related(NonlocalUser).one(db).await? { Some(nonlocal_user) => { - common::get_nonlocal_user_builder(user, nonlocal_user, user_opts) + common::get_nonlocal_user_builder(&user, nonlocal_user, user_opts?) } _ => { let federated_user = user.find_related(FederatedUser).all(db).await?; if !federated_user.is_empty() { - common::get_federated_user_builder(user, federated_user, user_opts) + common::get_federated_user_builder(&user, federated_user, user_opts?) } else { return Err(IdentityDatabaseError::MalformedUser(user_id.to_string()))?; }