Skip to content

Commit a428f05

Browse files
authored
Merge pull request #3354 from stefan0xC/bulk-delete-endpoints
add endpoints to bulk delete collections/groups
2 parents 5800ace + ed8091a commit a428f05

File tree

2 files changed

+112
-25
lines changed

2 files changed

+112
-25
lines changed

src/api/core/organizations.rs

+80-17
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub fn routes() -> Vec<Route> {
3939
put_organization_collection_update,
4040
delete_organization_collection,
4141
post_organization_collection_delete,
42+
bulk_delete_organization_collections,
4243
get_org_details,
4344
get_org_users,
4445
send_invite,
@@ -81,6 +82,7 @@ pub fn routes() -> Vec<Route> {
8182
get_group_details,
8283
delete_group,
8384
post_delete_group,
85+
bulk_delete_groups,
8486
get_group_users,
8587
put_group_users,
8688
get_user_groups,
@@ -537,35 +539,44 @@ async fn post_organization_collection_delete_user(
537539
delete_organization_collection_user(org_id, col_id, org_user_id, headers, conn).await
538540
}
539541

540-
#[delete("/organizations/<org_id>/collections/<col_id>")]
541-
async fn delete_organization_collection(
542-
org_id: String,
543-
col_id: String,
544-
headers: ManagerHeaders,
545-
mut conn: DbConn,
542+
async fn _delete_organization_collection(
543+
org_id: &str,
544+
col_id: &str,
545+
headers: &ManagerHeaders,
546+
conn: &mut DbConn,
546547
) -> EmptyResult {
547-
match Collection::find_by_uuid(&col_id, &mut conn).await {
548+
match Collection::find_by_uuid(col_id, conn).await {
548549
None => err!("Collection not found"),
549550
Some(collection) => {
550551
if collection.org_uuid == org_id {
551552
log_event(
552553
EventType::CollectionDeleted as i32,
553554
&collection.uuid,
554-
org_id,
555+
org_id.to_string(),
555556
headers.user.uuid.clone(),
556557
headers.device.atype,
557558
&headers.ip.ip,
558-
&mut conn,
559+
conn,
559560
)
560561
.await;
561-
collection.delete(&mut conn).await
562+
collection.delete(conn).await
562563
} else {
563564
err!("Collection and Organization id do not match")
564565
}
565566
}
566567
}
567568
}
568569

570+
#[delete("/organizations/<org_id>/collections/<col_id>")]
571+
async fn delete_organization_collection(
572+
org_id: String,
573+
col_id: String,
574+
headers: ManagerHeaders,
575+
mut conn: DbConn,
576+
) -> EmptyResult {
577+
_delete_organization_collection(&org_id, &col_id, &headers, &mut conn).await
578+
}
579+
569580
#[derive(Deserialize, Debug)]
570581
#[allow(non_snake_case, dead_code)]
571582
struct DeleteCollectionData {
@@ -579,9 +590,38 @@ async fn post_organization_collection_delete(
579590
col_id: String,
580591
headers: ManagerHeaders,
581592
_data: JsonUpcase<DeleteCollectionData>,
582-
conn: DbConn,
593+
mut conn: DbConn,
583594
) -> EmptyResult {
584-
delete_organization_collection(org_id, col_id, headers, conn).await
595+
_delete_organization_collection(&org_id, &col_id, &headers, &mut conn).await
596+
}
597+
598+
#[derive(Deserialize, Debug)]
599+
#[allow(non_snake_case)]
600+
struct BulkCollectionIds {
601+
Ids: Vec<String>,
602+
OrganizationId: String,
603+
}
604+
605+
#[delete("/organizations/<org_id>/collections", data = "<data>")]
606+
async fn bulk_delete_organization_collections(
607+
org_id: &str,
608+
headers: ManagerHeadersLoose,
609+
data: JsonUpcase<BulkCollectionIds>,
610+
mut conn: DbConn,
611+
) -> EmptyResult {
612+
let data: BulkCollectionIds = data.into_inner().data;
613+
if org_id != data.OrganizationId {
614+
err!("OrganizationId mismatch");
615+
}
616+
617+
let collections = data.Ids;
618+
619+
let headers = ManagerHeaders::from_loose(headers, &collections, &mut conn).await?;
620+
621+
for col_id in collections {
622+
_delete_organization_collection(org_id, &col_id, &headers, &mut conn).await?
623+
}
624+
Ok(())
585625
}
586626

587627
#[get("/organizations/<org_id>/collections/<coll_id>/details")]
@@ -2363,17 +2403,21 @@ async fn get_group_details(_org_id: String, group_id: String, _headers: AdminHea
23632403
}
23642404

23652405
#[post("/organizations/<org_id>/groups/<group_id>/delete")]
2366-
async fn post_delete_group(org_id: String, group_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult {
2367-
delete_group(org_id, group_id, headers, conn).await
2406+
async fn post_delete_group(org_id: String, group_id: String, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult {
2407+
_delete_group(org_id, group_id, &headers, &mut conn).await
23682408
}
23692409

23702410
#[delete("/organizations/<org_id>/groups/<group_id>")]
23712411
async fn delete_group(org_id: String, group_id: String, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult {
2412+
_delete_group(org_id, group_id, &headers, &mut conn).await
2413+
}
2414+
2415+
async fn _delete_group(org_id: String, group_id: String, headers: &AdminHeaders, conn: &mut DbConn) -> EmptyResult {
23722416
if !CONFIG.org_groups_enabled() {
23732417
err!("Group support is disabled");
23742418
}
23752419

2376-
let group = match Group::find_by_uuid(&group_id, &mut conn).await {
2420+
let group = match Group::find_by_uuid(&group_id, conn).await {
23772421
Some(group) => group,
23782422
_ => err!("Group not found"),
23792423
};
@@ -2385,11 +2429,30 @@ async fn delete_group(org_id: String, group_id: String, headers: AdminHeaders, m
23852429
headers.user.uuid.clone(),
23862430
headers.device.atype,
23872431
&headers.ip.ip,
2388-
&mut conn,
2432+
conn,
23892433
)
23902434
.await;
23912435

2392-
group.delete(&mut conn).await
2436+
group.delete(conn).await
2437+
}
2438+
2439+
#[delete("/organizations/<org_id>/groups", data = "<data>")]
2440+
async fn bulk_delete_groups(
2441+
org_id: String,
2442+
data: JsonUpcase<OrgBulkIds>,
2443+
headers: AdminHeaders,
2444+
mut conn: DbConn,
2445+
) -> EmptyResult {
2446+
if !CONFIG.org_groups_enabled() {
2447+
err!("Group support is disabled");
2448+
}
2449+
2450+
let data: OrgBulkIds = data.into_inner().data;
2451+
2452+
for group_id in data.Ids {
2453+
_delete_group(org_id.clone(), group_id, &headers, &mut conn).await?
2454+
}
2455+
Ok(())
23932456
}
23942457

23952458
#[get("/organizations/<_org_id>/groups/<group_id>")]

src/auth.rs

+32-8
Original file line numberDiff line numberDiff line change
@@ -598,14 +598,7 @@ impl<'r> FromRequest<'r> for ManagerHeaders {
598598
_ => err_handler!("Error getting DB"),
599599
};
600600

601-
if !headers.org_user.has_full_access()
602-
&& !Collection::has_access_by_collection_and_user_uuid(
603-
&col_id,
604-
&headers.org_user.user_uuid,
605-
&mut conn,
606-
)
607-
.await
608-
{
601+
if !can_access_collection(&headers.org_user, &col_id, &mut conn).await {
609602
err_handler!("The current user isn't a manager for this collection")
610603
}
611604
}
@@ -642,6 +635,7 @@ pub struct ManagerHeadersLoose {
642635
pub host: String,
643636
pub device: Device,
644637
pub user: User,
638+
pub org_user: UserOrganization,
645639
pub org_user_type: UserOrgType,
646640
pub ip: ClientIp,
647641
}
@@ -657,6 +651,7 @@ impl<'r> FromRequest<'r> for ManagerHeadersLoose {
657651
host: headers.host,
658652
device: headers.device,
659653
user: headers.user,
654+
org_user: headers.org_user,
660655
org_user_type: headers.org_user_type,
661656
ip: headers.ip,
662657
})
@@ -676,6 +671,35 @@ impl From<ManagerHeadersLoose> for Headers {
676671
}
677672
}
678673
}
674+
async fn can_access_collection(org_user: &UserOrganization, col_id: &str, conn: &mut DbConn) -> bool {
675+
org_user.has_full_access()
676+
|| Collection::has_access_by_collection_and_user_uuid(col_id, &org_user.user_uuid, conn).await
677+
}
678+
679+
impl ManagerHeaders {
680+
pub async fn from_loose(
681+
h: ManagerHeadersLoose,
682+
collections: &Vec<String>,
683+
conn: &mut DbConn,
684+
) -> Result<ManagerHeaders, Error> {
685+
for col_id in collections {
686+
if uuid::Uuid::parse_str(col_id).is_err() {
687+
err!("Collection Id is malformed!");
688+
}
689+
if !can_access_collection(&h.org_user, col_id, conn).await {
690+
err!("You don't have access to all collections!");
691+
}
692+
}
693+
694+
Ok(ManagerHeaders {
695+
host: h.host,
696+
device: h.device,
697+
user: h.user,
698+
org_user_type: h.org_user_type,
699+
ip: h.ip,
700+
})
701+
}
702+
}
679703

680704
pub struct OwnerHeaders {
681705
pub host: String,

0 commit comments

Comments
 (0)