fix: pricing page toggle and user auto-creation on OAuth login

- Fix monthly/annual price toggle by moving x-data scope to outer div
- Auto-create UserProfile in DB on first Authentik OAuth login
- Update and expand tests for oauth_callback and _ensure_user_profile

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-07 10:52:26 +00:00
parent 48092c98e7
commit dd207eef9b
3 changed files with 197 additions and 14 deletions
+40 -2
View File
@@ -5,11 +5,13 @@ import pathlib
from functools import wraps
from authlib.integrations.starlette_client import OAuth
from fastapi import APIRouter, Request, status
from fastapi import APIRouter, Depends, Request, status
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from starlette.responses import RedirectResponse
from app.config import settings
from app.database import get_db
oauth = OAuth()
@@ -94,7 +96,40 @@ async def oauth_login(request: Request):
return await oauth.authentik.authorize_redirect(request, redirect_uri)
async def oauth_callback(request: Request):
def _ensure_user_profile(db: Session, user_data: dict) -> None:
"""Create a UserProfile row for *user_data* if one does not yet exist.
Uses the same identifier priority as ``get_current_owner_id`` (sub →
preferred_username → email → id) so that the profile's ``user_id`` matches
``FileRecord.owner_id`` for every document the user uploads.
If a profile already exists it is left unchanged; only missing profiles
are created so that admin-managed settings (tier, limits, etc.) are
preserved across logins.
"""
from app.models import UserProfile
user_id = (
user_data.get("sub") or user_data.get("preferred_username") or user_data.get("email") or user_data.get("id")
)
if not user_id:
logger.warning("Cannot create UserProfile: no stable user identifier in OAuth userinfo")
return
try:
existing = db.query(UserProfile).filter(UserProfile.user_id == user_id).first()
if existing is None:
display_name = user_data.get("name") or user_data.get("preferred_username") or user_data.get("email")
profile = UserProfile(user_id=user_id, display_name=display_name)
db.add(profile)
db.commit()
logger.info("Auto-created UserProfile for user_id=%s", user_id)
except Exception:
db.rollback()
logger.exception("Failed to auto-create UserProfile for user_id=%s", user_id)
async def oauth_callback(request: Request, db: Session = Depends(get_db)):
"""Handle OAuth callback from provider"""
try:
token = await oauth.authentik.authorize_access_token(request)
@@ -126,6 +161,9 @@ async def oauth_callback(request: Request):
request.session["user"] = user_data
# Auto-create or update UserProfile so the user appears in admin user management
_ensure_user_profile(db, user_data)
# Log the successful authentication
logger.info(f"[SECURITY] OAUTH_LOGIN_SUCCESS user={user_data.get('email', 'unknown')} admin={is_admin}")