From 770c36479f65bb5d7c26aa6839dfd5a365398245 Mon Sep 17 00:00:00 2001 From: gilesb Date: Sat, 10 Jan 2026 00:25:09 +0000 Subject: [PATCH] Add support for more decentralized storage providers Added 4 new storage providers: - NFT.Storage (free for NFT data) - Infura IPFS (5GB free) - Filebase (5GB free, S3-compatible IPFS) - Storj (25GB free, decentralized cloud) Updated UI with 7 total storage options in a 4-column grid, each with distinct colored borders for visibility. Co-Authored-By: Claude Opus 4.5 --- server.py | 119 ++++++++-- storage_providers.py | 502 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 604 insertions(+), 17 deletions(-) diff --git a/server.py b/server.py index 035e475..3e7f86c 100644 --- a/server.py +++ b/server.py @@ -3089,7 +3089,8 @@ async def list_storage(request: Request, user: User = Depends(get_optional_user) async def add_storage(req: AddStorageRequest, user: User = Depends(get_required_user)): """Add a storage provider.""" # Validate provider type - if req.provider_type not in ["pinata", "web3storage", "local"]: + valid_types = ["pinata", "web3storage", "nftstorage", "infura", "filebase", "storj", "local"] + if req.provider_type not in valid_types: raise HTTPException(400, f"Invalid provider type: {req.provider_type}") # Test the provider connection before saving @@ -3129,6 +3130,10 @@ async def add_storage_form( api_key: Optional[str] = Form(None), secret_key: Optional[str] = Form(None), api_token: Optional[str] = Form(None), + project_id: Optional[str] = Form(None), + project_secret: Optional[str] = Form(None), + access_key: Optional[str] = Form(None), + bucket: Optional[str] = Form(None), path: Optional[str] = Form(None), ): """Add a storage provider via HTML form (cookie auth).""" @@ -3137,7 +3142,8 @@ async def add_storage_form( return HTMLResponse('
Not authenticated
', status_code=401) # Validate provider type - if provider_type not in ["pinata", "web3storage", "local"]: + valid_types = ["pinata", "web3storage", "nftstorage", "infura", "filebase", "storj", "local"] + if provider_type not in valid_types: return HTMLResponse(f'
Invalid provider type: {provider_type}
') # Build config based on provider type @@ -3150,6 +3156,22 @@ async def add_storage_form( if not api_token: return HTMLResponse('
web3.storage requires API Token
') config = {"api_token": api_token} + elif provider_type == "nftstorage": + if not api_token: + return HTMLResponse('
NFT.Storage requires API Token
') + config = {"api_token": api_token} + elif provider_type == "infura": + if not project_id or not project_secret: + return HTMLResponse('
Infura requires Project ID and Project Secret
') + config = {"project_id": project_id, "project_secret": project_secret} + elif provider_type == "filebase": + if not access_key or not secret_key or not bucket: + return HTMLResponse('
Filebase requires Access Key, Secret Key, and Bucket
') + config = {"access_key": access_key, "secret_key": secret_key, "bucket": bucket} + elif provider_type == "storj": + if not access_key or not secret_key or not bucket: + return HTMLResponse('
Storj requires Access Key, Secret Key, and Bucket
') + config = {"access_key": access_key, "secret_key": secret_key, "bucket": bucket} elif provider_type == "local": if not path: return HTMLResponse('
Local storage requires a path
') @@ -3359,21 +3381,41 @@ async def ui_storage_page(username: str, storages: list, request: Request) -> HT

Add Storage Provider

-
+
+ + + +
@@ -3399,6 +3441,54 @@ async def ui_storage_page(username: str, storages: list, request: Request) -> HT
+ + + + + + + +