rusty_s3/actions/
get_bucket_policy.rs1use std::iter;
2use std::time::Duration;
3
4use jiff::Timestamp;
5use serde::Deserialize;
6use url::Url;
7
8use super::S3Action;
9use crate::actions::Method;
10use crate::signing::sign;
11use crate::sorting_iter::SortingIterator;
12use crate::{Bucket, Credentials, Map};
13
14const POLICY_PARAM: &str = "policy";
15
16#[derive(Debug, Clone)]
22pub struct GetBucketPolicy<'a> {
23 bucket: &'a Bucket,
24 credentials: Option<&'a Credentials>,
25
26 query: Map<'a>,
27 headers: Map<'a>,
28}
29
30#[allow(clippy::module_name_repetitions)]
31#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
32pub struct GetBucketPolicyResponse {
33 #[serde(rename = "Version")]
34 pub version: String,
35 #[serde(rename = "Id")]
36 pub id: Option<String>,
37}
38
39impl<'a> GetBucketPolicy<'a> {
40 #[inline]
41 #[must_use]
42 pub const fn new(bucket: &'a Bucket, credentials: Option<&'a Credentials>) -> Self {
43 Self {
44 bucket,
45 credentials,
46
47 query: Map::new(),
48 headers: Map::new(),
49 }
50 }
51
52 pub fn parse_response(s: &str) -> Result<GetBucketPolicyResponse, serde_json::Error> {
58 serde_json::from_str(s)
59 }
60}
61
62impl<'a> S3Action<'a> for GetBucketPolicy<'a> {
63 const METHOD: Method = Method::Get;
64
65 fn query_mut(&mut self) -> &mut Map<'a> {
66 &mut self.query
67 }
68
69 fn headers_mut(&mut self) -> &mut Map<'a> {
70 &mut self.headers
71 }
72
73 fn sign_with_time(&self, expires_in: Duration, time: &Timestamp) -> Url {
74 let url = self.bucket.base_url().clone();
75 let query = SortingIterator::new(iter::once((POLICY_PARAM, "")), self.query.iter());
76
77 match self.credentials {
78 Some(credentials) => sign(
79 time,
80 Self::METHOD,
81 url,
82 credentials.key(),
83 credentials.secret(),
84 credentials.token(),
85 self.bucket.region(),
86 expires_in.as_secs(),
87 query,
88 self.headers.iter(),
89 ),
90 None => crate::signing::util::add_query_params(url, self.query.iter()),
91 }
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use pretty_assertions::assert_eq;
98
99 use super::*;
100
101 #[test]
102 fn aws_example() -> Result<(), serde_json::Error> {
103 assert_eq!(
104 GetBucketPolicy::parse_response(r#"{"Version":"1"}"#)?,
105 GetBucketPolicyResponse {
106 version: "1".to_string(),
107 id: None
108 }
109 );
110
111 let content = r#"{
112"Version":"2008-10-17",
113"Id":"aaaa-bbbb-cccc-dddd",
114"Statement" : [
115 {
116 "Effect":"Deny",
117 "Sid":"1",
118 "Principal" : {
119 "AWS":["111122223333","444455556666"]
120 },
121 "Action":["s3:*"],
122 "Resource":"arn:aws:s3:::bucket/*"
123 }
124]
125}
126"#;
127 assert_eq!(
128 GetBucketPolicy::parse_response(content)?,
129 GetBucketPolicyResponse {
130 version: "2008-10-17".to_string(),
131 id: Some("aaaa-bbbb-cccc-dddd".to_string()),
132 }
133 );
134 Ok(())
135 }
136}