From 2af9a9e9e4723dd3a51427e1d4286d2bf370a87e Mon Sep 17 00:00:00 2001 From: BlackDex Date: Fri, 8 May 2026 18:12:00 +0200 Subject: [PATCH] Remove "db_run!" macro calls where possible Signed-off-by: BlackDex --- src/db/models/archive.rs | 22 +- src/db/models/attachment.rs | 52 +- src/db/models/auth_request.rs | 32 +- src/db/models/cipher.rs | 505 +++++++++--------- src/db/models/collection.rs | 675 ++++++++++++++---------- src/db/models/device.rs | 68 ++- src/db/models/emergency_access.rs | 91 ++-- src/db/models/event.rs | 51 +- src/db/models/favorite.rs | 47 +- src/db/models/folder.rs | 50 +- src/db/models/group.rs | 241 +++++---- src/db/models/org_policy.rs | 69 ++- src/db/models/organization.rs | 333 ++++++------ src/db/models/send.rs | 57 +- src/db/models/sso_auth.rs | 15 +- src/db/models/two_factor.rs | 48 +- src/db/models/two_factor_duo_context.rs | 37 +- src/db/models/two_factor_incomplete.rs | 37 +- src/db/models/user.rs | 106 ++-- 19 files changed, 1340 insertions(+), 1196 deletions(-) diff --git a/src/db/models/archive.rs b/src/db/models/archive.rs index 74772abb..83d547f2 100644 --- a/src/db/models/archive.rs +++ b/src/db/models/archive.rs @@ -21,13 +21,15 @@ pub struct Archive { impl Archive { // Returns the date the specified cipher was archived pub async fn get_archived_at(cipher_uuid: &CipherId, user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { archives::table .filter(archives::cipher_uuid.eq(cipher_uuid)) .filter(archives::user_uuid.eq(user_uuid)) .select(archives::archived_at) - .first::(conn).ok() - }} + .first::(conn) + .ok() + }) + .await } // Saves (inserts or updates) an archive record with the provided timestamp @@ -68,26 +70,26 @@ impl Archive { // Deletes an archive record for a specific cipher pub async fn delete_by_cipher(user_uuid: &UserId, cipher_uuid: &CipherId, conn: &DbConn) -> EmptyResult { User::update_uuid_revision(user_uuid, conn).await; - db_run! { conn: { + conn.run(move |conn| { diesel::delete( - archives::table - .filter(archives::user_uuid.eq(user_uuid)) - .filter(archives::cipher_uuid.eq(cipher_uuid)) + archives::table.filter(archives::user_uuid.eq(user_uuid)).filter(archives::cipher_uuid.eq(cipher_uuid)), ) .execute(conn) .map_res("Error deleting archive") - }} + }) + .await } /// Return a vec with (cipher_uuid, archived_at) /// This is used during a full sync so we only need one query for all archive matches pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec<(CipherId, NaiveDateTime)> { - db_run! { conn: { + conn.run(move |conn| { archives::table .filter(archives::user_uuid.eq(user_uuid)) .select((archives::cipher_uuid, archives::archived_at)) .load::<(CipherId, NaiveDateTime)>(conn) .unwrap_or_default() - }} + }) + .await } } diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs index c2773f74..37d1205d 100644 --- a/src/db/models/attachment.rs +++ b/src/db/models/attachment.rs @@ -112,15 +112,15 @@ impl Attachment { } pub async fn delete(&self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { - crate::util::retry(|| - diesel::delete(attachments::table.filter(attachments::id.eq(&self.id))) - .execute(conn), + conn.run(move |conn| { + crate::util::retry( + || diesel::delete(attachments::table.filter(attachments::id.eq(&self.id))).execute(conn), 10, ) .map(|_| ()) .map_res("Error deleting attachment") - }}?; + }) + .await?; let operator = CONFIG.opendal_operator_for_path_type(&PathType::Attachments)?; let file_path = self.get_file_path(); @@ -144,25 +144,22 @@ impl Attachment { } pub async fn find_by_id(id: &AttachmentId, conn: &DbConn) -> Option { - db_run! { conn: { - attachments::table - .filter(attachments::id.eq(id.to_lowercase())) - .first::(conn) - .ok() - }} + conn.run(move |conn| attachments::table.filter(attachments::id.eq(id.to_lowercase())).first::(conn).ok()) + .await } pub async fn find_by_cipher(cipher_uuid: &CipherId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { attachments::table .filter(attachments::cipher_uuid.eq(cipher_uuid)) .load::(conn) .expect("Error loading attachments") - }} + }) + .await } pub async fn size_by_user(user_uuid: &UserId, conn: &DbConn) -> i64 { - db_run! { conn: { + conn.run(move |conn| { let result: Option = attachments::table .left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid))) .filter(ciphers::user_uuid.eq(user_uuid)) @@ -173,24 +170,26 @@ impl Attachment { match result.map(|r| r.to_i64()) { Some(Some(r)) => r, Some(None) => i64::MAX, - None => 0 + None => 0, } - }} + }) + .await } pub async fn count_by_user(user_uuid: &UserId, conn: &DbConn) -> i64 { - db_run! { conn: { + conn.run(move |conn| { attachments::table .left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid))) .filter(ciphers::user_uuid.eq(user_uuid)) .count() .first(conn) .unwrap_or(0) - }} + }) + .await } pub async fn size_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { + conn.run(move |conn| { let result: Option = attachments::table .left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid))) .filter(ciphers::organization_uuid.eq(org_uuid)) @@ -201,20 +200,22 @@ impl Attachment { match result.map(|r| r.to_i64()) { Some(Some(r)) => r, Some(None) => i64::MAX, - None => 0 + None => 0, } - }} + }) + .await } pub async fn count_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { + conn.run(move |conn| { attachments::table .left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid))) .filter(ciphers::organization_uuid.eq(org_uuid)) .count() .first(conn) .unwrap_or(0) - }} + }) + .await } // This will return all attachments linked to the user or org @@ -225,7 +226,7 @@ impl Attachment { org_uuids: &Vec, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { attachments::table .left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid))) .filter(ciphers::user_uuid.eq(user_uuid)) @@ -233,7 +234,8 @@ impl Attachment { .select(attachments::all_columns) .load::(conn) .expect("Error loading attachments") - }} + }) + .await } } diff --git a/src/db/models/auth_request.rs b/src/db/models/auth_request.rs index 2924518c..a3876661 100644 --- a/src/db/models/auth_request.rs +++ b/src/db/models/auth_request.rs @@ -114,31 +114,28 @@ impl AuthRequest { } pub async fn find_by_uuid(uuid: &AuthRequestId, conn: &DbConn) -> Option { - db_run! { conn: { - auth_requests::table - .filter(auth_requests::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| auth_requests::table.filter(auth_requests::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn find_by_uuid_and_user(uuid: &AuthRequestId, user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { auth_requests::table .filter(auth_requests::uuid.eq(uuid)) .filter(auth_requests::user_uuid.eq(user_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { auth_requests::table .filter(auth_requests::user_uuid.eq(user_uuid)) .load::(conn) .expect("Error loading auth_requests") - }} + }) + .await } pub async fn find_by_user_and_requested_device( @@ -146,7 +143,7 @@ impl AuthRequest { device_uuid: &DeviceId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { auth_requests::table .filter(auth_requests::user_uuid.eq(user_uuid)) .filter(auth_requests::request_device_identifier.eq(device_uuid)) @@ -154,24 +151,27 @@ impl AuthRequest { .order_by(auth_requests::creation_date.desc()) .first::(conn) .ok() - }} + }) + .await } pub async fn find_created_before(dt: &NaiveDateTime, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { auth_requests::table .filter(auth_requests::creation_date.lt(dt)) .load::(conn) .expect("Error loading auth_requests") - }} + }) + .await } pub async fn delete(&self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(auth_requests::table.filter(auth_requests::uuid.eq(&self.uuid))) .execute(conn) .map_res("Error deleting auth request") - }} + }) + .await } pub fn check_access_code(&self, access_code: &str) -> bool { diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 1070a337..3852ceff 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -481,11 +481,12 @@ impl Cipher { Attachment::delete_all_by_cipher(&self.uuid, conn).await?; Favorite::delete_all_by_cipher(&self.uuid, conn).await?; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(ciphers::table.filter(ciphers::uuid.eq(&self.uuid))) .execute(conn) .map_res("Error deleting cipher") - }} + }) + .await } pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { @@ -668,51 +669,51 @@ impl Cipher { } async fn get_user_collections_access_flags(&self, user_uuid: &UserId, conn: &DbConn) -> Vec<(bool, bool, bool)> { - db_run! { conn: { + conn.run(move |conn| { // Check whether this cipher is in any collections accessible to the // user. If so, retrieve the access flags for each collection. ciphers::table .filter(ciphers::uuid.eq(&self.uuid)) - .inner_join(ciphers_collections::table.on( - ciphers::uuid.eq(ciphers_collections::cipher_uuid) - )) - .inner_join(users_collections::table.on( - ciphers_collections::collection_uuid.eq(users_collections::collection_uuid) - .and(users_collections::user_uuid.eq(user_uuid)) - )) + .inner_join(ciphers_collections::table.on(ciphers::uuid.eq(ciphers_collections::cipher_uuid))) + .inner_join( + users_collections::table.on(ciphers_collections::collection_uuid + .eq(users_collections::collection_uuid) + .and(users_collections::user_uuid.eq(user_uuid))), + ) .select((users_collections::read_only, users_collections::hide_passwords, users_collections::manage)) .load::<(bool, bool, bool)>(conn) .expect("Error getting user access restrictions") - }} + }) + .await } async fn get_group_collections_access_flags(&self, user_uuid: &UserId, conn: &DbConn) -> Vec<(bool, bool, bool)> { if !CONFIG.org_groups_enabled() { return Vec::new(); } - db_run! { conn: { + conn.run(move |conn| { ciphers::table .filter(ciphers::uuid.eq(&self.uuid)) - .inner_join(ciphers_collections::table.on( - ciphers::uuid.eq(ciphers_collections::cipher_uuid) - )) - .inner_join(collections_groups::table.on( - collections_groups::collections_uuid.eq(ciphers_collections::collection_uuid) - )) - .inner_join(groups_users::table.on( - groups_users::groups_uuid.eq(collections_groups::groups_uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::uuid.eq(groups_users::users_organizations_uuid) - )) - .inner_join(groups::table.on(groups::uuid.eq(collections_groups::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) + .inner_join(ciphers_collections::table.on(ciphers::uuid.eq(ciphers_collections::cipher_uuid))) + .inner_join( + collections_groups::table + .on(collections_groups::collections_uuid.eq(ciphers_collections::collection_uuid)), + ) + .inner_join(groups_users::table.on(groups_users::groups_uuid.eq(collections_groups::groups_uuid))) + .inner_join( + users_organizations::table.on(users_organizations::uuid.eq(groups_users::users_organizations_uuid)), + ) + .inner_join( + groups::table.on(groups::uuid + .eq(collections_groups::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) .filter(users_organizations::user_uuid.eq(user_uuid)) .select((collections_groups::read_only, collections_groups::hide_passwords, collections_groups::manage)) .load::<(bool, bool, bool)>(conn) .expect("Error getting group access restrictions") - }} + }) + .await } pub async fn is_write_accessible_to_user(&self, user_uuid: &UserId, conn: &DbConn) -> bool { @@ -761,7 +762,7 @@ impl Cipher { } pub async fn get_folder_uuid(&self, user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { folders_ciphers::table .inner_join(folders::table) .filter(folders::user_uuid.eq(&user_uuid)) @@ -769,16 +770,12 @@ impl Cipher { .select(folders_ciphers::folder_uuid) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_uuid(uuid: &CipherId, conn: &DbConn) -> Option { - db_run! { conn: { - ciphers::table - .filter(ciphers::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| ciphers::table.filter(ciphers::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn find_by_uuid_and_org( @@ -786,13 +783,14 @@ impl Cipher { org_uuid: &OrganizationId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { ciphers::table .filter(ciphers::uuid.eq(cipher_uuid)) .filter(ciphers::organization_uuid.eq(org_uuid)) .first::(conn) .ok() - }} + }) + .await } // Find all ciphers accessible or visible to the specified user. @@ -814,32 +812,35 @@ impl Cipher { conn: &DbConn, ) -> Vec { if CONFIG.org_groups_enabled() { - db_run! { conn: { + conn.run(move |conn| { let mut query = ciphers::table - .left_join(ciphers_collections::table.on( - ciphers::uuid.eq(ciphers_collections::cipher_uuid) - )) - .left_join(users_organizations::table.on( - ciphers::organization_uuid.eq(users_organizations::org_uuid.nullable()) + .left_join(ciphers_collections::table.on(ciphers::uuid.eq(ciphers_collections::cipher_uuid))) + .left_join( + users_organizations::table.on(ciphers::organization_uuid + .eq(users_organizations::org_uuid.nullable()) .and(users_organizations::user_uuid.eq(user_uuid)) - .and(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) - )) - .left_join(users_collections::table.on( - ciphers_collections::collection_uuid.eq(users_collections::collection_uuid) + .and(users_organizations::status.eq(MembershipStatus::Confirmed as i32))), + ) + .left_join( + users_collections::table.on(ciphers_collections::collection_uuid + .eq(users_collections::collection_uuid) // Ensure that users_collections::user_uuid is NULL for unconfirmed users. - .and(users_organizations::user_uuid.eq(users_collections::user_uuid)) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - // Ensure that group and membership belong to the same org - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::collections_uuid.eq(ciphers_collections::collection_uuid) - .and(collections_groups::groups_uuid.eq(groups::uuid)) - )) + .and(users_organizations::user_uuid.eq(users_collections::user_uuid))), + ) + .left_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), + ) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + // Ensure that group and membership belong to the same org + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) + .left_join( + collections_groups::table.on(collections_groups::collections_uuid + .eq(ciphers_collections::collection_uuid) + .and(collections_groups::groups_uuid.eq(groups::uuid))), + ) .filter(ciphers::user_uuid.eq(user_uuid)) // Cipher owner .or_filter(users_organizations::access_all.eq(true)) // access_all in org .or_filter(users_collections::user_uuid.eq(user_uuid)) // Access to collection @@ -849,39 +850,34 @@ impl Cipher { if !visible_only { query = query.or_filter( - users_organizations::atype.le(MembershipType::Admin as i32) // Org admin/owner + users_organizations::atype.le(MembershipType::Admin as i32), // Org admin/owner ); } // Only filter for one specific cipher if !cipher_uuids.is_empty() { - query = query.filter( - ciphers::uuid.eq_any(cipher_uuids) - ); + query = query.filter(ciphers::uuid.eq_any(cipher_uuids)); } - query - .select(ciphers::all_columns) - .distinct() - .load::(conn) - .expect("Error loading ciphers") - }} + query.select(ciphers::all_columns).distinct().load::(conn).expect("Error loading ciphers") + }) + .await } else { - db_run! { conn: { + conn.run(move |conn| { let mut query = ciphers::table - .left_join(ciphers_collections::table.on( - ciphers::uuid.eq(ciphers_collections::cipher_uuid) - )) - .left_join(users_organizations::table.on( - ciphers::organization_uuid.eq(users_organizations::org_uuid.nullable()) + .left_join(ciphers_collections::table.on(ciphers::uuid.eq(ciphers_collections::cipher_uuid))) + .left_join( + users_organizations::table.on(ciphers::organization_uuid + .eq(users_organizations::org_uuid.nullable()) .and(users_organizations::user_uuid.eq(user_uuid)) - .and(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) - )) - .left_join(users_collections::table.on( - ciphers_collections::collection_uuid.eq(users_collections::collection_uuid) + .and(users_organizations::status.eq(MembershipStatus::Confirmed as i32))), + ) + .left_join( + users_collections::table.on(ciphers_collections::collection_uuid + .eq(users_collections::collection_uuid) // Ensure that users_collections::user_uuid is NULL for unconfirmed users. - .and(users_organizations::user_uuid.eq(users_collections::user_uuid)) - )) + .and(users_organizations::user_uuid.eq(users_collections::user_uuid))), + ) .filter(ciphers::user_uuid.eq(user_uuid)) // Cipher owner .or_filter(users_organizations::access_all.eq(true)) // access_all in org .or_filter(users_collections::user_uuid.eq(user_uuid)) // Access to collection @@ -889,23 +885,18 @@ impl Cipher { if !visible_only { query = query.or_filter( - users_organizations::atype.le(MembershipType::Admin as i32) // Org admin/owner + users_organizations::atype.le(MembershipType::Admin as i32), // Org admin/owner ); } // Only filter for one specific cipher if !cipher_uuids.is_empty() { - query = query.filter( - ciphers::uuid.eq_any(cipher_uuids) - ); + query = query.filter(ciphers::uuid.eq_any(cipher_uuids)); } - query - .select(ciphers::all_columns) - .distinct() - .load::(conn) - .expect("Error loading ciphers") - }} + query.select(ciphers::all_columns).distinct().load::(conn).expect("Error loading ciphers") + }) + .await } } @@ -928,193 +919,208 @@ impl Cipher { // Find all ciphers directly owned by the specified user. pub async fn find_owned_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { ciphers::table - .filter( - ciphers::user_uuid.eq(user_uuid) - .and(ciphers::organization_uuid.is_null()) - ) + .filter(ciphers::user_uuid.eq(user_uuid).and(ciphers::organization_uuid.is_null())) .load::(conn) .expect("Error loading ciphers") - }} + }) + .await } pub async fn count_owned_by_user(user_uuid: &UserId, conn: &DbConn) -> i64 { - db_run! { conn: { - ciphers::table - .filter(ciphers::user_uuid.eq(user_uuid)) - .count() - .first::(conn) - .ok() - .unwrap_or(0) - }} + conn.run(move |conn| { + ciphers::table.filter(ciphers::user_uuid.eq(user_uuid)).count().first::(conn).ok().unwrap_or(0) + }) + .await } pub async fn find_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { ciphers::table .filter(ciphers::organization_uuid.eq(org_uuid)) .load::(conn) .expect("Error loading ciphers") - }} + }) + .await } pub async fn count_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { - ciphers::table - .filter(ciphers::organization_uuid.eq(org_uuid)) - .count() - .first::(conn) - .ok() - .unwrap_or(0) - }} + conn.run(move |conn| { + ciphers::table.filter(ciphers::organization_uuid.eq(org_uuid)).count().first::(conn).ok().unwrap_or(0) + }) + .await } pub async fn find_by_folder(folder_uuid: &FolderId, conn: &DbConn) -> Vec { - db_run! { conn: { - folders_ciphers::table.inner_join(ciphers::table) + conn.run(move |conn| { + folders_ciphers::table + .inner_join(ciphers::table) .filter(folders_ciphers::folder_uuid.eq(folder_uuid)) .select(ciphers::all_columns) .load::(conn) .expect("Error loading ciphers") - }} + }) + .await } /// Find all ciphers that were deleted before the specified datetime. pub async fn find_deleted_before(dt: &NaiveDateTime, conn: &DbConn) -> Vec { - db_run! { conn: { - ciphers::table - .filter(ciphers::deleted_at.lt(dt)) - .load::(conn) - .expect("Error loading ciphers") - }} + conn.run(move |conn| { + ciphers::table.filter(ciphers::deleted_at.lt(dt)).load::(conn).expect("Error loading ciphers") + }) + .await } pub async fn get_collections(&self, user_uuid: UserId, conn: &DbConn) -> Vec { if CONFIG.org_groups_enabled() { - db_run! { conn: { + conn.run(move |conn| { ciphers_collections::table .filter(ciphers_collections::cipher_uuid.eq(&self.uuid)) - .inner_join(collections::table.on( - collections::uuid.eq(ciphers_collections::collection_uuid) - )) - .left_join(users_organizations::table.on( - users_organizations::org_uuid.eq(collections::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid.clone())) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(ciphers_collections::collection_uuid) - .and(users_collections::user_uuid.eq(user_uuid.clone())) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::collections_uuid.eq(ciphers_collections::collection_uuid) - .and(collections_groups::groups_uuid.eq(groups::uuid)) - )) - .filter(users_organizations::access_all.eq(true) // User has access all - .or(users_collections::user_uuid.eq(user_uuid) // User has access to collection - .and(users_collections::read_only.eq(false))) - .or(groups::access_all.eq(true)) // Access via groups - .or(collections_groups::collections_uuid.is_not_null() // Access via groups - .and(collections_groups::read_only.eq(false))) + .inner_join(collections::table.on(collections::uuid.eq(ciphers_collections::collection_uuid))) + .left_join( + users_organizations::table.on(users_organizations::org_uuid + .eq(collections::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(ciphers_collections::collection_uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), + ) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) + .left_join( + collections_groups::table.on(collections_groups::collections_uuid + .eq(ciphers_collections::collection_uuid) + .and(collections_groups::groups_uuid.eq(groups::uuid))), + ) + .filter( + users_organizations::access_all + .eq(true) // User has access all + .or(users_collections::user_uuid + .eq(user_uuid) // User has access to collection + .and(users_collections::read_only.eq(false))) + .or(groups::access_all.eq(true)) // Access via groups + .or(collections_groups::collections_uuid + .is_not_null() // Access via groups + .and(collections_groups::read_only.eq(false))), ) .select(ciphers_collections::collection_uuid) .load::(conn) .unwrap_or_default() - }} + }) + .await } else { - db_run! { conn: { + conn.run(move |conn| { ciphers_collections::table .filter(ciphers_collections::cipher_uuid.eq(&self.uuid)) - .inner_join(collections::table.on( - collections::uuid.eq(ciphers_collections::collection_uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::org_uuid.eq(collections::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid.clone())) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(ciphers_collections::collection_uuid) - .and(users_collections::user_uuid.eq(user_uuid.clone())) - )) - .filter(users_organizations::access_all.eq(true) // User has access all - .or(users_collections::user_uuid.eq(user_uuid) // User has access to collection - .and(users_collections::read_only.eq(false))) + .inner_join(collections::table.on(collections::uuid.eq(ciphers_collections::collection_uuid))) + .inner_join( + users_organizations::table.on(users_organizations::org_uuid + .eq(collections::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(ciphers_collections::collection_uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), + ) + .filter( + users_organizations::access_all + .eq(true) // User has access all + .or(users_collections::user_uuid + .eq(user_uuid) // User has access to collection + .and(users_collections::read_only.eq(false))), ) .select(ciphers_collections::collection_uuid) .load::(conn) .unwrap_or_default() - }} + }) + .await } } pub async fn get_admin_collections(&self, user_uuid: UserId, conn: &DbConn) -> Vec { if CONFIG.org_groups_enabled() { - db_run! { conn: { + conn.run(move |conn| { ciphers_collections::table .filter(ciphers_collections::cipher_uuid.eq(&self.uuid)) - .inner_join(collections::table.on( - collections::uuid.eq(ciphers_collections::collection_uuid) - )) - .left_join(users_organizations::table.on( - users_organizations::org_uuid.eq(collections::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid.clone())) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(ciphers_collections::collection_uuid) - .and(users_collections::user_uuid.eq(user_uuid.clone())) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::collections_uuid.eq(ciphers_collections::collection_uuid) - .and(collections_groups::groups_uuid.eq(groups::uuid)) - )) - .filter(users_organizations::access_all.eq(true) // User has access all - .or(users_collections::user_uuid.eq(user_uuid) // User has access to collection - .and(users_collections::read_only.eq(false))) - .or(groups::access_all.eq(true)) // Access via groups - .or(collections_groups::collections_uuid.is_not_null() // Access via groups - .and(collections_groups::read_only.eq(false))) - .or(users_organizations::atype.le(MembershipType::Admin as i32)) // User is admin or owner + .inner_join(collections::table.on(collections::uuid.eq(ciphers_collections::collection_uuid))) + .left_join( + users_organizations::table.on(users_organizations::org_uuid + .eq(collections::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(ciphers_collections::collection_uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), + ) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) + .left_join( + collections_groups::table.on(collections_groups::collections_uuid + .eq(ciphers_collections::collection_uuid) + .and(collections_groups::groups_uuid.eq(groups::uuid))), + ) + .filter( + users_organizations::access_all + .eq(true) // User has access all + .or(users_collections::user_uuid + .eq(user_uuid) // User has access to collection + .and(users_collections::read_only.eq(false))) + .or(groups::access_all.eq(true)) // Access via groups + .or(collections_groups::collections_uuid + .is_not_null() // Access via groups + .and(collections_groups::read_only.eq(false))) + .or(users_organizations::atype.le(MembershipType::Admin as i32)), // User is admin or owner ) .select(ciphers_collections::collection_uuid) .load::(conn) .unwrap_or_default() - }} + }) + .await } else { - db_run! { conn: { + conn.run(move |conn| { ciphers_collections::table .filter(ciphers_collections::cipher_uuid.eq(&self.uuid)) - .inner_join(collections::table.on( - collections::uuid.eq(ciphers_collections::collection_uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::org_uuid.eq(collections::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid.clone())) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(ciphers_collections::collection_uuid) - .and(users_collections::user_uuid.eq(user_uuid.clone())) - )) - .filter(users_organizations::access_all.eq(true) // User has access all - .or(users_collections::user_uuid.eq(user_uuid) // User has access to collection - .and(users_collections::read_only.eq(false))) - .or(users_organizations::atype.le(MembershipType::Admin as i32)) // User is admin or owner + .inner_join(collections::table.on(collections::uuid.eq(ciphers_collections::collection_uuid))) + .inner_join( + users_organizations::table.on(users_organizations::org_uuid + .eq(collections::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(ciphers_collections::collection_uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), + ) + .filter( + users_organizations::access_all + .eq(true) // User has access all + .or(users_collections::user_uuid + .eq(user_uuid) // User has access to collection + .and(users_collections::read_only.eq(false))) + .or(users_organizations::atype.le(MembershipType::Admin as i32)), // User is admin or owner ) .select(ciphers_collections::collection_uuid) .load::(conn) .unwrap_or_default() - }} + }) + .await } } @@ -1124,42 +1130,41 @@ impl Cipher { user_uuid: UserId, conn: &DbConn, ) -> Vec<(CipherId, CollectionId)> { - db_run! { conn: { + conn.run(move |conn| { ciphers_collections::table - .inner_join(collections::table.on( - collections::uuid.eq(ciphers_collections::collection_uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::org_uuid.eq(collections::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid.clone()) + .inner_join(collections::table.on(collections::uuid.eq(ciphers_collections::collection_uuid))) + .inner_join( + users_organizations::table.on(users_organizations::org_uuid + .eq(collections::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(ciphers_collections::collection_uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(ciphers_collections::collection_uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::collections_uuid.eq(ciphers_collections::collection_uuid).and( - collections_groups::groups_uuid.eq(groups::uuid) + .left_join(groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid))) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), ) - )) - .or_filter(users_collections::user_uuid.eq(user_uuid)) // User has access to collection - .or_filter(users_organizations::access_all.eq(true)) // User has access all - .or_filter(users_organizations::atype.le(MembershipType::Admin as i32)) // User is admin or owner - .or_filter(groups::access_all.eq(true)) //Access via group - .or_filter(collections_groups::collections_uuid.is_not_null()) //Access via group - .select(ciphers_collections::all_columns) - .distinct() - .load::<(CipherId, CollectionId)>(conn) - .unwrap_or_default() - }} + .left_join( + collections_groups::table.on(collections_groups::collections_uuid + .eq(ciphers_collections::collection_uuid) + .and(collections_groups::groups_uuid.eq(groups::uuid))), + ) + .or_filter(users_collections::user_uuid.eq(user_uuid)) // User has access to collection + .or_filter(users_organizations::access_all.eq(true)) // User has access all + .or_filter(users_organizations::atype.le(MembershipType::Admin as i32)) // User is admin or owner + .or_filter(groups::access_all.eq(true)) //Access via group + .or_filter(collections_groups::collections_uuid.is_not_null()) //Access via group + .select(ciphers_collections::all_columns) + .distinct() + .load::<(CipherId, CollectionId)>(conn) + .unwrap_or_default() + }) + .await } } diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index 13d93cef..f29843f7 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -197,11 +197,12 @@ impl Collection { CollectionUser::delete_all_by_collection(&self.uuid, conn).await?; CollectionGroup::delete_all_by_collection(&self.uuid, &self.org_uuid, conn).await?; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(collections::table.filter(collections::uuid.eq(self.uuid))) .execute(conn) .map_res("Error deleting collection") - }} + }) + .await } pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { @@ -218,84 +219,84 @@ impl Collection { } pub async fn find_by_uuid(uuid: &CollectionId, conn: &DbConn) -> Option { - db_run! { conn: { - collections::table - .filter(collections::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| collections::table.filter(collections::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn find_by_user_uuid(user_uuid: UserId, conn: &DbConn) -> Vec { if CONFIG.org_groups_enabled() { - db_run! { conn: { + conn.run(move |conn| { collections::table - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid.clone()) + .left_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid).and( - collections_groups::collections_uuid.eq(collections::uuid) + .left_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), ) - )) - .filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) - ) - .filter( - users_collections::user_uuid.eq(user_uuid).or( // Directly accessed collection - users_organizations::access_all.eq(true) // access_all in Organization - ).or( - groups::access_all.eq(true) // access_all in groups - ).or( // access via groups - groups_users::users_organizations_uuid.eq(users_organizations::uuid).and( - collections_groups::collections_uuid.is_not_null() - ) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), ) - ) - .select(collections::all_columns) - .distinct() - .load::(conn) - .expect("Error loading collections") - }} + .left_join( + collections_groups::table.on(collections_groups::groups_uuid + .eq(groups_users::groups_uuid) + .and(collections_groups::collections_uuid.eq(collections::uuid))), + ) + .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) + .filter( + users_collections::user_uuid + .eq(user_uuid) + .or( + // Directly accessed collection + users_organizations::access_all.eq(true), // access_all in Organization + ) + .or( + groups::access_all.eq(true), // access_all in groups + ) + .or( + // access via groups + groups_users::users_organizations_uuid + .eq(users_organizations::uuid) + .and(collections_groups::collections_uuid.is_not_null()), + ), + ) + .select(collections::all_columns) + .distinct() + .load::(conn) + .expect("Error loading collections") + }) + .await } else { - db_run! { conn: { + conn.run(move |conn| { collections::table - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid.clone()) + .left_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), ) - )) - .filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) - ) - .filter( - users_collections::user_uuid.eq(user_uuid).or( // Directly accessed collection - users_organizations::access_all.eq(true) // access_all in Organization - ) - ) - .select(collections::all_columns) - .distinct() - .load::(conn) - .expect("Error loading collections") - }} + .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) + .filter(users_collections::user_uuid.eq(user_uuid).or( + // Directly accessed collection + users_organizations::access_all.eq(true), // access_all in Organization + )) + .select(collections::all_columns) + .distinct() + .load::(conn) + .expect("Error loading collections") + }) + .await } } @@ -312,256 +313,311 @@ impl Collection { } pub async fn find_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { collections::table .filter(collections::org_uuid.eq(org_uuid)) .load::(conn) .expect("Error loading collections") - }} + }) + .await } pub async fn count_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { - collections::table - .filter(collections::org_uuid.eq(org_uuid)) - .count() - .first::(conn) - .ok() - .unwrap_or(0) - }} + conn.run(move |conn| { + collections::table.filter(collections::org_uuid.eq(org_uuid)).count().first::(conn).ok().unwrap_or(0) + }) + .await } pub async fn find_by_uuid_and_org(uuid: &CollectionId, org_uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { collections::table .filter(collections::uuid.eq(uuid)) .filter(collections::org_uuid.eq(org_uuid)) .select(collections::all_columns) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_uuid_and_user(uuid: &CollectionId, user_uuid: UserId, conn: &DbConn) -> Option { if CONFIG.org_groups_enabled() { - db_run! { conn: { + conn.run(move |conn| { collections::table - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid) + .left_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid).and( - collections_groups::collections_uuid.eq(collections::uuid) + .left_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), ) - )) - .filter(collections::uuid.eq(uuid)) - .filter( - users_collections::collection_uuid.eq(uuid).or( // Directly accessed collection - users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::atype.le(MembershipType::Admin as i32) // Org admin or owner - )).or( - groups::access_all.eq(true) // access_all in groups - ).or( // access via groups - groups_users::users_organizations_uuid.eq(users_organizations::uuid).and( - collections_groups::collections_uuid.is_not_null() - ) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), ) - ).select(collections::all_columns) - .first::(conn) - .ok() - }} + .left_join( + collections_groups::table.on(collections_groups::groups_uuid + .eq(groups_users::groups_uuid) + .and(collections_groups::collections_uuid.eq(collections::uuid))), + ) + .filter(collections::uuid.eq(uuid)) + .filter( + users_collections::collection_uuid + .eq(uuid) + .or( + // Directly accessed collection + users_organizations::access_all.eq(true).or( + // access_all in Organization + users_organizations::atype.le(MembershipType::Admin as i32), // Org admin or owner + ), + ) + .or( + groups::access_all.eq(true), // access_all in groups + ) + .or( + // access via groups + groups_users::users_organizations_uuid + .eq(users_organizations::uuid) + .and(collections_groups::collections_uuid.is_not_null()), + ), + ) + .select(collections::all_columns) + .first::(conn) + .ok() + }) + .await } else { - db_run! { conn: { + conn.run(move |conn| { collections::table - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid) + .left_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) - )) - .filter(collections::uuid.eq(uuid)) - .filter( - users_collections::collection_uuid.eq(uuid).or( // Directly accessed collection - users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::atype.le(MembershipType::Admin as i32) // Org admin or owner + .filter(collections::uuid.eq(uuid)) + .filter(users_collections::collection_uuid.eq(uuid).or( + // Directly accessed collection + users_organizations::access_all.eq(true).or( + // access_all in Organization + users_organizations::atype.le(MembershipType::Admin as i32), // Org admin or owner + ), )) - ).select(collections::all_columns) - .first::(conn) - .ok() - }} + .select(collections::all_columns) + .first::(conn) + .ok() + }) + .await } } pub async fn is_writable_by_user(&self, user_uuid: &UserId, conn: &DbConn) -> bool { let user_uuid = user_uuid.to_string(); if CONFIG.org_groups_enabled() { - db_run! { conn: { + conn.run(move |conn| { collections::table .filter(collections::uuid.eq(&self.uuid)) - .inner_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid.clone())) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid) - .and(users_collections::user_uuid.eq(user_uuid)) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid) - .and(collections_groups::collections_uuid.eq(collections::uuid)) - )) - .filter(users_organizations::atype.le(MembershipType::Admin as i32) // Org admin or owner - .or(users_organizations::access_all.eq(true)) // access_all via membership - .or(users_collections::collection_uuid.eq(&self.uuid) // write access given to collection - .and(users_collections::read_only.eq(false))) - .or(groups::access_all.eq(true)) // access_all via group - .or(collections_groups::collections_uuid.is_not_null() // write access given via group - .and(collections_groups::read_only.eq(false))) + .inner_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid))), + ) + .left_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), + ) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) + .left_join( + collections_groups::table.on(collections_groups::groups_uuid + .eq(groups_users::groups_uuid) + .and(collections_groups::collections_uuid.eq(collections::uuid))), + ) + .filter( + users_organizations::atype + .le(MembershipType::Admin as i32) // Org admin or owner + .or(users_organizations::access_all.eq(true)) // access_all via membership + .or(users_collections::collection_uuid + .eq(&self.uuid) // write access given to collection + .and(users_collections::read_only.eq(false))) + .or(groups::access_all.eq(true)) // access_all via group + .or(collections_groups::collections_uuid + .is_not_null() // write access given via group + .and(collections_groups::read_only.eq(false))), ) .count() .first::(conn) .ok() - .unwrap_or(0) != 0 - }} + .unwrap_or(0) + != 0 + }) + .await } else { - db_run! { conn: { + conn.run(move |conn| { collections::table .filter(collections::uuid.eq(&self.uuid)) - .inner_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid.clone())) - )) - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid) - .and(users_collections::user_uuid.eq(user_uuid)) - )) - .filter(users_organizations::atype.le(MembershipType::Admin as i32) // Org admin or owner - .or(users_organizations::access_all.eq(true)) // access_all via membership - .or(users_collections::collection_uuid.eq(&self.uuid) // write access given to collection - .and(users_collections::read_only.eq(false))) + .inner_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid.clone()))), + ) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid))), + ) + .filter( + users_organizations::atype + .le(MembershipType::Admin as i32) // Org admin or owner + .or(users_organizations::access_all.eq(true)) // access_all via membership + .or(users_collections::collection_uuid + .eq(&self.uuid) // write access given to collection + .and(users_collections::read_only.eq(false))), ) .count() .first::(conn) .ok() - .unwrap_or(0) != 0 - }} + .unwrap_or(0) + != 0 + }) + .await } } pub async fn hide_passwords_for_user(&self, user_uuid: &UserId, conn: &DbConn) -> bool { let user_uuid = user_uuid.to_string(); - db_run! { conn: { + conn.run(move |conn| { collections::table - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid) + .left_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid).and( - collections_groups::collections_uuid.eq(collections::uuid) + .left_join(groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid))) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), ) - )) - .filter(collections::uuid.eq(&self.uuid)) - .filter( - users_collections::collection_uuid.eq(&self.uuid).and(users_collections::hide_passwords.eq(true)).or(// Directly accessed collection - users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::atype.le(MembershipType::Admin as i32) // Org admin or owner - )).or( - groups::access_all.eq(true) // access_all in groups - ).or( // access via groups - groups_users::users_organizations_uuid.eq(users_organizations::uuid).and( - collections_groups::collections_uuid.is_not_null().and( - collections_groups::hide_passwords.eq(true)) - ) + .left_join( + collections_groups::table.on(collections_groups::groups_uuid + .eq(groups_users::groups_uuid) + .and(collections_groups::collections_uuid.eq(collections::uuid))), ) - ) - .count() - .first::(conn) - .ok() - .unwrap_or(0) != 0 - }} + .filter(collections::uuid.eq(&self.uuid)) + .filter( + users_collections::collection_uuid + .eq(&self.uuid) + .and(users_collections::hide_passwords.eq(true)) + .or( + // Directly accessed collection + users_organizations::access_all.eq(true).or( + // access_all in Organization + users_organizations::atype.le(MembershipType::Admin as i32), // Org admin or owner + ), + ) + .or( + groups::access_all.eq(true), // access_all in groups + ) + .or( + // access via groups + groups_users::users_organizations_uuid.eq(users_organizations::uuid).and( + collections_groups::collections_uuid + .is_not_null() + .and(collections_groups::hide_passwords.eq(true)), + ), + ), + ) + .count() + .first::(conn) + .ok() + .unwrap_or(0) + != 0 + }) + .await } pub async fn is_coll_manageable_by_user(uuid: &CollectionId, user_uuid: &UserId, conn: &DbConn) -> bool { let uuid = uuid.to_string(); let user_uuid = user_uuid.to_string(); - db_run! { conn: { + conn.run(move |conn| { collections::table - .left_join(users_collections::table.on( - users_collections::collection_uuid.eq(collections::uuid).and( - users_collections::user_uuid.eq(user_uuid.clone()) + .left_join( + users_collections::table.on(users_collections::collection_uuid + .eq(collections::uuid) + .and(users_collections::user_uuid.eq(user_uuid.clone()))), ) - )) - .left_join(users_organizations::table.on( - collections::org_uuid.eq(users_organizations::org_uuid).and( - users_organizations::user_uuid.eq(user_uuid) + .left_join( + users_organizations::table.on(collections::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) - )) - .left_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid).and( - collections_groups::collections_uuid.eq(collections::uuid) + .left_join(groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid))) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), ) - )) - .filter(collections::uuid.eq(&uuid)) - .filter( - users_collections::collection_uuid.eq(&uuid).and(users_collections::manage.eq(true)).or(// Directly accessed collection - users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::atype.le(MembershipType::Admin as i32) // Org admin or owner - )).or( - groups::access_all.eq(true) // access_all in groups - ).or( // access via groups - groups_users::users_organizations_uuid.eq(users_organizations::uuid).and( - collections_groups::collections_uuid.is_not_null().and( - collections_groups::manage.eq(true)) - ) + .left_join( + collections_groups::table.on(collections_groups::groups_uuid + .eq(groups_users::groups_uuid) + .and(collections_groups::collections_uuid.eq(collections::uuid))), ) - ) - .count() - .first::(conn) - .ok() - .unwrap_or(0) != 0 - }} + .filter(collections::uuid.eq(&uuid)) + .filter( + users_collections::collection_uuid + .eq(&uuid) + .and(users_collections::manage.eq(true)) + .or( + // Directly accessed collection + users_organizations::access_all.eq(true).or( + // access_all in Organization + users_organizations::atype.le(MembershipType::Admin as i32), // Org admin or owner + ), + ) + .or( + groups::access_all.eq(true), // access_all in groups + ) + .or( + // access via groups + groups_users::users_organizations_uuid.eq(users_organizations::uuid).and( + collections_groups::collections_uuid + .is_not_null() + .and(collections_groups::manage.eq(true)), + ), + ), + ) + .count() + .first::(conn) + .ok() + .unwrap_or(0) + != 0 + }) + .await } pub async fn is_manageable_by_user(&self, user_uuid: &UserId, conn: &DbConn) -> bool { @@ -576,7 +632,7 @@ impl CollectionUser { user_uuid: &UserId, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_collections::table .filter(users_collections::user_uuid.eq(user_uuid)) .inner_join(collections::table.on(collections::uuid.eq(users_collections::collection_uuid))) @@ -584,23 +640,34 @@ impl CollectionUser { .select(users_collections::all_columns) .load::(conn) .expect("Error loading users_collections") - }} + }) + .await } pub async fn find_by_organization_swap_user_uuid_with_member_uuid( org_uuid: &OrganizationId, conn: &DbConn, ) -> Vec { - let col_users = db_run! { conn: { - users_collections::table - .inner_join(collections::table.on(collections::uuid.eq(users_collections::collection_uuid))) - .filter(collections::org_uuid.eq(org_uuid)) - .inner_join(users_organizations::table.on(users_organizations::user_uuid.eq(users_collections::user_uuid))) - .filter(users_organizations::org_uuid.eq(org_uuid)) - .select((users_organizations::uuid, users_collections::collection_uuid, users_collections::read_only, users_collections::hide_passwords, users_collections::manage)) - .load::(conn) - .expect("Error loading users_collections") - }}; + let col_users = conn + .run(move |conn| { + users_collections::table + .inner_join(collections::table.on(collections::uuid.eq(users_collections::collection_uuid))) + .filter(collections::org_uuid.eq(org_uuid)) + .inner_join( + users_organizations::table.on(users_organizations::user_uuid.eq(users_collections::user_uuid)), + ) + .filter(users_organizations::org_uuid.eq(org_uuid)) + .select(( + users_organizations::uuid, + users_collections::collection_uuid, + users_collections::read_only, + users_collections::hide_passwords, + users_collections::manage, + )) + .load::(conn) + .expect("Error loading users_collections") + }) + .await; col_users.into_iter().map(Into::into).collect() } @@ -670,7 +737,7 @@ impl CollectionUser { pub async fn delete(self, conn: &DbConn) -> EmptyResult { User::update_uuid_revision(&self.user_uuid, conn).await; - db_run! { conn: { + conn.run(move |conn| { diesel::delete( users_collections::table .filter(users_collections::user_uuid.eq(&self.user_uuid)) @@ -678,17 +745,19 @@ impl CollectionUser { ) .execute(conn) .map_res("Error removing user from collection") - }} + }) + .await } pub async fn find_by_collection(collection_uuid: &CollectionId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_collections::table .filter(users_collections::collection_uuid.eq(collection_uuid)) .select(users_collections::all_columns) .load::(conn) .expect("Error loading users_collections") - }} + }) + .await } pub async fn find_by_org_and_coll_swap_user_uuid_with_member_uuid( @@ -696,15 +765,25 @@ impl CollectionUser { collection_uuid: &CollectionId, conn: &DbConn, ) -> Vec { - let col_users = db_run! { conn: { - users_collections::table - .filter(users_collections::collection_uuid.eq(collection_uuid)) - .filter(users_organizations::org_uuid.eq(org_uuid)) - .inner_join(users_organizations::table.on(users_organizations::user_uuid.eq(users_collections::user_uuid))) - .select((users_organizations::uuid, users_collections::collection_uuid, users_collections::read_only, users_collections::hide_passwords, users_collections::manage)) - .load::(conn) - .expect("Error loading users_collections") - }}; + let col_users = conn + .run(move |conn| { + users_collections::table + .filter(users_collections::collection_uuid.eq(collection_uuid)) + .filter(users_organizations::org_uuid.eq(org_uuid)) + .inner_join( + users_organizations::table.on(users_organizations::user_uuid.eq(users_collections::user_uuid)), + ) + .select(( + users_organizations::uuid, + users_collections::collection_uuid, + users_collections::read_only, + users_collections::hide_passwords, + users_collections::manage, + )) + .load::(conn) + .expect("Error loading users_collections") + }) + .await; col_users.into_iter().map(Into::into).collect() } @@ -713,24 +792,26 @@ impl CollectionUser { user_uuid: &UserId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { users_collections::table .filter(users_collections::collection_uuid.eq(collection_uuid)) .filter(users_collections::user_uuid.eq(user_uuid)) .select(users_collections::all_columns) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_collections::table .filter(users_collections::user_uuid.eq(user_uuid)) .select(users_collections::all_columns) .load::(conn) .expect("Error loading users_collections") - }} + }) + .await } pub async fn delete_all_by_collection(collection_uuid: &CollectionId, conn: &DbConn) -> EmptyResult { @@ -738,11 +819,12 @@ impl CollectionUser { User::update_uuid_revision(&collection.user_uuid, conn).await; } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(users_collections::table.filter(users_collections::collection_uuid.eq(collection_uuid))) .execute(conn) .map_res("Error deleting users from collection") - }} + }) + .await } pub async fn delete_all_by_user_and_org( @@ -752,17 +834,21 @@ impl CollectionUser { ) -> EmptyResult { let collectionusers = Self::find_by_organization_and_user_uuid(org_uuid, user_uuid, conn).await; - db_run! { conn: { + conn.run(move |conn| { for user in collectionusers { - let _: () = diesel::delete(users_collections::table.filter( - users_collections::user_uuid.eq(user_uuid) - .and(users_collections::collection_uuid.eq(user.collection_uuid)) - )) - .execute(conn) - .map_res("Error removing user from collections")?; + let _: () = diesel::delete( + users_collections::table.filter( + users_collections::user_uuid + .eq(user_uuid) + .and(users_collections::collection_uuid.eq(user.collection_uuid)), + ), + ) + .execute(conn) + .map_res("Error removing user from collections")?; } Ok(()) - }} + }) + .await } pub async fn has_access_to_collection_by_user(col_id: &CollectionId, user_uuid: &UserId, conn: &DbConn) -> bool { @@ -805,7 +891,7 @@ impl CollectionCipher { pub async fn delete(cipher_uuid: &CipherId, collection_uuid: &CollectionId, conn: &DbConn) -> EmptyResult { Self::update_users_revision(collection_uuid, conn).await; - db_run! { conn: { + conn.run(move |conn| { diesel::delete( ciphers_collections::table .filter(ciphers_collections::cipher_uuid.eq(cipher_uuid)) @@ -813,23 +899,26 @@ impl CollectionCipher { ) .execute(conn) .map_res("Error deleting cipher from collection") - }} + }) + .await } pub async fn delete_all_by_cipher(cipher_uuid: &CipherId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(ciphers_collections::table.filter(ciphers_collections::cipher_uuid.eq(cipher_uuid))) .execute(conn) .map_res("Error removing cipher from collections") - }} + }) + .await } pub async fn delete_all_by_collection(collection_uuid: &CollectionId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(ciphers_collections::table.filter(ciphers_collections::collection_uuid.eq(collection_uuid))) .execute(conn) .map_res("Error removing ciphers from collection") - }} + }) + .await } pub async fn update_users_revision(collection_uuid: &CollectionId, conn: &DbConn) { diff --git a/src/db/models/device.rs b/src/db/models/device.rs index 78c1ce9d..6c1b686a 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -169,21 +169,23 @@ impl Device { } pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(devices::table.filter(devices::user_uuid.eq(user_uuid))) .execute(conn) .map_res("Error removing devices for user") - }} + }) + .await } pub async fn find_by_uuid_and_user(uuid: &DeviceId, user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { devices::table .filter(devices::uuid.eq(uuid)) .filter(devices::user_uuid.eq(user_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_with_auth_request_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { @@ -197,71 +199,65 @@ impl Device { } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { - devices::table - .filter(devices::user_uuid.eq(user_uuid)) - .load::(conn) - .expect("Error loading devices") - }} + conn.run(move |conn| { + devices::table.filter(devices::user_uuid.eq(user_uuid)).load::(conn).expect("Error loading devices") + }) + .await } pub async fn find_by_uuid(uuid: &DeviceId, conn: &DbConn) -> Option { - db_run! { conn: { - devices::table - .filter(devices::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| devices::table.filter(devices::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn clear_push_token_by_uuid(uuid: &DeviceId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::update(devices::table) .filter(devices::uuid.eq(uuid)) .set(devices::push_token.eq::>(None)) .execute(conn) .map_res("Error removing push token") - }} + }) + .await } pub async fn find_by_refresh_token(refresh_token: &str, conn: &DbConn) -> Option { - db_run! { conn: { - devices::table - .filter(devices::refresh_token.eq(refresh_token)) - .first::(conn) - .ok() - }} + conn.run(move |conn| devices::table.filter(devices::refresh_token.eq(refresh_token)).first::(conn).ok()) + .await } pub async fn find_latest_active_by_user(user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { devices::table .filter(devices::user_uuid.eq(user_uuid)) .order(devices::updated_at.desc()) .first::(conn) .ok() - }} + }) + .await } pub async fn find_push_devices_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { devices::table .filter(devices::user_uuid.eq(user_uuid)) .filter(devices::push_token.is_not_null()) .load::(conn) .expect("Error loading push devices") - }} + }) + .await } pub async fn check_user_has_push_device(user_uuid: &UserId, conn: &DbConn) -> bool { - db_run! { conn: { + conn.run(move |conn| { devices::table - .filter(devices::user_uuid.eq(user_uuid)) - .filter(devices::push_token.is_not_null()) - .count() - .first::(conn) - .ok() - .unwrap_or(0) != 0 - }} + .filter(devices::user_uuid.eq(user_uuid)) + .filter(devices::push_token.is_not_null()) + .count() + .first::(conn) + .ok() + .unwrap_or(0) + != 0 + }) + .await } pub async fn rotate_refresh_tokens_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { diff --git a/src/db/models/emergency_access.rs b/src/db/models/emergency_access.rs index c7588050..45fad91f 100644 --- a/src/db/models/emergency_access.rs +++ b/src/db/models/emergency_access.rs @@ -186,28 +186,36 @@ impl EmergencyAccess { self.status = status; date.clone_into(&mut self.updated_at); - db_run! { conn: { - crate::util::retry(|| { - diesel::update(emergency_access::table.filter(emergency_access::uuid.eq(&self.uuid))) - .set((emergency_access::status.eq(status), emergency_access::updated_at.eq(date))) - .execute(conn) - }, 10) + conn.run(move |conn| { + crate::util::retry( + || { + diesel::update(emergency_access::table.filter(emergency_access::uuid.eq(&self.uuid))) + .set((emergency_access::status.eq(status), emergency_access::updated_at.eq(date))) + .execute(conn) + }, + 10, + ) .map_res("Error updating emergency access status") - }} + }) + .await } pub async fn update_last_notification_date_and_save(&mut self, date: &NaiveDateTime, conn: &DbConn) -> EmptyResult { self.last_notification_at = Some(date.to_owned()); date.clone_into(&mut self.updated_at); - db_run! { conn: { - crate::util::retry(|| { - diesel::update(emergency_access::table.filter(emergency_access::uuid.eq(&self.uuid))) - .set((emergency_access::last_notification_at.eq(date), emergency_access::updated_at.eq(date))) - .execute(conn) - }, 10) + conn.run(move |conn| { + crate::util::retry( + || { + diesel::update(emergency_access::table.filter(emergency_access::uuid.eq(&self.uuid))) + .set((emergency_access::last_notification_at.eq(date), emergency_access::updated_at.eq(date))) + .execute(conn) + }, + 10, + ) .map_res("Error updating emergency access status") - }} + }) + .await } pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { @@ -230,11 +238,12 @@ impl EmergencyAccess { pub async fn delete(self, conn: &DbConn) -> EmptyResult { User::update_uuid_revision(&self.grantor_uuid, conn).await; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(emergency_access::table.filter(emergency_access::uuid.eq(self.uuid))) .execute(conn) .map_res("Error removing user from emergency access") - }} + }) + .await } pub async fn find_by_grantor_uuid_and_grantee_uuid_or_email( @@ -243,23 +252,25 @@ impl EmergencyAccess { email: &str, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::grantor_uuid.eq(grantor_uuid)) .filter(emergency_access::grantee_uuid.eq(grantee_uuid).or(emergency_access::email.eq(email))) .first::(conn) .ok() - }} + }) + .await } pub async fn find_all_recoveries_initiated(conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::status.eq(EmergencyAccessStatus::RecoveryInitiated as i32)) .filter(emergency_access::recovery_initiated_at.is_not_null()) .load::(conn) .expect("Error loading emergency_access") - }} + }) + .await } pub async fn find_by_uuid_and_grantor_uuid( @@ -267,13 +278,14 @@ impl EmergencyAccess { grantor_uuid: &UserId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::uuid.eq(uuid)) .filter(emergency_access::grantor_uuid.eq(grantor_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_uuid_and_grantee_uuid( @@ -281,13 +293,14 @@ impl EmergencyAccess { grantee_uuid: &UserId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::uuid.eq(uuid)) .filter(emergency_access::grantee_uuid.eq(grantee_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_uuid_and_grantee_email( @@ -295,61 +308,67 @@ impl EmergencyAccess { grantee_email: &str, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::uuid.eq(uuid)) .filter(emergency_access::email.eq(grantee_email)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_all_by_grantee_uuid(grantee_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::grantee_uuid.eq(grantee_uuid)) .load::(conn) .expect("Error loading emergency_access") - }} + }) + .await } pub async fn find_invited_by_grantee_email(grantee_email: &str, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::email.eq(grantee_email)) .filter(emergency_access::status.eq(EmergencyAccessStatus::Invited as i32)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_all_invited_by_grantee_email(grantee_email: &str, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::email.eq(grantee_email)) .filter(emergency_access::status.eq(EmergencyAccessStatus::Invited as i32)) .load::(conn) .expect("Error loading emergency_access") - }} + }) + .await } pub async fn find_all_by_grantor_uuid(grantor_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::grantor_uuid.eq(grantor_uuid)) .load::(conn) .expect("Error loading emergency_access") - }} + }) + .await } pub async fn find_all_confirmed_by_grantor_uuid(grantor_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { emergency_access::table .filter(emergency_access::grantor_uuid.eq(grantor_uuid)) .filter(emergency_access::status.ge(EmergencyAccessStatus::Confirmed as i32)) .load::(conn) .expect("Error loading emergency_access") - }} + }) + .await } pub async fn accept_invite(&mut self, grantee_uuid: &UserId, grantee_email: &str, conn: &DbConn) -> EmptyResult { diff --git a/src/db/models/event.rs b/src/db/models/event.rs index dad57f44..3a6b610c 100644 --- a/src/db/models/event.rs +++ b/src/db/models/event.rs @@ -256,11 +256,10 @@ impl Event { } pub async fn delete(self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { - diesel::delete(event::table.filter(event::uuid.eq(self.uuid))) - .execute(conn) - .map_res("Error deleting event") - }} + conn.run(move |conn| { + diesel::delete(event::table.filter(event::uuid.eq(self.uuid))).execute(conn).map_res("Error deleting event") + }) + .await } /// ############## @@ -271,7 +270,7 @@ impl Event { end: &NaiveDateTime, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { event::table .filter(event::org_uuid.eq(org_uuid)) .filter(event::event_date.between(start, end)) @@ -279,18 +278,15 @@ impl Event { .limit(Self::PAGE_SIZE) .load::(conn) .expect("Error filtering events") - }} + }) + .await } pub async fn count_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { - event::table - .filter(event::org_uuid.eq(org_uuid)) - .count() - .first::(conn) - .ok() - .unwrap_or(0) - }} + conn.run(move |conn| { + event::table.filter(event::org_uuid.eq(org_uuid)).count().first::(conn).ok().unwrap_or(0) + }) + .await } pub async fn find_by_org_and_member( @@ -300,18 +296,23 @@ impl Event { end: &NaiveDateTime, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { event::table .inner_join(users_organizations::table.on(users_organizations::uuid.eq(member_uuid))) .filter(event::org_uuid.eq(org_uuid)) .filter(event::event_date.between(start, end)) - .filter(event::user_uuid.eq(users_organizations::user_uuid.nullable()).or(event::act_user_uuid.eq(users_organizations::user_uuid.nullable()))) + .filter( + event::user_uuid + .eq(users_organizations::user_uuid.nullable()) + .or(event::act_user_uuid.eq(users_organizations::user_uuid.nullable())), + ) .select(event::all_columns) .order_by(event::event_date.desc()) .limit(Self::PAGE_SIZE) .load::(conn) .expect("Error filtering events") - }} + }) + .await } pub async fn find_by_cipher_uuid( @@ -320,7 +321,7 @@ impl Event { end: &NaiveDateTime, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { event::table .filter(event::cipher_uuid.eq(cipher_uuid)) .filter(event::event_date.between(start, end)) @@ -328,17 +329,19 @@ impl Event { .limit(Self::PAGE_SIZE) .load::(conn) .expect("Error filtering events") - }} + }) + .await } pub async fn clean_events(conn: &DbConn) -> EmptyResult { if let Some(days_to_retain) = CONFIG.events_days_retain() { let dt = Utc::now().naive_utc() - TimeDelta::try_days(days_to_retain).unwrap(); - db_run! { conn: { + conn.run(move |conn| { diesel::delete(event::table.filter(event::event_date.lt(dt))) - .execute(conn) - .map_res("Error cleaning old events") - }} + .execute(conn) + .map_res("Error cleaning old events") + }) + .await } else { Ok(()) } diff --git a/src/db/models/favorite.rs b/src/db/models/favorite.rs index c6e780ad..ee79857a 100644 --- a/src/db/models/favorite.rs +++ b/src/db/models/favorite.rs @@ -19,16 +19,15 @@ pub struct Favorite { impl Favorite { // Returns whether the specified cipher is a favorite of the specified user. pub async fn is_favorite(cipher_uuid: &CipherId, user_uuid: &UserId, conn: &DbConn) -> bool { - db_run! { conn: { + conn.run(move |conn| { let query = favorites::table .filter(favorites::cipher_uuid.eq(cipher_uuid)) .filter(favorites::user_uuid.eq(user_uuid)) .count(); - query.first::(conn) - .ok() - .unwrap_or(0) != 0 - }} + query.first::(conn).ok().unwrap_or(0) != 0 + }) + .await } // Sets whether the specified cipher is a favorite of the specified user. @@ -42,27 +41,26 @@ impl Favorite { match (old, new) { (false, true) => { User::update_uuid_revision(user_uuid, conn).await; - db_run! { conn: { - diesel::insert_into(favorites::table) - .values(( - favorites::user_uuid.eq(user_uuid), - favorites::cipher_uuid.eq(cipher_uuid), - )) - .execute(conn) - .map_res("Error adding favorite") - }} + conn.run(move |conn| { + diesel::insert_into(favorites::table) + .values((favorites::user_uuid.eq(user_uuid), favorites::cipher_uuid.eq(cipher_uuid))) + .execute(conn) + .map_res("Error adding favorite") + }) + .await } (true, false) => { User::update_uuid_revision(user_uuid, conn).await; - db_run! { conn: { + conn.run(move |conn| { diesel::delete( favorites::table .filter(favorites::user_uuid.eq(user_uuid)) - .filter(favorites::cipher_uuid.eq(cipher_uuid)) + .filter(favorites::cipher_uuid.eq(cipher_uuid)), ) .execute(conn) .map_res("Error removing favorite") - }} + }) + .await } // Otherwise, the favorite status is already what it should be. _ => Ok(()), @@ -71,31 +69,34 @@ impl Favorite { // Delete all favorite entries associated with the specified cipher. pub async fn delete_all_by_cipher(cipher_uuid: &CipherId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(favorites::table.filter(favorites::cipher_uuid.eq(cipher_uuid))) .execute(conn) .map_res("Error removing favorites by cipher") - }} + }) + .await } // Delete all favorite entries associated with the specified user. pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(favorites::table.filter(favorites::user_uuid.eq(user_uuid))) .execute(conn) .map_res("Error removing favorites by user") - }} + }) + .await } /// Return a vec with (cipher_uuid) this will only contain favorite flagged ciphers /// This is used during a full sync so we only need one query for all favorite cipher matches. pub async fn get_all_cipher_uuid_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { favorites::table .filter(favorites::user_uuid.eq(user_uuid)) .select(favorites::cipher_uuid) .load::(conn) .unwrap_or_default() - }} + }) + .await } } diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs index dac52ec4..745608e3 100644 --- a/src/db/models/folder.rs +++ b/src/db/models/folder.rs @@ -110,11 +110,12 @@ impl Folder { User::update_uuid_revision(&self.user_uuid, conn).await; FolderCipher::delete_all_by_folder(&self.uuid, conn).await?; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(folders::table.filter(folders::uuid.eq(&self.uuid))) .execute(conn) .map_res("Error deleting folder") - }} + }) + .await } pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { @@ -125,22 +126,21 @@ impl Folder { } pub async fn find_by_uuid_and_user(uuid: &FolderId, user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { folders::table .filter(folders::uuid.eq(uuid)) .filter(folders::user_uuid.eq(user_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { - folders::table - .filter(folders::user_uuid.eq(user_uuid)) - .load::(conn) - .expect("Error loading folders") - }} + conn.run(move |conn| { + folders::table.filter(folders::user_uuid.eq(user_uuid)).load::(conn).expect("Error loading folders") + }) + .await } } @@ -168,7 +168,7 @@ impl FolderCipher { } pub async fn delete(self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete( folders_ciphers::table .filter(folders_ciphers::cipher_uuid.eq(self.cipher_uuid)) @@ -176,23 +176,26 @@ impl FolderCipher { ) .execute(conn) .map_res("Error removing cipher from folder") - }} + }) + .await } pub async fn delete_all_by_cipher(cipher_uuid: &CipherId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(folders_ciphers::table.filter(folders_ciphers::cipher_uuid.eq(cipher_uuid))) .execute(conn) .map_res("Error removing cipher from folders") - }} + }) + .await } pub async fn delete_all_by_folder(folder_uuid: &FolderId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(folders_ciphers::table.filter(folders_ciphers::folder_uuid.eq(folder_uuid))) .execute(conn) .map_res("Error removing ciphers from folder") - }} + }) + .await } pub async fn find_by_folder_and_cipher( @@ -200,35 +203,38 @@ impl FolderCipher { cipher_uuid: &CipherId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { folders_ciphers::table .filter(folders_ciphers::folder_uuid.eq(folder_uuid)) .filter(folders_ciphers::cipher_uuid.eq(cipher_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_folder(folder_uuid: &FolderId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { folders_ciphers::table .filter(folders_ciphers::folder_uuid.eq(folder_uuid)) .load::(conn) .expect("Error loading folders") - }} + }) + .await } /// Return a vec with (cipher_uuid, folder_uuid) /// This is used during a full sync so we only need one query for all folder matches. pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec<(CipherId, FolderId)> { - db_run! { conn: { + conn.run(move |conn| { folders_ciphers::table .inner_join(folders::table) .filter(folders::user_uuid.eq(user_uuid)) .select(folders_ciphers::all_columns) .load::<(CipherId, FolderId)>(conn) .unwrap_or_default() - }} + }) + .await } } diff --git a/src/db/models/group.rs b/src/db/models/group.rs index 53cc9be5..820d3700 100644 --- a/src/db/models/group.rs +++ b/src/db/models/group.rs @@ -203,33 +203,31 @@ impl Group { } pub async fn find_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { groups::table .filter(groups::organizations_uuid.eq(org_uuid)) .load::(conn) .expect("Error loading groups") - }} + }) + .await } pub async fn count_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { - groups::table - .filter(groups::organizations_uuid.eq(org_uuid)) - .count() - .first::(conn) - .ok() - .unwrap_or(0) - }} + conn.run(move |conn| { + groups::table.filter(groups::organizations_uuid.eq(org_uuid)).count().first::(conn).ok().unwrap_or(0) + }) + .await } pub async fn find_by_uuid_and_org(uuid: &GroupId, org_uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { groups::table .filter(groups::uuid.eq(uuid)) .filter(groups::organizations_uuid.eq(org_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_external_id_and_org( @@ -237,60 +235,64 @@ impl Group { org_uuid: &OrganizationId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { groups::table .filter(groups::external_id.eq(external_id)) .filter(groups::organizations_uuid.eq(org_uuid)) .first::(conn) .ok() - }} + }) + .await } //Returns all organizations the user has full access to pub async fn get_orgs_by_user_with_full_access(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { groups_users::table - .inner_join(users_organizations::table.on( - users_organizations::uuid.eq(groups_users::users_organizations_uuid) - )) - .inner_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) + .inner_join( + users_organizations::table.on(users_organizations::uuid.eq(groups_users::users_organizations_uuid)), + ) + .inner_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(groups::access_all.eq(true)) .select(groups::organizations_uuid) .distinct() .load::(conn) .expect("Error loading organization group full access information for user") - }} + }) + .await } pub async fn is_in_full_access_group(user_uuid: &UserId, org_uuid: &OrganizationId, conn: &DbConn) -> bool { - db_run! { conn: { + conn.run(move |conn| { groups::table - .inner_join(groups_users::table.on( - groups_users::groups_uuid.eq(groups::uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::uuid.eq(groups_users::users_organizations_uuid) - )) + .inner_join(groups_users::table.on(groups_users::groups_uuid.eq(groups::uuid))) + .inner_join( + users_organizations::table.on(users_organizations::uuid.eq(groups_users::users_organizations_uuid)), + ) .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(groups::organizations_uuid.eq(org_uuid)) .filter(groups::access_all.eq(true)) .select(groups::access_all) .first::(conn) .unwrap_or_default() - }} + }) + .await } pub async fn delete(&self, org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { CollectionGroup::delete_all_by_group(&self.uuid, org_uuid, conn).await?; GroupUser::delete_all_by_group(&self.uuid, org_uuid, conn).await?; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(groups::table.filter(groups::uuid.eq(&self.uuid))) .execute(conn) .map_res("Error deleting group") - }} + }) + .await } pub async fn update_revision(uuid: &GroupId, conn: &DbConn) { @@ -300,14 +302,18 @@ impl Group { } async fn update_revision_impl(uuid: &GroupId, date: &NaiveDateTime, conn: &DbConn) -> EmptyResult { - db_run! { conn: { - crate::util::retry(|| { - diesel::update(groups::table.filter(groups::uuid.eq(uuid))) - .set(groups::revision_date.eq(date)) - .execute(conn) - }, 10) + conn.run(move |conn| { + crate::util::retry( + || { + diesel::update(groups::table.filter(groups::uuid.eq(uuid))) + .set(groups::revision_date.eq(date)) + .execute(conn) + }, + 10, + ) .map_res("Error updating group revision") - }} + }) + .await } } @@ -372,60 +378,63 @@ impl CollectionGroup { } pub async fn find_by_group(group_uuid: &GroupId, org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { collections_groups::table - .inner_join(groups::table.on( - groups::uuid.eq(collections_groups::groups_uuid) - )) - .inner_join(collections::table.on( - collections::uuid.eq(collections_groups::collections_uuid) - .and(collections::org_uuid.eq(groups::organizations_uuid)) - )) + .inner_join(groups::table.on(groups::uuid.eq(collections_groups::groups_uuid))) + .inner_join( + collections::table.on(collections::uuid + .eq(collections_groups::collections_uuid) + .and(collections::org_uuid.eq(groups::organizations_uuid))), + ) .filter(collections_groups::groups_uuid.eq(group_uuid)) .filter(collections::org_uuid.eq(org_uuid)) .select(collections_groups::all_columns) .load::(conn) .expect("Error loading collection groups") - }} + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { collections_groups::table - .inner_join(groups_users::table.on( - groups_users::groups_uuid.eq(collections_groups::groups_uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::uuid.eq(groups_users::users_organizations_uuid) - )) - .inner_join(groups::table.on(groups::uuid.eq(collections_groups::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .inner_join(collections::table.on( - collections::uuid.eq(collections_groups::collections_uuid) - .and(collections::org_uuid.eq(groups::organizations_uuid)) - )) + .inner_join(groups_users::table.on(groups_users::groups_uuid.eq(collections_groups::groups_uuid))) + .inner_join( + users_organizations::table.on(users_organizations::uuid.eq(groups_users::users_organizations_uuid)), + ) + .inner_join( + groups::table.on(groups::uuid + .eq(collections_groups::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) + .inner_join( + collections::table.on(collections::uuid + .eq(collections_groups::collections_uuid) + .and(collections::org_uuid.eq(groups::organizations_uuid))), + ) .filter(users_organizations::user_uuid.eq(user_uuid)) .select(collections_groups::all_columns) .load::(conn) .expect("Error loading user collection groups") - }} + }) + .await } pub async fn find_by_collection(collection_uuid: &CollectionId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { collections_groups::table .filter(collections_groups::collections_uuid.eq(collection_uuid)) - .inner_join(collections::table.on( - collections::uuid.eq(collections_groups::collections_uuid) - )) - .inner_join(groups::table.on(groups::uuid.eq(collections_groups::groups_uuid) - .and(groups::organizations_uuid.eq(collections::org_uuid)) - )) + .inner_join(collections::table.on(collections::uuid.eq(collections_groups::collections_uuid))) + .inner_join( + groups::table.on(groups::uuid + .eq(collections_groups::groups_uuid) + .and(groups::organizations_uuid.eq(collections::org_uuid))), + ) .select(collections_groups::all_columns) .load::(conn) .expect("Error loading collection groups") - }} + }) + .await } pub async fn delete(&self, org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { @@ -434,13 +443,14 @@ impl CollectionGroup { group_user.update_user_revision(conn).await; } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(collections_groups::table) .filter(collections_groups::collections_uuid.eq(&self.collections_uuid)) .filter(collections_groups::groups_uuid.eq(&self.groups_uuid)) .execute(conn) .map_res("Error deleting collection group") - }} + }) + .await } pub async fn delete_all_by_group(group_uuid: &GroupId, org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { @@ -449,12 +459,13 @@ impl CollectionGroup { group_user.update_user_revision(conn).await; } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(collections_groups::table) .filter(collections_groups::groups_uuid.eq(group_uuid)) .execute(conn) .map_res("Error deleting collection group") - }} + }) + .await } pub async fn delete_all_by_collection( @@ -470,12 +481,13 @@ impl CollectionGroup { } } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(collections_groups::table) .filter(collections_groups::collections_uuid.eq(collection_uuid)) .execute(conn) .map_res("Error deleting collection group") - }} + }) + .await } } @@ -527,30 +539,31 @@ impl GroupUser { } pub async fn find_by_group(group_uuid: &GroupId, org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { groups_users::table - .inner_join(groups::table.on( - groups::uuid.eq(groups_users::groups_uuid) - )) - .inner_join(users_organizations::table.on( - users_organizations::uuid.eq(groups_users::users_organizations_uuid) - .and(users_organizations::org_uuid.eq(groups::organizations_uuid)) - )) + .inner_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid))) + .inner_join( + users_organizations::table.on(users_organizations::uuid + .eq(groups_users::users_organizations_uuid) + .and(users_organizations::org_uuid.eq(groups::organizations_uuid))), + ) .filter(groups_users::groups_uuid.eq(group_uuid)) .filter(groups::organizations_uuid.eq(org_uuid)) .select(groups_users::all_columns) .load::(conn) .expect("Error loading group users") - }} + }) + .await } pub async fn find_by_member(member_uuid: &MembershipId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { groups_users::table .filter(groups_users::users_organizations_uuid.eq(member_uuid)) .load::(conn) .expect("Error loading groups for user") - }} + }) + .await } pub async fn has_access_to_collection_by_member( @@ -558,24 +571,23 @@ impl GroupUser { member_uuid: &MembershipId, conn: &DbConn, ) -> bool { - db_run! { conn: { + conn.run(move |conn| { groups_users::table - .inner_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid) - )) - .inner_join(groups::table.on( - groups::uuid.eq(groups_users::groups_uuid) - )) - .inner_join(collections::table.on( - collections::uuid.eq(collections_groups::collections_uuid) - .and(collections::org_uuid.eq(groups::organizations_uuid)) - )) + .inner_join(collections_groups::table.on(collections_groups::groups_uuid.eq(groups_users::groups_uuid))) + .inner_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid))) + .inner_join( + collections::table.on(collections::uuid + .eq(collections_groups::collections_uuid) + .and(collections::org_uuid.eq(groups::organizations_uuid))), + ) .filter(collections_groups::collections_uuid.eq(collection_uuid)) .filter(groups_users::users_organizations_uuid.eq(member_uuid)) .count() .first::(conn) - .unwrap_or(0) != 0 - }} + .unwrap_or(0) + != 0 + }) + .await } pub async fn has_full_access_by_member( @@ -583,18 +595,18 @@ impl GroupUser { member_uuid: &MembershipId, conn: &DbConn, ) -> bool { - db_run! { conn: { + conn.run(move |conn| { groups_users::table - .inner_join(groups::table.on( - groups::uuid.eq(groups_users::groups_uuid) - )) + .inner_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid))) .filter(groups::organizations_uuid.eq(org_uuid)) .filter(groups::access_all.eq(true)) .filter(groups_users::users_organizations_uuid.eq(member_uuid)) .count() .first::(conn) - .unwrap_or(0) != 0 - }} + .unwrap_or(0) + != 0 + }) + .await } pub async fn update_user_revision(&self, conn: &DbConn) { @@ -614,13 +626,14 @@ impl GroupUser { None => warn!("Member could not be found!"), } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(groups_users::table) .filter(groups_users::groups_uuid.eq(group_uuid)) .filter(groups_users::users_organizations_uuid.eq(member_uuid)) .execute(conn) .map_res("Error deleting group users") - }} + }) + .await } pub async fn delete_all_by_group(group_uuid: &GroupId, org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { @@ -629,12 +642,13 @@ impl GroupUser { group_user.update_user_revision(conn).await; } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(groups_users::table) .filter(groups_users::groups_uuid.eq(group_uuid)) .execute(conn) .map_res("Error deleting group users") - }} + }) + .await } pub async fn delete_all_by_member(member_uuid: &MembershipId, conn: &DbConn) -> EmptyResult { @@ -643,12 +657,13 @@ impl GroupUser { None => warn!("Member could not be found!"), } - db_run! { conn: { + conn.run(move |conn| { diesel::delete(groups_users::table) .filter(groups_users::users_organizations_uuid.eq(member_uuid)) .execute(conn) .map_res("Error deleting user groups") - }} + }) + .await } } diff --git a/src/db/models/org_policy.rs b/src/db/models/org_policy.rs index b4d69009..88b7872c 100644 --- a/src/db/models/org_policy.rs +++ b/src/db/models/org_policy.rs @@ -151,37 +151,38 @@ impl OrgPolicy { } pub async fn delete(self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(org_policies::table.filter(org_policies::uuid.eq(self.uuid))) .execute(conn) .map_res("Error deleting org_policy") - }} + }) + .await } pub async fn find_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { org_policies::table .filter(org_policies::org_uuid.eq(org_uuid)) .load::(conn) .expect("Error loading org_policy") - }} + }) + .await } pub async fn find_confirmed_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { org_policies::table .inner_join( - users_organizations::table.on( - users_organizations::org_uuid.eq(org_policies::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid))) - ) - .filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) + users_organizations::table.on(users_organizations::org_uuid + .eq(org_policies::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) + .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .select(org_policies::all_columns) .load::(conn) .expect("Error loading org_policy") - }} + }) + .await } pub async fn find_by_org_and_type( @@ -189,21 +190,23 @@ impl OrgPolicy { policy_type: OrgPolicyType, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { org_policies::table .filter(org_policies::org_uuid.eq(org_uuid)) .filter(org_policies::atype.eq(policy_type as i32)) .first::(conn) .ok() - }} + }) + .await } pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(org_policies::table.filter(org_policies::org_uuid.eq(org_uuid))) .execute(conn) .map_res("Error deleting org_policy") - }} + }) + .await } pub async fn find_accepted_and_confirmed_by_user_and_active_policy( @@ -211,25 +214,22 @@ impl OrgPolicy { policy_type: OrgPolicyType, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { org_policies::table .inner_join( - users_organizations::table.on( - users_organizations::org_uuid.eq(org_policies::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid))) - ) - .filter( - users_organizations::status.eq(MembershipStatus::Accepted as i32) - ) - .or_filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) + users_organizations::table.on(users_organizations::org_uuid + .eq(org_policies::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) + .filter(users_organizations::status.eq(MembershipStatus::Accepted as i32)) + .or_filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .filter(org_policies::atype.eq(policy_type as i32)) .filter(org_policies::enabled.eq(true)) .select(org_policies::all_columns) .load::(conn) .expect("Error loading org_policy") - }} + }) + .await } pub async fn find_confirmed_by_user_and_active_policy( @@ -237,22 +237,21 @@ impl OrgPolicy { policy_type: OrgPolicyType, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { org_policies::table .inner_join( - users_organizations::table.on( - users_organizations::org_uuid.eq(org_policies::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid))) - ) - .filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) + users_organizations::table.on(users_organizations::org_uuid + .eq(org_policies::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid))), ) + .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .filter(org_policies::atype.eq(policy_type as i32)) .filter(org_policies::enabled.eq(true)) .select(org_policies::all_columns) .load::(conn) .expect("Error loading org_policy") - }} + }) + .await } /// Returns true if the user belongs to an org that has enabled the specified policy type, diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index d1d37283..d604add4 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -384,43 +384,30 @@ impl Organization { Group::delete_all_by_organization(&self.uuid, conn).await?; OrganizationApiKey::delete_all_by_organization(&self.uuid, conn).await?; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(organizations::table.filter(organizations::uuid.eq(self.uuid))) .execute(conn) .map_res("Error saving organization") - }} + }) + .await } pub async fn find_by_uuid(uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { - organizations::table - .filter(organizations::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| organizations::table.filter(organizations::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn find_by_name(name: &str, conn: &DbConn) -> Option { - db_run! { conn: { - organizations::table - .filter(organizations::name.eq(name)) - .first::(conn) - .ok() - }} + conn.run(move |conn| organizations::table.filter(organizations::name.eq(name)).first::(conn).ok()).await } pub async fn get_all(conn: &DbConn) -> Vec { - db_run! { conn: { - organizations::table - .load::(conn) - .expect("Error loading organizations") - }} + conn.run(move |conn| organizations::table.load::(conn).expect("Error loading organizations")).await } pub async fn find_main_org_user_email(user_email: &str, conn: &DbConn) -> Option { let lower_mail = user_email.to_lowercase(); - db_run! { conn: { + conn.run(move |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))) @@ -430,13 +417,14 @@ impl Organization { .select(organizations::all_columns) .first::(conn) .ok() - }} + }) + .await } pub async fn find_org_user_email(user_email: &str, conn: &DbConn) -> Vec { let lower_mail = user_email.to_lowercase(); - db_run! { conn: { + conn.run(move |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))) @@ -446,7 +434,8 @@ impl Organization { .select(organizations::all_columns) .load::(conn) .expect("Error loading user orgs") - }} + }) + .await } } @@ -786,11 +775,12 @@ impl Membership { CollectionUser::delete_all_by_user_and_org(&self.user_uuid, &self.org_uuid, conn).await?; GroupUser::delete_all_by_member(&self.uuid, conn).await?; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(users_organizations::table.filter(users_organizations::uuid.eq(self.uuid))) .execute(conn) .map_res("Error removing user from organization") - }} + }) + .await } pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { @@ -830,64 +820,67 @@ impl Membership { } pub async fn find_by_uuid(uuid: &MembershipId, conn: &DbConn) -> Option { - db_run! { conn: { - users_organizations::table - .filter(users_organizations::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| { + users_organizations::table.filter(users_organizations::uuid.eq(uuid)).first::(conn).ok() + }) + .await } pub async fn find_by_uuid_and_org(uuid: &MembershipId, org_uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::uuid.eq(uuid)) .filter(users_organizations::org_uuid.eq(org_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_confirmed_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .load::(conn) .unwrap_or_default() - }} + }) + .await } pub async fn find_invited_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::status.eq(MembershipStatus::Invited as i32)) .load::(conn) .unwrap_or_default() - }} + }) + .await } // Should be used only when email are disabled. // In Organizations::send_invite status is set to Accepted only if the user has a password. pub async fn accept_user_invitations(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::update(users_organizations::table) .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::status.eq(MembershipStatus::Invited as i32)) .set(users_organizations::status.eq(MembershipStatus::Accepted as i32)) .execute(conn) .map_res("Error confirming invitations") - }} + }) + .await } pub async fn find_any_state_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .load::(conn) .unwrap_or_default() - }} + }) + .await } pub async fn count_accepted_and_confirmed_by_user( @@ -895,70 +888,83 @@ impl Membership { excluded_org: &OrganizationId, conn: &DbConn, ) -> i64 { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::org_uuid.ne(excluded_org)) - .filter(users_organizations::status.eq(MembershipStatus::Accepted as i32).or(users_organizations::status.eq(MembershipStatus::Confirmed as i32))) + .filter( + users_organizations::status + .eq(MembershipStatus::Accepted as i32) + .or(users_organizations::status.eq(MembershipStatus::Confirmed as i32)), + ) .count() .first::(conn) .unwrap_or(0) - }} + }) + .await } pub async fn find_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) .load::(conn) .expect("Error loading user organizations") - }} + }) + .await } pub async fn find_confirmed_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .load::(conn) .unwrap_or_default() - }} + }) + .await } // Get all users which are either owner or admin, or a manager which can manage/access all pub async fn find_confirmed_and_manage_all_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .filter( - users_organizations::atype.eq_any(vec![MembershipType::Owner as i32, MembershipType::Admin as i32]) - .or(users_organizations::atype.eq(MembershipType::Manager as i32).and(users_organizations::access_all.eq(true))) + users_organizations::atype + .eq_any(vec![MembershipType::Owner as i32, MembershipType::Admin as i32]) + .or(users_organizations::atype + .eq(MembershipType::Manager as i32) + .and(users_organizations::access_all.eq(true))), ) .load::(conn) .unwrap_or_default() - }} + }) + .await } pub async fn count_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> i64 { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) .count() .first::(conn) .ok() .unwrap_or(0) - }} + }) + .await } pub async fn find_by_org_and_type(org_uuid: &OrganizationId, atype: MembershipType, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) .filter(users_organizations::atype.eq(atype as i32)) .load::(conn) .expect("Error loading user organizations") - }} + }) + .await } pub async fn count_confirmed_by_org_and_type( @@ -966,7 +972,7 @@ impl Membership { atype: MembershipType, conn: &DbConn, ) -> i64 { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) .filter(users_organizations::atype.eq(atype as i32)) @@ -974,17 +980,19 @@ impl Membership { .count() .first::(conn) .unwrap_or(0) - }} + }) + .await } pub async fn find_by_user_and_org(user_uuid: &UserId, org_uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::org_uuid.eq(org_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_confirmed_by_user_and_org( @@ -992,78 +1000,76 @@ impl Membership { org_uuid: &OrganizationId, conn: &DbConn, ) -> Option { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::org_uuid.eq(org_uuid)) - .filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) - ) + .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .load::(conn) .expect("Error loading user organizations") - }} + }) + .await } pub async fn get_orgs_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .select(users_organizations::org_uuid) .load::(conn) .unwrap_or_default() - }} + }) + .await } pub async fn find_by_user_and_policy(user_uuid: &UserId, policy_type: OrgPolicyType, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .inner_join( - org_policies::table.on( - org_policies::org_uuid.eq(users_organizations::org_uuid) - .and(users_organizations::user_uuid.eq(user_uuid)) - .and(org_policies::atype.eq(policy_type as i32)) - .and(org_policies::enabled.eq(true))) - ) - .filter( - users_organizations::status.eq(MembershipStatus::Confirmed as i32) + org_policies::table.on(org_policies::org_uuid + .eq(users_organizations::org_uuid) + .and(users_organizations::user_uuid.eq(user_uuid)) + .and(org_policies::atype.eq(policy_type as i32)) + .and(org_policies::enabled.eq(true))), ) + .filter(users_organizations::status.eq(MembershipStatus::Confirmed as i32)) .select(users_organizations::all_columns) .load::(conn) .unwrap_or_default() - }} + }) + .await } pub async fn find_by_cipher_and_org(cipher_uuid: &CipherId, org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table - .filter(users_organizations::org_uuid.eq(org_uuid)) - .left_join(users_collections::table.on( - users_collections::user_uuid.eq(users_organizations::user_uuid) - )) - .left_join(ciphers_collections::table.on( - ciphers_collections::collection_uuid.eq(users_collections::collection_uuid).and( - ciphers_collections::cipher_uuid.eq(&cipher_uuid) + .filter(users_organizations::org_uuid.eq(org_uuid)) + .left_join(users_collections::table.on(users_collections::user_uuid.eq(users_organizations::user_uuid))) + .left_join( + ciphers_collections::table.on(ciphers_collections::collection_uuid + .eq(users_collections::collection_uuid) + .and(ciphers_collections::cipher_uuid.eq(&cipher_uuid))), ) - )) - .filter( - users_organizations::access_all.eq(true).or( // AccessAll.. - ciphers_collections::cipher_uuid.eq(&cipher_uuid) // ..or access to collection with cipher - ) - ) - .select(users_organizations::all_columns) - .distinct() - .load::(conn) - .expect("Error loading user organizations") - }} + .filter(users_organizations::access_all.eq(true).or( + // AccessAll.. + ciphers_collections::cipher_uuid.eq(&cipher_uuid), // ..or access to collection with cipher + )) + .select(users_organizations::all_columns) + .distinct() + .load::(conn) + .expect("Error loading user organizations") + }) + .await } pub async fn find_by_cipher_and_org_with_group( @@ -1071,45 +1077,54 @@ impl Membership { org_uuid: &OrganizationId, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table - .filter(users_organizations::org_uuid.eq(org_uuid)) - .inner_join(groups_users::table.on( - groups_users::users_organizations_uuid.eq(users_organizations::uuid) - )) - .left_join(collections_groups::table.on( - collections_groups::groups_uuid.eq(groups_users::groups_uuid) - )) - .left_join(groups::table.on(groups::uuid.eq(groups_users::groups_uuid) - .and(groups::organizations_uuid.eq(users_organizations::org_uuid)) - )) - .left_join(ciphers_collections::table.on( - ciphers_collections::collection_uuid.eq(collections_groups::collections_uuid).and(ciphers_collections::cipher_uuid.eq(&cipher_uuid)) - - )) - .filter( - groups::access_all.eq(true).or( // AccessAll via groups - ciphers_collections::cipher_uuid.eq(&cipher_uuid) // ..or access to collection via group - ) + .filter(users_organizations::org_uuid.eq(org_uuid)) + .inner_join( + groups_users::table.on(groups_users::users_organizations_uuid.eq(users_organizations::uuid)), ) + .left_join(collections_groups::table.on(collections_groups::groups_uuid.eq(groups_users::groups_uuid))) + .left_join( + groups::table.on(groups::uuid + .eq(groups_users::groups_uuid) + .and(groups::organizations_uuid.eq(users_organizations::org_uuid))), + ) + .left_join( + ciphers_collections::table.on(ciphers_collections::collection_uuid + .eq(collections_groups::collections_uuid) + .and(ciphers_collections::cipher_uuid.eq(&cipher_uuid))), + ) + .filter(groups::access_all.eq(true).or( + // AccessAll via groups + ciphers_collections::cipher_uuid.eq(&cipher_uuid), // ..or access to collection via group + )) .select(users_organizations::all_columns) .distinct() - .load::(conn) - .expect("Error loading user organizations with groups") - }} + .load::(conn) + .expect("Error loading user organizations with groups") + }) + .await } pub async fn user_has_ge_admin_access_to_cipher(user_uuid: &UserId, cipher_uuid: &CipherId, conn: &DbConn) -> bool { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table - .inner_join(ciphers::table.on(ciphers::uuid.eq(cipher_uuid).and(ciphers::organization_uuid.eq(users_organizations::org_uuid.nullable())))) - .filter(users_organizations::user_uuid.eq(user_uuid)) - .filter(users_organizations::atype.eq_any(vec![MembershipType::Owner as i32, MembershipType::Admin as i32])) - .count() - .first::(conn) - .ok() - .unwrap_or(0) != 0 - }} + .inner_join( + ciphers::table.on(ciphers::uuid + .eq(cipher_uuid) + .and(ciphers::organization_uuid.eq(users_organizations::org_uuid.nullable()))), + ) + .filter(users_organizations::user_uuid.eq(user_uuid)) + .filter( + users_organizations::atype.eq_any(vec![MembershipType::Owner as i32, MembershipType::Admin as i32]), + ) + .count() + .first::(conn) + .ok() + .unwrap_or(0) + != 0 + }) + .await } pub async fn find_by_collection_and_org( @@ -1117,44 +1132,41 @@ impl Membership { org_uuid: &OrganizationId, conn: &DbConn, ) -> Vec { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table - .filter(users_organizations::org_uuid.eq(org_uuid)) - .left_join(users_collections::table.on( - users_collections::user_uuid.eq(users_organizations::user_uuid) - )) - .filter( - users_organizations::access_all.eq(true).or( // AccessAll.. - users_collections::collection_uuid.eq(&collection_uuid) // ..or access to collection with cipher - ) - ) - .select(users_organizations::all_columns) - .load::(conn) - .expect("Error loading user organizations") - }} + .filter(users_organizations::org_uuid.eq(org_uuid)) + .left_join(users_collections::table.on(users_collections::user_uuid.eq(users_organizations::user_uuid))) + .filter(users_organizations::access_all.eq(true).or( + // AccessAll.. + users_collections::collection_uuid.eq(&collection_uuid), // ..or access to collection with cipher + )) + .select(users_organizations::all_columns) + .load::(conn) + .expect("Error loading user organizations") + }) + .await } pub async fn find_by_external_id_and_org(ext_id: &str, org_uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table - .filter( - users_organizations::external_id.eq(ext_id) - .and(users_organizations::org_uuid.eq(org_uuid)) - ) - .first::(conn) - .ok() - }} + .filter(users_organizations::external_id.eq(ext_id).and(users_organizations::org_uuid.eq(org_uuid))) + .first::(conn) + .ok() + }) + .await } pub async fn find_main_user_org(user_uuid: &str, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) .filter(users_organizations::status.ne(MembershipStatus::Revoked as i32)) .order(users_organizations::atype.asc()) .first::(conn) .ok() - }} + }) + .await } } @@ -1192,20 +1204,19 @@ impl OrganizationApiKey { } pub async fn find_by_org_uuid(org_uuid: &OrganizationId, conn: &DbConn) -> Option { - db_run! { conn: { - organization_api_key::table - .filter(organization_api_key::org_uuid.eq(org_uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| { + organization_api_key::table.filter(organization_api_key::org_uuid.eq(org_uuid)).first::(conn).ok() + }) + .await } pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(organization_api_key::table.filter(organization_api_key::org_uuid.eq(org_uuid))) .execute(conn) .map_res("Error removing organization api key from organization") - }} + }) + .await } } diff --git a/src/db/models/send.rs b/src/db/models/send.rs index 1f209eaa..bf07c2bc 100644 --- a/src/db/models/send.rs +++ b/src/db/models/send.rs @@ -236,11 +236,10 @@ impl Send { operator.remove_all(&self.uuid).await.ok(); } - db_run! { conn: { - diesel::delete(sends::table.filter(sends::uuid.eq(&self.uuid))) - .execute(conn) - .map_res("Error deleting send") - }} + conn.run(move |conn| { + diesel::delete(sends::table.filter(sends::uuid.eq(&self.uuid))).execute(conn).map_res("Error deleting send") + }) + .await } /// Purge all sends that are past their deletion date. @@ -282,31 +281,21 @@ impl Send { } pub async fn find_by_uuid(uuid: &SendId, conn: &DbConn) -> Option { - db_run! { conn: { - sends::table - .filter(sends::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| sends::table.filter(sends::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn find_by_uuid_and_user(uuid: &SendId, user_uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { - sends::table - .filter(sends::uuid.eq(uuid)) - .filter(sends::user_uuid.eq(user_uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| { + sends::table.filter(sends::uuid.eq(uuid)).filter(sends::user_uuid.eq(user_uuid)).first::(conn).ok() + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { - sends::table - .filter(sends::user_uuid.eq(user_uuid)) - .load::(conn) - .expect("Error loading sends") - }} + conn.run(move |conn| { + sends::table.filter(sends::user_uuid.eq(user_uuid)).load::(conn).expect("Error loading sends") + }) + .await } pub async fn size_by_user(user_uuid: &UserId, conn: &DbConn) -> Option { @@ -331,22 +320,18 @@ impl Send { } pub async fn find_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec { - db_run! { conn: { - sends::table - .filter(sends::organization_uuid.eq(org_uuid)) - .load::(conn) - .expect("Error loading sends") - }} + conn.run(move |conn| { + sends::table.filter(sends::organization_uuid.eq(org_uuid)).load::(conn).expect("Error loading sends") + }) + .await } pub async fn find_by_past_deletion_date(conn: &DbConn) -> Vec { let now = Utc::now().naive_utc(); - db_run! { conn: { - sends::table - .filter(sends::deletion_date.lt(now)) - .load::(conn) - .expect("Error loading sends") - }} + conn.run(move |conn| { + sends::table.filter(sends::deletion_date.lt(now)).load::(conn).expect("Error loading sends") + }) + .await } } diff --git a/src/db/models/sso_auth.rs b/src/db/models/sso_auth.rs index cb7b0012..e6d41138 100644 --- a/src/db/models/sso_auth.rs +++ b/src/db/models/sso_auth.rs @@ -112,32 +112,35 @@ impl SsoAuth { pub async fn find(state: &OIDCState, conn: &DbConn) -> Option { let oldest = Utc::now().naive_utc() - *SSO_AUTH_EXPIRATION; - db_run! { conn: { + conn.run(move |conn| { sso_auth::table .filter(sso_auth::state.eq(state)) .filter(sso_auth::created_at.ge(oldest)) .first::(conn) .ok() - }} + }) + .await } pub async fn delete(self, conn: &DbConn) -> EmptyResult { - db_run! {conn: { + conn.run(move |conn| { diesel::delete(sso_auth::table.filter(sso_auth::state.eq(self.state))) .execute(conn) .map_res("Error deleting sso_auth") - }} + }) + .await } pub async fn delete_expired(pool: DbPool) -> EmptyResult { debug!("Purging expired sso_auth"); if let Ok(conn) = pool.get().await { let oldest = Utc::now().naive_utc() - *SSO_AUTH_EXPIRATION; - db_run! { conn: { + conn.run(move |conn| { diesel::delete(sso_auth::table.filter(sso_auth::created_at.lt(oldest))) .execute(conn) .map_res("Error deleting expired SSO nonce") - }} + }) + .await } else { err!("Failed to get DB connection while purging expired sso_auth") } diff --git a/src/db/models/two_factor.rs b/src/db/models/two_factor.rs index de3fba95..5f57635e 100644 --- a/src/db/models/two_factor.rs +++ b/src/db/models/two_factor.rs @@ -118,39 +118,43 @@ impl TwoFactor { } pub async fn delete(self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(twofactor::table.filter(twofactor::uuid.eq(self.uuid))) .execute(conn) .map_res("Error deleting twofactor") - }} + }) + .await } pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { twofactor::table .filter(twofactor::user_uuid.eq(user_uuid)) .filter(twofactor::atype.lt(1000)) // Filter implementation types .load::(conn) .expect("Error loading twofactor") - }} + }) + .await } pub async fn find_by_user_and_type(user_uuid: &UserId, atype: i32, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { twofactor::table .filter(twofactor::user_uuid.eq(user_uuid)) .filter(twofactor::atype.eq(atype)) .first::(conn) .ok() - }} + }) + .await } pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(twofactor::table.filter(twofactor::user_uuid.eq(user_uuid))) .execute(conn) .map_res("Error deleting twofactors") - }} + }) + .await } pub async fn migrate_u2f_to_webauthn(conn: &DbConn) -> EmptyResult { @@ -158,12 +162,14 @@ impl TwoFactor { use webauthn_rs::prelude::{COSEEC2Key, COSEKey, COSEKeyType, ECDSACurve}; use webauthn_rs_proto::{COSEAlgorithm, UserVerificationPolicy}; - let u2f_factors = db_run! { conn: { - twofactor::table - .filter(twofactor::atype.eq(TwoFactorType::U2f as i32)) - .load::(conn) - .expect("Error loading twofactor") - }}; + let u2f_factors = conn + .run(move |conn| { + twofactor::table + .filter(twofactor::atype.eq(TwoFactorType::U2f as i32)) + .load::(conn) + .expect("Error loading twofactor") + }) + .await; for mut u2f in u2f_factors { let mut regs: Vec = serde_json::from_str(&u2f.data)?; @@ -230,12 +236,14 @@ impl TwoFactor { } pub async fn migrate_credential_to_passkey(conn: &DbConn) -> EmptyResult { - let webauthn_factors = db_run! { conn: { - twofactor::table - .filter(twofactor::atype.eq(TwoFactorType::Webauthn as i32)) - .load::(conn) - .expect("Error loading twofactor") - }}; + let webauthn_factors = conn + .run(move |conn| { + twofactor::table + .filter(twofactor::atype.eq(TwoFactorType::Webauthn as i32)) + .load::(conn) + .expect("Error loading twofactor") + }) + .await; for webauthn_factor in webauthn_factors { // assume that a failure to parse into the old struct, means that it was already converted diff --git a/src/db/models/two_factor_duo_context.rs b/src/db/models/two_factor_duo_context.rs index 053e8525..1a4ae266 100644 --- a/src/db/models/two_factor_duo_context.rs +++ b/src/db/models/two_factor_duo_context.rs @@ -19,12 +19,10 @@ pub struct TwoFactorDuoContext { impl TwoFactorDuoContext { pub async fn find_by_state(state: &str, conn: &DbConn) -> Option { - db_run! { conn: { - twofactor_duo_ctx::table - .filter(twofactor_duo_ctx::state.eq(state)) - .first::(conn) - .ok() - }} + conn.run(move |conn| { + twofactor_duo_ctx::table.filter(twofactor_duo_ctx::state.eq(state)).first::(conn).ok() + }) + .await } pub async fn save(state: &str, user_email: &str, nonce: &str, ttl: i64, conn: &DbConn) -> EmptyResult { @@ -36,37 +34,38 @@ impl TwoFactorDuoContext { let exp = Utc::now().timestamp() + ttl; - db_run! { conn: { + conn.run(move |conn| { diesel::insert_into(twofactor_duo_ctx::table) .values(( twofactor_duo_ctx::state.eq(state), twofactor_duo_ctx::user_email.eq(user_email), twofactor_duo_ctx::nonce.eq(nonce), - twofactor_duo_ctx::exp.eq(exp) - )) - .execute(conn) - .map_res("Error saving context to twofactor_duo_ctx") - }} + twofactor_duo_ctx::exp.eq(exp), + )) + .execute(conn) + .map_res("Error saving context to twofactor_duo_ctx") + }) + .await } pub async fn find_expired(conn: &DbConn) -> Vec { let now = Utc::now().timestamp(); - db_run! { conn: { + conn.run(move |conn| { twofactor_duo_ctx::table .filter(twofactor_duo_ctx::exp.lt(now)) .load::(conn) .expect("Error finding expired contexts in twofactor_duo_ctx") - }} + }) + .await } pub async fn delete(&self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { - diesel::delete( - twofactor_duo_ctx::table - .filter(twofactor_duo_ctx::state.eq(&self.state))) + conn.run(move |conn| { + diesel::delete(twofactor_duo_ctx::table.filter(twofactor_duo_ctx::state.eq(&self.state))) .execute(conn) .map_res("Error deleting from twofactor_duo_ctx") - }} + }) + .await } pub async fn purge_expired_duo_contexts(conn: &DbConn) { diff --git a/src/db/models/two_factor_incomplete.rs b/src/db/models/two_factor_incomplete.rs index 1b1a1bf9..4b8cadcb 100644 --- a/src/db/models/two_factor_incomplete.rs +++ b/src/db/models/two_factor_incomplete.rs @@ -49,7 +49,7 @@ impl TwoFactorIncomplete { return Ok(()); } - db_run! { conn: { + conn.run(move |conn| { diesel::insert_into(twofactor_incomplete::table) .values(( twofactor_incomplete::user_uuid.eq(user_uuid), @@ -61,7 +61,8 @@ impl TwoFactorIncomplete { )) .execute(conn) .map_res("Error adding twofactor_incomplete record") - }} + }) + .await } pub async fn mark_complete(user_uuid: &UserId, device_uuid: &DeviceId, conn: &DbConn) -> EmptyResult { @@ -73,22 +74,24 @@ impl TwoFactorIncomplete { } pub async fn find_by_user_and_device(user_uuid: &UserId, device_uuid: &DeviceId, conn: &DbConn) -> Option { - db_run! { conn: { + conn.run(move |conn| { twofactor_incomplete::table .filter(twofactor_incomplete::user_uuid.eq(user_uuid)) .filter(twofactor_incomplete::device_uuid.eq(device_uuid)) .first::(conn) .ok() - }} + }) + .await } pub async fn find_logins_before(dt: &NaiveDateTime, conn: &DbConn) -> Vec { - db_run! { conn: { + conn.run(move |conn| { twofactor_incomplete::table .filter(twofactor_incomplete::login_time.lt(dt)) .load::(conn) .expect("Error loading twofactor_incomplete") - }} + }) + .await } pub async fn delete(self, conn: &DbConn) -> EmptyResult { @@ -96,20 +99,24 @@ impl TwoFactorIncomplete { } pub async fn delete_by_user_and_device(user_uuid: &UserId, device_uuid: &DeviceId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { - diesel::delete(twofactor_incomplete::table - .filter(twofactor_incomplete::user_uuid.eq(user_uuid)) - .filter(twofactor_incomplete::device_uuid.eq(device_uuid))) - .execute(conn) - .map_res("Error in twofactor_incomplete::delete_by_user_and_device()") - }} + conn.run(move |conn| { + diesel::delete( + twofactor_incomplete::table + .filter(twofactor_incomplete::user_uuid.eq(user_uuid)) + .filter(twofactor_incomplete::device_uuid.eq(device_uuid)), + ) + .execute(conn) + .map_res("Error in twofactor_incomplete::delete_by_user_and_device()") + }) + .await } pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(twofactor_incomplete::table.filter(twofactor_incomplete::user_uuid.eq(user_uuid))) .execute(conn) .map_res("Error in twofactor_incomplete::delete_all_by_user()") - }} + }) + .await } } diff --git a/src/db/models/user.rs b/src/db/models/user.rs index d366dfd3..24bee751 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -342,11 +342,10 @@ impl User { TwoFactorIncomplete::delete_all_by_user(&self.uuid, conn).await?; Invitation::take(&self.email, conn).await; // Delete invitation if any - db_run! { conn: { - diesel::delete(users::table.filter(users::uuid.eq(self.uuid))) - .execute(conn) - .map_res("Error deleting user") - }} + conn.run(move |conn| { + diesel::delete(users::table.filter(users::uuid.eq(self.uuid))).execute(conn).map_res("Error deleting user") + }) + .await } pub async fn update_uuid_revision(uuid: &UserId, conn: &DbConn) { @@ -358,14 +357,11 @@ impl User { pub async fn update_all_revisions(conn: &DbConn) -> EmptyResult { let updated_at = Utc::now().naive_utc(); - db_run! { conn: { - retry(|| { - diesel::update(users::table) - .set(users::updated_at.eq(updated_at)) - .execute(conn) - }, 10) - .map_res("Error updating revision date for all users") - }} + conn.run(move |conn| { + retry(|| diesel::update(users::table).set(users::updated_at.eq(updated_at)).execute(conn), 10) + .map_res("Error updating revision date for all users") + }) + .await } pub async fn update_revision(&mut self, conn: &DbConn) -> EmptyResult { @@ -375,51 +371,48 @@ impl User { } async fn update_revision_impl(uuid: &UserId, date: &NaiveDateTime, conn: &DbConn) -> EmptyResult { - db_run! { conn: { - retry(|| { - diesel::update(users::table.filter(users::uuid.eq(uuid))) - .set(users::updated_at.eq(date)) - .execute(conn) - }, 10) + conn.run(move |conn| { + retry( + || { + diesel::update(users::table.filter(users::uuid.eq(uuid))) + .set(users::updated_at.eq(date)) + .execute(conn) + }, + 10, + ) .map_res("Error updating user revision") - }} + }) + .await } pub async fn find_by_mail(mail: &str, conn: &DbConn) -> Option { let lower_mail = mail.to_lowercase(); - db_run! { conn: { - users::table - .filter(users::email.eq(lower_mail)) - .first::(conn) - .ok() - }} + conn.run(move |conn| users::table.filter(users::email.eq(lower_mail)).first::(conn).ok()).await } pub async fn find_by_uuid(uuid: &UserId, conn: &DbConn) -> Option { - db_run! { conn: { - users::table - .filter(users::uuid.eq(uuid)) - .first::(conn) - .ok() - }} + conn.run(move |conn| users::table.filter(users::uuid.eq(uuid)).first::(conn).ok()).await } pub async fn find_by_device_for_email2fa(device_uuid: &DeviceId, conn: &DbConn) -> Option { - if let Some(user_uuid) = db_run! ( conn: { - twofactor_incomplete::table - .filter(twofactor_incomplete::device_uuid.eq(device_uuid)) - .order_by(twofactor_incomplete::login_time.desc()) - .select(twofactor_incomplete::user_uuid) - .first::(conn) - .ok() - }) { + if let Some(user_uuid) = conn + .run(move |conn| { + twofactor_incomplete::table + .filter(twofactor_incomplete::device_uuid.eq(device_uuid)) + .order_by(twofactor_incomplete::login_time.desc()) + .select(twofactor_incomplete::user_uuid) + .first::(conn) + .ok() + }) + .await + { return Self::find_by_uuid(&user_uuid, conn).await; } None } pub async fn get_all(conn: &DbConn) -> Vec<(Self, Option)> { - db_run! { conn: { + conn.run(move |conn| { users::table .left_join(sso_users::table) .select(<(Self, Option)>::as_select()) @@ -427,7 +420,8 @@ impl User { .expect("Error loading groups for user") .into_iter() .collect() - }} + }) + .await } pub async fn last_active(&self, conn: &DbConn) -> Option { @@ -472,21 +466,18 @@ impl Invitation { } pub async fn delete(self, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(invitations::table.filter(invitations::email.eq(self.email))) .execute(conn) .map_res("Error deleting invitation") - }} + }) + .await } pub async fn find_by_mail(mail: &str, conn: &DbConn) -> Option { let lower_mail = mail.to_lowercase(); - db_run! { conn: { - invitations::table - .filter(invitations::email.eq(lower_mail)) - .first::(conn) - .ok() - }} + conn.run(move |conn| invitations::table.filter(invitations::email.eq(lower_mail)).first::(conn).ok()) + .await } pub async fn take(mail: &str, conn: &DbConn) -> bool { @@ -536,34 +527,37 @@ impl SsoUser { } pub async fn find_by_identifier(identifier: &str, conn: &DbConn) -> Option<(User, Self)> { - db_run! { conn: { + conn.run(move |conn| { users::table .inner_join(sso_users::table) .select(<(User, Self)>::as_select()) .filter(sso_users::identifier.eq(identifier)) .first::<(User, Self)>(conn) .ok() - }} + }) + .await } pub async fn find_by_mail(mail: &str, conn: &DbConn) -> Option<(User, Option)> { let lower_mail = mail.to_lowercase(); - db_run! { conn: { + conn.run(move |conn| { users::table .left_join(sso_users::table) .select(<(User, Option)>::as_select()) .filter(users::email.eq(lower_mail)) .first::<(User, Option)>(conn) .ok() - }} + }) + .await } pub async fn delete(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { - db_run! { conn: { + conn.run(move |conn| { diesel::delete(sso_users::table.filter(sso_users::user_uuid.eq(user_uuid))) .execute(conn) .map_res("Error deleting sso user") - }} + }) + .await } }