1#![recursion_limit = "1024"]
18#![allow(unused_imports)]
19
20pub mod domain;
22pub mod infrastructure;
23pub mod application;
24pub mod presentation;
25pub mod seeders;
26pub mod exports;
27
28#[path = "lib.ext.rs"]
30mod lib_ext;
31pub use lib_ext::*;
32#[allow(dead_code)]
34pub(crate) type ThisModule = BucketModule;
35#[allow(dead_code)]
36pub(crate) type ThisModuleBuilder = BucketModuleBuilder;
37
38pub use domain::entity::*;
40
41pub use domain::state_machine::*;
43
44pub use domain::computed::{HasComputedFields, ComputedFieldValues};
46
47pub use domain::permission::{Action, FieldRestriction, PermissionChecker, PermissionError, PermissionResult};
49
50pub use infrastructure::persistence::*;
52
53pub use application::service::AccessLogService;
55pub use application::service::BucketService;
56pub use application::service::ContentHashService;
57pub use application::service::ConversionJobService;
58pub use application::service::FileCommentService;
59pub use application::service::FileLockService;
60pub use application::service::FileShareService;
61pub use application::service::FileVersionService;
62pub use application::service::ProcessingJobService;
63pub use application::service::StoredFileService;
64pub use application::service::ThumbnailService;
65pub use application::service::UploadSessionService;
66pub use application::service::UserQuotaService;
67
68pub use application::validator::{ValidationError, ValidationResult};
70
71pub use application::triggers::*;
73
74pub use application::workflows::*;
76
77use std::sync::Arc;
78use axum::Router;
79use sqlx::PgPool;
80
81pub struct BucketModule {
94 #[allow(dead_code)]
95 pub(crate) access_log_service: Arc<AccessLogService>,
96 pub(crate) bucket_service: Arc<BucketService>,
97 pub(crate) content_hash_service: Arc<ContentHashService>,
98 pub(crate) conversion_job_service: Arc<ConversionJobService>,
99 pub(crate) file_comment_service: Arc<FileCommentService>,
100 pub(crate) file_lock_service: Arc<FileLockService>,
101 pub(crate) file_share_service: Arc<FileShareService>,
102 #[allow(dead_code)]
103 pub(crate) file_version_service: Arc<FileVersionService>,
104 pub(crate) processing_job_service: Arc<ProcessingJobService>,
105 pub(crate) stored_file_service: Arc<StoredFileService>,
106 #[allow(dead_code)]
107 pub(crate) thumbnail_service: Arc<ThumbnailService>,
108 pub(crate) upload_session_service: Arc<UploadSessionService>,
109 pub(crate) user_quota_service: Arc<UserQuotaService>,
110 pub(crate) ext: ModuleExt,
112}
113
114impl std::ops::Deref for BucketModule {
115 type Target = ModuleExt;
116 fn deref(&self) -> &Self::Target {
117 &self.ext
118 }
119}
120
121impl std::ops::DerefMut for BucketModule {
122 fn deref_mut(&mut self) -> &mut Self::Target {
123 &mut self.ext
124 }
125}
126
127#[allow(dead_code)]
129pub(crate) struct ModuleParts<'a> {
130 pub(crate) db_pool: &'a PgPool,
131 pub(crate) access_log_service: &'a Arc<AccessLogService>,
132 pub(crate) access_log_repository: &'a Arc<AccessLogRepository>,
133 pub(crate) bucket_service: &'a Arc<BucketService>,
134 pub(crate) bucket_repository: &'a Arc<BucketRepository>,
135 pub(crate) content_hash_service: &'a Arc<ContentHashService>,
136 pub(crate) content_hash_repository: &'a Arc<ContentHashRepository>,
137 pub(crate) conversion_job_service: &'a Arc<ConversionJobService>,
138 pub(crate) conversion_job_repository: &'a Arc<ConversionJobRepository>,
139 pub(crate) file_comment_service: &'a Arc<FileCommentService>,
140 pub(crate) file_comment_repository: &'a Arc<FileCommentRepository>,
141 pub(crate) file_lock_service: &'a Arc<FileLockService>,
142 pub(crate) file_lock_repository: &'a Arc<FileLockRepository>,
143 pub(crate) file_share_service: &'a Arc<FileShareService>,
144 pub(crate) file_share_repository: &'a Arc<FileShareRepository>,
145 pub(crate) file_version_service: &'a Arc<FileVersionService>,
146 pub(crate) file_version_repository: &'a Arc<FileVersionRepository>,
147 pub(crate) processing_job_service: &'a Arc<ProcessingJobService>,
148 pub(crate) processing_job_repository: &'a Arc<ProcessingJobRepository>,
149 pub(crate) stored_file_service: &'a Arc<StoredFileService>,
150 pub(crate) stored_file_repository: &'a Arc<StoredFileRepository>,
151 pub(crate) thumbnail_service: &'a Arc<ThumbnailService>,
152 pub(crate) thumbnail_repository: &'a Arc<ThumbnailRepository>,
153 pub(crate) upload_session_service: &'a Arc<UploadSessionService>,
154 pub(crate) upload_session_repository: &'a Arc<UploadSessionRepository>,
155 pub(crate) user_quota_service: &'a Arc<UserQuotaService>,
156 pub(crate) user_quota_repository: &'a Arc<UserQuotaRepository>,
157}
158
159impl BucketModule {
160 pub fn builder() -> BucketModuleBuilder {
162 BucketModuleBuilder::new()
163 }
164
165 pub fn all_crud_routes(&self) -> Router {
171 use presentation::http::{
172 create_bucket_routes,
173 create_content_hash_routes,
174 create_conversion_job_routes,
175 create_file_comment_routes,
176 create_file_lock_routes,
177 create_file_share_routes,
178 create_processing_job_routes,
179 create_stored_file_routes,
180 create_upload_session_routes,
181 create_user_quota_routes,
182 };
183
184 Router::new()
185 .merge(create_bucket_routes(self.bucket_service.clone()))
186 .merge(create_content_hash_routes(self.content_hash_service.clone()))
187 .merge(create_conversion_job_routes(self.conversion_job_service.clone()))
188 .merge(create_file_comment_routes(self.file_comment_service.clone()))
189 .merge(create_file_lock_routes(self.file_lock_service.clone()))
190 .merge(create_file_share_routes(self.file_share_service.clone()))
191 .merge(create_processing_job_routes(self.processing_job_service.clone()))
192 .merge(create_stored_file_routes(self.stored_file_service.clone()))
193 .merge(create_upload_session_routes(self.upload_session_service.clone()))
194 .merge(create_user_quota_routes(self.user_quota_service.clone()))
195 }
196
197 #[deprecated(note = "mounts unvalidated generic CRUD; prefer readonly_routes() + validated writes, or all_crud_routes() for the full/unguarded surface")]
203 pub fn routes(&self) -> Router {
204 self.all_crud_routes()
205 }
206
207 pub fn readonly_routes(&self) -> Router {
213 use presentation::http::{
214 create_bucket_read_routes,
215 create_content_hash_read_routes,
216 create_conversion_job_read_routes,
217 create_file_comment_read_routes,
218 create_file_lock_read_routes,
219 create_file_share_read_routes,
220 create_processing_job_read_routes,
221 create_stored_file_read_routes,
222 create_upload_session_read_routes,
223 create_user_quota_read_routes,
224 };
225
226 Router::new()
227 .merge(create_bucket_read_routes(self.bucket_service.clone()))
228 .merge(create_content_hash_read_routes(self.content_hash_service.clone()))
229 .merge(create_conversion_job_read_routes(self.conversion_job_service.clone()))
230 .merge(create_file_comment_read_routes(self.file_comment_service.clone()))
231 .merge(create_file_lock_read_routes(self.file_lock_service.clone()))
232 .merge(create_file_share_read_routes(self.file_share_service.clone()))
233 .merge(create_processing_job_read_routes(self.processing_job_service.clone()))
234 .merge(create_stored_file_read_routes(self.stored_file_service.clone()))
235 .merge(create_upload_session_read_routes(self.upload_session_service.clone()))
236 .merge(create_user_quota_read_routes(self.user_quota_service.clone()))
237 }
238
239}
240
241pub struct BucketModuleBuilder {
243 db_pool: Option<PgPool>,
244 ext: ModuleBuilderExt,
246}
247
248impl std::ops::Deref for BucketModuleBuilder {
249 type Target = ModuleBuilderExt;
250 fn deref(&self) -> &Self::Target {
251 &self.ext
252 }
253}
254
255impl std::ops::DerefMut for BucketModuleBuilder {
256 fn deref_mut(&mut self) -> &mut Self::Target {
257 &mut self.ext
258 }
259}
260
261impl BucketModuleBuilder {
262 pub fn new() -> Self {
264 Self {
265 db_pool: None,
266 ext: Default::default(),
267 }
268 }
269
270 pub fn with_database(mut self, pool: PgPool) -> Self {
272 self.db_pool = Some(pool);
273 self
274 }
275
276
277 pub fn build(self) -> anyhow::Result<BucketModule> {
279 let db_pool = self.db_pool
280 .ok_or_else(|| anyhow::anyhow!("Database pool not configured"))?;
281
282 let access_log_repository = Arc::new(AccessLogRepository::new(db_pool.clone()));
284 let access_log_service = Arc::new(AccessLogService::with_repository(access_log_repository.clone()));
285
286 let bucket_repository = Arc::new(BucketRepository::new(db_pool.clone()));
288 let bucket_service = Arc::new(BucketService::with_repository(bucket_repository.clone()).with_guard(Arc::new(crate::application::service::BucketRowRules)));
289
290 let content_hash_repository = Arc::new(ContentHashRepository::new(db_pool.clone()));
292 let content_hash_service = Arc::new(ContentHashService::with_repository(content_hash_repository.clone()));
293
294 let conversion_job_repository = Arc::new(ConversionJobRepository::new(db_pool.clone()));
296 let conversion_job_service = Arc::new(ConversionJobService::with_repository(conversion_job_repository.clone()).with_guard(Arc::new(crate::application::service::ConversionJobRowRules)));
297
298 let file_comment_repository = Arc::new(FileCommentRepository::new(db_pool.clone()));
300 let file_comment_service = Arc::new(FileCommentService::with_repository(file_comment_repository.clone()).with_guard(Arc::new(crate::application::service::FileCommentRowRules)));
301
302 let file_lock_repository = Arc::new(FileLockRepository::new(db_pool.clone()));
304 let file_lock_service = Arc::new(FileLockService::with_repository(file_lock_repository.clone()).with_guard(Arc::new(crate::application::service::FileLockRowRules)));
305
306 let file_share_repository = Arc::new(FileShareRepository::new(db_pool.clone()));
308 let file_share_service = Arc::new(FileShareService::with_repository(file_share_repository.clone()).with_guard(Arc::new(crate::application::service::FileShareRowRules)));
309
310 let file_version_repository = Arc::new(FileVersionRepository::new(db_pool.clone()));
312 let file_version_service = Arc::new(FileVersionService::with_repository(file_version_repository.clone()));
313
314 let processing_job_repository = Arc::new(ProcessingJobRepository::new(db_pool.clone()));
316 let processing_job_service = Arc::new(ProcessingJobService::with_repository(processing_job_repository.clone()).with_guard(Arc::new(crate::application::service::ProcessingJobRowRules)));
317
318 let stored_file_repository = Arc::new(StoredFileRepository::new(db_pool.clone()));
320 let stored_file_service = Arc::new(StoredFileService::with_repository(stored_file_repository.clone()).with_guard(Arc::new(crate::application::service::StoredFileRowRules)));
321
322 let thumbnail_repository = Arc::new(ThumbnailRepository::new(db_pool.clone()));
324 let thumbnail_service = Arc::new(ThumbnailService::with_repository(thumbnail_repository.clone()));
325
326 let upload_session_repository = Arc::new(UploadSessionRepository::new(db_pool.clone()));
328 let upload_session_service = Arc::new(UploadSessionService::with_repository(upload_session_repository.clone()).with_guard(Arc::new(crate::application::service::UploadSessionRowRules)));
329
330 let user_quota_repository = Arc::new(UserQuotaRepository::new(db_pool.clone()));
332 let user_quota_service = Arc::new(UserQuotaService::with_repository(user_quota_repository.clone()).with_guard(Arc::new(crate::application::service::UserQuotaRowRules)));
333
334
335 let ext = self.ext.build(&ModuleParts {
337 db_pool: &db_pool,
338 access_log_service: &access_log_service,
339 access_log_repository: &access_log_repository,
340 bucket_service: &bucket_service,
341 bucket_repository: &bucket_repository,
342 content_hash_service: &content_hash_service,
343 content_hash_repository: &content_hash_repository,
344 conversion_job_service: &conversion_job_service,
345 conversion_job_repository: &conversion_job_repository,
346 file_comment_service: &file_comment_service,
347 file_comment_repository: &file_comment_repository,
348 file_lock_service: &file_lock_service,
349 file_lock_repository: &file_lock_repository,
350 file_share_service: &file_share_service,
351 file_share_repository: &file_share_repository,
352 file_version_service: &file_version_service,
353 file_version_repository: &file_version_repository,
354 processing_job_service: &processing_job_service,
355 processing_job_repository: &processing_job_repository,
356 stored_file_service: &stored_file_service,
357 stored_file_repository: &stored_file_repository,
358 thumbnail_service: &thumbnail_service,
359 thumbnail_repository: &thumbnail_repository,
360 upload_session_service: &upload_session_service,
361 upload_session_repository: &upload_session_repository,
362 user_quota_service: &user_quota_service,
363 user_quota_repository: &user_quota_repository,
364 })?;
365
366 Ok(BucketModule {
367 access_log_service,
368 bucket_service,
369 content_hash_service,
370 conversion_job_service,
371 file_comment_service,
372 file_lock_service,
373 file_share_service,
374 file_version_service,
375 processing_job_service,
376 stored_file_service,
377 thumbnail_service,
378 upload_session_service,
379 user_quota_service,
380 ext,
381 })
382 }
383}
384
385impl Default for BucketModuleBuilder {
386 fn default() -> Self {
387 Self::new()
388 }
389}
390
391include!("mod.ext.rs");