





















































(For more resources related to this topic, see here.)
As we'll be extending Redmine's access control layer with our own custom permissions, our first course of action should be to better understand this system.
Redmine doesn't apply permissions directly to users; instead, it encapsulates permissions within roles. These roles in turn can have one to many users associated with them and are used to control access to content areas within projects, modules, and plugins.
The following screenshot shows the Administration | Roles and permissions view where new roles can be created, or existing roles can be modified:
Each role contains a subset of the available permissions, which are further grouped by project module, which can be toggled on or off. The following screenshot shows the Manager role that is available as a default in Redmine along with the available Project Permissions all toggled:
As Redmine is a project-oriented system, a project association must be made in order for the role to be applied. This is done by a project administrator or any user assigned to a role with the :manage_members permission in Settings | Members for the project window.
Permissions can be applied directly to users via roles, or they can be applied to groups of users. Groups are configured by a Redmine system administrator by navigating to Administration | Groups .
As we know already , permissions are registered in our plugin's init.rb file as part of the Redmine::Plugin.register block.
While registering a new permission, we populate a hash, which takes a controller as key, and an array of actions as the value. The syntax for this command is as follows:
permission(name, actions, options = {})
The permission helper that is available to us (plugin authors) is actually just a wrapper around Redmine::AccessControl#map, which is located in /path/to/redmine/lib/redmine/access_control.rb.
Before registering our permissions, we need to understand the two scopes of permissions that are available: global and project module.
Global permissions are a bit deceptive as they aren't actually "global" in nature. In fact, they belong to the Project category and are essentially just a sum of a user's permissions across all projects for which they are members.
Note that global permissions can mean different things depending on what context they're being used in:
In order to demonstrate, let's register the following permission:
permission :access_global_knowledgebase, { :knowledgebase => :index }
If we were to check the roles editor now by navigating to Administration | Roles and Permissions and selecting any role to edit, this new permission would in fact appear under the Project category.
Note that for a user to be able to take advantage of this permission, they would still need to be a member of a project. If a user should only have access to this feature, but not additional projects, a new project should be created that all users can be a member of.
Project module permissions are declared almost identically, but are contained within a project_module block.
project_module :knowledgebase do permission :view_kb_articles, { :articles => [:index, :show, :tagged], :categories => [:index, :show] } end
This block allows the permissions to be encapsulated and is therefore dependent on the project module being enabled in a project's module list before the permissions are applicable.
The previous example allows any user with the :view_kb_articles permission applied to be able to access the articles#index, articles#show, articles#tagged, categories#index, and categories#show routes.
As permissions target a controller action, we cannot provide more granular access control—for example, restricting access to individual articles—using the built-in permissions system.
Editing any role will now contain a new group for the project module :knowledgebase with the single permission we've defined.