Extension Point : IPermissionRequestor
Interface | IPermissionRequestor | Since | 0.9 |
Module | trac.perm | Source | perm.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:
- trac.timeline.web_ui.TimelineModule
return ['TIMELINE_VIEW']
- trac.search.web_ui.SearchModule
return ['SEARCH_VIEW']
- trac.about.AboutModule
return ['CONFIG_VIEW']
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:
- trac.admin.web_ui.PermissionAdminPanel
actions = ['PERMISSION_GRANT', 'PERMISSION_REVOKE'] return actions + [('PERMISSION_ADMIN', actions)]
Version control
An example of a component to combine permissions of other components into a meta permission.
- trac.versioncontrol.admin.VersionControlAdmin
return [('VERSIONCONTROL_ADMIN', ['BROWSER_VIEW', 'CHANGESET_VIEW', 'FILE_VIEW', 'LOG_VIEW'])]
- trac.versioncontrol.web_ui.browser.BrowserModule
return ['BROWSER_VIEW', 'FILE_VIEW']
- trac.versioncontrol.web_ui.changeset.ChangesetModule
return ['CHANGESET_VIEW']
- trac.versioncontrol.web_ui.log.LogModule
return ['LOG_VIEW']
Additional Information and References
- epydoc
- API Reference
- Ticket about extending exsting meta-permissions: #8036
- Mailing list message about the initial design of IPermissionRequestor, IPermissionStore and IPermissionGroupProvider