feat: add Goldfish Recap YouTube summary PWA
YouTube subtitles via OpenRouter become persistent, shareable recaps with timestamp jump links, PIN-protected creation, and Traefik deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hmac
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, HTTPException
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
|
||||
from server.settings import settings
|
||||
|
||||
_bearer = HTTPBearer(auto_error=False)
|
||||
ALGORITHM = "HS256"
|
||||
|
||||
|
||||
def verify_pin(pin: str) -> bool:
|
||||
return hmac.compare_digest(pin.strip(), settings.app_pin.strip())
|
||||
|
||||
|
||||
def create_token() -> str:
|
||||
expire = datetime.now(timezone.utc) + timedelta(days=settings.jwt_expire_days)
|
||||
payload = {"sub": "admin", "exp": expire}
|
||||
return jwt.encode(payload, settings.jwt_secret, algorithm=ALGORITHM)
|
||||
|
||||
|
||||
def decode_token(token: str) -> dict[str, Any]:
|
||||
try:
|
||||
return jwt.decode(token, settings.jwt_secret, algorithms=[ALGORITHM])
|
||||
except jwt.PyJWTError as exc:
|
||||
raise HTTPException(status_code=401, detail="Invalid token") from exc
|
||||
|
||||
|
||||
async def require_auth(
|
||||
creds: HTTPAuthorizationCredentials | None = Depends(_bearer),
|
||||
) -> dict[str, Any]:
|
||||
if creds is None or creds.scheme.lower() != "bearer":
|
||||
raise HTTPException(status_code=401, detail="Missing token")
|
||||
return decode_token(creds.credentials)
|
||||
Reference in New Issue
Block a user