== Extension Point : ''IPermissionRequestor'' == ||'''Interface'''||''IPermissionRequestor''||'''Since'''||0.9|| ||'''Module'''||''trac.perm''||'''Source'''||[source:trunk/trac/perm.py#L60 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 [wiki:TracDev/ComponentArchitecture] and of course [wiki: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 [../trac.web.api.IRequestHandler 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, [TicketComponent components] have no associated permissions. The following example defines two new permissions to be checked elsewhere: {{{#!python 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 ([../trac.env.IEnvironmentSetupParticipant IEnvironmentSetupParticipant]). A real example would be [h:TracPastePlugin], which changed from a single permission PASTEBIN_USE to multiple permissions PASTEBIN_VIEW and PASTEBIN_CREATE. In [h:changeset:4983 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 === #Simple One of the simplest use cases is to define one permission to view the resources of that module: * [source:trunk/trac/timeline/web_ui.py#L80 trac.timeline.web_ui.TimelineModule] {{{#!python return ['TIMELINE_VIEW'] }}} * [source:trunk/trac/search/web_ui.py#L72 trac.search.web_ui.SearchModule] {{{#!python return ['SEARCH_VIEW'] }}} * [source:trunk/trac/about.py#L49 trac.about.AboutModule] {{{#!python return ['CONFIG_VIEW'] }}} === Ticket === #Ticket The most complex example in Trac itself. Various meta permissions subsume certain / all other permissions for convenience. * [source:trunk/trac/ticket/api.py#L417 trac.ticket.api.TicketSystem] {{{#!python 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'])] }}} * [source:trunk/trac/ticket/report.py#L77 trac.ticket.report.ReportModule] {{{#!python actions = ['REPORT_CREATE', 'REPORT_DELETE', 'REPORT_MODIFY', 'REPORT_SQL_VIEW', 'REPORT_VIEW'] return actions + [('REPORT_ADMIN', actions)] }}} === Roadmap === #Roadmap For historical reasons a bit unintuitive. Planned to be simplified in the future (see #4292 / #3022) * [source:trunk/trac/ticket/roadmap.py#L361 trac.ticket.roadmap.RoadmapModule] {{{#!python actions = ['MILESTONE_CREATE', 'MILESTONE_DELETE', 'MILESTONE_MODIFY', 'MILESTONE_VIEW', 'ROADMAP_VIEW'] return ['ROADMAP_VIEW'] + [('ROADMAP_ADMIN', actions)] }}} * [source:trunk/trac/ticket/roadmap.py#L562 MilestoneModule] {{{#!python actions = ['MILESTONE_CREATE', 'MILESTONE_DELETE', 'MILESTONE_MODIFY', 'MILESTONE_VIEW'] return actions + [('MILESTONE_ADMIN', actions)] }}} === Wiki === #Wiki * [source:trunk/trac/wiki/web_ui.py#L96 trac.wiki.web_ui.WikiModule] {{{#!python actions = ['WIKI_CREATE', 'WIKI_DELETE', 'WIKI_MODIFY', 'WIKI_RENAME', 'WIKI_VIEW'] return actions + [('WIKI_ADMIN', actions)] }}} === Permissions === #Permissions As an interesting peculiarity, permissions to manipulate permissions: * [source:trunk/trac/admin/web_ui.py#L347 trac.admin.web_ui.PermissionAdminPanel] {{{#!python actions = ['PERMISSION_GRANT', 'PERMISSION_REVOKE'] return actions + [('PERMISSION_ADMIN', actions)] }}} === Version control === #VersionControl An example of a component to combine permissions of other components into a meta permission. * [source:trunk/trac/versioncontrol/admin.py#L156 trac.versioncontrol.admin.VersionControlAdmin] {{{#!python return [('VERSIONCONTROL_ADMIN', ['BROWSER_VIEW', 'CHANGESET_VIEW', 'FILE_VIEW', 'LOG_VIEW'])] }}} * [source:trunk/trac/versioncontrol/web_ui/browser.py#L301 trac.versioncontrol.web_ui.browser.BrowserModule] {{{#!python return ['BROWSER_VIEW', 'FILE_VIEW'] }}} * [source:trunk/trac/versioncontrol/web_ui/changeset.py#L176 trac.versioncontrol.web_ui.changeset.ChangesetModule] {{{#!python return ['CHANGESET_VIEW'] }}} * [source:trunk/trac/versioncontrol/web_ui/log.py#L66 trac.versioncontrol.web_ui.log.LogModule] {{{#!python return ['LOG_VIEW'] }}} == Additional Information and References == * [http://www.edgewall.org/docs/trac-trunk/html/api/trac_perm.html#trac.perm.IPermissionRequestor API Reference] * Ticket about extending exsting meta-permissions: #8036 * Mailing list [http://article.gmane.org/gmane.comp.version-control.subversion.trac.general/3119 message] about the initial design of IPermissionRequestor, [../trac.perm.IPermissionStore IPermissionStore] and [../trac.perm.IPermissionGroupProvider IPermissionGroupProvider]