Add Renderers page for L1 server management

- Add user_renderers table to track which L1 servers users are attached to
- Add L1_SERVERS config to define available renderers
- Add /renderers page showing attachment status for each L1 server
- Add attach functionality (redirects to L1 /auth with token)
- Add detach functionality with HTMX updates
- Add Renderers link to nav bar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-09 17:18:41 +00:00
parent 990ac44108
commit 28843ea185
2 changed files with 157 additions and 0 deletions

46
db.py
View File

@@ -100,6 +100,15 @@ CREATE TABLE IF NOT EXISTS followers (
UNIQUE(username, acct)
);
-- User's attached L1 renderers
CREATE TABLE IF NOT EXISTS user_renderers (
id SERIAL PRIMARY KEY,
username VARCHAR(255) NOT NULL REFERENCES users(username),
l1_url TEXT NOT NULL,
attached_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(username, l1_url)
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_users_created_at ON users(created_at);
CREATE INDEX IF NOT EXISTS idx_assets_content_hash ON assets(content_hash);
@@ -715,3 +724,40 @@ async def get_anchor_stats() -> dict:
"anchored_activities": anchored_activities,
"unanchored_activities": unanchored_activities
}
# ============ User Renderers (L1 attachments) ============
async def get_user_renderers(username: str) -> list[str]:
"""Get L1 renderer URLs attached by a user."""
async with get_connection() as conn:
rows = await conn.fetch(
"SELECT l1_url FROM user_renderers WHERE username = $1 ORDER BY attached_at",
username
)
return [row["l1_url"] for row in rows]
async def attach_renderer(username: str, l1_url: str) -> bool:
"""Attach a user to an L1 renderer. Returns True if newly attached."""
async with get_connection() as conn:
try:
await conn.execute(
"""INSERT INTO user_renderers (username, l1_url)
VALUES ($1, $2)
ON CONFLICT (username, l1_url) DO NOTHING""",
username, l1_url
)
return True
except Exception:
return False
async def detach_renderer(username: str, l1_url: str) -> bool:
"""Detach a user from an L1 renderer. Returns True if was attached."""
async with get_connection() as conn:
result = await conn.execute(
"DELETE FROM user_renderers WHERE username = $1 AND l1_url = $2",
username, l1_url
)
return "DELETE 1" in result