diff --git a/src/garage/admin_rpc.rs b/src/garage/admin_rpc.rs index 65bd24c0..f9d398c2 100644 --- a/src/garage/admin_rpc.rs +++ b/src/garage/admin_rpc.rs @@ -156,7 +156,36 @@ impl AdminRpcHandler { ))) } BucketOperation::Website(query) => { - Ok(AdminRPC::Ok(format!("test"))) + let bucket = self.get_existing_bucket(&query.bucket).await?; + if query.allow && query.deny { + return Err(Error::Message(format!("Website can not be both allowed and denied on a bucket"))); + } + + if query.allow || query.deny { + let exposed = query.allow; + if let BucketState::Present(ak) = bucket.state.get_mut() { + let old_ak = ak.take_and_clear(); + ak.merge(&old_ak.update_mutator( + key_id.to_string(), + PermissionSet { + allow_read, + allow_write, + }, + )); + } else { + return Err(Error::Message(format!( + "Bucket is deleted in update_bucket_key" + ))); + } + } + + let msg = if bucket.exposed { + "Bucket is exposed as a website." + } else { + "Bucket is not exposed." + }; + + Ok(AdminRPC::Ok(msg)) } } } @@ -240,6 +269,7 @@ impl AdminRpcHandler { .unwrap_or(Err(Error::BadRPC(format!("Key {} does not exist", id)))) } + /// Update **bucket table** to inform of the new linked key async fn update_bucket_key( &self, mut bucket: Bucket, @@ -265,6 +295,7 @@ impl AdminRpcHandler { Ok(()) } + /// Update **key table** to inform of the new linked bucket async fn update_key_bucket( &self, mut key: Key, diff --git a/src/garage/main.rs b/src/garage/main.rs index 7996d1f9..d97ca3b8 100644 --- a/src/garage/main.rs +++ b/src/garage/main.rs @@ -150,12 +150,12 @@ pub enum BucketOperation { #[derive(Serialize, Deserialize, StructOpt, Debug)] pub struct WebsiteOpt { /// Create - #[structopt(long = "create")] - pub create: bool, + #[structopt(long = "allow")] + pub allow: bool, /// Delete - #[structopt(long = "delete")] - pub delete: bool, + #[structopt(long = "deny")] + pub deny: bool, } #[derive(Serialize, Deserialize, StructOpt, Debug)] diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index b7f24d71..b6b0fceb 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -21,27 +21,43 @@ pub struct Bucket { #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum BucketState { Deleted, - Present(crdt::LWWMap), + Present(BucketParams), } impl CRDT for BucketState { fn merge(&mut self, o: &Self) { match o { BucketState::Deleted => *self = BucketState::Deleted, - BucketState::Present(other_ak) => { - if let BucketState::Present(ak) = self { - ak.merge(other_ak); + BucketState::Present(other_params) => { + if let BucketState::Present(params) = self { + params.merge(other_params); } } } } } +#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] +pub struct BucketParams { + pub authorized_keys: crdt::LWWMap, + pub website: crdt::LWW +} + +impl CRDT for BucketParams { + fn merge(&mut self, o: &Self) { + self.authorized_keys.merge(&o.authorized_keys); + self.website.merge(&o.website); + } +} + impl Bucket { pub fn new(name: String) -> Self { Bucket { name, - state: crdt::LWW::new(BucketState::Present(crdt::LWWMap::new())), + state: crdt::LWW::new(BucketState::Present(BucketParams { + authorized_keys: crdt::LWWMap::new(), + website: crdt::LWW::new(false) + })), } } pub fn is_deleted(&self) -> bool { @@ -50,7 +66,7 @@ impl Bucket { pub fn authorized_keys(&self) -> &[(String, u64, PermissionSet)] { match self.state.get() { BucketState::Deleted => &[], - BucketState::Present(ak) => ak.items(), + BucketState::Present(state) => state.authorized_keys.items(), } } }