use crate::ids::CardUid;
use crate::storage::artifact::StoredObjectRef;
use crate::storage::backend::StorageBackendKind;
use crate::storage::ids::UploadId;
use serde::{Deserialize, Serialize};
pub const IDEMPOTENCY_KEY_HEADER: &str = "idempotency-key";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct UploadInitRequest {
pub card_uid: CardUid,
pub relative_path: String,
pub expected_sha256: String,
pub expected_size_bytes: u64,
#[serde(default)]
pub content_type: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct UploadInitResponse {
pub upload_id: UploadId,
pub backend: StorageBackendKind,
pub plan: UploadPlan,
pub storage_path: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(tag = "protocol", content = "data", rename_all = "snake_case")]
pub enum UploadPlan {
SinglePut {
put_url: String,
ttl_secs: u32,
#[serde(default)]
required_headers: Vec<HeaderPair>,
},
LocalFs {
put_url: String,
ttl_secs: u32,
},
Multipart {
part_count: u32,
part_size_bytes: u64,
part_url_ttl_secs: u32,
#[serde(default)]
required_headers: Vec<HeaderPair>,
},
AzureBlockBlob {
sas_url: String,
block_size_bytes: u64,
block_count_planned: u32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum VerificationGuarantee {
ServerComputed,
ServerVerifiedAgainstClient,
ClientDeclared,
}
#[must_use]
pub fn backend_verification_guarantee(backend: StorageBackendKind) -> VerificationGuarantee {
match backend {
StorageBackendKind::S3 => VerificationGuarantee::ServerVerifiedAgainstClient,
StorageBackendKind::Gcs | StorageBackendKind::Azure => {
VerificationGuarantee::ClientDeclared
}
StorageBackendKind::Local => VerificationGuarantee::ServerComputed,
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct HeaderPair {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(tag = "protocol", content = "data", rename_all = "snake_case")]
pub enum UploadCompleteRequest {
SinglePut(SinglePutComplete),
Multipart(MultipartComplete),
AzureBlockBlob(AzureBlockBlobComplete),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct SinglePutComplete {}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct MultipartComplete {
pub parts: Vec<CompletedPart>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct CompletedPart {
pub part_number: u32,
pub e_tag: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct AzureBlockBlobComplete {
pub block_count: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct LocalBlobUploadResponse {
pub uploaded: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct UploadCompleteResponse {
pub stored: StoredObjectRef,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct PartUrlResponse {
pub url: String,
pub ttl_secs: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct AbortResponse {
pub aborted: bool,
}