use std::sync::Arc;
use chrono::{DateTime, Utc};
use dco3_crypto::{FileKey, PrivateKeyContainer};
use dco3_derive::FromResponse;
use serde::{Deserialize, Serialize};
use crate::{
client::{DracoonClient, DracoonErrorResponse, GetClient},
nodes::{S3FileUploadPart, S3UploadStatus, UploadOptions, UserUserPublicKey},
};
#[derive(Clone)]
pub struct PublicEndpoint<S> {
client: Arc<DracoonClient<S>>,
state: std::marker::PhantomData<S>,
}
impl<S> PublicEndpoint<S> {
pub fn new(client: Arc<DracoonClient<S>>) -> Self {
Self {
client,
state: std::marker::PhantomData,
}
}
pub fn client(&self) -> &Arc<DracoonClient<S>> {
&self.client
}
}
impl<S> GetClient<S> for PublicEndpoint<S> {
fn get_client(&self) -> &DracoonClient<S> {
&self.client
}
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct SoftwareVersionData {
pub rest_api_version: String,
pub sds_server_version: String,
pub build_date: DateTime<Utc>,
pub is_dracoon_cloud: Option<bool>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Clone, Deserialize, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct SystemInfo {
pub language_default: String,
pub s3_hosts: Vec<String>,
pub s3_enforce_direct_upload: bool,
#[serde(rename = "useS3Storage")]
pub use_s3_storage: bool,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, FromResponse)]
#[serde(rename_all = "camelCase")]
#[allow(non_snake_case)]
pub struct S3ShareUploadStatus {
pub status: S3UploadStatus,
pub file_name: String,
pub size: Option<u64>,
pub error_details: Option<DracoonErrorResponse>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct PublicDownloadShare {
pub is_protected: bool,
pub file_name: String,
pub size: u64,
pub limit_reached: bool,
pub creator_name: Option<String>,
pub created_at: DateTime<Utc>,
pub has_download_limit: bool,
pub media_type: String,
pub name: Option<String>,
pub creator_username: Option<String>,
pub expire_at: Option<DateTime<Utc>>,
pub notes: Option<String>,
pub is_encrypted: Option<bool>,
pub file_key: Option<FileKey>,
pub private_key_container: Option<PrivateKeyContainer>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Serialize, Clone, Default)]
pub struct PublicDownloadTokenGenerateRequest {
password: Option<String>,
}
impl PublicDownloadTokenGenerateRequest {
pub fn new(password: impl Into<String>) -> Self {
Self {
password: Some(password.into()),
}
}
pub fn has_password(&self) -> bool {
self.password.is_some()
}
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct PublicDownloadTokenGenerateResponse {
pub download_url: String,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
pub struct PublicShareEncryption {
pub file_key: FileKey,
pub private_key_container: PrivateKeyContainer,
}
impl PublicShareEncryption {
pub fn new(file_key: FileKey, private_key_container: PrivateKeyContainer) -> Self {
Self {
file_key,
private_key_container,
}
}
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct PublicUploadShare {
pub is_protected: bool,
pub created_at: DateTime<Utc>,
pub name: Option<String>,
pub is_encrypted: Option<bool>,
pub expire_at: Option<DateTime<Utc>>,
pub notes: Option<String>,
pub uploaded_files: Option<Vec<PublicUploadedFileData>>,
pub user_user_public_key_list: Option<UserUserPublicKeyList>,
pub show_uploaded_files: Option<bool>,
pub remaining_size: Option<u64>,
pub remaining_slots: Option<u32>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct PublicUploadedFileData {
pub name: String,
pub size: u64,
pub created_at: DateTime<Utc>,
pub hash: Option<String>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, Default)]
pub struct UserUserPublicKeyList {
pub items: Vec<UserUserPublicKey>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
#[allow(non_snake_case)]
pub struct CreateShareUploadChannelRequest {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
size: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
password: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
direct_S3_upload: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
timestamp_creation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
timestamp_modification: Option<String>,
}
impl CreateShareUploadChannelRequest {
pub fn builder(name: impl Into<String>) -> CreateShareUploadChannelRequestBuilder {
CreateShareUploadChannelRequestBuilder::new(name)
}
pub fn from_upload_options(
upload_options: &UploadOptions,
is_s3_upload: Option<bool>,
share_password: Option<String>,
) -> Self {
let req = Self::builder(upload_options.file_meta.name.clone())
.with_size(upload_options.file_meta.size);
let req = if let Some(timestamp_creation) = upload_options.file_meta.timestamp_creation {
req.with_timestamp_creation(timestamp_creation)
} else {
req
};
let mut req =
if let Some(timestamp_modification) = upload_options.file_meta.timestamp_modification {
req.with_timestamp_modification(timestamp_modification)
} else {
req
};
req.direct_s3_upload = is_s3_upload;
if let Some(share_password) = share_password {
req.password = Some(share_password);
}
req.build()
}
}
pub struct CreateShareUploadChannelRequestBuilder {
name: String,
size: Option<u64>,
password: Option<String>,
direct_s3_upload: Option<bool>,
timestamp_creation: Option<String>,
timestamp_modification: Option<String>,
}
impl CreateShareUploadChannelRequestBuilder {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
size: None,
password: None,
direct_s3_upload: None,
timestamp_creation: None,
timestamp_modification: None,
}
}
pub fn with_size(mut self, size: u64) -> Self {
self.size = Some(size);
self
}
pub fn with_password(mut self, password: impl Into<String>) -> Self {
self.password = Some(password.into());
self
}
pub fn with_direct_s3_upload(mut self, is_s3_upload: bool) -> Self {
self.direct_s3_upload = Some(is_s3_upload);
self
}
pub fn with_timestamp_creation(mut self, timestamp: DateTime<Utc>) -> Self {
self.timestamp_creation = Some(timestamp.to_rfc3339());
self
}
pub fn with_timestamp_modification(mut self, timestamp: DateTime<Utc>) -> Self {
self.timestamp_modification = Some(timestamp.to_rfc3339());
self
}
pub fn build(self) -> CreateShareUploadChannelRequest {
CreateShareUploadChannelRequest {
name: self.name,
size: self.size,
password: self.password,
direct_S3_upload: self.direct_s3_upload,
timestamp_creation: self.timestamp_creation,
timestamp_modification: self.timestamp_modification,
}
}
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Deserialize, Clone, FromResponse)]
#[serde(rename_all = "camelCase")]
pub struct CreateShareUploadChannelResponse {
pub upload_id: String,
pub upload_url: String,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UserFileKey {
user_id: u64,
file_key: FileKey,
}
impl UserFileKey {
pub fn new(user_id: u64, file_key: FileKey) -> Self {
Self { user_id, file_key }
}
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Serialize, Clone)]
pub struct UserFileKeyList {
pub items: Vec<UserFileKey>,
}
impl From<Vec<UserFileKey>> for UserFileKeyList {
fn from(items: Vec<UserFileKey>) -> Self {
Self { items }
}
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
#[allow(non_snake_case)]
pub struct CompleteS3ShareUploadRequest {
parts: Vec<S3FileUploadPart>,
#[serde(skip_serializing_if = "Option::is_none")]
user_file_key_list: Option<Vec<UserFileKey>>,
}
impl CompleteS3ShareUploadRequest {
pub fn new(parts: Vec<S3FileUploadPart>, user_file_key_list: Option<Vec<UserFileKey>>) -> Self {
Self {
parts,
user_file_key_list,
}
}
}
pub type FileName = String;