Skip to content

Commit 8bab5cd

Browse files
committed
feat: switch to presigned URLs, remove public-read ACL
- Upload without public-read ACL (private by default) - Generate 24h presigned GET URL after upload - Remove S3_PUBLIC_URL env var (no longer needed)
1 parent 9d43399 commit 8bab5cd

4 files changed

Lines changed: 20 additions & 12 deletions

File tree

agents/.do/app.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ services:
2929
- key: S3_REGION
3030
scope: RUN_TIME
3131
value: nyc3
32-
- key: S3_PUBLIC_URL
33-
scope: RUN_TIME
34-
value: https://agent-pdf.nyc3.cdn.digitaloceanspaces.com
3532
- key: DEFAULT_EDITOR_HOST
3633
scope: RUN_TIME
3734
value: ai.simplepdf.com

agents/src/config.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ pub struct Config {
22
pub s3_endpoint: String,
33
pub s3_bucket: String,
44
pub s3_region: String,
5-
pub s3_public_url: String,
65
pub default_editor_host: String,
76
pub rate_limit_per_minute: u32,
87
pub trust_proxy: bool,
@@ -14,7 +13,6 @@ impl Config {
1413
s3_endpoint: env("S3_ENDPOINT"),
1514
s3_bucket: env("S3_BUCKET"),
1615
s3_region: env("S3_REGION"),
17-
s3_public_url: env("S3_PUBLIC_URL"),
1816
default_editor_host: env("DEFAULT_EDITOR_HOST"),
1917
rate_limit_per_minute: env("RATE_LIMIT_PER_MIN")
2018
.parse()

agents/src/routes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ async fn handle_post(
142142
let result = state.storage.upload(pdf_bytes).await?;
143143

144144
Ok(Json(AgentResponse::new(
145-
&result.public_url,
145+
&result.presigned_url,
146146
&editor_base,
147147
company_identifier,
148148
)))

agents/src/storage.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1+
use aws_sdk_s3::presigning::PresigningConfig;
12
use aws_sdk_s3::primitives::ByteStream;
23
use aws_sdk_s3::Client;
4+
use std::time::Duration;
35
use uuid::Uuid;
46

57
use crate::config::Config;
68
use crate::error::AppError;
79

10+
const PRESIGN_EXPIRY: Duration = Duration::from_secs(24 * 60 * 60);
11+
812
pub struct Storage {
913
client: Client,
1014
bucket: String,
11-
public_url: String,
1215
}
1316

1417
pub struct UploadResult {
15-
pub public_url: String,
18+
pub presigned_url: String,
1619
}
1720

1821
impl Storage {
@@ -36,7 +39,6 @@ impl Storage {
3639
Self {
3740
client: Client::from_conf(s3_config),
3841
bucket: config.s3_bucket.clone(),
39-
public_url: config.s3_public_url.clone(),
4042
}
4143
}
4244

@@ -55,13 +57,24 @@ impl Storage {
5557
.body(ByteStream::from(bytes))
5658
.content_type("application/pdf")
5759
.content_disposition("attachment")
58-
.acl(aws_sdk_s3::types::ObjectCannedAcl::PublicRead)
5960
.send()
6061
.await
6162
.map_err(|e| AppError::StorageFailed(e.to_string()))?;
6263

63-
let public_url = format!("{}/{key}", self.public_url);
64+
let presign_config = PresigningConfig::expires_in(PRESIGN_EXPIRY)
65+
.map_err(|e| AppError::StorageFailed(e.to_string()))?;
66+
67+
let presigned_url = self
68+
.client
69+
.get_object()
70+
.bucket(&self.bucket)
71+
.key(&key)
72+
.presigned(presign_config)
73+
.await
74+
.map_err(|e| AppError::StorageFailed(e.to_string()))?
75+
.uri()
76+
.to_string();
6477

65-
Ok(UploadResult { public_url })
78+
Ok(UploadResult { presigned_url })
6679
}
6780
}

0 commit comments

Comments
 (0)