🔍 Code Extractor

class DocUser

Maturity: 30

Extended User model for document management system. This class wraps and extends the existing User model in the system, adding document-specific roles, departments, and permissions.

File:
/tf/active/vicechatdev/CDocs/models/user_extensions.py
Lines:
24 - 939
Complexity:
moderate

Purpose

Extended User model for document management system. This class wraps and extends the existing User model in the system, adding document-specific roles, departments, and permissions.

Source Code

class DocUser(BaseModel):
    """
    Extended User model for document management system.
    
    This class wraps and extends the existing User model in the system,
    adding document-specific roles, departments, and permissions.
    """
    
    def __init__(self, data: Optional[Dict[str, Any]] = None, uid: Optional[str] = None):
        """
        Initialize a DocUser instance.
        
        Args:
            data: Dictionary of user properties
            uid: User UID to load from database (if data not provided)
        """
        if data is None and uid is not None:
            # Fetch user data from database
            # Check if uid is a string or has a UID attribute (e.g., another model instance)
            if not isinstance(uid, str) and hasattr(uid, 'UID'):
                uid = uid.UID
            data = db.get_node_by_uid(uid)
            
        super().__init__(data or {})
        self._cache = {}  # Cache for expensive operations
        
    @classmethod
    def from_existing_user(cls, user_uid: str) -> 'DocUser':
        """
        Create a DocUser instance from an existing User node.
        
        Args:
            user_uid: UID of existing User node
            
        Returns:
            DocUser instance
        """
        # Get existing user data
        user_data = db.get_node_by_uid(user_uid)
        if not user_data:
            logger.error(f"User with UID {user_uid} not found")
            return None
            
        # Check if user already has CDocs extension
        has_extension = db.run_query(
            """
            MATCH (u:User {UID: $uid})-[:HAS_ROLE]->(r:CDocs_Role)
            RETURN count(r) > 0 AS has_extension
            """,
            {"uid": user_uid}
        )
        
        if not has_extension or not has_extension[0].get('has_extension', False):
            # Set up user for document system if not already set up
            logger.info(f"Setting up new CDocs extension for user {user_data.get('Name', user_uid)}")
            cls._setup_user_extension(user_uid)
            
        return cls(user_data)
    
    @staticmethod
    def _setup_user_extension(user_uid: str) -> bool:
        """
        Set up CDocs extension for a user.
        
        Args:
            user_uid: UID of user to set up
            
        Returns:
            Boolean indicating success
        """
        try:
            # Add CDocs_User label
            db.run_query(
                """
                MATCH (u:User {UID: $uid})
                SET u:CDocs_User
                """,
                {"uid": user_uid}
            )
            
            # First check if the VIEWER role definition already exists
            role_node = db.run_query(
                """
                MATCH (c:CDocs)-[:ROLE_DEFINITION]->(r:CDocs_Role {name: 'VIEWER'})
                RETURN r.UID as role_uid
                LIMIT 1
                """,
                {}
            )
            
            if role_node and role_node[0].get('role_uid'):
                # Role exists, create relationship between user and existing role
                db.run_query(
                    """
                    MATCH (u:User {UID: $uid}), (r:CDocs_Role {UID: $role_uid})
                    MERGE (u)-[:HAS_ROLE]->(r)
                    """,
                    {"uid": user_uid, "role_uid": role_node[0]['role_uid']}
                )
                logger.info(f"Added existing VIEWER role to user {user_uid}")
            else:
                # Role doesn't exist, create it first
                role_uid = str(uuid.uuid4())
                db.run_query(
                    """
                    MATCH (u:User {UID: $uid}), (c:CDocs)
                    MERGE (c)-[:ROLE_DEFINITION]->(r:CDocs_Role {
                        UID: $role_uid,
                        name: 'VIEWER',
                        createdDate: datetime()
                    })
                    MERGE (u)-[:HAS_ROLE]->(r)
                    """,
                    {
                        "uid": user_uid,
                        "role_uid": role_uid
                    }
                )
                logger.info(f"Created new VIEWER role and added to user {user_uid}")
            
            return True
        except Exception as e:
            logger.error(f"Error setting up user extension: {e}")
            return False
    
    @property
    def name(self) -> str:
        """Get user name."""
        return self._data.get('Name', '')
    
    @property
    def email(self) -> str:
        """Get user email."""
        return self._data.get('Mail', '')

    @property
    def UID(self) -> str:
        """Get user UID."""
        return self._data.get('UID', '')
    
    @property
    def username(self) -> str:
        """Get username, defaulting to Name."""
        return self._data.get('Name', '')
    
    @property
    def department(self) -> Optional[str]:
        """Get user department code."""
        return self._data.get('department')
            
    @department.setter
    def department(self, dept_code_or_name: str) -> None:
        """
        Set user department by code or name.
        
        Args:
            dept_code_or_name: Department code or full name
        """
        if not dept_code_or_name:
            return
            
        # Ensure we have the department code
        dept_code = settings.get_department_code(dept_code_or_name)
            
        # Update property
        self._data['department'] = dept_code
        db.update_node(self.uid, {'department': dept_code})
        
    def get_department_name(self) -> str:
        """Get full department name."""
        dept_code = self.department
        if not dept_code:
            return "Unassigned"
        return settings.get_department_name(dept_code)
    
    @property
    def roles(self) -> List[str]:
        """Get user document roles."""
        if 'roles' in self._cache:
            return self._cache['roles']
            
        roles = db.run_query(
            """
            MATCH (u:User {UID: $uid})-[:HAS_ROLE]->(r:CDocs_Role)
            RETURN r.name AS role
            """,
            {"uid": self.uid}
        )
        
        role_list = [r['role'] for r in roles if 'role' in r]
        self._cache['roles'] = role_list
        return role_list
    
    def add_role(self, role_name: str) -> bool:
        """
        Add a role to the user.
        
        Args:
            role_name: Role name from settings.USER_ROLES
            
        Returns:
            Boolean indicating success
        """
        if role_name not in settings.USER_ROLES:
            logger.error(f"Invalid role: {role_name}")
            return False
            
        try:
            # Check if user already has this role
            if role_name in self.roles:
                logger.debug(f"User {self.uid} already has role {role_name}")
                return True
                
            # First check if the role definition already exists
            role_node = db.run_query(
                """
                MATCH (c:CDocs)-[:ROLE_DEFINITION]->(r:CDocs_Role {name: $role_name})
                RETURN r.UID as role_uid
                LIMIT 1
                """,
                {"role_name": role_name}
            )
            
            if role_node and role_node[0].get('role_uid'):
                # Role exists, create relationship between user and existing role
                db.run_query(
                    """
                    MATCH (u:User {UID: $uid}), (r:CDocs_Role {UID: $role_uid})
                    MERGE (u)-[:HAS_ROLE]->(r)
                    """,
                    {"uid": self.uid, "role_uid": role_node[0]['role_uid']}
                )
                logger.info(f"Added existing role {role_name} to user {self.uid}")
            else:
                # Role doesn't exist, create it first
                role_uid = str(uuid.uuid4())
                db.run_query(
                    """
                    MATCH (u:User {UID: $uid}), (c:CDocs)
                    MERGE (c)-[:ROLE_DEFINITION]->(r:CDocs_Role {
                        UID: $role_uid,
                        name: $role_name,
                        createdDate: datetime()
                    })
                    MERGE (u)-[:HAS_ROLE]->(r)
                    """,
                    {
                        "uid": self.uid,
                        "role_uid": role_uid,
                        "role_name": role_name
                    }
                )
                logger.info(f"Created new role {role_name} and added to user {self.uid}")
            
            # Clear cache
            if 'roles' in self._cache:
                del self._cache['roles']
                
            return True
        except Exception as e:
            logger.error(f"Error adding role {role_name} to user {self.uid}: {e}")
            return False

    def remove_role(self, role_name: str) -> bool:
        """
        Remove a role from the user.
        
        Args:
            role_name: Role name to remove
            
        Returns:
            Boolean indicating success
        """
        if role_name not in self.roles:
            logger.debug(f"User {self.uid} doesn't have role {role_name}")
            return True  # Already doesn't have the role
            
        try:
            # Remove only the relationship, not the role node itself
            result = db.run_query(
                """
                MATCH (u:User {UID: $uid})-[r:HAS_ROLE]->(role:CDocs_Role {name: $role_name})
                DELETE r
                RETURN count(r) AS deleted
                """,
                {"uid": self.uid, "role_name": role_name}
            )
            
            success = result and result[0].get('deleted', 0) > 0
            
            if success:
                logger.info(f"Removed role {role_name} from user {self.uid}")
                
                # Clear cache
                if 'roles' in self._cache:
                    del self._cache['roles']
                    
            return success
        except Exception as e:
            logger.error(f"Error removing role {role_name} from user {self.uid}: {e}")
            return False
    
    def has_permission(self, permission: Union[str, Permission], resource: Optional[Dict[str, Any]] = None) -> bool:
        """
        Check if user has a specific permission.
        
        Args:
            permission: Permission to check
            resource: Optional resource for context-specific permission checks
            
        Returns:
            Boolean indicating whether user has the permission
        """
        logger.debug(f"Checking permission {permission} for user {self.username}")
        logger.debug(f"User roles: {self.roles}")
        
        # Convert permission object to string if needed
        if hasattr(permission, 'value'):
            permission_str = permission.value
        else:
            permission_str = str(permission)
            
        # Check for admin role which has all permissions
        if 'ADMIN' in self.roles:
            logger.debug(f"User {self.username} has ADMIN role, granting permission")
            return True
            
        # Check if role-based permissions include this permission
        for role in self.roles:
            if role in permissions.ROLE_PERMISSIONS and permission_str in permissions.ROLE_PERMISSIONS[role]:
                logger.debug(f"User has role {role} with permission {permission_str}")
                return True
                
        # Check resource-specific permissions
        if resource and 'owner_id' in resource and resource['owner_id'] == self.uid:
            # Document owners have additional permissions
            owner_permissions = [
                'VIEW_DOCUMENT', 'EDIT_DOCUMENT', 'DELETE_DOCUMENT',
                'CREATE_REVIEW', 'CREATE_APPROVAL'
            ]
            if permission_str in owner_permissions:
                return True
    
        logger.debug(f"Permission {permission_str} denied for user {self.username}")
        return False

    def get_permissions(self) -> Set[str]:
        """
        Get all permissions for this user.
        
        Returns:
            Set of permission strings
        """
        # Start with empty set
        user_permissions = set()
        
        # Add permissions from each role
        for role in self.roles:
            if role in permissions.ROLE_PERMISSIONS:
                user_permissions.update(permissions.ROLE_PERMISSIONS[role])
                
        return user_permissions

    def can_perform_action(self, action: str, resource: Dict[str, Any]) -> bool:
        """
        Check if user can perform a specific action on a resource.
        
        Args:
            action: Action to perform (e.g., 'edit', 'review', 'approve')
            resource: Resource dictionary (e.g., document)
            
        Returns:
            Boolean indicating whether the action is allowed
        """
        # Map actions to permissions
        action_permission_map = {
            'view': 'VIEW_DOCUMENT',
            'edit': 'EDIT_DOCUMENT',
            'delete': 'DELETE_DOCUMENT',
            'review': 'REVIEW_DOCUMENT',
            'approve': 'APPROVE_DOCUMENT',
            'publish': 'PUBLISH_DOCUMENT'
        }
        
        # Get the corresponding permission for the action
        if action in action_permission_map:
            return self.has_permission(action_permission_map[action], resource)
        
        # For unknown actions, deny by default
        return False
    
    def get_assigned_documents(self, status: Optional[str] = None) -> List[Dict[str, Any]]:
        """
        Get documents assigned to this user for review or approval.
        
        Args:
            status: Optional status filter (e.g., 'IN_REVIEW', 'IN_APPROVAL')
            
        Returns:
            List of document dictionaries
        """
        query = """
        MATCH (u:User {UID: $uid})
        MATCH (d:ControlledDocument)
        """
        
        if status:
            query += f"WHERE d.status = '{status}' "
            
        query += """
        OPTIONAL MATCH (d)-[:HAS_VERSION]->(v:DocumentVersion)-[:FOR_REVIEW]->(r:ReviewCycle)-[:REVIEWED_BY]->(u)
        OPTIONAL MATCH (d)-[:HAS_VERSION]->(v2:DocumentVersion)-[:FOR_REVIEW]->(r2:ReviewCycle)-[:FOR_APPROVAL]->(a:Approval)-[:APPROVED_BY]->(u)
        WITH d, v, r, v2, r2, a
        WHERE (v IS NOT NULL AND r IS NOT NULL) OR (v2 IS NOT NULL AND r2 IS NOT NULL AND a IS NOT NULL)
        RETURN DISTINCT d
        """
        
        try:
            result = db.run_query(query, {"uid": self.uid})
            return [record.get('d', {}) for record in result if 'd' in record]
        except Exception as e:
            logger.error(f"Error getting assigned documents: {e}")
            return []
    
    def get_owned_documents(self, status: Optional[str] = None) -> List[Dict[str, Any]]:
        """
        Get documents owned by this user.
        
        Args:
            status: Optional status filter
            
        Returns:
            List of document dictionaries
        """
        query = """
        MATCH (u:User {UID: $uid})
        MATCH (d:ControlledDocument)-[:HAS_VERSION]->(v:DocumentVersion)-[:AUTHORED_BY]->(u)
        """
        
        if status:
            query += f"WHERE d.status = '{status}' "
            
        query += "RETURN DISTINCT d"
        
        try:
            result = db.run_query(query, {"uid": self.uid})
            return [record.get('d', {}) for record in result if 'd' in record]
        except Exception as e:
            logger.error(f"Error getting owned documents: {e}")
            return []
    
    @classmethod
    def get_users_by_role(cls, role: str) -> List['DocUser']:
        """
        Get all users with a specific role.
        
        Args:
            role: Role name
            
        Returns:
            List of DocUser instances
        """
        try:
            result = db.run_query(
                """
                MATCH (u:User)-[:HAS_ROLE]->(r:CDocs_Role {name: $role})
                RETURN u
                """,
                {"role": role}
            )
            
            return [cls(record['u']) for record in result if 'u' in record]
        except Exception as e:
            logger.error(f"Error getting users by role {role}: {e}")
            return []
    
    @classmethod
    def get_users_by_department(cls, department: str) -> List['DocUser']:
        """
        Get all users in a specific department.
        
        Args:
            department: Department code
            
        Returns:
            List of DocUser instances
        """
        try:
            result = db.run_query(
                """
                MATCH (u:User)-[:BELONGS_TO]->(d:Department {code: $dept})
                RETURN u
                """,
                {"dept": department}
            )
            
            return [cls(record['u']) for record in result if 'u' in record]
        except Exception as e:
            logger.error(f"Error getting users by department {department}: {e}")
            return []
    
    @classmethod
    def get_by_username(cls, username: str) -> Optional['DocUser']:
        """
        Get a user by username.
        
        Parameters
        ----------
        username : str
            The username to look up
            
        Returns
        -------
        Optional[DocUser]
            The user object if found, None otherwise
        """
        try:
            from CDocs.db import db_operations
            
            result = db_operations.run_query(
                """
                MATCH (u:User {username: $username})
                RETURN u
                """,
                {"username": username}
            )
            
            # Handle result as list instead of Neo4j Record with single() method
            if result and len(result) > 0 and 'u' in result[0]:
                user_data = dict(result[0]['u'])
                return cls(data=user_data)  # Use data parameter correctly
            return None
        except Exception as e:
            logger.error(f"Error getting user by username: {e}")
            return None
    
    @classmethod
    def get_by_username_or_email(cls, login: str) -> Optional['DocUser']:
        """
        Get a user by username or email.
        
        Parameters
        ----------
        login : str
            The username or email to look up
            
        Returns
        -------
        Optional[DocUser]
            The user object if found, None otherwise
        """
        try:
            # Try to find by username or email
            result = db.run_query(
                """
                MATCH (u:User)
                WHERE u.username = $login OR u.Mail = $login OR u.Name = $login
                RETURN u LIMIT 1
                """,
                {"login": login}
            )
            
            # Handle result
            if result and len(result) > 0 and 'u' in result[0]:
                user_data = dict(result[0]['u'])
                return cls(data=user_data)
            return None
        except Exception as e:
            logger.error(f"Error getting user by login '{login}': {e}")
            return None

    @classmethod
    def create(cls, username: str, password: str, name: str = None, email: str = None, 
               department: str = 'General', role: str = 'USER') -> Optional['DocUser']:
        """
        Create a new user.
        
        Parameters
        ----------
        username : str
            The username
        password : str
            The password (will be hashed)
        name : str, optional
            Full name of the user
        email : str, optional
            Email address
        department : str, optional
            Department name
        role : str, optional
            User role (USER, ADMIN, etc.)
            
        Returns
        -------
        Optional[DocUser]
            The created user object if successful, None otherwise
        """
        try:
            from CDocs.db import db_operations
            import uuid
            from datetime import datetime
            
            # Check if user already exists
            existing = cls.get_by_username(username)
            if existing:
                logger.warning(f"User {username} already exists")
                return existing
            
            # Create new user with UID
            uid = str(uuid.uuid4())
            
            # In production, use proper password hashing
            # hashed_password = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
            
            user_data = {
                'UID': uid,
                'username': username,
                'password': password,  # In production, store hashed password
                'Name': name or username,
                'Mail': email or '',
                'department': department,
                'role': role,
                'created': datetime.now().isoformat(),
                'active': True
            }
            
            # Create user node in database
            result = db_operations.create_node_with_relationship('User', user_data,'c1df72ea-6b91-4fb3-a8be-88e83bfb0776','DIRECTORY','INCOMING')
            
            # Return user object with correct initialization
            return cls(data=user_data)  # Use the data parameter correctly
        except Exception as e:
            logger.error(f"Error creating user: {e}")
            raise e
    
    @classmethod
    def from_datacapture_user(cls, dc_user) -> 'DocUser':
        """
        Create a DocUser from the existing datacapture User instance.
        
        Parameters
        ----------
        dc_user : object
            User instance from datacapture.py
            
        Returns
        -------
        DocUser
            DocUser instance or None if it fails
        """
        try:
            if not dc_user:
                logger.error("Invalid datacapture user provided")
                return None
            
            # Extract essential attributes from datacapture user
            # Use getattr with defaults to handle missing attributes safely
            user_data = {
                'UID': getattr(dc_user, 'UID', ''),
                'Name': getattr(dc_user, 'user', ''),  # Primary name field from datacapture
                'Mail': getattr(dc_user, 'mail', ''),  # Email address
                'password': getattr(dc_user, 'password', ''),  # Password hash
                # Additional fields that might be needed
                'is_admin': getattr(dc_user, 'is_admin', False),
                'is_manager': getattr(dc_user, 'is_manager', False),
                'usergroups': getattr(dc_user, 'usergroups', []),
            }
            
            # Create a DocUser instance
            doc_user = cls(data=user_data)
            
            return doc_user
        except Exception as e:
            logger.error(f"Error creating DocUser from datacapture user: {e}")
            import traceback
            logger.error(traceback.format_exc())
            return None
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        result = super().to_dict()
        result.update({
            'name': self.name,
            'email': self.email,
            'username': self.username,
            'department': self.department,
            'roles': self.roles,
            'permissions': [str(p) for p in self.get_permissions()]
        })
        return result
    
    @classmethod
    def verify_user(cls, username: str, password: str) -> Optional['DocUser']:
        """
        Verify user credentials
        
        Parameters
        ----------
        username : str
            Username or email to verify
        password : str
            Password to check
            
        Returns
        -------
        DocUser or None
            DocUser instance if authentication successful, None otherwise
        """
        from passlib.hash import bcrypt
        
        # Try to find user
        user = cls.get_by_username(username)
        
        if not user:
            return None
        
        # Check if user has password in our system
        if 'password' in user._data and user._data['password']:
            # Verify with our password hash
            if bcrypt.verify(password, user._data['password']):
                return user
            return None
        
        # No password in our system, try direct database check
        query = """
        MATCH (u:User)
        WHERE (u.Name = $username OR u.Mail = $username) AND u.password IS NOT NULL
        RETURN u.password AS password
        """
        
        result = db.run_query(query, {'username': username})
        record = result.single()
        
        if record and record['password'] and bcrypt.verify(password, record['password']):
            return user
        
        return None

    @classmethod
    def authenticate(cls, login: str, password: str) -> Optional['DocUser']:
        """
        Authenticate a user with username/email and password.
        
        Parameters
        ----------
        login : str
            The username or email to authenticate
        password : str
            The plain text password to verify against stored hash
            
        Returns
        -------
        Optional[DocUser]
            The authenticated user object if successful, None otherwise
        """
        try:
            # Query for user with matching username, email or Name
            result = db.run_query(
                """
                MATCH (u:User)
                WHERE u.username = $login OR u.Mail = $login OR u.Name = $login
                RETURN u LIMIT 1
                """,
                {"login": login}
            )
            
            # Handle result
            if not result or len(result) == 0 or 'u' not in result[0]:
                logger.warning(f"User '{login}' not found during authentication")
                return None
                
            user_data = dict(result[0]['u'])
            
            # Check if user has password property
            stored_password = user_data.get('password')
            if not stored_password:
                logger.warning(f"No password defined for user '{login}'")
                return None
                
            # Verify password using SHA-256 hash
            import hashlib
            hashed_password = hashlib.sha256(password.encode('utf-8')).hexdigest()
            
            if hashed_password != stored_password:
                logger.warning(f"Invalid password for user '{login}'")
                return None
                
            # Create DocUser instance
            user = cls(data=user_data)
            
            logger.info(f"User '{login}' authenticated successfully")
            return user
            
        except Exception as e:
            logger.error(f"Error during authentication for '{login}': {str(e)}")
            return None
        
    @classmethod
    def get_by_email(cls, email: str) -> Optional['DocUser']:
        """
        Get a user by email address.
        
        Parameters
        ----------
        email : str
            The email address to look up
            
        Returns
        -------
        Optional[DocUser]
            The user object if found, None otherwise
        """
        try:
            # Query for user with matching email
            result = db.run_query(
                """
                MATCH (u:User)
                WHERE u.Mail = $email
                RETURN u LIMIT 1
                """,
                {"email": email}
            )
            
            # Handle result
            if result and len(result) > 0 and 'u' in result[0]:
                user_data = dict(result[0]['u'])
                return cls(data=user_data)
            return None
        except Exception as e:
            logger.error(f"Error getting user by email '{email}': {e}")
            return None
    
    @classmethod
    def get_or_create_from_sso(cls, email, name, sso_id=None):
        """
        Get an existing user or create a new one from SSO login info.
        
        Parameters
        ----------
        email : str
            User's email address
        name : str
            User's display name
        sso_id : str, optional
            User's SSO ID (from Azure AD)
            
        Returns
        -------
        DocUser
            User instance
        """
        try:
            # Log the SSO login attempt
            logger.info(f"Looking up or creating user for SSO login: {email}")
            
            # Check if user already exists with this email
            user = cls.get_by_email(email)
            
            if user:
                logger.info(f"Found existing user {user.username} for SSO login")
                
                # Update SSO ID if needed
                if sso_id and not hasattr(user, 'sso_id'):
                    logger.info(f"Updating SSO ID for user {user.username}")
                    from CDocs.db import db_operations
                    db_operations.update_node(user.uid, {'sso_id': sso_id})
                    
                return user
            
            # Create new user if not found
            logger.info(f"Creating new user for SSO login: {email}")
            
            # Generate a username from email (remove @ and everything after)
            username = email.split('@')[0].lower()
            
            # Set a random password (user will only log in via SSO)
            import secrets
            import string
            password_chars = string.ascii_letters + string.digits
            random_password = ''.join(secrets.choice(password_chars) for _ in range(16))
            
            # Get department from email domain (or default to General)
            from CDocs.config import settings
            domain = email.split('@')[1] if '@' in email else ''
            department = settings.get_department_for_domain(domain) or 'General'
            
            # Create the user
            user_data = {
                'username': username,
                'name': name,
                'email': email,
                'department': department,
                'role': 'USER',  # Default role
                'sso_id': sso_id,
                'sso_enabled': True
            }
            
            # Create user in the database
            from CDocs.db import db_operations
            user_uid = db_operations.create_node('User', user_data)
            
            if not user_uid:
                logger.error(f"Failed to create user for SSO login: {email}")
                return None
                
            # Get the user object
            user = cls.get_by_uid(user_uid)
            logger.info(f"Created new user {user.username} for SSO login")
            
            return user
            
        except Exception as e:
            logger.error(f"Error in get_or_create_from_sso: {e}")
            import traceback
            logger.error(traceback.format_exc())
            return None

