Edgewall Software

Version 17 (modified by Ryan J Ollos, 5 years ago) ( diff )

Document policy proposed in gmessage:trac-users:YcLn-OUkZyk/x5XqjPtbAgAJ.

Custom Permission Policies

Permission policies were introduced on the TracFineGrainedPermissions page. Custom policies can often be implemented with a short plugin. Some custom permission policy examples are given on this page.

Restrict a Workflow Action to the Ticket Owner

This permissions policy can be used to restrict a workflow action to the ticket owner that possesses TICKET_CHANGE_STATE. User with TICKET_ADMIN can perform the action even if they are not the owner.

To install and activate the plugin:

  1. Create a single file plugin that implements IPermissionPolicy and IPermissionRequestor:
    # -*- coding: utf-8 -*-
    #
    # Copyright (C) 2014-2017 Edgewall Software
    # All rights reserved.
    #
    # This software is licensed as described in the file COPYING, which
    # you should have received as part of this distribution. The terms
    # are also available at http://trac.edgewall.org/wiki/TracLicense.
    #
    # This software consists of voluntary contributions made by many
    # individuals. For the exact contribution history, see the revision
    # history and logs, available at http://trac.edgewall.org/log/.
    
    from trac.core import *
    from trac.perm import IPermissionPolicy, IPermissionRequestor
    from trac.resource import ResourceNotFound
    from trac.ticket.model import Ticket
    
    
    class RestrictTicketActionsPolicy(Component):
        """Provides a permission for restricting ticket actions to the
        ticket owner.
        """
    
        implements(IPermissionPolicy, IPermissionRequestor)
    
        _field = 'owner'
    
        # IPermissionRequestor methods
    
        def get_permission_actions(self):
            return ['TICKET_CHANGE_STATE']
    
        # IPermissionPolicy methods
    
        def check_permission(self, action, username, resource, perm):
            if action == 'TICKET_CHANGE_STATE' and \
                    resource is not None and \
                    resource.realm == 'ticket' and \
                    resource.id is not None:
                try:
                    ticket = Ticket(self.env, resource.id)
                except ResourceNotFound:
                    pass
                else:
                    if ticket[self._field] != username:
                        return 'TICKET_ADMIN' in perm
    
  2. Edit the permission_policies option in the [trac] section of trac.ini, adding the RestrictTicketActionsPolicy component before the default permission policy:
    [trac]
    permission_policies = RestrictTicketActionsPolicy, ...
    
  3. Require TICKET_CHANGE_STATE for one or more workflow actions. For example, the default workflow could be modified so that only the ticket owner can assign tickets:
    -reassign.permissions = TICKET_MODIFY
    +reassign.permissions = TICKET_CHANGE_STATE
    
  4. Grant the TICKET_CHANGE_STATE permission to your users.

The permission policy can be applied to the ticket reporter rather than the ticket owner by changing the _field class attribute from 'owner' to 'reporter'.

Grant a permission to the Ticket Owner

This permissions policy can be used to grant permissions to the ticket's owner.

To install and activate the plugin:

  1. Create a single file plugin that implements IPermissionPolicy:
    # -*- coding: utf-8 -*-
    #
    # Copyright (C) 2014-2017 Edgewall Software
    # All rights reserved.
    #
    # This software is licensed as described in the file COPYING, which
    # you should have received as part of this distribution. The terms
    # are also available at http://trac.edgewall.org/wiki/TracLicense.
    #
    # This software consists of voluntary contributions made by many
    # individuals. For the exact contribution history, see the revision
    # history and logs, available at http://trac.edgewall.org/log/.
    
    from trac.core import *
    from trac.perm import IPermissionPolicy
    from trac.resource import ResourceNotFound
    from trac.ticket.model import Ticket
    
    
    class GrantTicketOwnerPermissionsPolicy(Component):
        """Grants permissions to the ticket owner."""
    
        implements(IPermissionPolicy)
    
        allowed_actions = (
            'TICKET_CHGPROP',
            'TICKET_EDIT_CC',
            'TICKET_EDIT_DESCRIPTION',
            'TICKET_EDIT_COMMENT')
    
        # IPermissionPolicy methods
    
        def check_permission(self, action, username, resource, perm):
            if action in self.allowed_actions and \
                    resource is not None and \
                    resource.realm == 'ticket' and \
                    resource.id is not None:
                try:
                    ticket = Ticket(self.env, resource.id)
                except ResourceNotFound:
                    pass
                else:
                    if ticket['owner'] == username:
                        return True
    
  2. Edit the permission_policies option in the [trac] section of trac.ini, adding the GrantTicketOwnerPermissionsPolicy component before the default permission policy:
    [trac]
    permission_policies = GrantTicketOwnerPermissionsPolicy, ...
    

Variations

  • Remove permissions from the allowed_actions or add others.
  • Change ticket['owner'] to ticket['reporter'] to grant the permissions to the Ticket Reporter instead.

Support Desk Policy

This permission policy allows users to view only tickets they have reported.

