🔍 Code Extractor

function user_has_permission

Maturity: 60

Validates whether a user has one or more specified permissions based on their assigned roles and a role-permission mapping configuration.

File:
/tf/active/vicechatdev/CDocs/config/permissions.py
Lines:
16 - 66
Complexity:
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

  • logging
  • typing
  • CDocs.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

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function user_has_permission_for_resource 83.2% similar

    Checks if a user has a specific permission for a resource, considering both general permissions and resource-specific ownership/creator rights.

    From: /tf/active/vicechatdev/CDocs/config/permissions.py
  • function check_document_permission 75.9% similar

    Validates whether a user has specific permission(s) to access or modify a document based on their roles, ownership status, and configured role permissions.

    From: /tf/active/vicechatdev/CDocs/config/permissions.py
  • function get_user_permissions 70.1% similar

    Retrieves all permissions for a user by aggregating permissions from their assigned roles, with fallback to default USER role permissions.

    From: /tf/active/vicechatdev/CDocs/config/permissions.py
  • function require_permission 61.6% similar

    A decorator function that enforces permission-based access control by checking if a user has required permissions before executing the decorated function.

    From: /tf/active/vicechatdev/CDocs/controllers/__init__.py
  • function is_admin_user 51.8% similar

    Checks if the currently authenticated user has administrator privileges by comparing their email against a hardcoded list of admin emails.

    From: /tf/active/vicechatdev/docchat/app.py
← Back to Browse