Edgewall Software

Extension Point : IPermissionRequestor

InterfaceIPermissionRequestorSince0.9
Moduletrac.permSourceperm.py

The (somewhat confusingly named) IPermissionRequestor simply allows components to define permission actions (and meta permission actions and their relations to other permission actions).

Purpose

Many of Trac's features are only available to users with certain permissions. By default these are the coarse permissions described in TracPermissions. More fine-grained per-resource permissions as described by TracFineGrainedPermissions are also possible.

While a component can check for any permissions already defined by other components, it might want to define its own permission types for its actions on resources.

Usage

Implementing the interface follows the standard guidelines found in TracDev/ComponentArchitecture and of course TracDev/PluginDevelopment.

Only one method has to be defined: get_permission_actions(). This method should return a list of permission actions. Each action is either the name of the action (a simple string) or, for so called meta permissions a tuple, where the first tuple item is the name of the action, and the second tuple item is a list of subsumed action names. (The meta permission covers all listed permissions. If multiple implementations return the same meta permission, they are combined.)

Action names should be in ALL_CAPS_WITH_UNDERSCORES and usually consist of two parts:

  • The resource type / module name.
  • The action to perform on that resource.

The most common action is VIEW, to allow basic usage (viewing) of a resource. It is often required for components implementing IRequestHandler, where process_request() would check for permissions categorically (req.perm.require('RESOURCE_VIEW')) or selectively (if 'RESOURCE_ACTION' in req.perm:). (Such an IRequestHandler - or any other kind of checked resource access - could also be implemented by any other Component.)

Anyone with access to a perm (trac.perm.PermissionCache) can perform permission check. It is usually obtained from req (a trac.web.api.Request). More fine-grained per-resource permission checks can be performed by obtaining a specialized cache using req.perm(resource) or req.perm(realm, resource_id).

A slightly more complex pattern is to return multiple simple RESOURCE_ACTION permission actions and one RESOURCE_ADMIN meta permission action covering the others. Even more complex hierarchies of permissions are possible. (See #Ticket)

Examples

Minimal

A minimal IPermissionRequestor in isolation is not very useful (but possible) and usually accompanied by implementations of other interfaces that require these permissions. Hence the following example is best understood in context of the ComponentModuleExamples.

In Trac, components have no associated permissions. The following example defines two new permissions to be checked elsewhere:

from trac.core import Component, implements
from trac.perm import IPermissionRequestor

class ComponentModule(Component):
    implements(IPermissionRequestor)

    def get_permission_actions(self):
        return ['COMPONENT_LIST', 'COMPONENT_VIEW']

Upgrade example

If a new version of a component renames / merges / splits existing permissions of an older version, it might want to implement an environment upgrade (IEnvironmentSetupParticipant).

A real example would be TracPastePlugin, which changed from a single permission PASTEBIN_USE to multiple permissions PASTEBIN_VIEW and PASTEBIN_CREATE. In this changeset, (environment_needs_upgrade checks _has_old_permission for any of the old permissions and upgrade_environment calls convert_use_permissions (via the version_map if required) to convert them to the new permissions.

Available Implementations

Simple

One of the simplest use cases is to define one permission to view the resources of that module:

Ticket

The most complex example in Trac itself. Various meta permissions subsume certain / all other permissions for convenience.

  • trac.ticket.api.TicketSystem
    return ['TICKET_APPEND', 'TICKET_CREATE', 'TICKET_CHGPROP',
            'TICKET_VIEW', 'TICKET_EDIT_CC', 'TICKET_EDIT_DESCRIPTION',
            'TICKET_EDIT_COMMENT',
            ('TICKET_MODIFY', ['TICKET_APPEND', 'TICKET_CHGPROP']),
            ('TICKET_ADMIN', ['TICKET_CREATE', 'TICKET_MODIFY',
                              'TICKET_VIEW', 'TICKET_EDIT_CC',
                              'TICKET_EDIT_DESCRIPTION',
                              'TICKET_EDIT_COMMENT'])]
    
  • trac.ticket.report.ReportModule
    actions = ['REPORT_CREATE', 'REPORT_DELETE', 'REPORT_MODIFY', 
               'REPORT_SQL_VIEW', 'REPORT_VIEW'] 
    return actions + [('REPORT_ADMIN', actions)]  
    

Roadmap

For historical reasons a bit unintuitive. Planned to be simplified in the future (see #4292 / #3022)

  • trac.ticket.roadmap.RoadmapModule
    actions = ['MILESTONE_CREATE', 'MILESTONE_DELETE', 'MILESTONE_MODIFY',
               'MILESTONE_VIEW', 'ROADMAP_VIEW']
    return ['ROADMAP_VIEW'] + [('ROADMAP_ADMIN', actions)]
    
  • MilestoneModule
    actions = ['MILESTONE_CREATE', 'MILESTONE_DELETE', 'MILESTONE_MODIFY',
               'MILESTONE_VIEW']
    return actions + [('MILESTONE_ADMIN', actions)]
    

Wiki

  • trac.wiki.web_ui.WikiModule
    actions = ['WIKI_CREATE', 'WIKI_DELETE', 'WIKI_MODIFY', 'WIKI_RENAME',
               'WIKI_VIEW']
    return actions + [('WIKI_ADMIN', actions)]
    

Permissions

As an interesting peculiarity, permissions to manipulate permissions:

Version control

An example of a component to combine permissions of other components into a meta permission.

Additional Information and References

Last modified 4 years ago Last modified on Sep 11, 2013, 9:28:34 AM
Note: See TracWiki for help on using the wiki.