From d0046764a10d02886e7d0bce7fb60d844574a8be Mon Sep 17 00:00:00 2001 From: Stu Alexander Date: Sun, 13 Sep 2026 18:48:26 +0100 Subject: [PATCH] fix(api): accept is_server in S3Storage so v1 asset endpoints stop 500ing plane/api/views/asset.py constructs `S3Storage(request=request, is_server=True)` in three places, but `S3Storage.__init__` only takes `request`. Every call raised TypeError, so all three public-API asset endpoints answered 500 -- including GET /api/v1/workspaces/{slug}/assets/{asset_id}/, the only x-api-key route that turns a comment image's asset id into a download URL. Found because psyclo relays a developer's comment images to a bug reporter by email: the fetch failed on every image, silently. The argument is accepted and has no effect yet. Its callers hand the presigned URL to a client outside Plane's network, so the public endpoint -- the existing default -- is already what they need. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SsBurBNYE4Wxpx2k6atqcj --- apps/api/plane/settings/storage.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/api/plane/settings/storage.py b/apps/api/plane/settings/storage.py index e4a978bd2b1..be0a691b874 100644 --- a/apps/api/plane/settings/storage.py +++ b/apps/api/plane/settings/storage.py @@ -22,7 +22,15 @@ def url(self, name, parameters=None, expire=None, http_method=None): """S3 storage class to generate presigned URLs for S3 objects""" - def __init__(self, request=None): + def __init__(self, request=None, is_server=False): + # `is_server` is passed by the three public-API asset views + # (plane/api/views/asset.py) but was never accepted here, so every call + # to GET /api/v1/workspaces/{slug}/assets/{id}/ and the two upload + # endpoints raised TypeError and answered 500. It is accepted and + # currently has no effect: those callers hand the presigned URL to a + # client OUTSIDE Plane's network, so the public endpoint -- the existing + # behaviour -- is the correct one for them anyway. + self.is_server = is_server # Get the AWS credentials and bucket name from the environment self.aws_access_key_id = os.environ.get("AWS_ACCESS_KEY_ID") # Use the AWS_SECRET_ACCESS_KEY environment variable for the secret key