docbox_core/document_box/
create_document_box.rs1use crate::events::{TenantEventMessage, TenantEventPublisher};
2use docbox_database::{
3 DbErr, DbPool, DbResult, DbTransaction,
4 models::{
5 document_box::{DocumentBox, DocumentBoxScopeRaw},
6 folder::{CreateFolder, Folder},
7 user::UserId,
8 },
9};
10use std::ops::DerefMut;
11use thiserror::Error;
12
13const ROOT_FOLDER_NAME: &str = "Root";
14
15#[derive(Debug, Error)]
16pub enum CreateDocumentBoxError {
17 #[error("document box with matching scope already exists")]
18 ScopeAlreadyExists,
19
20 #[error(transparent)]
22 Database(#[from] DbErr),
23}
24
25#[derive(Debug)]
26pub struct CreateDocumentBox {
27 pub scope: String,
28 pub created_by: Option<String>,
29}
30
31pub async fn create_document_box(
33 db: &DbPool,
34 events: &TenantEventPublisher,
35 create: CreateDocumentBox,
36) -> Result<(DocumentBox, Folder), CreateDocumentBoxError> {
37 let mut transaction = db.begin().await?;
39
40 let document_box: DocumentBox =
41 create_document_box_entry(&mut transaction, create.scope).await?;
42 let root = create_root_folder(
43 &mut transaction,
44 document_box.scope.clone(),
45 create.created_by,
46 )
47 .await?;
48
49 transaction.commit().await?;
50
51 events.publish_event(TenantEventMessage::DocumentBoxCreated(document_box.clone()));
53
54 Ok((document_box, root))
55}
56
57async fn create_document_box_entry(
59 db: &mut DbTransaction<'_>,
60 scope: DocumentBoxScopeRaw,
61) -> Result<DocumentBox, CreateDocumentBoxError> {
62 DocumentBox::create(db.deref_mut(), scope)
63 .await
64 .map_err(|cause| {
65 if let Some(db_err) = cause.as_database_error() {
66 if db_err.is_unique_violation() {
68 return CreateDocumentBoxError::ScopeAlreadyExists;
69 }
70 }
71
72 tracing::error!(?cause, "failed to create document box");
73 CreateDocumentBoxError::from(cause)
74 })
75}
76
77async fn create_root_folder(
80 db: &mut DbTransaction<'_>,
81 document_box: DocumentBoxScopeRaw,
82 created_by: Option<UserId>,
83) -> DbResult<Folder> {
84 Folder::create(
85 db.deref_mut(),
86 CreateFolder {
87 name: ROOT_FOLDER_NAME.to_string(),
88 document_box,
89 folder_id: None,
90 created_by,
91 },
92 )
93 .await
94 .inspect_err(|error| tracing::error!(?error, "failed to create document box root folder"))
95}