feat: configurable expiry for presigned s3 public url signatures (#10835)

* feat: configurable expiry for presigned s3 public url signatures

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015JdZFeMXLGfeFNiQgx9QvA

* fix: describe expiry_secs clamping in the spec and pin the bounds in a test

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015JdZFeMXLGfeFNiQgx9QvA

* fix: omit null expiry_secs from the python sdk sign request

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015JdZFeMXLGfeFNiQgx9QvA

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Diego Imbert
2026-08-26 00:47:24 +02:00
committed by GitHub
parent 9fa8159ad1
commit 8a6dc27236
15 changed files with 322 additions and 81 deletions
+90 -1
View File
@@ -17,7 +17,11 @@
//! so two test functions sharing the one fixture workspace serve each other's stale — by then
//! deleted — filesystem root.
//!
//! Advanced S3 permissions are an enterprise feature, so this test requires the
//! A second test pins the `expiry_secs` bounds: the signature's `exp` follows the caller's
//! request, defaults to 12h, and is clamped to [60s, 7d]. It only mints signatures and never
//! fetches through the proxy, so it never populates or reads that cache.
//!
//! Advanced S3 permissions are an enterprise feature, so these tests require the
//! `enterprise` + `private` + `parquet` features.
#![cfg(all(feature = "enterprise", feature = "private", feature = "parquet"))]
@@ -175,3 +179,88 @@ async fn test_sign_s3_objects_enforces_read_authz(db: Pool<Postgres>) -> anyhow:
Ok(())
}
/// `exp` is signed into the HMAC message, so the only way a caller can influence
/// it is through `expiry_secs` — pin the default and both clamp bounds.
#[sqlx::test(fixtures("base"))]
async fn test_sign_s3_objects_expiry_secs(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
let server = ApiServer::start(db.clone()).await?;
let port = server.addr.port();
let base = format!("http://localhost:{port}/api/w/test-workspace");
let storage_dir = tempfile::tempdir()?;
configure_lfs(&db, &storage_dir.path().to_string_lossy()).await?;
async fn signed_exp(base: &str, body: serde_json::Value) -> anyhow::Result<i64> {
let resp = authed(
client().post(format!("{base}/apps/sign_s3_objects")),
"SECRET_TOKEN",
)
.json(&body)
.send()
.await?;
let status = resp.status();
let signed: serde_json::Value = resp.json().await?;
assert!(status.is_success(), "sign must succeed: {status} {signed}");
let presigned = signed[0]["presigned"]
.as_str()
.expect("sign must return a presigned string");
let exp = presigned
.split('&')
.find_map(|kv| kv.strip_prefix("exp="))
.expect("presigned string must carry exp");
Ok(exp.parse::<i64>()?)
}
let key = json!([{ "s3": "allowed/file.txt" }]);
// The handler stamps `now` itself, so assert on a window rather than an exact value.
// Keep the window well under the 60s lower bound, or an unclamped 1s would pass.
let ttl_around = |exp: i64| exp - chrono::Utc::now().timestamp();
let tolerance = 30;
let default_ttl = ttl_around(signed_exp(&base, json!({ "s3_objects": key.clone() })).await?);
assert!(
(43200 - tolerance..=43200).contains(&default_ttl),
"omitting expiry_secs must keep the 12h default, got {default_ttl}s"
);
let honored = ttl_around(
signed_exp(
&base,
json!({ "s3_objects": key.clone(), "expiry_secs": 300 }),
)
.await?,
);
assert!(
(300 - tolerance..=300).contains(&honored),
"expiry_secs must be honored verbatim inside the bounds, got {honored}s"
);
let clamped_low = ttl_around(
signed_exp(
&base,
json!({ "s3_objects": key.clone(), "expiry_secs": 1 }),
)
.await?,
);
assert!(
(60 - tolerance..=60).contains(&clamped_low),
"expiry_secs below 60s must clamp up to 60s, got {clamped_low}s"
);
let clamped_high = ttl_around(
signed_exp(
&base,
json!({ "s3_objects": key.clone(), "expiry_secs": 99_999_999 }),
)
.await?,
);
assert!(
(604800 - tolerance..=604800).contains(&clamped_high),
"expiry_secs above 7d must clamp down to 7d, got {clamped_high}s"
);
Ok(())
}
+4
View File
@@ -13468,6 +13468,10 @@ paths:
type: array
items:
$ref: "#/components/schemas/S3Object"
expiry_secs:
type: integer
format: int64
description: how long the signature stays valid, in seconds. Defaults to 43200 (12h) and is clamped server-side to [60, 604800] (1 minute to 7 days).
required:
- s3_objects
responses:
+14 -1
View File
@@ -4112,10 +4112,18 @@ struct S3DeleteTokenClaims {
pub exp: usize,
}
#[cfg(feature = "parquet")]
const SIGN_S3_DEFAULT_EXPIRY_SECS: i64 = 12 * 60 * 60;
#[cfg(feature = "parquet")]
const SIGN_S3_MIN_EXPIRY_SECS: i64 = 60;
#[cfg(feature = "parquet")]
const SIGN_S3_MAX_EXPIRY_SECS: i64 = 7 * 24 * 60 * 60;
#[cfg(feature = "parquet")]
#[derive(Deserialize)]
struct S3TokenRequestBody {
s3_objects: Vec<S3Object>,
expiry_secs: Option<i64>,
}
#[cfg(feature = "parquet")]
async fn sign_s3_objects(
@@ -4126,6 +4134,12 @@ async fn sign_s3_objects(
) -> Result<Json<Vec<S3Object>>> {
let workspace_key = get_workspace_key(&w_id, &db).await?;
let expiry_secs = body
.expiry_secs
.unwrap_or(SIGN_S3_DEFAULT_EXPIRY_SECS)
.clamp(SIGN_S3_MIN_EXPIRY_SECS, SIGN_S3_MAX_EXPIRY_SECS);
let exp = (chrono::Utc::now() + chrono::Duration::seconds(expiry_secs)).timestamp();
let futures = body.s3_objects.into_iter().map(|s3_object| async {
// The signature this mints is a transferable bearer capability: `validate_s3_signature`
// only checks the HMAC and expiry, so anyone who obtains the string can read this key.
@@ -4156,7 +4170,6 @@ async fn sign_s3_objects(
)
.await?;
let exp = (chrono::Utc::now() + chrono::Duration::hours(12)).timestamp();
let message = format!(
"file_key={}&exp={}{}",
s3_object.s3.clone(),
+36 -16
View File
@@ -848,31 +848,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -1631,31 +1635,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -2508,31 +2516,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -4225,19 +4237,23 @@ def delete_s3_object(s3object: S3Object | str, s3_resource_path: str | None = No
#
# Args:
# s3_objects: List of S3 objects to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed S3 objects
def sign_s3_objects(s3_objects: list[S3Object | str]) -> list[S3Object]
def sign_s3_objects(s3_objects: list[S3Object | str], expiry_secs: int | None = None) -> list[S3Object]
# Sign a single S3 object for use by anonymous users in public apps.
#
# Args:
# s3_object: S3 object to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed S3 object
def sign_s3_object(s3_object: S3Object | str) -> S3Object
def sign_s3_object(s3_object: S3Object | str, expiry_secs: int | None = None) -> S3Object
# Generate presigned public URLs for an array of S3 objects.
# If an S3 object is not signed yet, it will be signed first.
@@ -4245,6 +4261,8 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Args:
# s3_objects: List of S3 objects to sign
# base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
# expiry_secs: How long the signatures stay valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed public URLs
@@ -4252,7 +4270,7 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Example:
# >>> s3_objs = [S3Object(s3="/path/to/file1.txt"), S3Object(s3="/path/to/file2.txt")]
# >>> urls = client.get_presigned_s3_public_urls(s3_objs)
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None) -> list[str]
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None, expiry_secs: int | None = None) -> list[str]
# Generate a presigned public URL for an S3 object.
# If the S3 object is not signed yet, it will be signed first.
@@ -4260,6 +4278,8 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Args:
# s3_object: S3 object to sign
# base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed public URL
@@ -4267,7 +4287,7 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Example:
# >>> s3_obj = S3Object(s3="/path/to/file.txt")
# >>> url = client.get_presigned_s3_public_url(s3_obj)
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None) -> str
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None, expiry_secs: int | None = None) -> str
# Get the current user information.
#
+50 -12
View File
@@ -31,6 +31,15 @@ logger = logging.getLogger("windmill_client")
JobStatus = Literal["RUNNING", "WAITING", "COMPLETED"]
def _sign_s3_objects_body(s3_objects: list, expiry_secs: int | None) -> dict:
# `expiry_secs` is optional but not nullable in the spec, so omit it rather than
# sending an explicit null a validating gateway would reject.
body: dict = {"s3_objects": s3_objects}
if expiry_secs is not None:
body["expiry_secs"] = expiry_secs
return body
class Windmill:
"""Windmill client for interacting with the Windmill API."""
@@ -1044,37 +1053,45 @@ class Windmill:
except Exception as e:
raise Exception("Could not delete file from S3") from e
def sign_s3_objects(self, s3_objects: list[S3Object | str]) -> list[S3Object]:
def sign_s3_objects(
self, s3_objects: list[S3Object | str], expiry_secs: int | None = None
) -> list[S3Object]:
"""Sign S3 objects for use by anonymous users in public apps.
Args:
s3_objects: List of S3 objects to sign
expiry_secs: How long the signature stays valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
Returns:
List of signed S3 objects
"""
return self.post(
f"/w/{self.workspace}/apps/sign_s3_objects", json={"s3_objects": list(map(parse_s3_object, s3_objects))}
f"/w/{self.workspace}/apps/sign_s3_objects",
json=_sign_s3_objects_body(list(map(parse_s3_object, s3_objects)), expiry_secs),
).json()
def sign_s3_object(self, s3_object: S3Object | str) -> S3Object:
def sign_s3_object(self, s3_object: S3Object | str, expiry_secs: int | None = None) -> S3Object:
"""Sign a single S3 object for use by anonymous users in public apps.
Args:
s3_object: S3 object to sign
expiry_secs: How long the signature stays valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
Returns:
Signed S3 object
"""
return self.post(
f"/w/{self.workspace}/apps/sign_s3_objects",
json={"s3_objects": [s3_object]},
json=_sign_s3_objects_body([s3_object], expiry_secs),
).json()[0]
def get_presigned_s3_public_urls(
self,
s3_objects: list[S3Object | str],
base_url: str | None = None,
expiry_secs: int | None = None,
) -> list[str]:
"""
Generate presigned public URLs for an array of S3 objects.
@@ -1083,6 +1100,8 @@ class Windmill:
Args:
s3_objects: List of S3 objects to sign
base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
expiry_secs: How long the signatures stay valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
Returns:
List of signed public URLs
@@ -1104,7 +1123,7 @@ class Windmill:
if s3_objs_to_sign:
signed_s3_objs = self.sign_s3_objects(
[s3_obj for s3_obj, _ in s3_objs_to_sign]
[s3_obj for s3_obj, _ in s3_objs_to_sign], expiry_secs
)
for i, (_, original_index) in enumerate(s3_objs_to_sign):
s3_objs[original_index] = parse_s3_object(signed_s3_objs[i])
@@ -1123,6 +1142,7 @@ class Windmill:
self,
s3_object: S3Object | str,
base_url: str | None = None,
expiry_secs: int | None = None,
) -> str:
"""
Generate a presigned public URL for an S3 object.
@@ -1131,6 +1151,8 @@ class Windmill:
Args:
s3_object: S3 object to sign
base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
expiry_secs: How long the signature stays valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
Returns:
Signed public URL
@@ -1139,7 +1161,7 @@ class Windmill:
>>> s3_obj = S3Object(s3="/path/to/file.txt")
>>> url = client.get_presigned_s3_public_url(s3_obj)
"""
urls = self.get_presigned_s3_public_urls([s3_object], base_url)
urls = self.get_presigned_s3_public_urls([s3_object], base_url, expiry_secs)
return urls[0]
def _get_public_base_url(self) -> str:
@@ -1814,27 +1836,38 @@ def delete_s3_object(
@init_global_client
def sign_s3_objects(s3_objects: list[S3Object | str]) -> list[S3Object]:
def sign_s3_objects(s3_objects: list[S3Object | str], expiry_secs: int | None = None) -> list[S3Object]:
"""
Sign S3 objects to be used by anonymous users in public apps
Returns a list of signed s3 tokens
Args:
s3_objects: List of S3 objects to sign
expiry_secs: How long the signatures stay valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
"""
return _client.sign_s3_objects(s3_objects)
return _client.sign_s3_objects(s3_objects, expiry_secs)
@init_global_client
def sign_s3_object(s3_object: S3Object| str) -> S3Object:
def sign_s3_object(s3_object: S3Object| str, expiry_secs: int | None = None) -> S3Object:
"""
Sign S3 object to be used by anonymous users in public apps
Returns a signed s3 object
Args:
s3_object: S3 object to sign
expiry_secs: How long the signature stays valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
"""
return _client.sign_s3_object(s3_object)
return _client.sign_s3_object(s3_object, expiry_secs)
@init_global_client
def get_presigned_s3_public_urls(
s3_objects: list[S3Object | str],
base_url: str | None = None,
expiry_secs: int | None = None,
) -> list[str]:
"""
Generate presigned public URLs for an array of S3 objects.
@@ -1843,6 +1876,8 @@ def get_presigned_s3_public_urls(
Args:
s3_objects: List of S3 objects to sign
base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
expiry_secs: How long the signatures stay valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
Returns:
List of signed public URLs
@@ -1853,13 +1888,14 @@ def get_presigned_s3_public_urls(
>>> s3_objs = [S3Object(s3="/path/to/file1.txt"), S3Object(s3="/path/to/file2.txt")]
>>> urls = wmill.get_presigned_s3_public_urls(s3_objs)
"""
return _client.get_presigned_s3_public_urls(s3_objects, base_url)
return _client.get_presigned_s3_public_urls(s3_objects, base_url, expiry_secs)
@init_global_client
def get_presigned_s3_public_url(
s3_object: S3Object | str,
base_url: str | None = None,
expiry_secs: int | None = None,
) -> str:
"""
Generate a presigned public URL for an S3 object.
@@ -1868,6 +1904,8 @@ def get_presigned_s3_public_url(
Args:
s3_object: S3 object to sign
base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
expiry_secs: How long the signature stays valid, in seconds
(defaults to 43200 = 12h, clamped to [60, 604800])
Returns:
Signed public URL
@@ -1878,7 +1916,7 @@ def get_presigned_s3_public_url(
>>> s3_obj = S3Object(s3="/path/to/file.txt")
>>> url = wmill.get_presigned_s3_public_url(s3_obj)
"""
return _client.get_presigned_s3_public_url(s3_object, base_url)
return _client.get_presigned_s3_public_url(s3_object, base_url, expiry_secs)
@init_global_client
+20 -8
View File
@@ -1546,31 +1546,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -2169,19 +2173,23 @@ def delete_s3_object(s3object: S3Object | str, s3_resource_path: str | None = No
#
# Args:
# s3_objects: List of S3 objects to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed S3 objects
def sign_s3_objects(s3_objects: list[S3Object | str]) -> list[S3Object]
def sign_s3_objects(s3_objects: list[S3Object | str], expiry_secs: int | None = None) -> list[S3Object]
# Sign a single S3 object for use by anonymous users in public apps.
#
# Args:
# s3_object: S3 object to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed S3 object
def sign_s3_object(s3_object: S3Object | str) -> S3Object
def sign_s3_object(s3_object: S3Object | str, expiry_secs: int | None = None) -> S3Object
# Generate presigned public URLs for an array of S3 objects.
# If an S3 object is not signed yet, it will be signed first.
@@ -2189,6 +2197,8 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Args:
# s3_objects: List of S3 objects to sign
# base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
# expiry_secs: How long the signatures stay valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed public URLs
@@ -2196,7 +2206,7 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Example:
# >>> s3_objs = [S3Object(s3="/path/to/file1.txt"), S3Object(s3="/path/to/file2.txt")]
# >>> urls = client.get_presigned_s3_public_urls(s3_objs)
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None) -> list[str]
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None, expiry_secs: int | None = None) -> list[str]
# Generate a presigned public URL for an S3 object.
# If the S3 object is not signed yet, it will be signed first.
@@ -2204,6 +2214,8 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Args:
# s3_object: S3 object to sign
# base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed public URL
@@ -2211,7 +2223,7 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Example:
# >>> s3_obj = S3Object(s3="/path/to/file.txt")
# >>> url = client.get_presigned_s3_public_url(s3_obj)
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None) -> str
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None, expiry_secs: int | None = None) -> str
# Get the current user information.
#
+20 -8
View File
@@ -1738,31 +1738,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -2361,19 +2365,23 @@ def delete_s3_object(s3object: S3Object | str, s3_resource_path: str | None = No
#
# Args:
# s3_objects: List of S3 objects to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed S3 objects
def sign_s3_objects(s3_objects: list[S3Object | str]) -> list[S3Object]
def sign_s3_objects(s3_objects: list[S3Object | str], expiry_secs: int | None = None) -> list[S3Object]
# Sign a single S3 object for use by anonymous users in public apps.
#
# Args:
# s3_object: S3 object to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed S3 object
def sign_s3_object(s3_object: S3Object | str) -> S3Object
def sign_s3_object(s3_object: S3Object | str, expiry_secs: int | None = None) -> S3Object
# Generate presigned public URLs for an array of S3 objects.
# If an S3 object is not signed yet, it will be signed first.
@@ -2381,6 +2389,8 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Args:
# s3_objects: List of S3 objects to sign
# base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
# expiry_secs: How long the signatures stay valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed public URLs
@@ -2388,7 +2398,7 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Example:
# >>> s3_objs = [S3Object(s3="/path/to/file1.txt"), S3Object(s3="/path/to/file2.txt")]
# >>> urls = client.get_presigned_s3_public_urls(s3_objs)
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None) -> list[str]
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None, expiry_secs: int | None = None) -> list[str]
# Generate a presigned public URL for an S3 object.
# If the S3 object is not signed yet, it will be signed first.
@@ -2396,6 +2406,8 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Args:
# s3_object: S3 object to sign
# base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed public URL
@@ -2403,7 +2415,7 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Example:
# >>> s3_obj = S3Object(s3="/path/to/file.txt")
# >>> url = client.get_presigned_s3_public_url(s3_obj)
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None) -> str
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None, expiry_secs: int | None = None) -> str
# Get the current user information.
#
+12 -4
View File
@@ -313,19 +313,23 @@ def delete_s3_object(s3object: S3Object | str, s3_resource_path: str | None = No
#
# Args:
# s3_objects: List of S3 objects to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed S3 objects
def sign_s3_objects(s3_objects: list[S3Object | str]) -> list[S3Object]
def sign_s3_objects(s3_objects: list[S3Object | str], expiry_secs: int | None = None) -> list[S3Object]
# Sign a single S3 object for use by anonymous users in public apps.
#
# Args:
# s3_object: S3 object to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed S3 object
def sign_s3_object(s3_object: S3Object | str) -> S3Object
def sign_s3_object(s3_object: S3Object | str, expiry_secs: int | None = None) -> S3Object
# Generate presigned public URLs for an array of S3 objects.
# If an S3 object is not signed yet, it will be signed first.
@@ -333,6 +337,8 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Args:
# s3_objects: List of S3 objects to sign
# base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
# expiry_secs: How long the signatures stay valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed public URLs
@@ -340,7 +346,7 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Example:
# >>> s3_objs = [S3Object(s3="/path/to/file1.txt"), S3Object(s3="/path/to/file2.txt")]
# >>> urls = client.get_presigned_s3_public_urls(s3_objs)
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None) -> list[str]
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None, expiry_secs: int | None = None) -> list[str]
# Generate a presigned public URL for an S3 object.
# If the S3 object is not signed yet, it will be signed first.
@@ -348,6 +354,8 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Args:
# s3_object: S3 object to sign
# base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed public URL
@@ -355,7 +363,7 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Example:
# >>> s3_obj = S3Object(s3="/path/to/file.txt")
# >>> url = client.get_presigned_s3_public_url(s3_obj)
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None) -> str
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None, expiry_secs: int | None = None) -> str
# Get the current user information.
#
@@ -303,31 +303,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -474,31 +474,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -474,31 +474,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -476,31 +476,35 @@ async deleteS3File(s3object: S3Object, workspace: string | undefined = undefined
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
async signS3Objects(s3objects: S3Object[]): Promise<S3Object[]>
async signS3Objects(s3objects: S3Object[], { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object[]>
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
async signS3Object(s3object: S3Object): Promise<S3Object>
async signS3Object(s3object: S3Object, { expirySecs }: { expirySecs?: number } = {}): Promise<S3Object>
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl }: { baseUrl?: string } = {}): Promise<string[]>
async getPresignedS3PublicUrls(s3Objects: S3Object[], { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string[]>
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl }: { baseUrl?: string } = {}): Promise<string>
async getPresignedS3PublicUrl(s3Objects: S3Object, { baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}): Promise<string>
/**
* Get URLs needed for resuming a flow after this step
@@ -498,19 +498,23 @@ def delete_s3_object(s3object: S3Object | str, s3_resource_path: str | None = No
#
# Args:
# s3_objects: List of S3 objects to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed S3 objects
def sign_s3_objects(s3_objects: list[S3Object | str]) -> list[S3Object]
def sign_s3_objects(s3_objects: list[S3Object | str], expiry_secs: int | None = None) -> list[S3Object]
# Sign a single S3 object for use by anonymous users in public apps.
#
# Args:
# s3_object: S3 object to sign
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed S3 object
def sign_s3_object(s3_object: S3Object | str) -> S3Object
def sign_s3_object(s3_object: S3Object | str, expiry_secs: int | None = None) -> S3Object
# Generate presigned public URLs for an array of S3 objects.
# If an S3 object is not signed yet, it will be signed first.
@@ -518,6 +522,8 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Args:
# s3_objects: List of S3 objects to sign
# base_url: Optional base URL for the presigned URLs (defaults to WM_BASE_URL)
# expiry_secs: How long the signatures stay valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# List of signed public URLs
@@ -525,7 +531,7 @@ def sign_s3_object(s3_object: S3Object | str) -> S3Object
# Example:
# >>> s3_objs = [S3Object(s3="/path/to/file1.txt"), S3Object(s3="/path/to/file2.txt")]
# >>> urls = client.get_presigned_s3_public_urls(s3_objs)
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None) -> list[str]
def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str | None = None, expiry_secs: int | None = None) -> list[str]
# Generate a presigned public URL for an S3 object.
# If the S3 object is not signed yet, it will be signed first.
@@ -533,6 +539,8 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Args:
# s3_object: S3 object to sign
# base_url: Optional base URL for the presigned URL (defaults to WM_BASE_URL)
# expiry_secs: How long the signature stays valid, in seconds
# (defaults to 43200 = 12h, clamped to [60, 604800])
#
# Returns:
# Signed public URL
@@ -540,7 +548,7 @@ def get_presigned_s3_public_urls(s3_objects: list[S3Object | str], base_url: str
# Example:
# >>> s3_obj = S3Object(s3="/path/to/file.txt")
# >>> url = client.get_presigned_s3_public_url(s3_obj)
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None) -> str
def get_presigned_s3_public_url(s3_object: S3Object | str, base_url: str | None = None, expiry_secs: int | None = None) -> str
# Get the current user information.
#
+12 -4
View File
@@ -200,37 +200,45 @@ export declare function writeS3File(
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
export declare function signS3Objects(
s3objects: S3Object[]
s3objects: S3Object[],
{ expirySecs }?: { expirySecs?: number }
): Promise<S3Object[]>;
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
export declare function signS3Object(s3object: S3Object): Promise<S3Object>;
export declare function signS3Object(
s3object: S3Object,
{ expirySecs }?: { expirySecs?: number }
): Promise<S3Object>;
/**
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
export declare function getPresignedS3PublicUrls(
s3Objects: S3Object[],
{ baseUrl }: { baseUrl?: string }
{ baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number }
): Promise<string[]>;
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
export declare function getPresignedS3PublicUrl(
s3Objects: S3Object,
{ baseUrl }: { baseUrl?: string }
{ baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number }
): Promise<string>;
/**
+20 -7
View File
@@ -1057,15 +1057,18 @@ export async function deleteS3File(
/**
* Sign S3 objects to be used by anonymous users in public apps
* @param s3objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 objects
*/
export async function signS3Objects(
s3objects: S3Object[]
s3objects: S3Object[],
{ expirySecs }: { expirySecs?: number } = {}
): Promise<S3Object[]> {
const signedKeys = await AppService.signS3Objects({
workspace: getWorkspace(),
requestBody: {
s3_objects: s3objects.map(parseS3Object),
expiry_secs: expirySecs,
},
});
return signedKeys;
@@ -1073,10 +1076,14 @@ export async function signS3Objects(
/**
* Sign S3 object to be used by anonymous users in public apps
* @param s3object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed s3 object
*/
export async function signS3Object(s3object: S3Object): Promise<S3Object> {
const [signedObject] = await signS3Objects([s3object]);
export async function signS3Object(
s3object: S3Object,
{ expirySecs }: { expirySecs?: number } = {}
): Promise<S3Object> {
const [signedObject] = await signS3Objects([s3object], { expirySecs });
return signedObject;
}
@@ -1084,11 +1091,12 @@ export async function signS3Object(s3object: S3Object): Promise<S3Object> {
* Generate a presigned public URL for an array of S3 objects.
* If an S3 object is not signed yet, it will be signed first.
* @param s3Objects s3 objects to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns list of signed public URLs
*/
export async function getPresignedS3PublicUrls(
s3Objects: S3Object[],
{ baseUrl }: { baseUrl?: string } = {}
{ baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}
): Promise<string[]> {
baseUrl ??= getPublicBaseUrl();
@@ -1100,7 +1108,8 @@ export async function getPresignedS3PublicUrls(
.filter(([s3Obj, _]) => s3Obj.presigned === undefined);
if (s3ObjsToSign.length > 0) {
const signedS3Objs = await signS3Objects(
s3ObjsToSign.map(([s3Obj, _]) => s3Obj)
s3ObjsToSign.map(([s3Obj, _]) => s3Obj),
{ expirySecs }
);
for (let i = 0; i < s3ObjsToSign.length; i++) {
const [_, originalIndex] = s3ObjsToSign[i];
@@ -1120,13 +1129,17 @@ export async function getPresignedS3PublicUrls(
/**
* Generate a presigned public URL for an S3 object. If the S3 object is not signed yet, it will be signed first.
* @param s3Object s3 object to sign
* @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])
* @returns signed public URL
*/
export async function getPresignedS3PublicUrl(
s3Objects: S3Object,
{ baseUrl }: { baseUrl?: string } = {}
{ baseUrl, expirySecs }: { baseUrl?: string; expirySecs?: number } = {}
): Promise<string> {
const [s3Object] = await getPresignedS3PublicUrls([s3Objects], { baseUrl });
const [s3Object] = await getPresignedS3PublicUrls([s3Objects], {
baseUrl,
expirySecs,
});
return s3Object;
}