Add form-based storage endpoint for browser submissions
The POST /storage endpoint required Bearer token auth and JSON body, which didn't work with browser form submissions using cookies. Added new /storage/add endpoint that accepts form data and cookie auth. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
94
server.py
94
server.py
@@ -27,7 +27,7 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Request, Response, Depends, Cookie
|
||||
from fastapi import FastAPI, HTTPException, Request, Response, Depends, Cookie, Form
|
||||
from fastapi.responses import JSONResponse, HTMLResponse, RedirectResponse, FileResponse
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from pydantic import BaseModel
|
||||
@@ -3120,6 +3120,72 @@ async def add_storage(req: AddStorageRequest, user: User = Depends(get_required_
|
||||
return {"id": storage_id, "message": f"Storage provider added: {provider_name}"}
|
||||
|
||||
|
||||
@app.post("/storage/add")
|
||||
async def add_storage_form(
|
||||
request: Request,
|
||||
provider_type: str = Form(...),
|
||||
provider_name: Optional[str] = Form(None),
|
||||
capacity_gb: int = Form(5),
|
||||
api_key: Optional[str] = Form(None),
|
||||
secret_key: Optional[str] = Form(None),
|
||||
api_token: Optional[str] = Form(None),
|
||||
path: Optional[str] = Form(None),
|
||||
):
|
||||
"""Add a storage provider via HTML form (cookie auth)."""
|
||||
username = get_user_from_cookie(request)
|
||||
if not username:
|
||||
return HTMLResponse('<div class="text-red-400">Not authenticated</div>', status_code=401)
|
||||
|
||||
# Validate provider type
|
||||
if provider_type not in ["pinata", "web3storage", "local"]:
|
||||
return HTMLResponse(f'<div class="text-red-400">Invalid provider type: {provider_type}</div>')
|
||||
|
||||
# Build config based on provider type
|
||||
config = {}
|
||||
if provider_type == "pinata":
|
||||
if not api_key or not secret_key:
|
||||
return HTMLResponse('<div class="text-red-400">Pinata requires API Key and Secret Key</div>')
|
||||
config = {"api_key": api_key, "secret_key": secret_key}
|
||||
elif provider_type == "web3storage":
|
||||
if not api_token:
|
||||
return HTMLResponse('<div class="text-red-400">web3.storage requires API Token</div>')
|
||||
config = {"api_token": api_token}
|
||||
elif provider_type == "local":
|
||||
if not path:
|
||||
return HTMLResponse('<div class="text-red-400">Local storage requires a path</div>')
|
||||
config = {"path": path}
|
||||
|
||||
# Test the provider connection before saving
|
||||
provider = storage_providers.create_provider(provider_type, {
|
||||
**config,
|
||||
"capacity_gb": capacity_gb
|
||||
})
|
||||
if not provider:
|
||||
return HTMLResponse('<div class="text-red-400">Failed to create provider with given config</div>')
|
||||
|
||||
success, message = await provider.test_connection()
|
||||
if not success:
|
||||
return HTMLResponse(f'<div class="text-red-400">Provider connection failed: {message}</div>')
|
||||
|
||||
# Save to database
|
||||
name = provider_name or f"{provider_type}-{username}"
|
||||
storage_id = await db.add_user_storage(
|
||||
username=username,
|
||||
provider_type=provider_type,
|
||||
provider_name=name,
|
||||
config=config,
|
||||
capacity_gb=capacity_gb
|
||||
)
|
||||
|
||||
if not storage_id:
|
||||
return HTMLResponse('<div class="text-red-400">Failed to save storage provider</div>')
|
||||
|
||||
return HTMLResponse(f'''
|
||||
<div class="text-green-400 mb-2">Storage provider "{name}" added successfully!</div>
|
||||
<script>setTimeout(() => window.location.reload(), 1500);</script>
|
||||
''')
|
||||
|
||||
|
||||
@app.get("/storage/{storage_id}")
|
||||
async def get_storage(storage_id: int, user: User = Depends(get_required_user)):
|
||||
"""Get a specific storage provider."""
|
||||
@@ -3312,7 +3378,7 @@ async def ui_storage_page(username: str, storages: list, request: Request) -> HT
|
||||
</div>
|
||||
|
||||
<div id="add-form" class="hidden bg-dark-600 rounded-lg p-4">
|
||||
<form id="storage-form" hx-post="/storage" hx-target="#add-result" hx-swap="innerHTML">
|
||||
<form id="storage-form" hx-post="/storage/add" hx-target="#add-result" hx-swap="innerHTML">
|
||||
<input type="hidden" name="provider_type" id="provider_type">
|
||||
|
||||
<div id="pinata-fields" class="hidden space-y-4">
|
||||
@@ -3383,30 +3449,6 @@ async def ui_storage_page(username: str, storages: list, request: Request) -> HT
|
||||
function hideAddForm() {{
|
||||
document.getElementById('add-form').classList.add('hidden');
|
||||
}}
|
||||
|
||||
// Handle form submission to build proper JSON
|
||||
document.getElementById('storage-form').addEventListener('htmx:configRequest', function(evt) {{
|
||||
const formData = new FormData(evt.detail.elt);
|
||||
const providerType = formData.get('provider_type');
|
||||
const config = {{}};
|
||||
|
||||
if (providerType === 'pinata') {{
|
||||
config.api_key = formData.get('api_key');
|
||||
config.secret_key = formData.get('secret_key');
|
||||
}} else if (providerType === 'web3storage') {{
|
||||
config.api_token = formData.get('api_token');
|
||||
}} else if (providerType === 'local') {{
|
||||
config.path = formData.get('path');
|
||||
}}
|
||||
|
||||
evt.detail.headers['Content-Type'] = 'application/json';
|
||||
evt.detail.parameters = JSON.stringify({{
|
||||
provider_type: providerType,
|
||||
provider_name: formData.get('provider_name') || null,
|
||||
config: config,
|
||||
capacity_gb: parseInt(formData.get('capacity_gb'))
|
||||
}});
|
||||
}});
|
||||
</script>
|
||||
'''
|
||||
|
||||
|
||||
Reference in New Issue
Block a user