Spaces:
Running
Running
File size: 2,410 Bytes
5cd1866 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | """
Google OAuth token verification and lightweight user store.
Uses google-auth to verify JWT credentials issued by Google Identity Services.
User profiles are stored in a JSON file (/tmp) — ephemeral on HF Spaces,
which is acceptable for a demo. Client-side localStorage persists the session.
"""
import json
import os
from pathlib import Path
from datetime import datetime, timezone
from google.oauth2 import id_token
from google.auth.transport import requests as google_requests
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID", "")
USER_STORE_PATH = Path(os.getenv("USER_STORE_PATH", "/tmp/urbanflow_users.json"))
def _load_users() -> dict:
if USER_STORE_PATH.exists():
return json.loads(USER_STORE_PATH.read_text())
return {}
def _save_users(users: dict):
USER_STORE_PATH.write_text(json.dumps(users, indent=2))
def verify_google_token(credential: str) -> dict:
"""
Verify a Google ID token (JWT) and return the decoded payload.
Raises ValueError on invalid/expired tokens.
"""
idinfo = id_token.verify_oauth2_token(
credential,
google_requests.Request(),
GOOGLE_CLIENT_ID,
)
return {
"email": idinfo["email"],
"name": idinfo.get("name", ""),
"picture": idinfo.get("picture", ""),
}
def get_or_create_user(email: str, name: str, picture: str) -> dict:
"""
Look up a user by email. If they don't exist, create a stub record.
Returns the user record with a `new_user` flag.
"""
users = _load_users()
is_new = email not in users
if is_new:
users[email] = {
"username": "",
"name": name,
"picture": picture,
"created_at": datetime.now(timezone.utc).isoformat(),
}
_save_users(users)
user = users[email]
return {
"email": email,
"username": user.get("username", ""),
"name": user.get("name", name),
"picture": user.get("picture", picture),
"new_user": is_new or not user.get("username"),
}
def set_username(email: str, username: str) -> bool:
"""
Save a display username for a first-time user.
Returns True on success, False if the user record doesn't exist.
"""
users = _load_users()
if email not in users:
return False
users[email]["username"] = username.strip()
_save_users(users)
return True
|