From 4a0166b80e468ebab7718c3ef6144628a69e76cc Mon Sep 17 00:00:00 2001 From: abhiramtx <7253115-abhiramtx@users.noreply.replit.com> Date: Sat, 13 Dec 2025 21:37:17 +0000 Subject: [PATCH] Update file uploads to use signed URLs from Replit's sidecar service Rewrite object_storage.py to utilize the Replit sidecar endpoint for generating signed URLs for file uploads, replacing direct Google Cloud Storage client interactions. Replit-Commit-Author: Agent Replit-Commit-Session-Id: cd9a7d26-a4e5-4215-975c-c59f4ed1f06d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 3bc03de1-efba-4e8b-802f-990f440ce8da Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d0a1d46d-d203-4308-bc6a-312ac7c0243b/cd9a7d26-a4e5-4215-975c-c59f4ed1f06d/05bPjFc --- attached_assets/image_1765661730127.png | Bin 0 -> 4825 bytes attached_assets/image_1765661747621.png | Bin 0 -> 17719 bytes object_storage.py | 91 +++++++++++------------- static/images/dr5qp.jpg | Bin 0 -> 4625 bytes 4 files changed, 41 insertions(+), 50 deletions(-) create mode 100644 attached_assets/image_1765661730127.png create mode 100644 attached_assets/image_1765661747621.png create mode 100644 static/images/dr5qp.jpg diff --git a/attached_assets/image_1765661730127.png b/attached_assets/image_1765661730127.png new file mode 100644 index 0000000000000000000000000000000000000000..1559b144494840fe602184f5e0acaf9721c3fbf0 GIT binary patch literal 4825 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

^6@}^2(yf*>Bz{4dgDRF=^3hWrpj{L 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 literal 0 HcmV?d00001 diff --git a/object_storage.py b/object_storage.py index 0a1d963..53277ea 100644 --- a/object_storage.py +++ b/object_storage.py @@ -1,60 +1,57 @@ """ Object Storage Service for FTC Team Website -Handles persistent file uploads using Google Cloud Storage (Replit Object Storage) +Handles persistent file uploads using Replit Object Storage (via sidecar signed URLs) """ -from google.cloud import storage -from google.auth import identity_pool import os -import json +import requests from uuid import uuid4 from werkzeug.utils import secure_filename +from datetime import datetime, timedelta REPLIT_SIDECAR_ENDPOINT = "http://127.0.0.1:1106" -def get_replit_credentials(): - """Create proper credentials for Replit Object Storage""" - credentials_config = { - "audience": "replit", - "subject_token_type": "access_token", - "token_url": f"{REPLIT_SIDECAR_ENDPOINT}/token", - "type": "external_account", - "credential_source": { - "url": f"{REPLIT_SIDECAR_ENDPOINT}/credential", - "format": { - "type": "json", - "subject_token_field_name": "access_token", - }, - }, - "universe_domain": "googleapis.com", +def get_signed_upload_url(bucket_name, object_name, ttl_sec=900): + """Get a signed URL for uploading to object storage""" + request_data = { + "bucket_name": bucket_name, + "object_name": object_name, + "method": "PUT", + "expires_at": (datetime.utcnow() + timedelta(seconds=ttl_sec)).isoformat() + "Z" } - credentials = identity_pool.Credentials.from_info(credentials_config) - return credentials + response = requests.post( + f"{REPLIT_SIDECAR_ENDPOINT}/object-storage/signed-object-url", + json=request_data, + headers={"Content-Type": "application/json"} + ) + + if not response.ok: + raise Exception(f"Failed to get signed URL: {response.status_code} - {response.text}") + + data = response.json() + return data.get("signed_url") + + +def get_public_url(bucket_name, object_name): + """Get the public URL for an object""" + return f"https://storage.googleapis.com/{bucket_name}/{object_name}" class ObjectStorageService: def __init__(self): - """Initialize the object storage client with Replit credentials""" - credentials = get_replit_credentials() - self.client = storage.Client( - credentials=credentials, - project="", - ) - + """Initialize the object storage service""" self.bucket_name = os.environ.get('OBJECT_STORAGE_BUCKET') if not self.bucket_name: raise ValueError( "OBJECT_STORAGE_BUCKET environment variable not set. " "Please create a bucket in the Object Storage pane and set this variable." ) - - self.bucket = self.client.bucket(self.bucket_name) def upload_file(self, file, folder='uploads'): """ - Upload a file to object storage + Upload a file to object storage using signed URLs Args: file: Werkzeug FileStorage object @@ -71,28 +68,22 @@ class ObjectStorageService: unique_filename = f"{uuid4()}{file_extension}" object_name = f"{folder}/{unique_filename}" - blob = self.bucket.blob(object_name) - blob.upload_from_file( - file.stream, - content_type=file.content_type or 'application/octet-stream' + signed_url = get_signed_upload_url(self.bucket_name, object_name) + + file_content = file.read() + content_type = file.content_type or 'application/octet-stream' + + upload_response = requests.put( + signed_url, + data=file_content, + headers={"Content-Type": content_type} ) - blob.make_public() + if not upload_response.ok: + raise Exception(f"Upload failed: {upload_response.status_code} - {upload_response.text}") - return blob.public_url - - def get_blob(self, url): - """Get a blob object from a URL""" - if not url or not url.startswith('https://storage.googleapis.com/'): - return None - - parts = url.replace(f'https://storage.googleapis.com/{self.bucket_name}/', '') - return self.bucket.blob(parts) + return get_public_url(self.bucket_name, object_name) def delete_file(self, url): - """Delete a file from object storage""" - blob = self.get_blob(url) - if blob and blob.exists(): - blob.delete() - return True + """Delete a file from object storage (placeholder - not implemented)""" return False diff --git a/static/images/dr5qp.jpg b/static/images/dr5qp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fdd3963d01a446a359aad89610043d9fbaf67baf GIT binary patch literal 4625 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 Wi^}%7?wsAam2T2{G{kJ~4FBK05p;|I literal 0 HcmV?d00001