bucketwarden-server 0.1.0

BucketWarden storage server runtime.
Documentation
use super::*;

fn default_bucket_region() -> String {
    DEFAULT_BUCKET_REGION.to_string()
}

fn default_tenant_id() -> String {
    DEFAULT_TENANT_ID.to_string()
}

fn default_request_payment_payer() -> String {
    "BucketOwner".to_string()
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BucketState {
    #[serde(default)]
    pub owner: String,
    #[serde(default = "default_tenant_id")]
    pub tenant_id: String,
    #[serde(default = "default_bucket_region")]
    pub region: String,
    #[serde(default)]
    pub created_epoch_seconds: u64,
    pub versioning: BucketVersioningStatus,
    pub cors_rules: Vec<CorsRule>,
    #[serde(default)]
    pub logging: Option<String>,
    #[serde(default)]
    pub website: Option<BucketWebsiteConfiguration>,
    pub policy: Option<BucketPolicyState>,
    pub tags: BTreeMap<String, String>,
    #[serde(default)]
    pub accelerate_enabled: bool,
    #[serde(default)]
    pub abac_enabled: bool,
    #[serde(default = "default_request_payment_payer")]
    pub request_payment_payer: String,
    #[serde(default)]
    pub public_access_block: Option<BucketPublicAccessBlockState>,
    #[serde(default)]
    pub metadata_configuration: Option<BucketMetadataConfiguration>,
    #[serde(default)]
    pub metadata_table_configuration: Option<BucketMetadataTableConfiguration>,
    #[serde(default)]
    pub metrics_configurations: BTreeMap<String, MetricsConfiguration>,
    #[serde(default)]
    pub analytics_configurations: BTreeMap<String, AnalyticsConfiguration>,
    #[serde(default)]
    pub inventory_configurations: BTreeMap<String, InventoryConfiguration>,
    #[serde(default)]
    pub intelligent_tiering_configurations: BTreeMap<String, IntelligentTieringConfiguration>,
    pub object_lock: BucketObjectLockState,
    pub encryption: Option<ServerSideEncryption>,
    pub lifecycle_rules: Vec<LifecycleRule>,
    pub notification_rules: Vec<NotificationRule>,
    pub replication: BucketReplicationState,
    #[serde(default)]
    pub quota: BucketQuotaConfiguration,
    #[serde(default)]
    pub request_count: u64,
    #[serde(default)]
    pub ownership: BucketOwnershipState,
    pub objects: BTreeMap<String, ObjectState>,
}

impl Default for BucketState {
    fn default() -> Self {
        Self {
            owner: String::default(),
            tenant_id: default_tenant_id(),
            region: default_bucket_region(),
            created_epoch_seconds: 0,
            versioning: BucketVersioningStatus::default(),
            cors_rules: Vec::default(),
            logging: None,
            website: None,
            policy: None,
            tags: BTreeMap::default(),
            accelerate_enabled: false,
            abac_enabled: false,
            request_payment_payer: default_request_payment_payer(),
            public_access_block: None,
            metadata_configuration: None,
            metadata_table_configuration: None,
            metrics_configurations: BTreeMap::default(),
            analytics_configurations: BTreeMap::default(),
            inventory_configurations: BTreeMap::default(),
            intelligent_tiering_configurations: BTreeMap::default(),
            object_lock: BucketObjectLockState::default(),
            encryption: None,
            lifecycle_rules: Vec::default(),
            notification_rules: Vec::default(),
            replication: BucketReplicationState::default(),
            quota: BucketQuotaConfiguration::default(),
            request_count: 0,
            ownership: BucketOwnershipState::default(),
            objects: BTreeMap::default(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BucketPolicyState {
    pub json: String,
    pub policy: Policy,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct BucketPublicAccessBlockState {
    pub block_public_acls: bool,
    pub ignore_public_acls: bool,
    pub block_public_policy: bool,
    pub restrict_public_buckets: bool,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct BucketObjectLockState {
    pub enabled: bool,
    pub default_retention: Option<ObjectLockDefaultRetention>,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct BucketReplicationState {
    pub role: Option<String>,
    pub rules: Vec<ReplicationRule>,
    #[serde(default)]
    pub configured_epoch_seconds: u64,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BucketOwnershipState {
    pub object_ownership: String,
}

impl Default for BucketOwnershipState {
    fn default() -> Self {
        Self {
            object_ownership: "BucketOwnerEnforced".to_string(),
        }
    }
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct ObjectState {
    pub versions: Vec<StoredVersion>,
}

impl ObjectState {
    pub(crate) fn next_local_ordinal(&self) -> u64 {
        self.versions
            .iter()
            .map(|version| version.local_ordinal)
            .max()
            .unwrap_or_default()
            + 1
    }

    pub(crate) fn normalize_missing_local_ordinals(&mut self) {
        let mut used_ordinals = self
            .versions
            .iter()
            .filter_map(|version| (version.local_ordinal > 0).then_some(version.local_ordinal))
            .collect::<Vec<_>>();
        for index in 0..self.versions.len() {
            let version = &mut self.versions[index];
            if version.local_ordinal == 0 {
                let mut candidate = index as u64 + 1;
                while used_ordinals.contains(&candidate) {
                    candidate += 1;
                }
                version.local_ordinal = candidate;
                used_ordinals.push(candidate);
            }
        }
    }

    pub(crate) fn current_version(&self) -> Option<&StoredVersion> {
        self.versions
            .last()
            .and_then(|version| (!version.delete_marker).then_some(version))
    }

    pub(crate) fn current_version_mut(&mut self) -> Option<&mut StoredVersion> {
        self.versions
            .last_mut()
            .and_then(|version| (!version.delete_marker).then_some(version))
    }

    pub(crate) fn has_current_version(&self) -> bool {
        self.current_version().is_some()
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StoredVersion {
    pub version_id: String,
    #[serde(default)]
    pub local_ordinal: u64,
    pub ciphertext: Ciphertext,
    pub etag: String,
    pub last_modified_epoch_seconds: u64,
    pub metadata: ObjectMetadata,
    #[serde(default)]
    pub envelope: Option<EnvelopeMetadata>,
    #[serde(default)]
    pub integrity: IntegrityRecord,
    pub tags: BTreeMap<String, String>,
    pub lock: ObjectLock,
    pub delete_marker: bool,
    #[serde(default)]
    pub owner: String,
    #[serde(default)]
    pub replication_status: Option<String>,
}

impl StoredVersion {
    pub(crate) fn content_length(&self) -> usize {
        self.ciphertext.bytes.len()
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MultipartUploadState {
    pub bucket: String,
    pub key: String,
    pub metadata: ObjectMetadata,
    pub lock: ObjectLock,
    pub initiated_epoch_seconds: u64,
    pub parts: BTreeMap<u16, MultipartPartState>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MultipartPartState {
    pub etag: String,
    pub body: Vec<u8>,
    #[serde(default)]
    pub checksum_sha256: String,
}