aboutsummaryrefslogtreecommitdiff
path: root/src/api/s3_bucket.rs
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2021-12-14 13:55:11 +0100
committerAlex Auvolat <alex@adnab.me>2022-01-04 12:45:46 +0100
commit5b1117e582db16cc5aa50840a685875cbd5501f4 (patch)
tree06fec47bf56cb08cb51334454dc15f98352c98f2 /src/api/s3_bucket.rs
parent8f6026de5ecd44cbe0fc0bcd47638a1ece860439 (diff)
downloadgarage-5b1117e582db16cc5aa50840a685875cbd5501f4.tar.gz
garage-5b1117e582db16cc5aa50840a685875cbd5501f4.zip
New model for buckets
Diffstat (limited to 'src/api/s3_bucket.rs')
-rw-r--r--src/api/s3_bucket.rs62
1 files changed, 55 insertions, 7 deletions
diff --git a/src/api/s3_bucket.rs b/src/api/s3_bucket.rs
index 2be0a818..dc131a31 100644
--- a/src/api/s3_bucket.rs
+++ b/src/api/s3_bucket.rs
@@ -1,9 +1,12 @@
+use std::collections::HashMap;
use std::sync::Arc;
use hyper::{Body, Response};
use garage_model::garage::Garage;
use garage_model::key_table::Key;
+use garage_table::util::EmptyKey;
+use garage_util::crdt::*;
use garage_util::time::*;
use crate::error::*;
@@ -34,20 +37,65 @@ pub fn handle_get_bucket_versioning() -> Result<Response<Body>, Error> {
.body(Body::from(xml.into_bytes()))?)
}
-pub fn handle_list_buckets(api_key: &Key) -> Result<Response<Body>, Error> {
+pub async fn handle_list_buckets(garage: &Garage, api_key: &Key) -> Result<Response<Body>, Error> {
+ let key_state = api_key.state.as_option().ok_or_internal_error(
+ "Key should not be in deleted state at this point (internal error)",
+ )?;
+
+ // Collect buckets user has access to
+ let ids = api_key
+ .state
+ .as_option()
+ .unwrap()
+ .authorized_buckets
+ .items()
+ .iter()
+ .filter(|(_, perms)| perms.allow_read || perms.allow_write)
+ .map(|(id, _)| *id)
+ .collect::<Vec<_>>();
+
+ let mut buckets_by_id = HashMap::new();
+ let mut aliases = HashMap::new();
+
+ for bucket_id in ids.iter() {
+ let bucket = garage.bucket_table.get(bucket_id, &EmptyKey).await?;
+ if let Some(bucket) = bucket {
+ if let Deletable::Present(param) = bucket.state {
+ for (alias, _, active) in param.aliases.items() {
+ if *active {
+ let alias_ent = garage.bucket_alias_table.get(&EmptyKey, alias).await?;
+ if let Some(alias_ent) = alias_ent {
+ if let Some(alias_p) = alias_ent.state.get().as_option() {
+ if alias_p.bucket_id == *bucket_id {
+ aliases.insert(alias_ent.name.clone(), *bucket_id);
+ }
+ }
+ }
+ }
+ }
+ buckets_by_id.insert(bucket_id, param);
+ }
+ }
+ }
+
+ for (alias, _, id) in key_state.local_aliases.items() {
+ if let Some(id) = id.as_option() {
+ aliases.insert(alias.clone(), *id);
+ }
+ }
+
+ // Generate response
let list_buckets = s3_xml::ListAllMyBucketsResult {
owner: s3_xml::Owner {
display_name: s3_xml::Value(api_key.name.get().to_string()),
id: s3_xml::Value(api_key.key_id.to_string()),
},
buckets: s3_xml::BucketList {
- entries: api_key
- .authorized_buckets
- .items()
+ entries: aliases
.iter()
- .filter(|(_, _, perms)| perms.allow_read || perms.allow_write)
- .map(|(name, ts, _)| s3_xml::Bucket {
- creation_date: s3_xml::Value(msec_to_rfc3339(*ts)),
+ .filter_map(|(name, id)| buckets_by_id.get(id).map(|p| (name, id, p)))
+ .map(|(name, _id, param)| s3_xml::Bucket {
+ creation_date: s3_xml::Value(msec_to_rfc3339(param.creation_date)),
name: s3_xml::Value(name.to_string()),
})
.collect(),