Parameters

Name Type Default Kind
bases BaseModel -

Parameter Details

bases: Parameter of type BaseModel

Return Value

Returns unspecified type

Class Interface

Methods

__init__(self, data, uid)

Purpose: Initialize a DocUser instance. Args: data: Dictionary of user properties uid: User UID to load from database (if data not provided)

Parameters:

  • data: Type: Optional[Dict[str, Any]]
  • uid: Type: Optional[str]

Returns: None

from_existing_user(cls, user_uid) -> 'DocUser'

Purpose: Create a DocUser instance from an existing User node. Args: user_uid: UID of existing User node Returns: DocUser instance

Parameters:

  • cls: Parameter
  • user_uid: Type: str

Returns: Returns 'DocUser'

_setup_user_extension(user_uid) -> bool static

Purpose: Set up CDocs extension for a user. Args: user_uid: UID of user to set up Returns: Boolean indicating success

Parameters:

  • user_uid: Type: str

Returns: Returns bool

name(self) -> str property

Purpose: Get user name.

Returns: Returns str

email(self) -> str property

Purpose: Get user email.

Returns: Returns str

UID(self) -> str property

Purpose: Get user UID.

Returns: Returns str

username(self) -> str property

Purpose: Get username, defaulting to Name.

Returns: Returns str

