refactor(api): introduce UserContext schema for API dependency injection
Replace direct User database model imports in API endpoints with UserContext schema, following the architecture principle that API routes should not import database models directly. Changes: - Create UserContext schema in models/schema/auth.py with from_user() factory - Update app/api/deps.py to return UserContext from all auth dependencies - Add _get_user_model() helper for functions needing User model access - Update 58 API endpoint files to use UserContext instead of User - Add noqa comments for 4 legitimate edge cases (enums, internal helpers) Architecture validation: 0 errors (down from 61), 11 warnings remain Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -163,3 +163,109 @@ class VendorUserResponse(BaseModel):
|
||||
is_active: bool
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class UserContext(BaseModel):
|
||||
"""
|
||||
User context for dependency injection in API endpoints.
|
||||
|
||||
This schema replaces direct use of the User database model in API routes,
|
||||
following the principle that routes should not import database models directly.
|
||||
|
||||
Used by:
|
||||
- get_current_admin_api / get_current_admin_from_cookie_or_header
|
||||
- get_current_vendor_api / get_current_vendor_from_cookie_or_header
|
||||
- get_current_super_admin
|
||||
|
||||
For admin users:
|
||||
- is_super_admin indicates full platform access
|
||||
- accessible_platform_ids is None for super admins (all platforms)
|
||||
- accessible_platform_ids is a list for platform admins
|
||||
|
||||
For vendor users:
|
||||
- token_vendor_id/code/role come from JWT token
|
||||
- These indicate which vendor context the user is operating in
|
||||
"""
|
||||
|
||||
# Core user fields
|
||||
id: int
|
||||
email: str
|
||||
username: str
|
||||
role: str # "admin" or "vendor"
|
||||
is_active: bool = True
|
||||
|
||||
# Admin-specific fields
|
||||
is_super_admin: bool = False
|
||||
accessible_platform_ids: list[int] | None = None # None = all platforms (super admin)
|
||||
|
||||
# Vendor-specific fields (from JWT token)
|
||||
token_vendor_id: int | None = None
|
||||
token_vendor_code: str | None = None
|
||||
token_vendor_role: str | None = None
|
||||
|
||||
# Optional profile fields
|
||||
first_name: str | None = None
|
||||
last_name: str | None = None
|
||||
preferred_language: str | None = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@property
|
||||
def full_name(self) -> str:
|
||||
"""Returns the full name of the user."""
|
||||
if self.first_name and self.last_name:
|
||||
return f"{self.first_name} {self.last_name}"
|
||||
return self.username
|
||||
|
||||
@property
|
||||
def is_admin(self) -> bool:
|
||||
"""Check if user is a platform admin."""
|
||||
return self.role == "admin"
|
||||
|
||||
@property
|
||||
def is_vendor(self) -> bool:
|
||||
"""Check if user is a vendor."""
|
||||
return self.role == "vendor"
|
||||
|
||||
@classmethod
|
||||
def from_user(cls, user, include_vendor_context: bool = True) -> "UserContext":
|
||||
"""
|
||||
Create UserContext from a User database model.
|
||||
|
||||
Args:
|
||||
user: User database model instance
|
||||
include_vendor_context: Whether to include token_vendor_* fields
|
||||
|
||||
Returns:
|
||||
UserContext instance
|
||||
"""
|
||||
data = {
|
||||
"id": user.id,
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
"role": user.role,
|
||||
"is_active": user.is_active,
|
||||
"is_super_admin": getattr(user, "is_super_admin", False),
|
||||
"first_name": getattr(user, "first_name", None),
|
||||
"last_name": getattr(user, "last_name", None),
|
||||
"preferred_language": getattr(user, "preferred_language", None),
|
||||
}
|
||||
|
||||
# Add admin platform access info
|
||||
if user.role == "admin":
|
||||
if getattr(user, "is_super_admin", False):
|
||||
data["accessible_platform_ids"] = None # All platforms
|
||||
else:
|
||||
# Get platform IDs from admin_platforms relationship
|
||||
admin_platforms = getattr(user, "admin_platforms", [])
|
||||
data["accessible_platform_ids"] = [
|
||||
ap.platform_id for ap in admin_platforms if ap.is_active
|
||||
]
|
||||
|
||||
# Add vendor context from JWT token if present
|
||||
if include_vendor_context:
|
||||
data["token_vendor_id"] = getattr(user, "token_vendor_id", None)
|
||||
data["token_vendor_code"] = getattr(user, "token_vendor_code", None)
|
||||
data["token_vendor_role"] = getattr(user, "token_vendor_role", None)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
Reference in New Issue
Block a user