1use crate::error::S3Error;
2use crate::Region;
3
4#[allow(dead_code)]
6#[derive(Clone, Debug)]
7pub enum CannedBucketAcl {
8 Private,
9 PublicRead,
10 PublicReadWrite,
11 AuthenticatedRead,
12 Custom(String),
13}
14
15use http::header::HeaderName;
16use http::HeaderMap;
17use std::fmt;
18
19impl fmt::Display for CannedBucketAcl {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 match self {
22 CannedBucketAcl::Private => write!(f, "private"),
23 CannedBucketAcl::PublicRead => write!(f, "public-read"),
24 CannedBucketAcl::PublicReadWrite => write!(f, "public-read-write"),
25 CannedBucketAcl::AuthenticatedRead => write!(f, "authenticated-read"),
26 CannedBucketAcl::Custom(policy) => write!(f, "{policy}"),
27 }
28 }
29}
30
31#[allow(dead_code)]
33#[derive(Clone, Debug)]
34pub enum BucketAcl {
35 Id { id: String },
36 Uri { uri: String },
37 Email { email: String },
38}
39
40impl fmt::Display for BucketAcl {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 BucketAcl::Id { id } => write!(f, "id=\"{}\"", id),
44 BucketAcl::Uri { uri } => write!(f, "uri=\"{}\"", uri),
45 BucketAcl::Email { email } => write!(f, "email=\"{}\"", email),
46 }
47 }
48}
49
50#[derive(Clone, Debug)]
51pub struct BucketConfiguration {
52 acl: CannedBucketAcl,
53 object_lock_enabled: bool,
54 grant_full_control: Option<Vec<BucketAcl>>,
55 grant_read: Option<Vec<BucketAcl>>,
56 grant_read_acp: Option<Vec<BucketAcl>>,
57 grant_write: Option<Vec<BucketAcl>>,
58 grant_write_acp: Option<Vec<BucketAcl>>,
59 location_constraint: Option<Region>,
60}
61
62impl Default for BucketConfiguration {
63 fn default() -> Self {
64 BucketConfiguration::private()
65 }
66}
67
68fn acl_list(acl: &[BucketAcl]) -> String {
69 acl.iter()
70 .map(|x| x.to_string())
71 .collect::<Vec<String>>()
72 .join(",")
73}
74
75impl BucketConfiguration {
76 #[allow(clippy::too_many_arguments)]
77 pub fn new(
78 acl: CannedBucketAcl,
79 object_lock_enabled: bool,
80 grant_full_control: Option<Vec<BucketAcl>>,
81 grant_read: Option<Vec<BucketAcl>>,
82 grant_read_acp: Option<Vec<BucketAcl>>,
83 grant_write: Option<Vec<BucketAcl>>,
84 grant_write_acp: Option<Vec<BucketAcl>>,
85 location_constraint: Option<Region>,
86 ) -> Self {
87 Self {
88 acl,
89 object_lock_enabled,
90 grant_full_control,
91 grant_read,
92 grant_read_acp,
93 grant_write,
94 grant_write_acp,
95 location_constraint,
96 }
97 }
98
99 pub fn public() -> Self {
100 BucketConfiguration {
101 acl: CannedBucketAcl::PublicReadWrite,
102 object_lock_enabled: false,
103 grant_full_control: None,
104 grant_read: None,
105 grant_read_acp: None,
106 grant_write: None,
107 grant_write_acp: None,
108 location_constraint: None,
109 }
110 }
111
112 pub fn private() -> Self {
113 BucketConfiguration {
114 acl: CannedBucketAcl::Private,
115 object_lock_enabled: false,
116 grant_full_control: None,
117 grant_read: None,
118 grant_read_acp: None,
119 grant_write: None,
120 grant_write_acp: None,
121 location_constraint: None,
122 }
123 }
124
125 pub fn set_region(&mut self, region: Region) {
126 self.set_location_constraint(region)
127 }
128
129 pub fn set_location_constraint(&mut self, region: Region) {
130 self.location_constraint = Some(region)
131 }
132
133 pub fn location_constraint_payload(&self) -> Option<String> {
134 if let Some(ref location_constraint) = self.location_constraint {
135 if location_constraint == &Region::UsEast1 {
136 return None;
137 }
138 Some(format!(
139 "<CreateBucketConfiguration><LocationConstraint>{}</LocationConstraint></CreateBucketConfiguration>",
140 location_constraint
141 ))
142 } else {
143 None
144 }
145 }
146
147 pub fn add_headers(&self, headers: &mut HeaderMap) -> Result<(), S3Error> {
148 headers.insert(
149 HeaderName::from_static("x-amz-acl"),
150 self.acl.to_string().parse()?,
151 );
152 if self.object_lock_enabled {
153 headers.insert(
154 HeaderName::from_static("x-amz-bucket-object-lock-enabled"),
155 "Enabled".to_string().parse()?,
156 );
157 }
158 if let Some(ref value) = self.grant_full_control {
159 headers.insert(
160 HeaderName::from_static("x-amz-grant-full-control"),
161 acl_list(value).parse()?,
162 );
163 }
164 if let Some(ref value) = self.grant_read {
165 headers.insert(
166 HeaderName::from_static("x-amz-grant-read"),
167 acl_list(value).parse()?,
168 );
169 }
170 if let Some(ref value) = self.grant_read_acp {
171 headers.insert(
172 HeaderName::from_static("x-amz-grant-read-acp"),
173 acl_list(value).parse()?,
174 );
175 }
176 if let Some(ref value) = self.grant_write {
177 headers.insert(
178 HeaderName::from_static("x-amz-grant-write"),
179 acl_list(value).parse()?,
180 );
181 }
182 if let Some(ref value) = self.grant_write_acp {
183 headers.insert(
184 HeaderName::from_static("x-amz-grant-write-acp"),
185 acl_list(value).parse()?,
186 );
187 }
188 Ok(())
189 }
190}