To install and activate the plugin:

  1. Create a single file plugin that implements IPermissionPolicy:
    # -*- coding: utf-8 -*-
    #
    # Copyright (C) 2017 Edgewall Software
    # All rights reserved.
    #
    # This software is licensed as described in the file COPYING, which
    # you should have received as part of this distribution. The terms
    # are also available at http://trac.edgewall.org/wiki/TracLicense.
    #
    # This software consists of voluntary contributions made by many
    # individuals. For the exact contribution history, see the revision
    # history and logs, available at http://trac.edgewall.org/log/.
    
    from trac.core import *
    from trac.perm import IPermissionPolicy, IPermissionRequestor
    from trac.resource import ResourceNotFound
    from trac.ticket.model import Ticket
    
    
    class SupportDeskPolicy(Component):
        """Provides a permission for restricting ticket actions to the
        ticket owner.
        """
    
        implements(IPermissionPolicy, IPermissionRequestor)
    
        # IPermissionRequestor methods
    
        def get_permission_actions(self):
            return ['TICKET_VIEW_REPORTED']
    
        # IPermissionPolicy methods
    
        def check_permission(self, action, username, resource, perm):
            if username != 'anonymous' and \
                    action == 'TICKET_VIEW' and \
                    'TICKET_ADMIN' not in perm:
                if 'TICKET_VIEW_REPORTED' in perm:
                    if resource is None or \
                            resource.realm == 'ticket' and \
                            resource.id is None:
                        return True
                    elif resource.realm == 'ticket' and \
                            resource.id is not None:
                        try:
                            ticket = Ticket(self.env, resource.id)
                        except ResourceNotFound:
                            pass
                        else:
                            return username in (ticket['reporter'], ticket['owner'])
    
    
  2. Edit the permission_policies option in the [trac] section of trac.ini, adding the SupportDeskPolicy component before the default permission policy:
    [trac]
    permission_policies = SupportDeskPolicy, ...
    
  3. Revoke TICKET_VIEW and grant TICKET_VIEW_REPORTED for users that should only view tickets they reported. Users with TICKET_VIEW can view all tickets, provided they don't also have TICKET_VIEW_REPORTED.
  4. Grant other permissions such as TICKET_CHGPROP, TICKET_APPEND or TICKET_MODIFY. Users can only change tickets they can view, therefore you'll only be granting these permissions for tickets the user reported.

Restrict Tickets Per Milestone

Milestones access can be restricted per-milestone using AuthzPolicy. This permission policy further allows users to only view tickets that are assigned to viewable milestones.

To install and activate the plugin:

  1. Create a single file plugin that implements IPermissionPolicy:
    # -*- coding: utf-8 -*-
    #
    # Copyright (C) 2019 Edgewall Software
    # All rights reserved.
    #
    # This software is licensed as described in the file COPYING, which
    # you should have received as part of this distribution. The terms
    # are also available at https://trac.edgewall.org/wiki/TracLicense.
    #
    # This software consists of voluntary contributions made by many
    # individuals. For the exact contribution history, see the revision
    # history and logs, available at https://trac.edgewall.org/log/.
    
    from trac.core import *
    from trac.perm import IPermissionPolicy
    from trac.resource import ResourceNotFound
    from trac.ticket.model import Ticket
    
    
    class TicketMilestonePolicy(Component):
        """Provides a permission for restricting ticket access to
        viewable milestones.
        """
    
        implements(IPermissionPolicy)
    
        # IPermissionPolicy methods
    
        def check_permission(self, action, username, resource, perm):
            if action == 'TICKET_VIEW':
                if resource is None or \
                        resource.realm == 'ticket' and \
                        resource.id is None:
                    return True
                elif resource.realm == 'ticket' and \
                        resource.id is not None:
                    try:
                        ticket = Ticket(self.env, resource.id)
                    except ResourceNotFound:
                        pass
                    else:
                        return 'MILESTONE_VIEW' in perm('milestone',
                                                        ticket['milestone'])
    
    
  2. Edit [trac] permission_policies in trac.ini, adding the TicketMilestonePolicy and AuthzPolicy components before the default permission policy:
    [trac]
    permission_policies = TicketMilestonePolicy, AuthzPolicy, ...
    
  3. Revoke the coarse-grained MILESTONE_VIEW and configure AuthzPolicy with a policy that grants MILESTONE_VIEW per milestone-resource:
    [milestone:milestone1]
    user1 = MILESTONE_VIEW
    
    [milestone:milestone2]
    user2 = MILESTONE_VIEW
    
  4. Grant TICKET_VIEW to any users that you wish to view some (but not necessarily all) tickets. The TicketMilestonePolicy will deny access to a ticket if the users isn't allowed to view the associated milestone for the ticket, even though the user has coarse-grained TICKET_VIEW.
  5. Grant other permissions such as TICKET_CHGPROP, TICKET_APPEND or TICKET_MODIFY. Users can only change tickets they can view, therefore you'll only be granting these permissions for tickets assigned to milestones they can view.

Restrict Changing Ticket Milestone

With the default permission policies enabled, a user with TICKET_CHGPROP and MILESTONE_VIEW can change the milestone of a ticket. Since 1.3.2 the behavior is implemented in the permission policy DefaultTicketPolicy. The action TICKET_CHG_MILESTONE is used to grant the privilege, however this permission is not defined through an IPermissionRequestor implementation and therefore not available to be assigned to users.

The action can be defined using ExtraPermissionsProvider, and with no other changes to the permission policy, changing the milestone property will be restricted to users with the TICKET_CHG_MILESTONE permission.

[extra-permissions]
_perms = TICKET_CHG_MILESTONE

See also: #8778.


See also: ReadonlySignedTickets policy, mailing list discussion about RestrictTicketActionsPolicy

Note: See TracWiki for help on using the wiki.