vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 2d90c6ac249f24115536151fc0352556d9d35f16
parent d209df9e10544b7c1fc8ebfdb3a7910400ba0289
Author: BlackDex <black.dex@gmail.com>
Date:   Fri,  2 Dec 2022 17:39:19 +0100

Fix managers and groups link

This PR should fix the managers and group link.
Although i think there might be a cleaner sollution, there are a lot of
other items to fix here which we should do in time.

But for now, with theh group support already merged, this fix should at
least help solving issue #2932.

Fixes #2932

Diffstat:
Msrc/auth.rs | 12+++++-------
Msrc/db/models/collection.rs | 35+++++++++++++++++++++++++++++++----
2 files changed, 36 insertions(+), 11 deletions(-)

diff --git 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 @@ -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> { 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)