""" Object Storage Service for FTC Team Website Handles persistent file uploads using Google Cloud Storage (Replit Object Storage) """ from google.cloud import storage import os from uuid import uuid4 from werkzeug.utils import secure_filename REPLIT_SIDECAR_ENDPOINT = "http://127.0.0.1:1106" class ObjectStorageService: def __init__(self): """Initialize the object storage client with Replit credentials""" self.client = storage.Client( credentials={ "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", }, project="", ) # Get bucket name from environment variable 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 Args: file: Werkzeug FileStorage object folder: Folder name in the bucket (default: 'uploads') Returns: str: Public URL of the uploaded file """ if not file or not file.filename: return None # Generate unique filename original_filename = secure_filename(file.filename) file_extension = os.path.splitext(original_filename)[1] unique_filename = f"{uuid4()}{file_extension}" object_name = f"{folder}/{unique_filename}" # Upload to bucket blob = self.bucket.blob(object_name) blob.upload_from_file( file.stream, content_type=file.content_type or 'application/octet-stream' ) # Make the blob publicly accessible blob.make_public() # Return the public URL 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 # Extract blob name from URL parts = url.replace(f'https://storage.googleapis.com/{self.bucket_name}/', '') return self.bucket.blob(parts) 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 return False