diff --git a/src/minio.rs b/src/minio.rs index b9dfc55..7bea047 100644 --- a/src/minio.rs +++ b/src/minio.rs @@ -74,6 +74,11 @@ struct MinioVersioning { pub status: String, } +#[derive(Debug, Clone, Deserialize)] +struct MinioAnonymousAccess { + pub permission: String, +} + impl BasicMinioResult { pub fn success(&self) -> bool { self.status == "success" @@ -206,19 +211,8 @@ impl MinioService { } self.bucket_set_versioning(&b.name, b.versioning).await?; - - // Enable anonymous access, eg. public hosting - if b.anonymous_read_access { - let target = format!("{}/*", bucket_name); - - let res = self - .exec_mc_cmd::(&["anonymous", "set", "download", target.as_str()]) - .await?; - - if res.get(0).map(|r| r.success()) != Some(true) { - return Err(MinioError::SetAnonymousAcccessFailed.into()); - } - } + self.bucket_set_anonymous_access(&b.name, b.anonymous_read_access) + .await?; // Set quota, if requested if let Some(quota) = &b.quota { @@ -289,13 +283,52 @@ impl MinioService { /// Get current bucket versioning status pub async fn bucket_get_versioning(&self, bucket_name: &str) -> anyhow::Result { let bucket_name = self.absolute_bucket_name(bucket_name); - Ok(self.exec_mc_cmd::(&["version", "info", bucket_name.as_str()]) + Ok(self + .exec_mc_cmd::(&["version", "info", bucket_name.as_str()]) .await? .remove(0) .versioning .map(|v| v.status.to_lowercase().eq("enabled")) .unwrap_or_default()) } + + /// Set bucket anonymous access + pub async fn bucket_set_anonymous_access( + &self, + bucket_name: &str, + access: bool, + ) -> anyhow::Result<()> { + let target = self.absolute_bucket_name(bucket_name); + + let res = self + .exec_mc_cmd::(&[ + "anonymous", + "set", + match access { + true => "download", + false => "private", + }, + target.as_str(), + ]) + .await?; + + if res.get(0).map(|r| r.success()) != Some(true) { + return Err(MinioError::SetAnonymousAcccessFailed.into()); + } + + Ok(()) + } + + /// Get current bucket anonymous access status + pub async fn bucket_get_anonymous_access(&self, bucket_name: &str) -> anyhow::Result { + let bucket_name = self.absolute_bucket_name(bucket_name); + Ok(self + .exec_mc_cmd::(&["anonymous", "get", bucket_name.as_str()]) + .await? + .remove(0) + .permission + == "download") + } } #[cfg(test)] @@ -361,6 +394,10 @@ mod test { .unwrap(); assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap()); + assert!(service + .bucket_get_anonymous_access(TEST_BUCKET_NAME) + .await + .unwrap()); assert_eq!( reqwest::get(format!("{}/{}/test", service.hostname, TEST_BUCKET_NAME)) .await @@ -402,6 +439,59 @@ mod test { ); } + #[tokio::test] + async fn bucket_creation_without_anonymous_access_updating_status() { + let _ = env_logger::builder().is_test(true).try_init(); + + let srv = MinioTestServer::start().await.unwrap(); + let service = srv.as_service(); + service + .create_bucket(&MinioBucketSpec { + instance: "".to_string(), + name: TEST_BUCKET_NAME.to_string(), + secret: "".to_string(), + anonymous_read_access: false, + versioning: false, + quota: None, + lock: false, + retention: None, + }) + .await + .unwrap(); + + assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap()); + let test_url = format!("{}/{}/test", service.hostname, TEST_BUCKET_NAME); + assert_eq!( + reqwest::get(&test_url).await.unwrap().status().as_u16(), + 403 + ); + service + .bucket_set_anonymous_access(TEST_BUCKET_NAME, true) + .await + .unwrap(); + assert!(service + .bucket_get_anonymous_access(TEST_BUCKET_NAME) + .await + .unwrap()); + assert_eq!( + reqwest::get(&test_url).await.unwrap().status().as_u16(), + 404 + ); + + service + .bucket_set_anonymous_access(TEST_BUCKET_NAME, false) + .await + .unwrap(); + assert!(!service + .bucket_get_anonymous_access(TEST_BUCKET_NAME) + .await + .unwrap()); + assert_eq!( + reqwest::get(&test_url).await.unwrap().status().as_u16(), + 403 + ); + } + // With versioning #[tokio::test] async fn bucket_with_versioning() { @@ -424,7 +514,10 @@ mod test { .unwrap(); assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap()); - assert!(service.bucket_get_versioning(TEST_BUCKET_NAME).await.unwrap()); + assert!(service + .bucket_get_versioning(TEST_BUCKET_NAME) + .await + .unwrap()); } #[tokio::test] @@ -448,7 +541,10 @@ mod test { .unwrap(); assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap()); - assert!(!service.bucket_get_versioning(TEST_BUCKET_NAME).await.unwrap()); + assert!(!service + .bucket_get_versioning(TEST_BUCKET_NAME) + .await + .unwrap()); } #[tokio::test] @@ -472,11 +568,26 @@ mod test { .unwrap(); assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap()); - assert!(!service.bucket_get_versioning(TEST_BUCKET_NAME).await.unwrap()); - service.bucket_set_versioning(TEST_BUCKET_NAME, true).await.unwrap(); - assert!(service.bucket_get_versioning(TEST_BUCKET_NAME).await.unwrap()); - service.bucket_set_versioning(TEST_BUCKET_NAME, false).await.unwrap(); - assert!(!service.bucket_get_versioning(TEST_BUCKET_NAME).await.unwrap()); + assert!(!service + .bucket_get_versioning(TEST_BUCKET_NAME) + .await + .unwrap()); + service + .bucket_set_versioning(TEST_BUCKET_NAME, true) + .await + .unwrap(); + assert!(service + .bucket_get_versioning(TEST_BUCKET_NAME) + .await + .unwrap()); + service + .bucket_set_versioning(TEST_BUCKET_NAME, false) + .await + .unwrap(); + assert!(!service + .bucket_get_versioning(TEST_BUCKET_NAME) + .await + .unwrap()); } // TODO : with quota