diff --git a/src/auth.rs b/src/auth.rs index 8dea4165..f3e3af8b 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -266,7 +266,7 @@ use rocket::{ }; use crate::db::{ - models::{CollectionUser, Device, User, UserOrgStatus, UserOrgType, UserOrganization, UserStampException}, + models::{Collection, Device, User, UserOrgStatus, UserOrgType, UserOrganization, UserStampException}, DbConn, }; @@ -558,17 +558,15 @@ impl<'r> FromRequest<'r> for ManagerHeaders { _ => err_handler!("Error getting DB"), }; - if !headers.org_user.has_full_access() { - match CollectionUser::find_by_collection_and_user( + if !headers.org_user.has_full_access() + && !Collection::has_access_by_collection_and_user_uuid( &col_id, &headers.org_user.user_uuid, &mut conn, ) .await - { - Some(_) => (), - None => err_handler!("The current user isn't a manager for this collection"), - } + { + err_handler!("The current user isn't a manager for this collection") } } _ => err_handler!("Error getting the collection id"), diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index c4507e10..14eef617 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -167,15 +167,15 @@ impl Collection { users_collections::user_uuid.eq(user_uuid.clone()) ) )) - .left_join(users_organizations::table.on( + .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(groups_users::table.on( + .inner_join(groups_users::table.on( groups_users::users_organizations_uuid.eq(users_organizations::uuid) )) - .left_join(groups::table.on( + .inner_join(groups::table.on( groups::uuid.eq(groups_users::groups_uuid) )) .left_join(collections_groups::table.on( @@ -203,6 +203,17 @@ impl Collection { }} } + // Check if a user has access to a specific collection + // FIXME: This needs to be reviewed. The query used by `find_by_user_uuid` could be adjusted to filter when needed. + // For now this is a good solution without making to much changes. + pub async fn has_access_by_collection_and_user_uuid( + collection_uuid: &str, + user_uuid: &str, + conn: &mut DbConn, + ) -> bool { + Self::find_by_user_uuid(user_uuid.to_owned(), conn).await.into_iter().any(|c| c.uuid == collection_uuid) + } + pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Vec { Self::find_by_user_uuid(user_uuid.to_owned(), conn) .await @@ -241,16 +252,32 @@ impl Collection { users_collections::user_uuid.eq(user_uuid.clone()) ) )) - .left_join(users_organizations::table.on( + .inner_join(users_organizations::table.on( collections::org_uuid.eq(users_organizations::org_uuid).and( users_organizations::user_uuid.eq(user_uuid) ) )) + .inner_join(groups_users::table.on( + groups_users::users_organizations_uuid.eq(users_organizations::uuid) + )) + .inner_join(groups::table.on( + groups::uuid.eq(groups_users::groups_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(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(UserOrgType::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)