department(self) -> Optional[str] property

Purpose: Get user department code.

Returns: Returns Optional[str]

department(self, dept_code_or_name) -> None

Purpose: Set user department by code or name. Args: dept_code_or_name: Department code or full name

Parameters:

  • dept_code_or_name: Type: str

Returns: Returns None

get_department_name(self) -> str

Purpose: Get full department name.

Returns: Returns str

roles(self) -> List[str] property

Purpose: Get user document roles.

Returns: Returns List[str]

add_role(self, role_name) -> bool

Purpose: Add a role to the user. Args: role_name: Role name from settings.USER_ROLES Returns: Boolean indicating success

Parameters:

  • role_name: Type: str

Returns: Returns bool

remove_role(self, role_name) -> bool

Purpose: Remove a role from the user. Args: role_name: Role name to remove Returns: Boolean indicating success

Parameters:

  • role_name: Type: str

Returns: Returns bool

has_permission(self, permission, resource) -> bool

Purpose: Check if user has a specific permission. Args: permission: Permission to check resource: Optional resource for context-specific permission checks Returns: Boolean indicating whether user has the permission

Parameters:

  • permission: Type: Union[str, Permission]
  • resource: Type: Optional[Dict[str, Any]]

Returns: Returns bool

get_permissions(self) -> Set[str]

