Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2025-01-07 11:45:40 +01:00
add collection_membership type
Dieser Commit ist enthalten in:
Ursprung
6355985539
Commit
3d42b66a10
2 geänderte Dateien mit 53 neuen und 27 gelöschten Zeilen
|
@ -43,13 +43,13 @@ pub fn routes() -> Vec<Route> {
|
|||
get_org_details,
|
||||
get_members,
|
||||
send_invite,
|
||||
reinvite_user,
|
||||
bulk_reinvite_user,
|
||||
reinvite_member,
|
||||
bulk_reinvite_member,
|
||||
confirm_invite,
|
||||
bulk_confirm_invite,
|
||||
accept_invite,
|
||||
get_user,
|
||||
edit_user,
|
||||
edit_membership,
|
||||
put_membership,
|
||||
delete_user,
|
||||
bulk_delete_user,
|
||||
|
@ -340,7 +340,8 @@ async fn get_org_collections_details(
|
|||
};
|
||||
|
||||
// get all collection memberships for the current organization
|
||||
let col_users = CollectionUser::find_by_organization(&org_id, &mut conn).await;
|
||||
// NOTE: the loaded col_users have a MembershipId
|
||||
let col_users = CollectionUser::find_by_organization_swap_user_uuid_with_member_uuid(&org_id, &mut conn).await;
|
||||
|
||||
// check if current user has full access to the organization (either directly or via any group)
|
||||
let has_full_access_to_org = member.access_all
|
||||
|
@ -688,9 +689,9 @@ async fn get_collection_users(
|
|||
err!("Collection not found in Organization")
|
||||
};
|
||||
|
||||
let mut user_list = Vec::new();
|
||||
let mut member_list = Vec::new();
|
||||
for col_user in CollectionUser::find_by_collection(&collection.uuid, &mut conn).await {
|
||||
user_list.push(
|
||||
member_list.push(
|
||||
Membership::find_by_user_and_org(&col_user.user_uuid, &org_id, &mut conn)
|
||||
.await
|
||||
.unwrap()
|
||||
|
@ -698,7 +699,7 @@ async fn get_collection_users(
|
|||
);
|
||||
}
|
||||
|
||||
Ok(Json(json!(user_list)))
|
||||
Ok(Json(json!(member_list)))
|
||||
}
|
||||
|
||||
#[put("/organizations/<org_id>/collections/<col_id>/users", data = "<data>")]
|
||||
|
@ -972,7 +973,7 @@ async fn send_invite(
|
|||
}
|
||||
|
||||
#[post("/organizations/<org_id>/users/reinvite", data = "<data>")]
|
||||
async fn bulk_reinvite_user(
|
||||
async fn bulk_reinvite_member(
|
||||
org_id: OrganizationId,
|
||||
data: Json<BulkMembershipIds>,
|
||||
headers: AdminHeaders,
|
||||
|
@ -982,7 +983,7 @@ async fn bulk_reinvite_user(
|
|||
|
||||
let mut bulk_response = Vec::new();
|
||||
for member_id in data.ids {
|
||||
let err_msg = match _reinvite_user(&org_id, &member_id, &headers.user.email, &mut conn).await {
|
||||
let err_msg = match _reinvite_member(&org_id, &member_id, &headers.user.email, &mut conn).await {
|
||||
Ok(_) => String::new(),
|
||||
Err(e) => format!("{e:?}"),
|
||||
};
|
||||
|
@ -1004,16 +1005,16 @@ async fn bulk_reinvite_user(
|
|||
}
|
||||
|
||||
#[post("/organizations/<org_id>/users/<member_id>/reinvite")]
|
||||
async fn reinvite_user(
|
||||
async fn reinvite_member(
|
||||
org_id: OrganizationId,
|
||||
member_id: MembershipId,
|
||||
headers: AdminHeaders,
|
||||
mut conn: DbConn,
|
||||
) -> EmptyResult {
|
||||
_reinvite_user(&org_id, &member_id, &headers.user.email, &mut conn).await
|
||||
_reinvite_member(&org_id, &member_id, &headers.user.email, &mut conn).await
|
||||
}
|
||||
|
||||
async fn _reinvite_user(
|
||||
async fn _reinvite_member(
|
||||
org_id: &OrganizationId,
|
||||
member_id: &MembershipId,
|
||||
invited_by_email: &str,
|
||||
|
@ -1104,7 +1105,7 @@ async fn accept_invite(
|
|||
err!("Reset password key is required, but not provided.");
|
||||
}
|
||||
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_membership_type
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_membership(), edit_membership(), admin::update_membership_type
|
||||
// It returns different error messages per function.
|
||||
if member.atype < MembershipType::Admin {
|
||||
match OrgPolicy::is_user_allowed(&member.user_uuid, &org_id, false, &mut conn).await {
|
||||
|
@ -1245,7 +1246,7 @@ async fn _confirm_invite(
|
|||
err!("User in invalid state")
|
||||
}
|
||||
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_membership_type
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_membership(), edit_membership(), admin::update_membership_type
|
||||
// It returns different error messages per function.
|
||||
if member_to_confirm.atype < MembershipType::Admin {
|
||||
match OrgPolicy::is_user_allowed(&member_to_confirm.user_uuid, org_id, true, conn).await {
|
||||
|
@ -1336,11 +1337,11 @@ async fn put_membership(
|
|||
headers: AdminHeaders,
|
||||
conn: DbConn,
|
||||
) -> EmptyResult {
|
||||
edit_user(org_id, member_id, data, headers, conn).await
|
||||
edit_membership(org_id, member_id, data, headers, conn).await
|
||||
}
|
||||
|
||||
#[post("/organizations/<org_id>/users/<member_id>", data = "<data>", rank = 1)]
|
||||
async fn edit_user(
|
||||
async fn edit_membership(
|
||||
org_id: OrganizationId,
|
||||
member_id: MembershipId,
|
||||
data: Json<EditUserData>,
|
||||
|
@ -1378,7 +1379,7 @@ async fn edit_user(
|
|||
}
|
||||
}
|
||||
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_membership_type
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_membership(), edit_membership(), admin::update_membership_type
|
||||
// It returns different error messages per function.
|
||||
if new_type < MembershipType::Admin {
|
||||
match OrgPolicy::is_user_allowed(&member_to_edit.user_uuid, &org_id, true, &mut conn).await {
|
||||
|
@ -2282,7 +2283,7 @@ async fn _restore_membership(
|
|||
err!("Only owners can restore other owners")
|
||||
}
|
||||
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_membership_type
|
||||
// This check is also done at accept_invite(), _confirm_invite, _activate_membership(), edit_membership(), admin::update_membership_type
|
||||
// It returns different error messages per function.
|
||||
if member.atype < MembershipType::Admin {
|
||||
match OrgPolicy::is_user_allowed(&member.user_uuid, org_id, false, conn).await {
|
||||
|
|
|
@ -3,7 +3,8 @@ use rocket::request::FromParam;
|
|||
use serde_json::Value;
|
||||
|
||||
use super::{
|
||||
CipherId, CollectionGroup, GroupUser, Membership, MembershipStatus, MembershipType, OrganizationId, User, UserId,
|
||||
CipherId, CollectionGroup, GroupUser, Membership, MembershipId, MembershipStatus, MembershipType, OrganizationId,
|
||||
User, UserId,
|
||||
};
|
||||
use crate::CONFIG;
|
||||
|
||||
|
@ -527,8 +528,11 @@ impl CollectionUser {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
pub async fn find_by_organization_swap_user_uuid_with_member_uuid(
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<CollectionMembership> {
|
||||
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))
|
||||
|
@ -537,7 +541,8 @@ impl CollectionUser {
|
|||
.load::<CollectionUserDb>(conn)
|
||||
.expect("Error loading users_collections")
|
||||
.from_db()
|
||||
}}
|
||||
}};
|
||||
col_users.into_iter().map(|c| c.into()).collect()
|
||||
}
|
||||
|
||||
pub async fn save(
|
||||
|
@ -626,8 +631,8 @@ impl CollectionUser {
|
|||
pub async fn find_by_collection_swap_user_uuid_with_member_uuid(
|
||||
collection_uuid: &CollectionId,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
) -> Vec<CollectionMembership> {
|
||||
let col_users = db_run! { conn: {
|
||||
users_collections::table
|
||||
.filter(users_collections::collection_uuid.eq(collection_uuid))
|
||||
.inner_join(users_organizations::table.on(users_organizations::user_uuid.eq(users_collections::user_uuid)))
|
||||
|
@ -635,7 +640,8 @@ impl CollectionUser {
|
|||
.load::<CollectionUserDb>(conn)
|
||||
.expect("Error loading users_collections")
|
||||
.from_db()
|
||||
}}
|
||||
}};
|
||||
col_users.into_iter().map(|c| c.into()).collect()
|
||||
}
|
||||
|
||||
pub async fn find_by_collection_and_user(
|
||||
|
@ -775,10 +781,18 @@ impl CollectionCipher {
|
|||
}
|
||||
}
|
||||
|
||||
impl CollectionUser {
|
||||
// Added in case we need the membership_uuid instead of the user_uuid
|
||||
pub struct CollectionMembership {
|
||||
pub membership_uuid: MembershipId,
|
||||
pub collection_uuid: CollectionId,
|
||||
pub read_only: bool,
|
||||
pub hide_passwords: bool,
|
||||
}
|
||||
|
||||
impl CollectionMembership {
|
||||
pub fn to_json_details_for_user(&self) -> Value {
|
||||
json!({
|
||||
"id": self.user_uuid,
|
||||
"id": self.membership_uuid,
|
||||
"readOnly": self.read_only,
|
||||
"hidePasswords": self.hide_passwords,
|
||||
"manage": false
|
||||
|
@ -786,6 +800,17 @@ impl CollectionUser {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<CollectionUser> for CollectionMembership {
|
||||
fn from(c: CollectionUser) -> Self {
|
||||
Self {
|
||||
membership_uuid: c.user_uuid.to_string().into(),
|
||||
collection_uuid: c.collection_uuid,
|
||||
read_only: c.read_only,
|
||||
hide_passwords: c.hide_passwords,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, AsRef, Deref, DieselNewType, Display, From, FromForm, Hash, PartialEq, Eq, Serialize, Deserialize,
|
||||
)]
|
||||
|
|
Laden …
In neuem Issue referenzieren