use async_trait::async_trait;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::domain::entity::FileShare;
use crate::infrastructure::persistence::FileShareRepository;
use super::CommandHandler;
#[deprecated(since = "0.2.0", note = "Use CommandHandler<C> trait instead")]
#[async_trait]
pub trait FileShareCommand: Send + Sync {
type Output;
async fn execute(&self) -> Result<Self::Output>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileShareCommand {
pub file_id: Uuid,
pub owner_id: Uuid,
pub token: String,
pub share_type: ShareType,
pub permission: SharePermission,
pub shared_with: Vec<Uuid>,
pub password_hash: Option<String>,
pub max_downloads: Option<i32>,
pub download_count: i32,
pub expires_at: Option<DateTime<Utc>>,
pub status: ShareStatus,
pub revoked_at: Option<DateTime<Utc>>,
pub revoked_by: Option<Uuid>,
pub message: Option<String>,
pub metadata: serde_json::Value,
}
pub struct CreateFileShareHandler<R: FileShareRepository> {
repository: std::sync::Arc<R>,
}
impl<R: FileShareRepository> CreateFileShareHandler<R> {
pub fn new(repository: std::sync::Arc<R>) -> Self {
Self { repository }
}
}
#[async_trait]
impl<R: FileShareRepository + 'static> CommandHandler<CreateFileShareCommand> for CreateFileShareHandler<R> {
type Output = FileShare;
async fn handle(&self, cmd: CreateFileShareCommand) -> Result<Self::Output> {
let entity = FileShare::builder()
.id(Uuid::new_v4().to_string())
.file_id(cmd.file_id)
.owner_id(cmd.owner_id)
.token(cmd.token)
.share_type(cmd.share_type)
.permission(cmd.permission)
.shared_with(cmd.shared_with)
.password_hash(cmd.password_hash)
.max_downloads(cmd.max_downloads)
.download_count(cmd.download_count)
.expires_at(cmd.expires_at)
.status(cmd.status)
.revoked_at(cmd.revoked_at)
.revoked_by(cmd.revoked_by)
.message(cmd.message)
.metadata(cmd.metadata)
.build()?;
self.repository.save(&entity).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateFileShareCommand {
pub id: String,
pub file_id: Option<Uuid>,
pub owner_id: Option<Uuid>,
pub token: Option<String>,
pub share_type: Option<ShareType>,
pub permission: Option<SharePermission>,
pub shared_with: Option<Vec<Uuid>>,
pub password_hash: Option<String>,
pub max_downloads: Option<i32>,
pub download_count: Option<i32>,
pub expires_at: Option<DateTime<Utc>>,
pub status: Option<ShareStatus>,
pub revoked_at: Option<DateTime<Utc>>,
pub revoked_by: Option<Uuid>,
pub message: Option<String>,
pub metadata: Option<serde_json::Value>,
}
pub struct UpdateFileShareHandler<R: FileShareRepository> {
repository: std::sync::Arc<R>,
}
impl<R: FileShareRepository> UpdateFileShareHandler<R> {
pub fn new(repository: std::sync::Arc<R>) -> Self {
Self { repository }
}
}
#[async_trait]
impl<R: FileShareRepository + 'static> CommandHandler<UpdateFileShareCommand> for UpdateFileShareHandler<R> {
type Output = Option<FileShare>;
async fn handle(&self, cmd: UpdateFileShareCommand) -> Result<Self::Output> {
let existing = self.repository.find_by_id(&cmd.id).await?;
let Some(mut entity) = existing else {
return Ok(None);
};
if let Some(value) = cmd.file_id {
entity.file_id = value;
}
if let Some(value) = cmd.owner_id {
entity.owner_id = value;
}
if let Some(value) = cmd.token {
entity.token = value;
}
if let Some(value) = cmd.share_type {
entity.share_type = value;
}
if let Some(value) = cmd.permission {
entity.permission = value;
}
if let Some(value) = cmd.shared_with {
entity.shared_with = value;
}
entity.password_hash = cmd.password_hash;
entity.max_downloads = cmd.max_downloads;
if let Some(value) = cmd.download_count {
entity.download_count = value;
}
entity.expires_at = cmd.expires_at;
if let Some(value) = cmd.status {
entity.status = value;
}
entity.revoked_at = cmd.revoked_at;
entity.revoked_by = cmd.revoked_by;
entity.message = cmd.message;
if let Some(value) = cmd.metadata {
entity.metadata = value;
}
self.repository.update(&cmd.id, &entity).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteFileShareCommand {
pub id: String,
pub hard_delete: bool,
}
pub struct DeleteFileShareHandler<R: FileShareRepository> {
repository: std::sync::Arc<R>,
}
impl<R: FileShareRepository> DeleteFileShareHandler<R> {
pub fn new(repository: std::sync::Arc<R>) -> Self {
Self { repository }
}
}
#[async_trait]
impl<R: FileShareRepository + 'static> CommandHandler<DeleteFileShareCommand> for DeleteFileShareHandler<R> {
type Output = bool;
async fn handle(&self, cmd: DeleteFileShareCommand) -> Result<Self::Output> {
if cmd.hard_delete {
self.repository.delete(&cmd.id).await
} else {
self.repository.soft_delete(&cmd.id).await
}
}
}