Purpose: Get all permissions for this user. Returns: Set of permission strings

Returns: Returns Set[str]

can_perform_action(self, action, resource) -> bool

Purpose: Check if user can perform a specific action on a resource. Args: action: Action to perform (e.g., 'edit', 'review', 'approve') resource: Resource dictionary (e.g., document) Returns: Boolean indicating whether the action is allowed

Parameters:

  • action: Type: str
  • resource: Type: Dict[str, Any]

Returns: Returns bool

get_assigned_documents(self, status) -> List[Dict[str, Any]]

Purpose: Get documents assigned to this user for review or approval. Args: status: Optional status filter (e.g., 'IN_REVIEW', 'IN_APPROVAL') Returns: List of document dictionaries

Parameters:

  • status: Type: Optional[str]

Returns: Returns List[Dict[str, Any]]

get_owned_documents(self, status) -> List[Dict[str, Any]]

Purpose: Get documents owned by this user. Args: status: Optional status filter Returns: List of document dictionaries

Parameters:

  • status: Type: Optional[str]

Returns: Returns List[Dict[str, Any]]

get_users_by_role(cls, role) -> List['DocUser']

Purpose: Get all users with a specific role. Args: role: Role name Returns: List of DocUser instances

Parameters:

  • cls: Parameter
  • role: Type: str

