1use async_trait::async_trait;
4
5use crate::{
6 acl_common::{build_get_object_acl_request, build_put_object_acl_request, parse_object_acl_from_xml},
7 common::VersionIdOnlyOptions,
8 object_common::ObjectAcl,
9 Client, Result,
10};
11
12pub type PutObjectAclOptions = VersionIdOnlyOptions;
13pub type GetObjectAclOptions = VersionIdOnlyOptions;
14
15#[async_trait]
16pub trait ObjectAclOperations {
17 async fn get_object_acl<S1, S2>(&self, bucket_name: S1, object_key: S2, options: Option<GetObjectAclOptions>) -> Result<ObjectAcl>
21 where
22 S1: AsRef<str> + Send,
23 S2: AsRef<str> + Send;
24
25 async fn put_object_acl<S1, S2>(&self, bucket_name: S1, object_key: S2, acl: ObjectAcl, options: Option<GetObjectAclOptions>) -> Result<()>
29 where
30 S1: AsRef<str> + Send,
31 S2: AsRef<str> + Send;
32}
33
34#[async_trait]
35impl ObjectAclOperations for Client {
36 async fn get_object_acl<S1, S2>(&self, bucket_name: S1, object_key: S2, options: Option<GetObjectAclOptions>) -> Result<ObjectAcl>
40 where
41 S1: AsRef<str> + Send,
42 S2: AsRef<str> + Send,
43 {
44 let request = build_get_object_acl_request(bucket_name.as_ref(), object_key.as_ref(), &options)?;
45 let (_, content) = self.do_request::<String>(request).await?;
46 parse_object_acl_from_xml(&content)
47 }
48
49 async fn put_object_acl<S1, S2>(&self, bucket_name: S1, object_key: S2, acl: ObjectAcl, options: Option<GetObjectAclOptions>) -> Result<()>
53 where
54 S1: AsRef<str> + Send,
55 S2: AsRef<str> + Send,
56 {
57 let request = build_put_object_acl_request(bucket_name.as_ref(), object_key.as_ref(), acl, &options)?;
58 let _ = self.do_request::<()>(request).await?;
59 Ok(())
60 }
61}
62
63#[cfg(test)]
64mod test_object_acl_async {
65 use std::sync::Once;
66
67 use reqwest::StatusCode;
68 use uuid::Uuid;
69
70 use crate::{acl::ObjectAclOperations, object::ObjectOperations, object_common::ObjectAcl, Client};
71
72 static INIT: Once = Once::new();
73
74 fn setup() {
75 INIT.call_once(|| {
76 simple_logger::init_with_level(log::Level::Debug).unwrap();
77 dotenvy::dotenv().unwrap();
78 });
79 }
80
81 #[tokio::test]
82 async fn test_object_acl_async() {
83 log::debug!("test a private object update to public");
84 setup();
85
86 let client = Client::from_env();
87
88 let bucket_name = "yuanyq";
89 let object_key = format!("rust-sdk-test/{}.jpg", Uuid::new_v4());
90 let file_path = "/home/yuanyq/Pictures/01-cover.jpg";
91
92 let response = client.put_object_from_file(bucket_name, &object_key, file_path, None).await;
93
94 assert!(response.is_ok());
95
96 let response = client.put_object_acl(bucket_name, &object_key, ObjectAcl::PublicRead, None).await;
97 assert!(response.is_ok());
98
99 let response = client.get_object_acl(bucket_name, &object_key, None).await;
100 assert!(response.is_ok());
101 let ret = response.unwrap();
102 assert_eq!(ObjectAcl::PublicRead, ret);
103
104 let url = format!("https://{}.oss-cn-beijing.aliyuncs.com/{}", bucket_name, object_key);
105 let status = reqwest::get(&url).await.unwrap().status();
106 assert_eq!(StatusCode::OK, status);
107
108 let response = client.put_object_acl(bucket_name, &object_key, ObjectAcl::Default, None).await;
109 assert!(response.is_ok());
110
111 let response = client.get_object_acl(bucket_name, &object_key, None).await;
112 assert!(response.is_ok());
113 let ret = response.unwrap();
114 assert_eq!(ObjectAcl::Default, ret);
115
116 let url = format!("https://{}.oss-cn-beijing.aliyuncs.com/{}", bucket_name, object_key);
117 let status = reqwest::get(&url).await.unwrap().status();
118 assert_eq!(StatusCode::FORBIDDEN, status);
119
120 client.delete_object(bucket_name, &object_key, None).await.unwrap();
121 }
122}