function user_has_permission
Validates whether a user has one or more specified permissions based on their assigned roles and a role-permission mapping configuration.
/tf/active/vicechatdev/CDocs/config/permissions.py
16 - 66
moderate
Purpose
This function implements role-based access control (RBAC) by checking if a user object has the necessary permissions to perform an action. It supports checking single or multiple permissions, handles users without roles by defaulting to 'USER' role, grants all permissions to 'ADMIN' role users, and logs permission checks for debugging and auditing purposes. The function is designed to be used as a permission gate in applications requiring authorization logic.
Source Code
def user_has_permission(user: Any, permission_type: Union[str, List[str]]) -> bool:
"""
Check if a user has a specific permission or any permission from a list.
Args:
user: The user to check permissions for
permission_type: Permission name or list of permission names to check
Returns:
bool: True if user has the permission, False otherwise
"""
if not user:
logger.debug("No user provided, denying permission")
return False
# Get all user roles
user_roles = user.roles if hasattr(user, 'roles') else []
# Convert permission_type to list if it's a single string
if isinstance(permission_type, str):
permissions_to_check = [permission_type]
else:
permissions_to_check = permission_type
logger.info("Checking permissions %s for user with roles: %s", permissions_to_check, user_roles)
# If no roles, fall back to USER role
if not user_roles:
logger.debug("No roles found, falling back to USER role")
for perm in permissions_to_check:
if perm in settings.ROLE_PERMISSIONS.get('USER', []):
return True
return False
# Admin users have all permissions
if 'ADMIN' in user_roles:
logger.debug(f"User has ADMIN role, granting permission")
return True
# Check if any of the user's roles has any of the requested permissions
for role in user_roles:
if role in settings.ROLE_PERMISSIONS:
role_permissions = settings.ROLE_PERMISSIONS[role]
for perm in permissions_to_check:
if perm in role_permissions:
logger.debug(f"Permission {perm} granted via role {role}")
return True
# Default denial
logger.debug(f"Permission denied for {permissions_to_check}, user roles: {user_roles}")
return False
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
user |
Any | - | positional_or_keyword |
permission_type |
Union[str, List[str]] | - | positional_or_keyword |
Parameter Details
user: The user object to check permissions for. Expected to have a 'roles' attribute containing a list of role names (strings). Can be None or any object type, but must have a 'roles' attribute for proper permission checking. If None or falsy, permission is automatically denied.
permission_type: Either a single permission name as a string (e.g., 'read_documents') or a list of permission names (e.g., ['read_documents', 'write_documents']). The function returns True if the user has ANY of the specified permissions. Permission names should match those defined in settings.ROLE_PERMISSIONS configuration.
Return Value
Type: bool
Returns a boolean value: True if the user has at least one of the requested permissions through any of their assigned roles, or if the user has the 'ADMIN' role (which grants all permissions). Returns False if the user is None/falsy, has no matching permissions, or has no roles and the default 'USER' role doesn't grant the requested permissions.
Dependencies
loggingtypingCDocs.config
Required Imports
import logging
from typing import Any, Union, List
from CDocs.config import settings
Usage Example
# Setup (in settings.py or config module)
class Settings:
ROLE_PERMISSIONS = {
'ADMIN': ['read', 'write', 'delete'],
'USER': ['read'],
'EDITOR': ['read', 'write']
}
settings = Settings()
# Setup logger
import logging
logger = logging.getLogger(__name__)
# Create a user object
class User:
def __init__(self, roles):
self.roles = roles
# Usage examples
user = User(roles=['USER'])
has_read = user_has_permission(user, 'read') # Returns True
has_write = user_has_permission(user, 'write') # Returns False
admin_user = User(roles=['ADMIN'])
has_any = user_has_permission(admin_user, 'delete') # Returns True (admin has all)
# Check multiple permissions (OR logic)
editor = User(roles=['EDITOR'])
has_either = user_has_permission(editor, ['write', 'delete']) # Returns True (has write)
# No user
has_perm = user_has_permission(None, 'read') # Returns False
Best Practices
- Ensure settings.ROLE_PERMISSIONS is properly configured before using this function, as it's the source of truth for all permission checks
- The function uses OR logic when checking multiple permissions - it returns True if ANY permission matches. If you need AND logic (all permissions required), call the function multiple times
- ADMIN role is hardcoded to bypass all permission checks - ensure this role is only assigned to trusted users
- The function logs permission checks at various levels (debug, info) - configure logging appropriately to avoid performance issues in production
- Users without roles default to 'USER' role permissions - ensure 'USER' role is defined in settings.ROLE_PERMISSIONS
- The user object must have a 'roles' attribute (list of strings) - consider using a consistent user model across your application
- Permission names are case-sensitive - maintain consistent naming conventions in your settings configuration
- Consider caching permission checks if called frequently for the same user to improve performance
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function user_has_permission_for_resource 83.2% similar
-
function check_document_permission 75.9% similar
-
function get_user_permissions 70.1% similar
-
function require_permission 61.6% similar
-
function is_admin_user 51.8% similar