Skip to content

Commit

Permalink
Added automatic bucket creation with public download policy on initia…
Browse files Browse the repository at this point in the history
…lization
  • Loading branch information
Mervin committed Jun 4, 2024
1 parent 3c1ec26 commit e47fa3b
Showing 1 changed file with 82 additions and 5 deletions.
87 changes: 82 additions & 5 deletions server/dal/src/storage_engine.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use std::ops::Deref;
use std::time::{Duration, Instant};

use aws_credential_types::Credentials;
use aws_sdk_s3::error::HeadBucketError;
use aws_sdk_s3::presigning::config::PresigningConfig;
use aws_sdk_s3::types::ByteStream;
use aws_sdk_s3::{Client, Config};
use aws_smithy_http::result::SdkError;
use aws_types::region::Region;
use std::ops::Deref;
use std::time::Duration;
use strum_macros::Display;
use tracing::log::info;

#[derive(Debug, Clone, PartialEq, Display)]
pub enum PhotoQuality {
Expand All @@ -29,14 +33,16 @@ pub mod aws_error {
}

pub mod error {
use aws_sdk_s3::error::{DeleteObjectError, GetObjectError, PutObjectError};
use aws_sdk_s3::error::{DeleteObjectError, GetObjectError, HeadBucketError, PutObjectError};
pub use aws_sdk_s3::types::SdkError;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum InitError {
#[error("Invalid App name provided")]
AppName(#[from] aws_types::app_name::InvalidAppName),
#[error("Failed to retrieve information about Bucket: {0}")]
HeadBucket(#[from] SdkError<HeadBucketError>),
}

#[derive(Debug, Error)]
Expand Down Expand Up @@ -92,6 +98,8 @@ impl Storage {
.build(),
);

Self::setup_bucket(&client, &config.bucket_name).await?;

Ok(Storage {
client,
bucket_name: config.bucket_name,
Expand All @@ -114,9 +122,9 @@ impl Storage {
.presigned(PresigningConfig::expires_in(Duration::from_secs(6000))?)
.await?;

let url = response.uri();
let url = String::from(response.uri().to_string().split('?').next().unwrap());

Ok(url.to_string())
Ok(url)
}

pub async fn get_photo_bytes_by_id<S: AsRef<str>>(
Expand Down Expand Up @@ -178,6 +186,75 @@ impl Storage {
Ok(())
}

async fn setup_bucket(
client: &Client,
bucket_name: &String,
) -> Result<(), SdkError<HeadBucketError>> {
if let Err(err) = client.head_bucket().bucket(bucket_name).send().await {
match err {
SdkError::ServiceError(ref error) => {
// If the error is not found, a new bucket can be created, otherwise rethrow the error
if error.err().is_not_found() {
// Track how long the bucket creation takes
let start = Instant::now();

// Create the bucket
client
.create_bucket()
.bucket(bucket_name)
.send()
.await
.expect("failed to create new bucket");

// Update the bucket access policy
client
.put_bucket_policy()
.bucket(bucket_name)
.policy(format!(
r#"{{
"Version": "2012-10-17",
"Statement": [
{{
"Effect": "Allow",
"Principal": {{
"AWS": [
"*"
]
}},
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::{}/*"
]
}}
]
}}"#,
bucket_name
))
.send()
.await
.expect("failed to set bucket policy");

// Stop the timer
let duration = start.elapsed();

// Log the duration of the bucket creation
info!(
"bucket '{}' did not exist yet; created new bucket (took {:?})",
bucket_name, duration
);
} else {
return Err(err);
}
}
_ => return Err(err),
}
}

Ok(())
}

fn format_id_with_quality(photo_id: &str, photo_quality: PhotoQuality) -> String {
format!("{}_{}", photo_id, photo_quality)
}
Expand Down

0 comments on commit e47fa3b

Please sign in to comment.