feat: implement super admin and platform admin roles
Add multi-platform admin authorization system with: - AdminPlatform junction table for admin-platform assignments - is_super_admin flag on User model for global admin access - Platform selection flow for platform admins after login - JWT token updates to include platform context - New API endpoints for admin user management (super admin only) - Auth dependencies for super admin and platform access checks Includes comprehensive test coverage: - Unit tests for AdminPlatform model and User admin methods - Unit tests for AdminPlatformService operations - Integration tests for admin users API endpoints Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -140,6 +140,8 @@ class AuthManager:
|
||||
vendor_id: int | None = None,
|
||||
vendor_code: str | None = None,
|
||||
vendor_role: str | None = None,
|
||||
platform_id: int | None = None,
|
||||
platform_code: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Create a JWT access token for an authenticated user.
|
||||
|
||||
@@ -151,6 +153,8 @@ class AuthManager:
|
||||
vendor_id (int, optional): Vendor ID if logging into vendor context
|
||||
vendor_code (str, optional): Vendor code if logging into vendor context
|
||||
vendor_role (str, optional): User's role in this vendor (owner, manager, etc.)
|
||||
platform_id (int, optional): Platform ID for platform admin context
|
||||
platform_code (str, optional): Platform code for platform admin context
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Dictionary containing:
|
||||
@@ -172,6 +176,21 @@ class AuthManager:
|
||||
"iat": datetime.now(UTC), # Issued at time (JWT standard claim)
|
||||
}
|
||||
|
||||
# Include admin-specific information for admin users
|
||||
if user.is_admin:
|
||||
payload["is_super_admin"] = user.is_super_admin
|
||||
# For platform admins, include their accessible platform IDs
|
||||
if not user.is_super_admin:
|
||||
accessible = user.get_accessible_platform_ids()
|
||||
if accessible is not None:
|
||||
payload["accessible_platforms"] = accessible
|
||||
|
||||
# Include platform context for platform admins
|
||||
if platform_id is not None:
|
||||
payload["platform_id"] = platform_id
|
||||
if platform_code is not None:
|
||||
payload["platform_code"] = platform_code
|
||||
|
||||
# Include vendor information in token if provided (vendor-specific login)
|
||||
if vendor_id is not None:
|
||||
payload["vendor_id"] = vendor_id
|
||||
@@ -242,6 +261,18 @@ class AuthManager:
|
||||
), # Default to "user" role if not specified
|
||||
}
|
||||
|
||||
# Include admin-specific information if present
|
||||
if "is_super_admin" in payload:
|
||||
user_data["is_super_admin"] = payload["is_super_admin"]
|
||||
if "accessible_platforms" in payload:
|
||||
user_data["accessible_platforms"] = payload["accessible_platforms"]
|
||||
|
||||
# Include platform context for platform admins
|
||||
if "platform_id" in payload:
|
||||
user_data["platform_id"] = payload["platform_id"]
|
||||
if "platform_code" in payload:
|
||||
user_data["platform_code"] = payload["platform_code"]
|
||||
|
||||
# Include vendor information if present in token
|
||||
if "vendor_id" in payload:
|
||||
user_data["vendor_id"] = payload["vendor_id"]
|
||||
@@ -302,8 +333,20 @@ class AuthManager:
|
||||
if not user.is_active:
|
||||
raise UserNotActiveException()
|
||||
|
||||
# Attach vendor information to user object if present in token
|
||||
# Attach admin-specific information to user object if present in token
|
||||
# These become dynamic attributes on the user object for this request
|
||||
if "is_super_admin" in user_data:
|
||||
user.token_is_super_admin = user_data["is_super_admin"]
|
||||
if "accessible_platforms" in user_data:
|
||||
user.token_accessible_platforms = user_data["accessible_platforms"]
|
||||
|
||||
# Attach platform context to user object if present in token
|
||||
if "platform_id" in user_data:
|
||||
user.token_platform_id = user_data["platform_id"]
|
||||
if "platform_code" in user_data:
|
||||
user.token_platform_code = user_data["platform_code"]
|
||||
|
||||
# Attach vendor information to user object if present in token
|
||||
if "vendor_id" in user_data:
|
||||
user.token_vendor_id = user_data["vendor_id"]
|
||||
if "vendor_code" in user_data:
|
||||
@@ -443,12 +486,14 @@ class AuthManager:
|
||||
hashed_password = self.hash_password("admin123")
|
||||
|
||||
# Create new admin user with default credentials
|
||||
# Default admin is a super admin with access to all platforms
|
||||
admin_user = User(
|
||||
email="admin@example.com",
|
||||
username="admin",
|
||||
hashed_password=hashed_password,
|
||||
role="admin",
|
||||
is_active=True,
|
||||
is_super_admin=True,
|
||||
)
|
||||
|
||||
# Save to database
|
||||
|
||||
Reference in New Issue
Block a user