Returns: Returns List['DocUser']

get_users_by_department(cls, department) -> List['DocUser']

Purpose: Get all users in a specific department. Args: department: Department code Returns: List of DocUser instances

Parameters:

  • cls: Parameter
  • department: Type: str

Returns: Returns List['DocUser']

get_by_username(cls, username) -> Optional['DocUser']

Purpose: Get a user by username. Parameters ---------- username : str The username to look up Returns ------- Optional[DocUser] The user object if found, None otherwise

Parameters:

  • cls: Parameter
  • username: Type: str

Returns: Returns Optional['DocUser']

get_by_username_or_email(cls, login) -> Optional['DocUser']

Purpose: Get a user by username or email. Parameters ---------- login : str The username or email to look up Returns ------- Optional[DocUser] The user object if found, None otherwise

Parameters:

  • cls: Parameter
  • login: Type: str

Returns: Returns Optional['DocUser']

create(cls, username, password, name, email, department, role) -> Optional['DocUser']

Purpose: Create a new user. Parameters ---------- username : str The username password : str The password (will be hashed) name : str, optional Full name of the user email : str, optional Email address department : str, optional Department name role : str, optional User role (USER, ADMIN, etc.) Returns ------- Optional[DocUser] The created user object if successful, None otherwise

Parameters:

  • cls: Parameter
  • username: Type: str
  • password: Type: str
  • name: Type: str
  • email: Type: str
  • department: Type: str
  • role: Type: str

