trac-componentpermissions / componentpermissions /

Full commit
import re

from trac.core import *
from trac.config import Option
from trac.perm import IPermissionRequestor, IPermissionPolicy
from trac.ticket import model
from trac.resource import ResourceNotFound

class ComponentPermissionsPolicy(Component):
    This component provides permissions based on ticket components for Trac.

    implements(IPermissionRequestor, IPermissionPolicy)

    ticket_field_name = Option('component-permissions', 'ticket_field_name', 'component_permissions_field',
        """The name of the field which should be checked to see if the component permission is required.""")

    # IPermissionRequestor methods
    def _get_permission_name(self, component):
        return 'COMPONENT_%s_VIEW' % (re.sub('[^a-zA-Z]+', '_', component).strip('_').upper(),)

    def get_permission_actions(self):
        for component in
            yield self._get_permission_name(

    # IPermissionPolicy methods

    def check_permission(self, action, username, resource, perm):
        # To prevent recursion
        if action in self.get_permission_actions():

        # Check whether we're dealing with a ticket resource
        while resource:
            if resource.realm == 'ticket':
            resource = resource.parent
        if resource and resource.realm == 'ticket' and is not None:
                ticket = model.Ticket(self.env, int(
                should_check_permissions = ticket.values.get(self.ticket_field_name, 0)
            except ResourceNotFound:
                # There is a short race condition here but we cannot do much

            if should_check_permissions and int(should_check_permissions) and 'component' in ticket.values:
                permission = self._get_permission_name(ticket['component'])
                if permission not in perm and 'TICKET_ADMIN' not in perm:
                    return False