add collection_membership type

pull/5320/head
Stefan Melmuk 5 days ago
parent 6355985539
commit 3d42b66a10
No known key found for this signature in database
GPG Key ID: 817020C608FE9C09

@ -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,
)]

Loading…
Cancel
Save