style: apply cargo fmt to entire codebase
Standardize code formatting across all 173 Rust source files using rustfmt. No functional changes - purely cosmetic. This establishes a consistent code style baseline for the project going forward.
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
use async_trait::async_trait;
|
||||
use crate::domain::entities::user::User;
|
||||
use crate::domain::entities::session::Session;
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::domain::entities::session::Session;
|
||||
use crate::domain::entities::user::User;
|
||||
use async_trait::async_trait;
|
||||
|
||||
// ============================================================================
|
||||
// Cryptography Ports - Extracted from Domain to maintain Clean Architecture
|
||||
// ============================================================================
|
||||
|
||||
/// Port for password hashing operations.
|
||||
///
|
||||
///
|
||||
/// This trait abstracts cryptographic password operations, allowing the domain
|
||||
/// layer to remain independent of specific hashing implementations (argon2, bcrypt, etc.)
|
||||
pub trait PasswordHasherPort: Send + Sync + 'static {
|
||||
/// Hash a plain text password
|
||||
fn hash_password(&self, password: &str) -> Result<String, DomainError>;
|
||||
|
||||
|
||||
/// Verify a plain text password against a hash
|
||||
fn verify_password(&self, password: &str, hash: &str) -> Result<bool, DomainError>;
|
||||
}
|
||||
@@ -39,22 +39,22 @@ pub struct TokenClaims {
|
||||
}
|
||||
|
||||
/// Port for JWT token operations.
|
||||
///
|
||||
///
|
||||
/// This trait abstracts token generation and validation, allowing the domain
|
||||
/// layer to remain independent of specific JWT implementations.
|
||||
pub trait TokenServicePort: Send + Sync + 'static {
|
||||
/// Generate an access token for a user
|
||||
fn generate_access_token(&self, user: &User) -> Result<String, DomainError>;
|
||||
|
||||
|
||||
/// Validate a token and extract its claims
|
||||
fn validate_token(&self, token: &str) -> Result<TokenClaims, DomainError>;
|
||||
|
||||
|
||||
/// Generate a refresh token
|
||||
fn generate_refresh_token(&self) -> String;
|
||||
|
||||
|
||||
/// Get refresh token expiry in seconds
|
||||
fn refresh_token_expiry_secs(&self) -> i64;
|
||||
|
||||
|
||||
/// Get refresh token expiry in days
|
||||
fn refresh_token_expiry_days(&self) -> i64;
|
||||
}
|
||||
@@ -65,38 +65,46 @@ pub trait TokenServicePort: Send + Sync + 'static {
|
||||
|
||||
#[async_trait]
|
||||
pub trait UserStoragePort: Send + Sync + 'static {
|
||||
/// Creates a new user
|
||||
/// Creates a new user
|
||||
async fn create_user(&self, user: User) -> Result<User, DomainError>;
|
||||
|
||||
|
||||
/// Gets a user by ID
|
||||
async fn get_user_by_id(&self, id: &str) -> Result<User, DomainError>;
|
||||
|
||||
|
||||
/// Gets a user by username
|
||||
async fn get_user_by_username(&self, username: &str) -> Result<User, DomainError>;
|
||||
|
||||
|
||||
/// Gets a user by email
|
||||
async fn get_user_by_email(&self, email: &str) -> Result<User, DomainError>;
|
||||
|
||||
|
||||
/// Updates an existing user
|
||||
async fn update_user(&self, user: User) -> Result<User, DomainError>;
|
||||
|
||||
|
||||
/// Updates only the storage usage of a user
|
||||
async fn update_storage_usage(&self, user_id: &str, usage_bytes: i64) -> Result<(), DomainError>;
|
||||
|
||||
async fn update_storage_usage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
usage_bytes: i64,
|
||||
) -> Result<(), DomainError>;
|
||||
|
||||
/// Lists users with pagination
|
||||
async fn list_users(&self, limit: i64, offset: i64) -> Result<Vec<User>, DomainError>;
|
||||
|
||||
|
||||
/// Lists users by role (e.g., "admin" or "user")
|
||||
async fn list_users_by_role(&self, role: &str) -> Result<Vec<User>, DomainError>;
|
||||
|
||||
|
||||
/// Deletes a user by their ID
|
||||
async fn delete_user(&self, user_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
|
||||
/// Changes a user's password
|
||||
async fn change_password(&self, user_id: &str, password_hash: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Finds a user by OIDC provider + subject pair
|
||||
async fn get_user_by_oidc_subject(&self, provider: &str, subject: &str) -> Result<User, DomainError>;
|
||||
async fn get_user_by_oidc_subject(
|
||||
&self,
|
||||
provider: &str,
|
||||
subject: &str,
|
||||
) -> Result<User, DomainError>;
|
||||
|
||||
/// Activates or deactivates a user
|
||||
async fn set_user_active_status(&self, user_id: &str, active: bool) -> Result<(), DomainError>;
|
||||
@@ -105,7 +113,11 @@ pub trait UserStoragePort: Send + Sync + 'static {
|
||||
async fn change_role(&self, user_id: &str, role: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Updates a user's storage quota
|
||||
async fn update_storage_quota(&self, user_id: &str, quota_bytes: i64) -> Result<(), DomainError>;
|
||||
async fn update_storage_quota(
|
||||
&self,
|
||||
user_id: &str,
|
||||
quota_bytes: i64,
|
||||
) -> Result<(), DomainError>;
|
||||
|
||||
/// Counts the total number of users
|
||||
async fn count_users(&self) -> Result<i64, DomainError>;
|
||||
@@ -139,14 +151,27 @@ pub trait OidcServicePort: Send + Sync + 'static {
|
||||
/// Get the authorization URL for redirecting the user to the IdP.
|
||||
/// Includes PKCE code_challenge (S256) and nonce for ID token binding.
|
||||
/// This is async because it may need to fetch the OIDC discovery document.
|
||||
async fn get_authorize_url(&self, state: &str, nonce: &str, pkce_challenge: &str) -> Result<String, DomainError>;
|
||||
async fn get_authorize_url(
|
||||
&self,
|
||||
state: &str,
|
||||
nonce: &str,
|
||||
pkce_challenge: &str,
|
||||
) -> Result<String, DomainError>;
|
||||
|
||||
/// Exchange an authorization code for tokens, providing PKCE code_verifier.
|
||||
async fn exchange_code(&self, code: &str, pkce_verifier: &str) -> Result<OidcTokenSet, DomainError>;
|
||||
async fn exchange_code(
|
||||
&self,
|
||||
code: &str,
|
||||
pkce_verifier: &str,
|
||||
) -> Result<OidcTokenSet, DomainError>;
|
||||
|
||||
/// Validate an ID token and extract claims.
|
||||
/// If `expected_nonce` is provided, verifies the `nonce` claim matches.
|
||||
async fn validate_id_token(&self, id_token: &str, expected_nonce: Option<&str>) -> Result<OidcIdClaims, DomainError>;
|
||||
async fn validate_id_token(
|
||||
&self,
|
||||
id_token: &str,
|
||||
expected_nonce: Option<&str>,
|
||||
) -> Result<OidcIdClaims, DomainError>;
|
||||
|
||||
/// Fetch user info from the UserInfo endpoint (fallback for missing ID token claims)
|
||||
async fn fetch_user_info(&self, access_token: &str) -> Result<OidcIdClaims, DomainError>;
|
||||
@@ -159,13 +184,16 @@ pub trait OidcServicePort: Send + Sync + 'static {
|
||||
pub trait SessionStoragePort: Send + Sync + 'static {
|
||||
/// Creates a new session
|
||||
async fn create_session(&self, session: Session) -> Result<Session, DomainError>;
|
||||
|
||||
|
||||
/// Gets a session by refresh token
|
||||
async fn get_session_by_refresh_token(&self, refresh_token: &str) -> Result<Session, DomainError>;
|
||||
|
||||
async fn get_session_by_refresh_token(
|
||||
&self,
|
||||
refresh_token: &str,
|
||||
) -> Result<Session, DomainError>;
|
||||
|
||||
/// Revokes a specific session
|
||||
async fn revoke_session(&self, session_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
|
||||
/// Revokes all sessions of a user
|
||||
async fn revoke_all_user_sessions(&self, user_id: &str) -> Result<u64, DomainError>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
//! The application and interface layers remain independent of the caching
|
||||
//! implementation details.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use crate::common::errors::DomainError;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Statistics for monitoring write-behind cache status.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
@@ -1,47 +1,108 @@
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use crate::application::dtos::calendar_dto::{
|
||||
CalendarDto, CalendarEventDto, CreateCalendarDto, UpdateCalendarDto,
|
||||
CreateEventDto, UpdateEventDto, CreateEventICalDto
|
||||
CalendarDto, CalendarEventDto, CreateCalendarDto, CreateEventDto, CreateEventICalDto,
|
||||
UpdateCalendarDto, UpdateEventDto,
|
||||
};
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
/// Port for external calendar storage mechanisms
|
||||
#[async_trait]
|
||||
pub trait CalendarStoragePort: Send + Sync + 'static {
|
||||
// Calendar operations
|
||||
async fn create_calendar(&self, calendar: CreateCalendarDto, owner_id: &str) -> Result<CalendarDto, DomainError>;
|
||||
async fn update_calendar(&self, calendar_id: &str, update: UpdateCalendarDto) -> Result<CalendarDto, DomainError>;
|
||||
async fn create_calendar(
|
||||
&self,
|
||||
calendar: CreateCalendarDto,
|
||||
owner_id: &str,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn update_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
update: UpdateCalendarDto,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn delete_calendar(&self, calendar_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_calendar(&self, calendar_id: &str) -> Result<CalendarDto, DomainError>;
|
||||
async fn list_calendars_by_owner(&self, owner_id: &str) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_calendars_shared_with_user(&self, user_id: &str) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_public_calendars(&self, limit: i64, offset: i64) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn check_calendar_access(&self, calendar_id: &str, user_id: &str) -> Result<bool, DomainError>;
|
||||
|
||||
async fn list_calendars_by_owner(
|
||||
&self,
|
||||
owner_id: &str,
|
||||
) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_calendars_shared_with_user(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_public_calendars(
|
||||
&self,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn check_calendar_access(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<bool, DomainError>;
|
||||
|
||||
// Calendar sharing
|
||||
async fn share_calendar(&self, calendar_id: &str, user_id: &str, access_level: &str) -> Result<(), DomainError>;
|
||||
async fn remove_calendar_sharing(&self, calendar_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_calendar_shares(&self, calendar_id: &str) -> Result<Vec<(String, String)>, DomainError>;
|
||||
|
||||
async fn share_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
access_level: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn remove_calendar_sharing(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_calendar_shares(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
) -> Result<Vec<(String, String)>, DomainError>;
|
||||
|
||||
// Calendar properties
|
||||
async fn set_calendar_property(&self, calendar_id: &str, property_name: &str, property_value: &str) -> Result<(), DomainError>;
|
||||
async fn get_calendar_property(&self, calendar_id: &str, property_name: &str) -> Result<Option<String>, DomainError>;
|
||||
async fn get_calendar_properties(&self, calendar_id: &str) -> Result<std::collections::HashMap<String, String>, DomainError>;
|
||||
|
||||
async fn set_calendar_property(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
property_name: &str,
|
||||
property_value: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_calendar_property(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
property_name: &str,
|
||||
) -> Result<Option<String>, DomainError>;
|
||||
async fn get_calendar_properties(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
) -> Result<std::collections::HashMap<String, String>, DomainError>;
|
||||
|
||||
// Event operations
|
||||
async fn create_event(&self, event: CreateEventDto) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn create_event_from_ical(&self, event: CreateEventICalDto) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn update_event(&self, event_id: &str, update: UpdateEventDto) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn create_event_from_ical(
|
||||
&self,
|
||||
event: CreateEventICalDto,
|
||||
) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn update_event(
|
||||
&self,
|
||||
event_id: &str,
|
||||
update: UpdateEventDto,
|
||||
) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn delete_event(&self, event_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_event(&self, event_id: &str) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn list_events_by_calendar(&self, calendar_id: &str) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn list_events_by_calendar_paginated(&self, calendar_id: &str, limit: i64, offset: i64) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn list_events_by_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn list_events_by_calendar_paginated(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn get_events_in_time_range(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
start: &DateTime<Utc>,
|
||||
end: &DateTime<Utc>
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
start: &DateTime<Utc>,
|
||||
end: &DateTime<Utc>,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
}
|
||||
|
||||
@@ -49,41 +110,113 @@ pub trait CalendarStoragePort: Send + Sync + 'static {
|
||||
#[async_trait]
|
||||
pub trait CalendarUseCase: Send + Sync + 'static {
|
||||
// Calendar operations
|
||||
async fn create_calendar(&self, calendar: CreateCalendarDto) -> Result<CalendarDto, DomainError>;
|
||||
async fn update_calendar(&self, calendar_id: &str, update: UpdateCalendarDto) -> Result<CalendarDto, DomainError>;
|
||||
async fn create_calendar(
|
||||
&self,
|
||||
calendar: CreateCalendarDto,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn update_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
update: UpdateCalendarDto,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn delete_calendar(&self, calendar_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_calendar(&self, calendar_id: &str) -> Result<CalendarDto, DomainError>;
|
||||
async fn list_my_calendars(&self) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_shared_calendars(&self) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_public_calendars(&self, limit: Option<i64>, offset: Option<i64>) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
|
||||
async fn list_public_calendars(
|
||||
&self,
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
|
||||
// Calendar sharing
|
||||
async fn share_calendar(&self, calendar_id: &str, user_id: &str, access_level: &str) -> Result<(), DomainError>;
|
||||
async fn remove_calendar_sharing(&self, calendar_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_calendar_shares(&self, calendar_id: &str) -> Result<Vec<(String, String)>, DomainError>;
|
||||
|
||||
async fn share_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
access_level: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn remove_calendar_sharing(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_calendar_shares(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
) -> Result<Vec<(String, String)>, DomainError>;
|
||||
|
||||
// Event operations
|
||||
async fn create_event(&self, event: CreateEventDto) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn create_event_from_ical(&self, event: CreateEventICalDto) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn update_event(&self, event_id: &str, update: UpdateEventDto) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn create_event_from_ical(
|
||||
&self,
|
||||
event: CreateEventICalDto,
|
||||
) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn update_event(
|
||||
&self,
|
||||
event_id: &str,
|
||||
update: UpdateEventDto,
|
||||
) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn delete_event(&self, event_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_event(&self, event_id: &str) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn list_events(&self, calendar_id: &str, limit: Option<i64>, offset: Option<i64>) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn get_events_in_range(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
start: DateTime<Utc>,
|
||||
end: DateTime<Utc>
|
||||
async fn list_events(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
|
||||
async fn get_events_in_range(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
start: DateTime<Utc>,
|
||||
end: DateTime<Utc>,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
|
||||
// ─── User-contextualized variants (for CalDAV protocol handler) ──
|
||||
async fn create_calendar_for_user(&self, calendar: CreateCalendarDto, user_id: &str) -> Result<CalendarDto, DomainError>;
|
||||
async fn update_calendar_for_user(&self, calendar_id: &str, update: UpdateCalendarDto, user_id: &str) -> Result<CalendarDto, DomainError>;
|
||||
async fn delete_calendar_for_user(&self, calendar_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_calendar_for_user(&self, calendar_id: &str, user_id: &str) -> Result<CalendarDto, DomainError>;
|
||||
async fn list_my_calendars_for_user(&self, user_id: &str) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_events_for_user(&self, calendar_id: &str, limit: Option<i64>, offset: Option<i64>, user_id: &str) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn get_events_in_range_for_user(&self, calendar_id: &str, start: DateTime<Utc>, end: DateTime<Utc>, user_id: &str) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn create_event_from_ical_for_user(&self, event: CreateEventICalDto, user_id: &str) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn delete_event_for_user(&self, event_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
}
|
||||
async fn create_calendar_for_user(
|
||||
&self,
|
||||
calendar: CreateCalendarDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn update_calendar_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
update: UpdateCalendarDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn delete_calendar_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_calendar_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError>;
|
||||
async fn list_my_calendars_for_user(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarDto>, DomainError>;
|
||||
async fn list_events_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn get_events_in_range_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
start: DateTime<Utc>,
|
||||
end: DateTime<Utc>,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError>;
|
||||
async fn create_event_from_ical_for_user(
|
||||
&self,
|
||||
event: CreateEventICalDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarEventDto, DomainError>;
|
||||
async fn delete_event_for_user(&self, event_id: &str, user_id: &str)
|
||||
-> Result<(), DomainError>;
|
||||
}
|
||||
|
||||
@@ -1,57 +1,143 @@
|
||||
use async_trait::async_trait;
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::application::dtos::address_book_dto::{
|
||||
AddressBookDto, CreateAddressBookDto, UpdateAddressBookDto,
|
||||
ShareAddressBookDto, UnshareAddressBookDto
|
||||
AddressBookDto, CreateAddressBookDto, ShareAddressBookDto, UnshareAddressBookDto,
|
||||
UpdateAddressBookDto,
|
||||
};
|
||||
use crate::application::dtos::contact_dto::{
|
||||
ContactDto, CreateContactDto, UpdateContactDto, CreateContactVCardDto,
|
||||
ContactGroupDto, CreateContactGroupDto, UpdateContactGroupDto, GroupMembershipDto
|
||||
ContactDto, ContactGroupDto, CreateContactDto, CreateContactGroupDto, CreateContactVCardDto,
|
||||
GroupMembershipDto, UpdateContactDto, UpdateContactGroupDto,
|
||||
};
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
|
||||
pub type CardDavRepositoryError = DomainError;
|
||||
|
||||
#[async_trait]
|
||||
pub trait AddressBookUseCase: Send + Sync + 'static {
|
||||
// Address Book operations
|
||||
async fn create_address_book(&self, dto: CreateAddressBookDto) -> Result<AddressBookDto, DomainError>;
|
||||
async fn update_address_book(&self, address_book_id: &str, update: UpdateAddressBookDto) -> Result<AddressBookDto, DomainError>;
|
||||
async fn delete_address_book(&self, address_book_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_address_book(&self, address_book_id: &str, user_id: &str) -> Result<AddressBookDto, DomainError>;
|
||||
async fn list_user_address_books(&self, user_id: &str) -> Result<Vec<AddressBookDto>, DomainError>;
|
||||
async fn create_address_book(
|
||||
&self,
|
||||
dto: CreateAddressBookDto,
|
||||
) -> Result<AddressBookDto, DomainError>;
|
||||
async fn update_address_book(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
update: UpdateAddressBookDto,
|
||||
) -> Result<AddressBookDto, DomainError>;
|
||||
async fn delete_address_book(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_address_book(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<AddressBookDto, DomainError>;
|
||||
async fn list_user_address_books(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<AddressBookDto>, DomainError>;
|
||||
async fn list_public_address_books(&self) -> Result<Vec<AddressBookDto>, DomainError>;
|
||||
|
||||
|
||||
// Address Book sharing
|
||||
async fn share_address_book(&self, dto: ShareAddressBookDto, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn unshare_address_book(&self, dto: UnshareAddressBookDto, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_address_book_shares(&self, address_book_id: &str, user_id: &str) -> Result<Vec<(String, bool)>, DomainError>;
|
||||
async fn share_address_book(
|
||||
&self,
|
||||
dto: ShareAddressBookDto,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn unshare_address_book(
|
||||
&self,
|
||||
dto: UnshareAddressBookDto,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn get_address_book_shares(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<(String, bool)>, DomainError>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait ContactUseCase: Send + Sync + 'static {
|
||||
// Contact operations
|
||||
async fn create_contact(&self, dto: CreateContactDto) -> Result<ContactDto, DomainError>;
|
||||
async fn create_contact_from_vcard(&self, dto: CreateContactVCardDto) -> Result<ContactDto, DomainError>;
|
||||
async fn update_contact(&self, contact_id: &str, update: UpdateContactDto) -> Result<ContactDto, DomainError>;
|
||||
async fn create_contact_from_vcard(
|
||||
&self,
|
||||
dto: CreateContactVCardDto,
|
||||
) -> Result<ContactDto, DomainError>;
|
||||
async fn update_contact(
|
||||
&self,
|
||||
contact_id: &str,
|
||||
update: UpdateContactDto,
|
||||
) -> Result<ContactDto, DomainError>;
|
||||
async fn delete_contact(&self, contact_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_contact(&self, contact_id: &str, user_id: &str) -> Result<ContactDto, DomainError>;
|
||||
async fn list_contacts(&self, address_book_id: &str, user_id: &str) -> Result<Vec<ContactDto>, DomainError>;
|
||||
async fn search_contacts(&self, address_book_id: &str, query: &str, user_id: &str) -> Result<Vec<ContactDto>, DomainError>;
|
||||
|
||||
async fn get_contact(&self, contact_id: &str, user_id: &str)
|
||||
-> Result<ContactDto, DomainError>;
|
||||
async fn list_contacts(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<ContactDto>, DomainError>;
|
||||
async fn search_contacts(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
query: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<ContactDto>, DomainError>;
|
||||
|
||||
// Contact Group operations
|
||||
async fn create_group(&self, dto: CreateContactGroupDto) -> Result<ContactGroupDto, DomainError>;
|
||||
async fn update_group(&self, group_id: &str, update: UpdateContactGroupDto) -> Result<ContactGroupDto, DomainError>;
|
||||
async fn create_group(
|
||||
&self,
|
||||
dto: CreateContactGroupDto,
|
||||
) -> Result<ContactGroupDto, DomainError>;
|
||||
async fn update_group(
|
||||
&self,
|
||||
group_id: &str,
|
||||
update: UpdateContactGroupDto,
|
||||
) -> Result<ContactGroupDto, DomainError>;
|
||||
async fn delete_group(&self, group_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn get_group(&self, group_id: &str, user_id: &str) -> Result<ContactGroupDto, DomainError>;
|
||||
async fn list_groups(&self, address_book_id: &str, user_id: &str) -> Result<Vec<ContactGroupDto>, DomainError>;
|
||||
|
||||
async fn get_group(
|
||||
&self,
|
||||
group_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<ContactGroupDto, DomainError>;
|
||||
async fn list_groups(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<ContactGroupDto>, DomainError>;
|
||||
|
||||
// Group membership
|
||||
async fn add_contact_to_group(&self, dto: GroupMembershipDto, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn remove_contact_from_group(&self, dto: GroupMembershipDto, user_id: &str) -> Result<(), DomainError>;
|
||||
async fn list_contacts_in_group(&self, group_id: &str, user_id: &str) -> Result<Vec<ContactDto>, DomainError>;
|
||||
async fn list_groups_for_contact(&self, contact_id: &str, user_id: &str) -> Result<Vec<ContactGroupDto>, DomainError>;
|
||||
|
||||
async fn add_contact_to_group(
|
||||
&self,
|
||||
dto: GroupMembershipDto,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn remove_contact_from_group(
|
||||
&self,
|
||||
dto: GroupMembershipDto,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn list_contacts_in_group(
|
||||
&self,
|
||||
group_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<ContactDto>, DomainError>;
|
||||
async fn list_groups_for_contact(
|
||||
&self,
|
||||
contact_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<ContactGroupDto>, DomainError>;
|
||||
|
||||
// vCard operations
|
||||
async fn get_contact_vcard(&self, contact_id: &str, user_id: &str) -> Result<String, DomainError>;
|
||||
async fn get_contacts_as_vcards(&self, address_book_id: &str, user_id: &str) -> Result<Vec<(String, String)>, DomainError>;
|
||||
}
|
||||
async fn get_contact_vcard(
|
||||
&self,
|
||||
contact_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<String, DomainError>;
|
||||
async fn get_contacts_as_vcards(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<(String, String)>, DomainError>;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
//! operations, keeping the application and interface layers independent of
|
||||
//! the specific upload implementation (TUS-like protocol, S3 multipart, etc.).
|
||||
|
||||
use std::path::PathBuf;
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use serde::Serialize;
|
||||
use crate::common::errors::DomainError;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Default chunk size (5 MB) — optimised for parallel transfers.
|
||||
pub const DEFAULT_CHUNK_SIZE: usize = 5 * 1024 * 1024;
|
||||
@@ -80,10 +80,7 @@ pub trait ChunkedUploadPort: Send + Sync + 'static {
|
||||
) -> Result<ChunkUploadResponseDto, DomainError>;
|
||||
|
||||
/// Get the current status of an upload session.
|
||||
async fn get_status(
|
||||
&self,
|
||||
upload_id: &str,
|
||||
) -> Result<UploadStatusResponseDto, DomainError>;
|
||||
async fn get_status(&self, upload_id: &str) -> Result<UploadStatusResponseDto, DomainError>;
|
||||
|
||||
/// Assemble all chunks into the final file.
|
||||
///
|
||||
@@ -94,16 +91,10 @@ pub trait ChunkedUploadPort: Send + Sync + 'static {
|
||||
) -> Result<(PathBuf, String, Option<String>, String, u64), DomainError>;
|
||||
|
||||
/// Finalize upload: clean up the session and temporary files.
|
||||
async fn finalize_upload(
|
||||
&self,
|
||||
upload_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn finalize_upload(&self, upload_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Cancel an upload and clean up all temporary data.
|
||||
async fn cancel_upload(
|
||||
&self,
|
||||
upload_id: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
async fn cancel_upload(&self, upload_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Check if a file size qualifies for chunked upload.
|
||||
fn should_use_chunked(&self, size: u64) -> bool;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
//! keeping the application and interface layers independent of specific
|
||||
//! compression implementations (gzip, zstd, etc.).
|
||||
|
||||
use async_trait::async_trait;
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
|
||||
/// Compression level settings for file compression operations.
|
||||
///
|
||||
@@ -30,7 +30,11 @@ pub enum CompressionLevel {
|
||||
#[async_trait]
|
||||
pub trait CompressionPort: Send + Sync + 'static {
|
||||
/// Compress data in memory.
|
||||
async fn compress_data(&self, data: &[u8], level: CompressionLevel) -> Result<Vec<u8>, DomainError>;
|
||||
async fn compress_data(
|
||||
&self,
|
||||
data: &[u8],
|
||||
level: CompressionLevel,
|
||||
) -> Result<Vec<u8>, DomainError>;
|
||||
|
||||
/// Decompress data in memory.
|
||||
async fn decompress_data(&self, compressed_data: &[u8]) -> Result<Vec<u8>, DomainError>;
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
//! keeping the application and interface layers independent of the specific
|
||||
//! content-addressable storage implementation.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use serde::Serialize;
|
||||
use crate::common::errors::DomainError;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Metadata of a stored blob in the dedup system.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
use async_trait::async_trait;
|
||||
use crate::common::errors::Result;
|
||||
use crate::application::dtos::favorites_dto::FavoriteItemDto;
|
||||
use crate::common::errors::Result;
|
||||
use async_trait::async_trait;
|
||||
|
||||
/// Defines operations for managing user favorites
|
||||
#[async_trait]
|
||||
pub trait FavoritesUseCase: Send + Sync {
|
||||
/// Get all favorites for a user
|
||||
async fn get_favorites(&self, user_id: &str) -> Result<Vec<FavoriteItemDto>>;
|
||||
|
||||
|
||||
/// Add an item to user's favorites
|
||||
async fn add_to_favorites(&self, user_id: &str, item_id: &str, item_type: &str) -> Result<()>;
|
||||
|
||||
|
||||
/// Remove an item from user's favorites
|
||||
async fn remove_from_favorites(&self, user_id: &str, item_id: &str, item_type: &str) -> Result<bool>;
|
||||
|
||||
async fn remove_from_favorites(
|
||||
&self,
|
||||
user_id: &str,
|
||||
item_id: &str,
|
||||
item_type: &str,
|
||||
) -> Result<bool>;
|
||||
|
||||
/// Check if an item is in user's favorites
|
||||
async fn is_favorite(&self, user_id: &str, item_id: &str, item_type: &str) -> Result<bool>;
|
||||
}
|
||||
@@ -40,4 +45,4 @@ pub trait FavoritesRepositoryPort: Send + Sync + 'static {
|
||||
|
||||
/// Checks if an item is in favorites.
|
||||
async fn is_favorite(&self, user_id: &str, item_id: &str, item_type: &str) -> Result<bool>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
use std::pin::Pin;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::application::dtos::file_dto::FileDto;
|
||||
use crate::common::errors::DomainError;
|
||||
@@ -48,7 +48,13 @@ pub trait FileUploadUseCase: Send + Sync + 'static {
|
||||
) -> Result<(FileDto, UploadStrategy), DomainError>;
|
||||
|
||||
/// Creates a new file at the specified path (for WebDAV)
|
||||
async fn create_file(&self, parent_path: &str, filename: &str, content: &[u8], content_type: &str) -> Result<FileDto, DomainError>;
|
||||
async fn create_file(
|
||||
&self,
|
||||
parent_path: &str,
|
||||
filename: &str,
|
||||
content: &[u8],
|
||||
content_type: &str,
|
||||
) -> Result<FileDto, DomainError>;
|
||||
|
||||
/// Updates the content of an existing file (for WebDAV)
|
||||
async fn update_file(&self, path: &str, content: &[u8]) -> Result<(), DomainError>;
|
||||
@@ -81,18 +87,21 @@ pub enum OptimizedFileContent {
|
||||
pub trait FileRetrievalUseCase: Send + Sync + 'static {
|
||||
/// Gets a file by its ID
|
||||
async fn get_file(&self, id: &str) -> Result<FileDto, DomainError>;
|
||||
|
||||
|
||||
/// Gets a file by its path (for WebDAV)
|
||||
async fn get_file_by_path(&self, path: &str) -> Result<FileDto, DomainError>;
|
||||
|
||||
|
||||
/// Lists files in a folder
|
||||
async fn list_files(&self, folder_id: Option<&str>) -> Result<Vec<FileDto>, DomainError>;
|
||||
|
||||
|
||||
/// Gets file content as bytes (for small files)
|
||||
async fn get_file_content(&self, id: &str) -> Result<Vec<u8>, DomainError>;
|
||||
|
||||
|
||||
/// Gets file content as a stream (for large files)
|
||||
async fn get_file_stream(&self, id: &str) -> Result<Box<dyn Stream<Item = Result<Bytes, std::io::Error>> + Send>, DomainError>;
|
||||
async fn get_file_stream(
|
||||
&self,
|
||||
id: &str,
|
||||
) -> Result<Box<dyn Stream<Item = Result<Bytes, std::io::Error>> + Send>, DomainError>;
|
||||
|
||||
/// Optimized multi-tier download.
|
||||
///
|
||||
@@ -123,11 +132,15 @@ pub trait FileRetrievalUseCase: Send + Sync + 'static {
|
||||
#[async_trait]
|
||||
pub trait FileManagementUseCase: Send + Sync + 'static {
|
||||
/// Moves a file to another folder
|
||||
async fn move_file(&self, file_id: &str, folder_id: Option<String>) -> Result<FileDto, DomainError>;
|
||||
|
||||
async fn move_file(
|
||||
&self,
|
||||
file_id: &str,
|
||||
folder_id: Option<String>,
|
||||
) -> Result<FileDto, DomainError>;
|
||||
|
||||
/// Renames a file
|
||||
async fn rename_file(&self, file_id: &str, new_name: &str) -> Result<FileDto, DomainError>;
|
||||
|
||||
|
||||
/// Deletes a file
|
||||
async fn delete_file(&self, id: &str) -> Result<(), DomainError>;
|
||||
|
||||
@@ -138,11 +151,7 @@ pub trait FileManagementUseCase: Send + Sync + 'static {
|
||||
/// 3. Decrements the dedup reference count for the content hash.
|
||||
///
|
||||
/// Returns `Ok(true)` when trashed, `Ok(false)` when permanently deleted.
|
||||
async fn delete_with_cleanup(
|
||||
&self,
|
||||
id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<bool, DomainError>;
|
||||
async fn delete_with_cleanup(&self, id: &str, user_id: &str) -> Result<bool, DomainError>;
|
||||
}
|
||||
|
||||
/// Factory for creating file use case implementations
|
||||
@@ -150,4 +159,4 @@ pub trait FileUseCaseFactory: Send + Sync + 'static {
|
||||
fn create_file_upload_use_case(&self) -> Arc<dyn FileUploadUseCase>;
|
||||
fn create_file_retrieval_use_case(&self) -> Arc<dyn FileRetrievalUseCase>;
|
||||
fn create_file_management_use_case(&self) -> Arc<dyn FileManagementUseCase>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::application::dtos::folder_dto::{CreateFolderDto, FolderDto, MoveFolderDto, RenameFolderDto};
|
||||
use crate::application::dtos::folder_dto::{
|
||||
CreateFolderDto, FolderDto, MoveFolderDto, RenameFolderDto,
|
||||
};
|
||||
use crate::application::dtos::search_dto::{SearchCriteriaDto, SearchResultsDto};
|
||||
use crate::common::errors::DomainError;
|
||||
|
||||
@@ -9,36 +11,37 @@ use crate::common::errors::DomainError;
|
||||
pub trait FolderUseCase: Send + Sync + 'static {
|
||||
/// Creates a new folder
|
||||
async fn create_folder(&self, dto: CreateFolderDto) -> Result<FolderDto, DomainError>;
|
||||
|
||||
|
||||
/// Gets a folder by its ID
|
||||
async fn get_folder(&self, id: &str) -> Result<FolderDto, DomainError>;
|
||||
|
||||
|
||||
/// Gets a folder by its path
|
||||
async fn get_folder_by_path(&self, path: &str) -> Result<FolderDto, DomainError>;
|
||||
|
||||
|
||||
/// Lists folders within a parent folder
|
||||
async fn list_folders(&self, parent_id: Option<&str>) -> Result<Vec<FolderDto>, DomainError>;
|
||||
|
||||
|
||||
/// Lists folders with pagination
|
||||
async fn list_folders_paginated(
|
||||
&self,
|
||||
&self,
|
||||
parent_id: Option<&str>,
|
||||
pagination: &crate::application::dtos::pagination::PaginationRequestDto
|
||||
pagination: &crate::application::dtos::pagination::PaginationRequestDto,
|
||||
) -> Result<crate::application::dtos::pagination::PaginatedResponseDto<FolderDto>, DomainError>;
|
||||
|
||||
|
||||
/// Renames a folder
|
||||
async fn rename_folder(&self, id: &str, dto: RenameFolderDto) -> Result<FolderDto, DomainError>;
|
||||
|
||||
async fn rename_folder(&self, id: &str, dto: RenameFolderDto)
|
||||
-> Result<FolderDto, DomainError>;
|
||||
|
||||
/// Moves a folder to another parent
|
||||
async fn move_folder(&self, id: &str, dto: MoveFolderDto) -> Result<FolderDto, DomainError>;
|
||||
|
||||
|
||||
/// Deletes a folder
|
||||
async fn delete_folder(&self, id: &str) -> Result<(), DomainError>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary port for file and folder search
|
||||
*
|
||||
*
|
||||
* Defines the operations related to advanced search of
|
||||
* files and folders based on various criteria.
|
||||
*/
|
||||
@@ -46,16 +49,16 @@ pub trait FolderUseCase: Send + Sync + 'static {
|
||||
pub trait SearchUseCase: Send + Sync + 'static {
|
||||
/**
|
||||
* Performs a search based on the specified criteria
|
||||
*
|
||||
*
|
||||
* @param criteria Search criteria including text, dates, sizes, etc.
|
||||
* @return Search results containing matching files and folders
|
||||
*/
|
||||
async fn search(&self, criteria: SearchCriteriaDto) -> Result<SearchResultsDto, DomainError>;
|
||||
|
||||
|
||||
/**
|
||||
* Clears the search results cache
|
||||
*
|
||||
*
|
||||
* @return Result indicating success or error
|
||||
*/
|
||||
async fn clear_search_cache(&self) -> Result<(), DomainError>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,4 +15,4 @@ pub mod storage_ports;
|
||||
pub mod thumbnail_ports;
|
||||
pub mod transcode_ports;
|
||||
pub mod trash_ports;
|
||||
pub mod zip_ports;
|
||||
pub mod zip_ports;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::path::PathBuf;
|
||||
use async_trait::async_trait;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
|
||||
// Re-export domain repository traits for backward compatibility
|
||||
pub use crate::domain::repositories::folder_repository::FolderRepository;
|
||||
@@ -14,13 +14,13 @@ use super::storage_ports::{FileReadPort, FileWritePort};
|
||||
pub trait StoragePort: Send + Sync + 'static {
|
||||
/// Resolves a domain path to a physical path
|
||||
fn resolve_path(&self, storage_path: &StoragePath) -> PathBuf;
|
||||
|
||||
|
||||
/// Creates directories if they don't exist
|
||||
async fn ensure_directory(&self, storage_path: &StoragePath) -> Result<(), DomainError>;
|
||||
|
||||
|
||||
/// Checks if a file exists at the given path
|
||||
async fn file_exists(&self, storage_path: &StoragePath) -> Result<bool, DomainError>;
|
||||
|
||||
|
||||
/// Checks if a directory exists at the given path
|
||||
async fn directory_exists(&self, storage_path: &StoragePath) -> Result<bool, DomainError>;
|
||||
}
|
||||
@@ -54,28 +54,28 @@ impl<T: FolderRepository> FolderStoragePort for T {}
|
||||
pub trait IdMappingPort: Send + Sync + 'static {
|
||||
/// Gets or creates an ID for a path
|
||||
async fn get_or_create_id(&self, path: &StoragePath) -> Result<String, DomainError>;
|
||||
|
||||
|
||||
/// Gets a path by its ID
|
||||
async fn get_path_by_id(&self, id: &str) -> Result<StoragePath, DomainError>;
|
||||
|
||||
|
||||
/// Updates the path for an existing ID
|
||||
async fn update_path(&self, id: &str, new_path: &StoragePath) -> Result<(), DomainError>;
|
||||
|
||||
|
||||
/// Removes an ID from the mapping
|
||||
async fn remove_id(&self, id: &str) -> Result<(), DomainError>;
|
||||
|
||||
|
||||
/// Saves pending changes
|
||||
async fn save_changes(&self) -> Result<(), DomainError>;
|
||||
|
||||
|
||||
/// Gets the file path as a PathBuf
|
||||
async fn get_file_path(&self, file_id: &str) -> Result<PathBuf, DomainError> {
|
||||
let storage_path = self.get_path_by_id(file_id).await?;
|
||||
Ok(PathBuf::from(storage_path.to_string()))
|
||||
}
|
||||
|
||||
|
||||
/// Updates a file's path
|
||||
async fn update_file_path(&self, file_id: &str, new_path: &PathBuf) -> Result<(), DomainError> {
|
||||
let storage_path = StoragePath::from_string(new_path.to_string_lossy().as_ref());
|
||||
self.update_path(file_id, &storage_path).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
use async_trait::async_trait;
|
||||
use crate::common::errors::Result;
|
||||
use crate::application::dtos::recent_dto::RecentItemDto;
|
||||
use crate::common::errors::Result;
|
||||
use async_trait::async_trait;
|
||||
|
||||
/// Defines operations for managing user recent items
|
||||
#[async_trait]
|
||||
pub trait RecentItemsUseCase: Send + Sync {
|
||||
/// Get all recent items for a user
|
||||
async fn get_recent_items(&self, user_id: &str, limit: Option<i32>) -> Result<Vec<RecentItemDto>>;
|
||||
|
||||
async fn get_recent_items(
|
||||
&self,
|
||||
user_id: &str,
|
||||
limit: Option<i32>,
|
||||
) -> Result<Vec<RecentItemDto>>;
|
||||
|
||||
/// Record access to an item
|
||||
async fn record_item_access(&self, user_id: &str, item_id: &str, item_type: &str) -> Result<()>;
|
||||
|
||||
async fn record_item_access(&self, user_id: &str, item_id: &str, item_type: &str)
|
||||
-> Result<()>;
|
||||
|
||||
/// Remove an item from recents
|
||||
async fn remove_from_recent(&self, user_id: &str, item_id: &str, item_type: &str) -> Result<bool>;
|
||||
|
||||
async fn remove_from_recent(
|
||||
&self,
|
||||
user_id: &str,
|
||||
item_id: &str,
|
||||
item_type: &str,
|
||||
) -> Result<bool>;
|
||||
|
||||
/// Clear the entire recent items list
|
||||
async fn clear_recent_items(&self, user_id: &str) -> Result<()>;
|
||||
}
|
||||
@@ -42,4 +52,4 @@ pub trait RecentItemsRepositoryPort: Send + Sync + 'static {
|
||||
|
||||
/// Removes items exceeding `max_items` (the oldest ones).
|
||||
async fn prune(&self, user_id: &str, max_items: i32) -> Result<()>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,12 @@ use async_trait::async_trait;
|
||||
use crate::{
|
||||
application::dtos::{
|
||||
pagination::PaginatedResponseDto,
|
||||
share_dto::{CreateShareDto, ShareDto, UpdateShareDto}
|
||||
share_dto::{CreateShareDto, ShareDto, UpdateShareDto},
|
||||
},
|
||||
common::errors::DomainError,
|
||||
domain::entities::share::ShareItemType,
|
||||
};
|
||||
|
||||
|
||||
#[async_trait]
|
||||
pub trait ShareUseCase: Send + Sync + 'static {
|
||||
/// Create a new shared link for a file or folder
|
||||
@@ -56,30 +55,45 @@ pub trait ShareUseCase: Send + Sync + 'static {
|
||||
token: &str,
|
||||
password: &str,
|
||||
) -> Result<bool, DomainError>;
|
||||
|
||||
|
||||
/// Register an access to a shared link
|
||||
async fn register_shared_link_access(&self, token: &str) -> Result<(), DomainError>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait ShareStoragePort: Send + Sync + 'static {
|
||||
async fn save_share(&self, share: &crate::domain::entities::share::Share)
|
||||
-> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_share_by_id(&self, id: &str)
|
||||
-> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_share_by_token(&self, token: &str)
|
||||
-> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_shares_by_item(&self, item_id: &str, item_type: &ShareItemType)
|
||||
-> Result<Vec<crate::domain::entities::share::Share>, DomainError>;
|
||||
|
||||
async fn update_share(&self, share: &crate::domain::entities::share::Share)
|
||||
-> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn save_share(
|
||||
&self,
|
||||
share: &crate::domain::entities::share::Share,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_share_by_id(
|
||||
&self,
|
||||
id: &str,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_share_by_token(
|
||||
&self,
|
||||
token: &str,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_shares_by_item(
|
||||
&self,
|
||||
item_id: &str,
|
||||
item_type: &ShareItemType,
|
||||
) -> Result<Vec<crate::domain::entities::share::Share>, DomainError>;
|
||||
|
||||
async fn update_share(
|
||||
&self,
|
||||
share: &crate::domain::entities::share::Share,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn delete_share(&self, id: &str) -> Result<(), DomainError>;
|
||||
|
||||
async fn find_shares_by_user(&self, user_id: &str, offset: usize, limit: usize)
|
||||
-> Result<(Vec<crate::domain::entities::share::Share>, usize), DomainError>;
|
||||
|
||||
async fn find_shares_by_user(
|
||||
&self,
|
||||
user_id: &str,
|
||||
offset: usize,
|
||||
limit: usize,
|
||||
) -> Result<(Vec<crate::domain::entities::share::Share>, usize), DomainError>;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
use std::path::PathBuf;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
use serde_json::Value;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::domain::entities::file::File;
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
use crate::common::errors::DomainError;
|
||||
|
||||
// Re-export domain repository traits for backward compatibility.
|
||||
// The canonical definitions now live in domain/repositories/.
|
||||
pub use crate::domain::repositories::file_repository::{FileReadRepository, FileWriteRepository, FileRepository};
|
||||
pub use crate::domain::repositories::file_repository::{
|
||||
FileReadRepository, FileRepository, FileWriteRepository,
|
||||
};
|
||||
pub use crate::domain::repositories::folder_repository::FolderRepository;
|
||||
|
||||
// ─────────────────────────────────────────────────────
|
||||
@@ -92,17 +94,14 @@ pub trait FileWritePort: Send + Sync + 'static {
|
||||
) -> Result<File, DomainError>;
|
||||
|
||||
/// Renames a file (same folder, different name).
|
||||
async fn rename_file(
|
||||
&self,
|
||||
file_id: &str,
|
||||
new_name: &str,
|
||||
) -> Result<File, DomainError>;
|
||||
async fn rename_file(&self, file_id: &str, new_name: &str) -> Result<File, DomainError>;
|
||||
|
||||
/// Deletes a file.
|
||||
async fn delete_file(&self, id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Updates the content of an existing file.
|
||||
async fn update_file_content(&self, file_id: &str, content: Vec<u8>) -> Result<(), DomainError>;
|
||||
async fn update_file_content(&self, file_id: &str, content: Vec<u8>)
|
||||
-> Result<(), DomainError>;
|
||||
|
||||
/// Registers file metadata WITHOUT writing content to disk (write-behind).
|
||||
///
|
||||
@@ -122,7 +121,11 @@ pub trait FileWritePort: Send + Sync + 'static {
|
||||
async fn move_to_trash(&self, file_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Restores a file from the trash to its original location
|
||||
async fn restore_from_trash(&self, file_id: &str, original_path: &str) -> Result<(), DomainError>;
|
||||
async fn restore_from_trash(
|
||||
&self,
|
||||
file_id: &str,
|
||||
original_path: &str,
|
||||
) -> Result<(), DomainError>;
|
||||
|
||||
/// Permanently deletes a file (used by the trash)
|
||||
async fn delete_file_permanently(&self, file_id: &str) -> Result<(), DomainError>;
|
||||
@@ -174,4 +177,4 @@ pub trait StorageUsagePort: Send + Sync + 'static {
|
||||
pub trait StorageUseCase: Send + Sync + 'static {
|
||||
/// Handle a request with the specified action and parameters
|
||||
async fn handle_request(&self, action: &str, params: Value) -> Result<Value, DomainError>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
//! keeping the application and interface layers independent of specific
|
||||
//! image processing implementations.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use crate::common::errors::DomainError;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Thumbnail sizes supported by the system.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@@ -42,7 +42,11 @@ impl ThumbnailSize {
|
||||
|
||||
/// Get all thumbnail sizes.
|
||||
pub fn all() -> &'static [ThumbnailSize] {
|
||||
&[ThumbnailSize::Icon, ThumbnailSize::Preview, ThumbnailSize::Large]
|
||||
&[
|
||||
ThumbnailSize::Icon,
|
||||
ThumbnailSize::Preview,
|
||||
ThumbnailSize::Large,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +81,7 @@ pub trait ThumbnailPort: Send + Sync + 'static {
|
||||
/// Generate all thumbnail sizes for a file in the background.
|
||||
///
|
||||
/// Called after file upload to pre-generate thumbnails.
|
||||
fn generate_all_sizes_background(
|
||||
self: Arc<Self>,
|
||||
file_id: String,
|
||||
original_path: PathBuf,
|
||||
);
|
||||
fn generate_all_sizes_background(self: Arc<Self>, file_id: String, original_path: PathBuf);
|
||||
|
||||
/// Delete all thumbnails for a file.
|
||||
async fn delete_thumbnails(&self, file_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
//! (e.g., JPEG/PNG → WebP), keeping the application and interface layers
|
||||
//! independent of specific image processing implementations.
|
||||
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use crate::common::errors::DomainError;
|
||||
|
||||
/// Supported output formats for image transcoding.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
||||
@@ -8,16 +8,16 @@ use crate::common::errors::Result;
|
||||
pub trait TrashUseCase: Send + Sync {
|
||||
/// List items in the user's trash
|
||||
async fn get_trash_items(&self, user_id: &str) -> Result<Vec<TrashedItemDto>>;
|
||||
|
||||
|
||||
/// Move a file or folder to trash
|
||||
async fn move_to_trash(&self, item_id: &str, item_type: &str, user_id: &str) -> Result<()>;
|
||||
|
||||
|
||||
/// Restore an item from trash to its original location
|
||||
async fn restore_item(&self, trash_id: &str, user_id: &str) -> Result<()>;
|
||||
|
||||
|
||||
/// Permanently delete an item from trash
|
||||
async fn delete_permanently(&self, trash_id: &str, user_id: &str) -> Result<()>;
|
||||
|
||||
|
||||
/// Empty the trash for a specific user
|
||||
async fn empty_trash(&self, user_id: &str) -> Result<()>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
//! keeping the interface layer independent of specific ZIP
|
||||
//! implementation details.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use crate::common::errors::DomainError;
|
||||
use async_trait::async_trait;
|
||||
|
||||
/// Port for ZIP archive operations.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user