Returns: Returns Optional['DocUser']

from_datacapture_user(cls, dc_user) -> 'DocUser'

Purpose: Create a DocUser from the existing datacapture User instance. Parameters ---------- dc_user : object User instance from datacapture.py Returns ------- DocUser DocUser instance or None if it fails

Parameters:

  • cls: Parameter
  • dc_user: Parameter

Returns: Returns 'DocUser'

to_dict(self) -> Dict[str, Any]

Purpose: Convert to dictionary representation.

Returns: Returns Dict[str, Any]

verify_user(cls, username, password) -> Optional['DocUser']

Purpose: Verify user credentials Parameters ---------- username : str Username or email to verify password : str Password to check Returns ------- DocUser or None DocUser instance if authentication successful, None otherwise

Parameters:

  • cls: Parameter
  • username: Type: str
  • password: Type: str

Returns: Returns Optional['DocUser']

authenticate(cls, login, password) -> Optional['DocUser']

Purpose: Authenticate a user with username/email and password. Parameters ---------- login : str The username or email to authenticate password : str The plain text password to verify against stored hash Returns ------- Optional[DocUser] The authenticated user object if successful, None otherwise

Parameters:

  • cls: Parameter
  • login: Type: str
  • password: Type: str

Returns: Returns Optional['DocUser']

