| Class | Authorization::Reader::AuthorizationRulesReader |
| In: |
lib/declarative_authorization/reader.rb
|
| Parent: | Object |
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.
# File lib/declarative_authorization/reader.rb, line 389
389: def contains (&block)
390: [:contains, block]
391: end
Sets a description for the current role. E.g.
role :admin
description "To be assigned to administrative personnel"
has_permission_on ...
end
# File lib/declarative_authorization/reader.rb, line 254
254: def description (text)
255: raise DSLError, "description only allowed in role blocks" if @current_role.nil?
256: role_descriptions[@current_role] = text
257: end
The negation of contains. Currently, query rewriting is disabled for does_not_contain.
# File lib/declarative_authorization/reader.rb, line 395
395: def does_not_contain (&block)
396: [:does_not_contain, block]
397: 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
# File lib/declarative_authorization/reader.rb, line 225
225: def has_permission_on (*args, &block)
226: options = args.extract_options!
227: context = args.flatten
228:
229: raise DSLError, "has_permission_on only allowed in role blocks" if @current_role.nil?
230: options = {:to => [], :join_by => :or}.merge(options)
231:
232: privs = options[:to]
233: privs = [privs] unless privs.is_a?(Array)
234: raise DSLError, "has_permission_on either needs a block or :to option" if !block_given? and privs.empty?
235:
236: file, line = file_and_line_number_from_call_stack
237: rule = AuthorizationRule.new(@current_role, privs, context, options[:join_by],
238: :source_file => file, :source_line => line)
239: @auth_rules << rule
240: if block_given?
241: @current_rule = rule
242: yield
243: raise DSLError, "has_permission_on block content specifies no privileges" if rule.privileges.empty?
244: # TODO ensure?
245: @current_rule = nil
246: end
247: end
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
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
Arrays and fixed values may be used directly as hash values:
if_attribute :id => 1 if_attribute :type => "special" if_attribute :id => [1,2]
# File lib/declarative_authorization/reader.rb, line 322
322: def if_attribute (attr_conditions_hash)
323: raise DSLError, "if_attribute only in has_permission blocks" if @current_rule.nil?
324: parse_attribute_conditions_hash!(attr_conditions_hash)
325: @current_rule.append_attribute Attribute.new(attr_conditions_hash)
326: end
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 => includes { user }
end
has_permission_on :employees, :to => :read do
if_permitted_to :read, :branch
# instead of
# if_attribute :branch => { :employees => includes { user } }
end
end
if_permitted_to associations may be nested as well:
if_permitted_to :read, :branch => :company
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 => includes { user }
end
has_permission_on :branches, :to => :paint_green do
if_permitted_to :update
end
Normally, one would merge those rules into one. Deviding makes sense if additional if_attribute are used in the second rule or those rules are applied to different roles.
Options:
if_permitted_to :read, :home_branch, :context => :branches if_permitted_to :read, :branch => :main_company, :context => :companies
# File lib/declarative_authorization/reader.rb, line 365
365: def if_permitted_to (privilege, attr_or_hash = nil, options = {})
366: raise DSLError, "if_permitted_to only in has_permission blocks" if @current_rule.nil?
367: options[:context] ||= attr_or_hash.delete(:context) if attr_or_hash.is_a?(Hash)
368: # only :context option in attr_or_hash:
369: attr_or_hash = nil if attr_or_hash.is_a?(Hash) and attr_or_hash.empty?
370: @current_rule.append_attribute AttributeWithPermission.new(privilege,
371: attr_or_hash, options[:context])
372: end
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
# File lib/declarative_authorization/reader.rb, line 191
191: def includes (*roles)
192: raise DSLError, "includes only in role blocks" if @current_role.nil?
193: @role_hierarchy[@current_role] ||= []
194: @role_hierarchy[@current_role] += roles.flatten
195: 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.
# File lib/declarative_authorization/reader.rb, line 403
403: def intersects_with (&block)
404: [:intersects_with, block]
405: end
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.
# File lib/declarative_authorization/reader.rb, line 377
377: def is (&block)
378: [:is, block]
379: end
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.
# File lib/declarative_authorization/reader.rb, line 410
410: def is_in (&block)
411: [:is_in, block]
412: end
Defines the authorization rules for the given role in the following block.
role :admin do
has_permissions_on ...
end
# File lib/declarative_authorization/reader.rb, line 173
173: def role (role, options = {}, &block)
174: append_role role, options
175: @current_role = role
176: yield
177: ensure
178: @current_role = nil
179: end
Sets a human-readable title for the current role. E.g.
role :admin
title "Administrator"
has_permission_on ...
end
# File lib/declarative_authorization/reader.rb, line 264
264: def title (text)
265: raise DSLError, "title only allowed in role blocks" if @current_role.nil?
266: role_titles[@current_role] = text
267: 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
# File lib/declarative_authorization/reader.rb, line 277
277: def to (*privs)
278: raise DSLError, "to only allowed in has_permission_on blocks" if @current_rule.nil?
279: @current_rule.append_privileges(privs)
280: end