docbox_core/document_box/
delete_document_box.rs

1use crate::{
2    events::{TenantEventMessage, TenantEventPublisher},
3    folders::delete_folder::delete_folder,
4};
5use docbox_database::{
6    DbErr, DbPool,
7    models::{document_box::DocumentBox, folder::Folder},
8};
9use docbox_search::TenantSearchIndex;
10use docbox_storage::TenantStorageLayer;
11use thiserror::Error;
12
13#[derive(Debug, Error)]
14pub enum DeleteDocumentBoxError {
15    /// Database error occurred
16    #[error(transparent)]
17    Database(#[from] DbErr),
18
19    #[error("unknown document box scope")]
20    UnknownScope,
21
22    #[error(transparent)]
23    DeleteSearchData(anyhow::Error),
24
25    #[error("failed to delete root folder")]
26    FailedToDeleteRoot(anyhow::Error),
27}
28
29pub async fn delete_document_box(
30    db: &DbPool,
31    search: &TenantSearchIndex,
32    storage: &TenantStorageLayer,
33    events: &TenantEventPublisher,
34    scope: String,
35) -> Result<(), DeleteDocumentBoxError> {
36    let document_box = DocumentBox::find_by_scope(db, &scope)
37        .await?
38        .ok_or(DeleteDocumentBoxError::UnknownScope)?;
39
40    let root = Folder::find_root(db, &scope).await?;
41
42    if let Some(root) = root {
43        // Delete root folder
44        delete_folder(db, storage, search, events, root)
45            .await
46            .inspect_err(|error| tracing::error!(?error, "failed to delete bucket root folder"))
47            .map_err(DeleteDocumentBoxError::FailedToDeleteRoot)?;
48    }
49
50    // Delete document box
51    let result = document_box.delete(db).await?;
52
53    // Check we actually removed something before emitting an event
54    if result.rows_affected() < 1 {
55        return Ok(());
56    }
57
58    search
59        .delete_by_scope(scope)
60        .await
61        .map_err(DeleteDocumentBoxError::DeleteSearchData)?;
62
63    // Publish an event
64    events.publish_event(TenantEventMessage::DocumentBoxDeleted(document_box));
65
66    Ok(())
67}