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:
@@ -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)
|
||||
|
||||
@@ -22,12 +22,13 @@ from app.utils.timer import compute_block_elapsed, compute_break_elapsed
|
||||
router = APIRouter(prefix="/api/dashboard", tags=["dashboard"])
|
||||
|
||||
|
||||
@router.get("/{child_id}", response_model=DashboardSnapshot)
|
||||
async def get_dashboard(child_id: int, db: AsyncSession = Depends(get_db)):
|
||||
child_result = await db.execute(select(Child).where(Child.id == child_id, Child.is_active == True))
|
||||
@router.get("/{tv_token}", response_model=DashboardSnapshot)
|
||||
async def get_dashboard(tv_token: int, db: AsyncSession = Depends(get_db)):
|
||||
child_result = await db.execute(select(Child).where(Child.tv_token == tv_token, Child.is_active == True))
|
||||
child = child_result.scalar_one_or_none()
|
||||
if not child:
|
||||
raise HTTPException(status_code=404, detail="Child not found")
|
||||
child_id = child.id
|
||||
|
||||
# Get today's active session
|
||||
session_result = await db.execute(
|
||||
|
||||
Reference in New Issue
Block a user