🔍 Code Extractor

function check_document_permission

Maturity: 64

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

File:
/tf/active/vicechatdev/CDocs/config/permissions.py
Lines:
103 - 174
Complexity:
moderate

Purpose

This function implements a role-based access control (RBAC) system for document permissions. It checks if a user has the required permission(s) for a document by evaluating: (1) user roles including ADMIN privileges, (2) document ownership status, (3) role-based permissions from settings, and (4) fallback to default USER permissions. It supports checking single or multiple permissions simultaneously and handles edge cases like missing user/document data.

Source Code

def check_document_permission(user: Any, document: Dict[str, Any], 
                              permission_type: Union[str, List[str]]) -> bool:
    """
    Check if a user has a specific permission for a document.
    
    Parameters
    ----------
    user : Any
        The user to check permissions for
    document : Dict[str, Any]
        The document to check against
    permission_type : Union[str, List[str]]
        The type of permission to check or a list of permissions
        
    Returns
    -------
    bool
        True if user has the permission for the document, False otherwise
    """
    if not user or not document:
        return False
        
    # Get all user roles
    user_roles = user.roles if hasattr(user, 'roles') else []
    
    # If no roles, fall back to USER role
    if not user_roles:
        if isinstance(permission_type, str):
            return permission_type in settings.ROLE_PERMISSIONS.get('USER', [])
        else:
            return any(perm in settings.ROLE_PERMISSIONS.get('USER', []) for perm in permission_type)
    
    # Admin users have all permissions
    if 'ADMIN' in user_roles:
        logger.debug(f"User has ADMIN role, granting document permission")
        return True
    
    # 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
    
    # Check if user is the document owner
    owner_id = document.get('owner_id', document.get('owner_uid'))
    if owner_id and getattr(user, 'uid', '') == owner_id:
        # Document owners have additional permissions on their own documents
        owner_permissions = [
            'VIEW_DOCUMENT', 'EDIT_DOCUMENT', 'DELETE_DOCUMENT',
            'CREATE_REVIEW', 'CREATE_APPROVAL'
        ]
        
        for perm in permissions_to_check:
            if perm in owner_permissions:
                logger.debug(f"Permission {perm} granted as document owner")
                return True
    
    # Check roles for 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"Document permission {perm} granted via role {role}")
                    return True
    
    # Fall back to USER permissions
    for perm in permissions_to_check:
        if perm in settings.ROLE_PERMISSIONS['USER']:
            return True
            
    return False

Parameters

Name Type Default Kind
user Any - positional_or_keyword
document Dict[str, 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 optional 'roles' attribute (list of role strings) and 'uid' attribute (user identifier string). Can be None or any object type, though None will return False immediately.

document: A dictionary representing the document to check permissions against. Should contain 'owner_id' or 'owner_uid' key with the document owner's user identifier. Can be None or empty dict, which will return False immediately.

permission_type: Either a single permission string (e.g., 'VIEW_DOCUMENT') or a list of permission strings to check. When a list is provided, the function returns True if ANY of the permissions are granted. Common permission types include 'VIEW_DOCUMENT', 'EDIT_DOCUMENT', 'DELETE_DOCUMENT', 'CREATE_REVIEW', 'CREATE_APPROVAL'.

Return Value

Type: bool

Returns a boolean value: True if the user has at least one of the specified permissions for the document (through any of the checked mechanisms: admin role, ownership, role permissions, or default USER permissions), False otherwise. Also returns False if user or document parameters are None/empty.

Dependencies

  • logging
  • typing
  • CDocs.config

Required Imports

import logging
from typing import Dict, List, Any, Union
from CDocs.config import settings

Usage Example

from typing import Any, Dict, List
from CDocs.config import settings
import logging

# Setup logger
logger = logging.getLogger(__name__)

# Configure settings
settings.ROLE_PERMISSIONS = {
    'USER': ['VIEW_DOCUMENT'],
    'EDITOR': ['VIEW_DOCUMENT', 'EDIT_DOCUMENT'],
    'ADMIN': ['VIEW_DOCUMENT', 'EDIT_DOCUMENT', 'DELETE_DOCUMENT', 'CREATE_REVIEW', 'CREATE_APPROVAL']
}

# Create mock user and document
class User:
    def __init__(self, uid, roles):
        self.uid = uid
        self.roles = roles

user = User(uid='user123', roles=['EDITOR'])
document = {'owner_id': 'user456', 'title': 'My Document'}

# Check single permission
can_view = check_document_permission(user, document, 'VIEW_DOCUMENT')
print(f"Can view: {can_view}")  # True

# Check multiple permissions (returns True if ANY match)
can_edit_or_delete = check_document_permission(user, document, ['EDIT_DOCUMENT', 'DELETE_DOCUMENT'])
print(f"Can edit or delete: {can_edit_or_delete}")  # True (has EDIT_DOCUMENT)

# Document owner gets special permissions
owner = User(uid='user456', roles=['USER'])
can_owner_delete = check_document_permission(owner, document, 'DELETE_DOCUMENT')
print(f"Owner can delete: {can_owner_delete}")  # True (owner privilege)

Best Practices

  • Ensure settings.ROLE_PERMISSIONS is properly configured before calling this function, including at minimum 'USER' and 'ADMIN' roles
  • Always include 'owner_id' or 'owner_uid' in document dictionaries to enable ownership-based permissions
  • Use list of permissions when checking if user has ANY of multiple permissions; use separate calls for AND logic
  • ADMIN role bypasses all other checks and grants all permissions - use this role carefully
  • Document owners automatically receive VIEW_DOCUMENT, EDIT_DOCUMENT, DELETE_DOCUMENT, CREATE_REVIEW, and CREATE_APPROVAL permissions regardless of their roles
  • The function gracefully handles None/missing user or document by returning False, but consider validating inputs before calling for better error messages
  • Configure a logger in the module scope to enable debug logging for permission grant tracking
  • When user has no roles attribute or empty roles list, the function falls back to checking USER role permissions

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function user_has_permission_for_resource 78.1% 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 user_has_permission 75.9% similar

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

    From: /tf/active/vicechatdev/CDocs/config/permissions.py
  • function get_document_access 66.5% similar

    Retrieves document access information for a specific user, including permissions (write access, owner, reviewer, approver status) and share URL.

    From: /tf/active/vicechatdev/CDocs/controllers/api_handler.py
  • function get_document_permissions 65.9% similar

    Retrieves permission information for a specific document by its unique identifier, returning structured data about who can access the document and their permission levels.

    From: /tf/active/vicechatdev/CDocs/controllers/api_handler.py
  • function set_document_permissions_in_filecloud 64.4% similar

    Sets user and group permissions for a document in FileCloud by updating access controls on the document's folder path and logging the permission changes to an audit trail.

    From: /tf/active/vicechatdev/CDocs/controllers/filecloud_controller.py
← Back to Browse