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,
})
}
}