Rename content_hash/output_hash to cid throughout

Refactor to use IPFS CID as the primary content identifier:
- Update database schema: content_hash -> cid, output_hash -> output_cid
- Update all services, routers, and tasks to use cid terminology
- Update HTML templates to display CID instead of hash
- Update cache_manager parameter names
- Update README documentation

This completes the transition to CID-only content addressing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-12 08:02:44 +00:00
parent 494a2a8650
commit 92d26b2b72
22 changed files with 981 additions and 988 deletions

View File

@@ -40,9 +40,9 @@ def get_cache_service():
return CacheService(database, get_cache_manager())
@router.get("/{content_hash}")
@router.get("/{cid}")
async def get_cached(
content_hash: str,
cid: str,
request: Request,
cache_service: CacheService = Depends(get_cache_service),
):
@@ -50,16 +50,16 @@ async def get_cached(
auth_service = AuthService(get_redis_client())
ctx = auth_service.get_user_from_cookie(request)
cache_item = await cache_service.get_cache_item(content_hash)
cache_item = await cache_service.get_cache_item(cid)
if not cache_item:
if wants_html(request):
templates = get_templates(request)
return render(templates, "cache/not_found.html", request,
content_hash=content_hash,
cid=cid,
user=ctx,
active_tab="media",
)
raise HTTPException(404, f"Content {content_hash} not in cache")
raise HTTPException(404, f"Content {cid} not in cache")
# JSON response
if wants_json(request):
@@ -71,7 +71,7 @@ async def get_cached(
return RedirectResponse(url="/auth", status_code=302)
# Check access
has_access = await cache_service.check_access(content_hash, ctx.actor_id, ctx.username)
has_access = await cache_service.check_access(cid, ctx.actor_id, ctx.username)
if not has_access:
raise HTTPException(403, "Access denied")
@@ -83,27 +83,27 @@ async def get_cached(
)
@router.get("/{content_hash}/raw")
@router.get("/{cid}/raw")
async def get_cached_raw(
content_hash: str,
cid: str,
cache_service: CacheService = Depends(get_cache_service),
):
"""Get raw cached content (file download)."""
file_path, media_type, filename = await cache_service.get_raw_file(content_hash)
file_path, media_type, filename = await cache_service.get_raw_file(cid)
if not file_path:
raise HTTPException(404, f"Content {content_hash} not in cache")
raise HTTPException(404, f"Content {cid} not in cache")
return FileResponse(file_path, media_type=media_type, filename=filename)
@router.get("/{content_hash}/mp4")
@router.get("/{cid}/mp4")
async def get_cached_mp4(
content_hash: str,
cid: str,
cache_service: CacheService = Depends(get_cache_service),
):
"""Get cached content as MP4 (transcodes MKV on first request)."""
mp4_path, error = await cache_service.get_as_mp4(content_hash)
mp4_path, error = await cache_service.get_as_mp4(cid)
if error:
raise HTTPException(400 if "not a video" in error else 404, error)
@@ -111,29 +111,29 @@ async def get_cached_mp4(
return FileResponse(mp4_path, media_type="video/mp4")
@router.get("/{content_hash}/meta")
@router.get("/{cid}/meta")
async def get_metadata(
content_hash: str,
cid: str,
ctx: UserContext = Depends(require_auth),
cache_service: CacheService = Depends(get_cache_service),
):
"""Get content metadata."""
meta = await cache_service.get_metadata(content_hash, ctx.actor_id)
meta = await cache_service.get_metadata(cid, ctx.actor_id)
if meta is None:
raise HTTPException(404, "Content not found")
return meta
@router.patch("/{content_hash}/meta")
@router.patch("/{cid}/meta")
async def update_metadata(
content_hash: str,
cid: str,
req: UpdateMetadataRequest,
ctx: UserContext = Depends(require_auth),
cache_service: CacheService = Depends(get_cache_service),
):
"""Update content metadata."""
success, error = await cache_service.update_metadata(
content_hash=content_hash,
cid=cid,
actor_id=ctx.actor_id,
title=req.title,
description=req.description,
@@ -147,16 +147,16 @@ async def update_metadata(
return {"updated": True}
@router.post("/{content_hash}/publish")
@router.post("/{cid}/publish")
async def publish_content(
content_hash: str,
cid: str,
request: Request,
ctx: UserContext = Depends(require_auth),
cache_service: CacheService = Depends(get_cache_service),
):
"""Publish content to L2 and IPFS."""
ipfs_cid, error = await cache_service.publish_to_l2(
content_hash=content_hash,
cid=cid,
actor_id=ctx.actor_id,
l2_server=ctx.l2_server,
auth_token=request.cookies.get("auth_token"),
@@ -173,14 +173,14 @@ async def publish_content(
return {"ipfs_cid": ipfs_cid, "published": True}
@router.delete("/{content_hash}")
@router.delete("/{cid}")
async def delete_content(
content_hash: str,
cid: str,
ctx: UserContext = Depends(require_auth),
cache_service: CacheService = Depends(get_cache_service),
):
"""Delete content from cache."""
success, error = await cache_service.delete_content(content_hash, ctx.actor_id)
success, error = await cache_service.delete_content(cid, ctx.actor_id)
if error:
raise HTTPException(400 if "Cannot" in error or "pinned" in error else 404, error)
@@ -195,12 +195,12 @@ async def import_from_ipfs(
cache_service: CacheService = Depends(get_cache_service),
):
"""Import content from IPFS."""
content_hash, error = await cache_service.import_from_ipfs(ipfs_cid, ctx.actor_id)
cid, error = await cache_service.import_from_ipfs(ipfs_cid, ctx.actor_id)
if error:
raise HTTPException(400, error)
return {"content_hash": content_hash, "imported": True}
return {"cid": cid, "imported": True}
@router.post("/upload")
@@ -211,7 +211,7 @@ async def upload_content(
):
"""Upload content to cache and IPFS."""
content = await file.read()
content_hash, ipfs_cid, error = await cache_service.upload_content(
cid, ipfs_cid, error = await cache_service.upload_content(
content=content,
filename=file.filename,
actor_id=ctx.actor_id,
@@ -222,7 +222,7 @@ async def upload_content(
return {
"cid": ipfs_cid,
"content_hash": content_hash, # Legacy, for backwards compatibility
"cid": cid, # Legacy, for backwards compatibility
"filename": file.filename,
"size": len(content),
"uploaded": True,
@@ -272,9 +272,9 @@ async def list_media(
# HTMX metadata form
@router.get("/{content_hash}/meta-form", response_class=HTMLResponse)
@router.get("/{cid}/meta-form", response_class=HTMLResponse)
async def get_metadata_form(
content_hash: str,
cid: str,
request: Request,
cache_service: CacheService = Depends(get_cache_service),
):
@@ -285,11 +285,11 @@ async def get_metadata_form(
if not ctx:
return HTMLResponse('<div class="text-red-400">Login required</div>')
meta = await cache_service.get_metadata(content_hash, ctx.actor_id)
meta = await cache_service.get_metadata(cid, ctx.actor_id)
return HTMLResponse(f'''
<h2 class="text-lg font-semibold mb-4">Metadata</h2>
<form hx-patch="/cache/{content_hash}/meta"
<form hx-patch="/cache/{cid}/meta"
hx-target="#metadata-section"
hx-swap="innerHTML"
class="space-y-4">
@@ -312,9 +312,9 @@ async def get_metadata_form(
''')
@router.patch("/{content_hash}/meta", response_class=HTMLResponse)
@router.patch("/{cid}/meta", response_class=HTMLResponse)
async def update_metadata_htmx(
content_hash: str,
cid: str,
request: Request,
cache_service: CacheService = Depends(get_cache_service),
):
@@ -328,7 +328,7 @@ async def update_metadata_htmx(
form_data = await request.form()
success, error = await cache_service.update_metadata(
content_hash=content_hash,
cid=cid,
actor_id=ctx.actor_id,
title=form_data.get("title"),
description=form_data.get("description"),