fraiseql_server/files/
traits.rs1use std::{collections::HashMap, time::Duration};
4
5use async_trait::async_trait;
6use bytes::Bytes;
7
8use crate::files::{
9 config::{FileConfig, ProcessingConfig},
10 error::{FileError, ProcessingError, ScanError, StorageError},
11 processing::ProcessedImages,
12};
13
14#[async_trait]
16pub trait StorageBackend: Send + Sync {
17 fn name(&self) -> &'static str;
18
19 async fn upload(
20 &self,
21 key: &str,
22 data: Bytes,
23 content_type: &str,
24 metadata: Option<&StorageMetadata>,
25 ) -> Result<StorageResult, StorageError>;
26
27 async fn download(&self, key: &str) -> Result<Bytes, StorageError>;
28 async fn delete(&self, key: &str) -> Result<(), StorageError>;
29 async fn exists(&self, key: &str) -> Result<bool, StorageError>;
30 async fn metadata(&self, key: &str) -> Result<StorageMetadata, StorageError>;
31 async fn signed_url(&self, key: &str, expiry: Duration) -> Result<String, StorageError>;
32 fn public_url(&self, key: &str) -> String;
33}
34
35#[derive(Debug, Clone)]
36pub struct StorageMetadata {
37 pub content_type: String,
38 pub content_length: u64,
39 pub etag: Option<String>,
40 pub last_modified: Option<chrono::DateTime<chrono::Utc>>,
41 pub custom: HashMap<String, String>,
42}
43
44#[derive(Debug)]
45pub struct StorageResult {
46 pub key: String,
47 pub url: String,
48 pub etag: Option<String>,
49 pub size: u64,
50}
51
52pub trait FileValidator: Send + Sync {
54 fn validate(
55 &self,
56 data: &Bytes,
57 declared_type: &str,
58 filename: &str,
59 config: &FileConfig,
60 ) -> Result<ValidatedFile, FileError>;
61}
62
63#[async_trait]
65pub trait ImageProcessor: Send + Sync {
66 async fn process(
67 &self,
68 data: &Bytes,
69 config: &ProcessingConfig,
70 ) -> Result<ProcessedImages, ProcessingError>;
71}
72
73#[async_trait]
75pub trait MalwareScanner: Send + Sync {
76 async fn scan(&self, data: &Bytes) -> Result<ScanResult, ScanError>;
77}
78
79#[derive(Debug)]
80pub struct ScanResult {
81 pub clean: bool,
82 pub threat_name: Option<String>,
83 pub scanner_version: String,
84}
85
86#[derive(Debug)]
87pub struct ValidatedFile {
88 pub content_type: String,
89 pub sanitized_filename: String,
90 pub size: usize,
91 pub detected_type: Option<String>,
92}