Class Authorization::Reader::AuthorizationRulesReader
In: lib/declarative_authorization/reader.rb
Parent: Object

Methods

Public Instance methods

In an if_attribute statement, contains says that the value has to be part of the collection specified by the if_attribute attribute. For information on the block argument, see if_attribute.

Sets a description for the current role. E.g.

  role :admin
    description "To be assigned to administrative personnel"
    has_permission_on ...
  end

The negation of contains. Currently, query rewriting is disabled for does_not_contain.

Greater than

Greater than or equal to

Removes any permission checks for the current role.

  role :admin
    has_omnipotence
  end

Allows the definition of privileges to be allowed for the current role, either in a has_permission_on block or directly in one call.

  role :admin
    has_permission_on :employees, :to => :read
    has_permission_on [:employees, :orders], :to => :read
    has_permission_on :employees do
      to :create
      if_attribute ...
    end
    has_permission_on :employees, :to => :delete do
      if_attribute ...
    end
  end

The block form allows to describe restrictions on the permissions using if_attribute. Multiple has_permission_on statements are OR‘ed when evaluating the permissions. Also, multiple if_attribute statements in one block are OR‘ed if no :join_by option is given (see below). To AND conditions, either set :join_by to :and or place them in one if_attribute statement.

Available options

:to
A symbol or an array of symbols representing the privileges that should be granted in this statement.
:join_by
Join operator to logically connect the constraint statements inside of the has_permission_on block. May be :and or :or. Defaults to :or.

In a has_permission_on block, if_attribute specifies conditions of dynamic parameters that have to be met for the user to meet the privileges in this block. Conditions are evaluated on the context object. Thus, the following allows CRUD for branch admins only on employees that belong to the same branch as the current user.

  role :branch_admin
    has_permission_on :employees do
      to :create, :read, :update, :delete
      if_attribute :branch => is { user.branch }
    end
  end

In this case, is is the operator for evaluating the condition. Another operator is contains for collections. In the block supplied to the operator, user specifies the current user for whom the condition is evaluated.

Conditions may be nested:

  role :company_admin
    has_permission_on :employees do
      to :create, :read, :update, :delete
      if_attribute :branch => { :company => is {user.branch.company} }
    end
  end

has_many and has_many through associations may also be nested. Then, at least one item in the association needs to fulfill the subsequent condition:

  if_attribute :company => { :branches => { :manager => { :last_name => is { user.last_name } } }

Beware of possible performance issues when using has_many associations in permitted_to? checks. For

  permitted_to? :read, object

a check like

  object.company.branches.any? { |branch| branch.manager ... }

will be executed. with_permission_to scopes construct efficient SQL joins, though.

Multiple attributes in one :if_attribute statement are AND‘ed. Multiple if_attribute statements are OR‘ed if the join operator for the has_permission_on block isn‘t explicitly set. Thus, the following would require the current user either to be of the same branch AND the employee to be "changeable_by_coworker". OR the current user has to be the employee in question.

  has_permission_on :employees, :to => :manage do
    if_attribute :branch => is {user.branch}, :changeable_by_coworker => true
    if_attribute :id => is {user.id}
  end

The join operator for if_attribute rules can explicitly set to AND, though. See has_permission_on for details.

Arrays and fixed values may be used directly as hash values:

  if_attribute :id   => 1
  if_attribute :type => "special"
  if_attribute :id   => [1,2]

if_permitted_to allows the has_permission_on block to depend on permissions on associated objects. By using it, the authorization rules may be a lot DRYer. E.g.:

  role :branch_manager
    has_permission_on :branches, :to => :manage do
      if_attribute :employees => contains { user }
    end
    has_permission_on :employees, :to => :read do
      if_permitted_to :read, :branch
      # instead of
      # if_attribute :branch => { :employees => contains { user } }
    end
  end

if_permitted_to associations may be nested as well:

  if_permitted_to :read, :branch => :company

You can even use has_many associations as target. Then, it is checked if the current user has the required privilege on any of the target objects.

  if_permitted_to :read, :branch => :employees

Beware of performance issues with permission checks. In the current implementation, all employees are checked until the first permitted is found. with_permissions_to, on the other hand, constructs more efficient SQL instead.

To check permissions based on the current object, the attribute has to be left out:

  has_permission_on :branches, :to => :manage do
    if_attribute :employees => contains { user }
  end
  has_permission_on :branches, :to => :paint_green do
    if_permitted_to :update
  end

Normally, one would merge those rules into one. Dividing makes sense if additional if_attribute are used in the second rule or those rules are applied to different roles.

Options:

:context
When using with_permissions_to, the target context of the if_permitted_to statement is inferred from the last reflections target class. Still, you may override this algorithm by setting the context explicitly.
  if_permitted_to :read, :home_branch, :context => :branches
  if_permitted_to :read, :branch => :main_company, :context => :companies

Roles may inherit all the rights from subroles. The given roles become subroles of the current block‘s role.

  role :admin do
    includes :user
    has_permission_on :employees, :to => [:update, :create]
  end
  role :user do
    has_permission_on :employees, :to => :read
  end

In an if_attribute statement, intersects_with requires that at least one of the values has to be part of the collection specified by the if_attribute attribute. The value block needs to evaluate to an Enumerable. For information on the block argument, see if_attribute.

In an if_attribute statement, is says that the value has to be met exactly by the if_attribute attribute. For information on the block argument, see if_attribute.

In an if_attribute statement, is_in says that the value has to contain the attribute value. For information on the block argument, see if_attribute.

The negation of is.

The negation of is_in.

Less than

Less than or equal to

Defines the authorization rules for the given role in the following block.

  role :admin do
    has_permissions_on ...
  end

Sets a human-readable title for the current role. E.g.

  role :admin
    title "Administrator"
    has_permission_on ...
  end

Used in a has_permission_on block, to may be used to specify privileges to be assigned to the current role under the conditions specified in the current block.

  role :admin
    has_permission_on :employees do
      to :create, :read, :update, :delete
    end
  end

[Validate]