get_by_email(cls, email) -> Optional['DocUser']

Purpose: Get a user by email address. Parameters ---------- email : str The email address to look up Returns ------- Optional[DocUser] The user object if found, None otherwise

Parameters:

  • cls: Parameter
  • email: Type: str

Returns: Returns Optional['DocUser']

get_or_create_from_sso(cls, email, name, sso_id)

Purpose: Get an existing user or create a new one from SSO login info. Parameters ---------- email : str User's email address name : str User's display name sso_id : str, optional User's SSO ID (from Azure AD) Returns ------- DocUser User instance

Parameters:

  • cls: Parameter
  • email: Parameter
  • name: Parameter
  • sso_id: Parameter

Returns: See docstring for return details

Required Imports

import logging
import uuid
from typing import Dict
from typing import List
from typing import Any

Usage Example

# Example usage:
# result = DocUser(bases)

Tags

class docuser

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class FlaskUser 57.8% similar

    A Flask-Login compatible user wrapper class that adapts CDocs DocUser objects for authentication and authorization in Flask applications.

    From: /tf/active/vicechatdev/CDocs/main_flask.py
  • class Document 55.7% similar

    A dataclass representing a document with hierarchical structure, versioning, metadata, and collaboration features.

    From: /tf/active/vicechatdev/vice_ai/models.py
  • class UserTraining 53.5% similar

    A model class representing a user's training status for a specific controlled document, managing training assignments, completion tracking, and expiration dates.

    From: /tf/active/vicechatdev/CDocs/models/training.py
  • class User 52.2% similar

    A user management class that handles authentication, authorization, user profiles, preferences, file management, and logging for a Panel-based web application with Neo4j backend.

    From: /tf/active/vicechatdev/userclass.py
  • class DocumentTraining 50.8% similar

    A model class that manages training requirements and assignments for controlled documents, including enabling/disabling training, assigning training to users, and tracking training status.

    From: /tf/active/vicechatdev/CDocs/models/training.py
← Back to Browse