fix: platform admin authentication and UserContext completeness

Issues fixed:
- Platform selection returned LoginResponse requiring user timestamps,
  but UserContext doesn't have created_at/updated_at. Created dedicated
  PlatformSelectResponse that returns only token and platform info.

- UserContext was missing platform context fields (token_platform_id,
  token_platform_code). JWT token included them but they weren't
  extracted into UserContext, causing fallback warnings.

- admin_menu_config.py accessed admin_platforms (SQLAlchemy relationship)
  on UserContext (Pydantic schema). Changed to use accessible_platform_ids.

- Static file mount order in main.py caused 404 for locale files.
  More specific paths (/static/modules/X/locales) must be mounted
  before less specific paths (/static/modules/X).

Changes:
- models/schema/auth.py: Add PlatformSelectResponse, token_platform_id,
  token_platform_code, can_access_platform(), get_accessible_platform_ids()
- admin_auth.py: Use PlatformSelectResponse for select-platform endpoint
- admin_platform_service.py: Accept User | UserContext in validation
- admin_menu_config.py: Use accessible_platform_ids instead of admin_platforms
- main.py: Mount locales before static for correct path priority

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-02 22:31:35 +01:00
parent 9a0dd84035
commit b935592430
6 changed files with 344 additions and 20 deletions

View File

@@ -23,7 +23,7 @@ from app.modules.core.services.auth_service import auth_service
from middleware.auth import AuthManager
from app.modules.tenancy.models import Platform # noqa: API-007 - Admin needs to query platforms
from models.schema.auth import UserContext
from models.schema.auth import LoginResponse, LogoutResponse, UserLogin, UserResponse
from models.schema.auth import LoginResponse, LogoutResponse, PlatformSelectResponse, UserLogin, UserResponse
admin_auth_router = APIRouter(prefix="/auth")
logger = logging.getLogger(__name__)
@@ -160,7 +160,7 @@ def get_accessible_platforms(
}
@admin_auth_router.post("/select-platform")
@admin_auth_router.post("/select-platform", response_model=PlatformSelectResponse)
def select_platform(
platform_id: int,
response: Response,
@@ -177,7 +177,7 @@ def select_platform(
platform_id: Platform ID to select
Returns:
LoginResponse with new token containing platform context
PlatformSelectResponse with new token and platform info
"""
if current_user.is_super_admin:
raise InvalidCredentialsException(
@@ -213,9 +213,10 @@ def select_platform(
logger.info(f"Admin {current_user.username} selected platform {platform.code}")
return LoginResponse(
return PlatformSelectResponse(
access_token=token_data["access_token"],
token_type=token_data["token_type"],
expires_in=token_data["expires_in"],
user=current_user,
platform_id=platform.id,
platform_code=platform.code,
)