Add random 4-digit TV token per child for obfuscated TV URLs

Each child is assigned a unique permanent tv_token on creation. The TV
dashboard URL (/tv/:tvToken) and WebSocket (/ws/:tvToken) now use this
token instead of the internal DB ID. Existing children are backfilled
on startup. README updated to reflect the change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 22:53:26 -07:00
parent 4bd9218bf5
commit 68a5e9cb4f
7 changed files with 52 additions and 12 deletions

View File

@@ -1,3 +1,4 @@
import random
from datetime import datetime, timezone
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
@@ -49,13 +50,22 @@ async def list_children(
return children
async def _generate_tv_token(db: AsyncSession) -> int:
while True:
token = random.randint(1000, 9999)
result = await db.execute(select(Child).where(Child.tv_token == token))
if not result.scalar_one_or_none():
return token
@router.post("", response_model=ChildOut, status_code=status.HTTP_201_CREATED)
async def create_child(
body: ChildCreate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
child = Child(**body.model_dump(), user_id=current_user.id)
tv_token = await _generate_tv_token(db)
child = Child(**body.model_dump(), user_id=current_user.id, tv_token=tv_token)
db.add(child)
await db.commit()
await db.refresh(child)