bucketwarden-server 0.1.0

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

impl BucketWarden {
    pub(crate) fn object_version_rows(
        &self,
        bucket: &str,
        key: &str,
    ) -> Result<Vec<ConsoleApiObjectVersionRow>, RuntimeError> {
        let bucket_state = self.require_bucket(bucket)?;
        let object = bucket_state
            .objects
            .get(key)
            .ok_or_else(|| RuntimeError::NoSuchKey(object_resource(bucket, key)))?;
        let latest_index = object.versions.len().saturating_sub(1);
        let mut rows = object
            .versions
            .iter()
            .enumerate()
            .rev()
            .map(|(index, version)| ConsoleApiObjectVersionRow {
                bucket: bucket.to_string(),
                key: key.to_string(),
                version_id: version.version_id.clone(),
                version_ordinal: version.local_ordinal,
                version_label: format!("Version {}", version.local_ordinal),
                is_latest: index == latest_index,
                delete_marker: version.delete_marker,
                content_length: version.content_length(),
                etag: version.etag.clone(),
                last_modified_epoch_seconds: version.last_modified_epoch_seconds,
                owner: stored_owner(bucket_state, version),
                legal_hold: version.lock.legal_hold,
                retention_mode: version.lock.retention_mode.map(|mode| format!("{mode:?}")),
                retain_until_epoch_seconds: version.lock.retain_until_epoch_seconds,
                replication_status: version.replication_status.clone(),
            })
            .collect::<Vec<_>>();
        rows.sort_by(|left, right| {
            right
                .last_modified_epoch_seconds
                .cmp(&left.last_modified_epoch_seconds)
                .then(right.version_id.cmp(&left.version_id))
        });
        Ok(rows)
    }

    pub(crate) fn object_governance_summary(
        &self,
        bucket: &str,
        key: &str,
        version_id: Option<&str>,
    ) -> Result<ConsoleApiObjectGovernanceSummary, RuntimeError> {
        let version = if let Some(version_id) = version_id {
            self.version_by_id(bucket, key, version_id)?
        } else {
            self.current_version(bucket, key)?
        };
        let retention_active = version
            .lock
            .retain_until_epoch_seconds
            .is_some_and(|retain_until| retain_until > self.clock_epoch_seconds);
        let mut effective_constraints = Vec::new();
        if version.lock.legal_hold {
            effective_constraints.push("legal-hold".to_string());
        }
        if retention_active {
            match version.lock.retention_mode {
                Some(RetentionMode::Compliance) => {
                    effective_constraints.push("compliance-retention".to_string())
                }
                Some(RetentionMode::Governance) => {
                    effective_constraints.push("governance-retention".to_string())
                }
                None => effective_constraints.push("retention-active".to_string()),
            }
        }
        if version.delete_marker {
            effective_constraints.push("delete-marker".to_string());
        }
        let delete_allowed_without_bypass =
            !version.lock.legal_hold && !retention_active && !version.delete_marker;
        Ok(ConsoleApiObjectGovernanceSummary {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: version.version_id.clone(),
            legal_hold: version.lock.legal_hold,
            retention_mode: version.lock.retention_mode.map(|mode| format!("{mode:?}")),
            retain_until_epoch_seconds: version.lock.retain_until_epoch_seconds,
            retention_active,
            delete_allowed_without_bypass,
            effective_constraints,
            delete_marker: version.delete_marker,
        })
    }
}