Class Authorization::Engine
In: lib/declarative_authorization/authorization.rb
Parent: Object

Authorization::Engine implements the reference monitor. It may be used for querying the permission and retrieving obligations under which a certain privilege is granted for the current user.

Methods

Attributes

reader  [R] 

Public Class methods

Returns an instance of Engine, which is created if there isn‘t one yet. If dsl_file is given, it is passed on to Engine.new and a new instance is always created.

[Source]

     # File lib/declarative_authorization/authorization.rb, line 284
284:     def self.instance (dsl_file = nil)
285:       if dsl_file
286:         @@instance = new(dsl_file)
287:       else
288:         @@instance ||= new
289:       end
290:     end

If reader is not given, a new one is created with the default authorization configuration of AUTH_DSL_FILES. If given, may be either a Reader object or a path to a configuration file.

[Source]

    # File lib/declarative_authorization/authorization.rb, line 87
87:     def initialize (reader = nil)
88:       #@auth_rules = AuthorizationRuleSet.new reader.auth_rules_reader.auth_rules
89:       @reader = Reader::DSLReader.factory(reader || AUTH_DSL_FILES)
90:     end

Public Instance methods

Returns the description for the given role. The description may be specified with the authorization rules. Returns nil if none was given.

[Source]

     # File lib/declarative_authorization/authorization.rb, line 247
247:     def description_for (role)
248:       role_descriptions[role]
249:     end

Returns the obligations to be met by the current user for the given privilege as an array of obligation hashes in form of

  [{:object_attribute => obligation_value, ...}, ...]

where obligation_value is either (recursively) another obligation hash or a value spec, such as

  [operator, literal_value]

The obligation hashes in the array should be OR‘ed, conditions inside the hashes AND‘ed.

Example

  {:branch => {:company => [:is, 24]}, :active => [:is, true]}

Options

:context
See permit!
:user
See permit!

[Source]

     # File lib/declarative_authorization/authorization.rb, line 230
230:     def obligations (privilege, options = {})
231:       options = {:context => nil}.merge(options)
232:       user, roles, privileges = user_roles_privleges_from_options(privilege, options)
233: 
234:       permit!(privilege, :skip_attribute_test => true, :user => user, :context => options[:context])
235:       
236:       return [] if roles.is_a?(Array) and not (roles & omnipotent_roles).empty?
237:       
238:       attr_validator = AttributeValidator.new(self, user, nil, privilege, options[:context])
239:       matching_auth_rules(roles, privileges, options[:context]).collect do |rule|
240:         rule.obligations(attr_validator)
241:       end.flatten
242:     end

Returns true if privilege is met by the current user. Raises AuthorizationError otherwise. privilege may be given with or without context. In the latter case, the :context option is required.

Options:

:context
The context part of the privilege. Defaults either to the tableized class_name of the given :object, if given. That is, :users for :object of type User. Raises AuthorizationUsageError if context is missing and not to be inferred.
:object
An context object to test attribute checks against.
:skip_attribute_test
Skips those attribute checks in the authorization rules. Defaults to false.
:user
The user to check the authorization for. Defaults to Authorization#current_user.
:bang
Should NotAuthorized exceptions be raised Defaults to true.

[Source]

     # File lib/declarative_authorization/authorization.rb, line 145
145:     def permit! (privilege, options = {})
146:       return true if Authorization.ignore_access_control
147:       options = {
148:         :object => nil,
149:         :skip_attribute_test => false,
150:         :context => nil,
151:         :bang => true
152:       }.merge(options)
153:       
154:       # Make sure we're handling all privileges as symbols.
155:       privilege = privilege.is_a?( Array ) ?
156:                   privilege.flatten.collect { |priv| priv.to_sym } :
157:                   privilege.to_sym
158:       
159:       #
160:       # If the object responds to :proxy_reflection, we're probably working with
161:       # an association proxy.  Use 'new' to leverage ActiveRecord's builder
162:       # functionality to obtain an object against which we can check permissions.
163:       #
164:       # Example: permit!( :edit, :object => user.posts )
165:       #
166:       if Authorization.is_a_association_proxy?(options[:object]) && options[:object].respond_to?(:new)
167:         options[:object] = options[:object].new
168:       end
169:       
170:       options[:context] ||= options[:object] && (
171:         options[:object].class.respond_to?(:decl_auth_context) ?
172:             options[:object].class.decl_auth_context :
173:             options[:object].class.name.tableize.to_sym
174:       ) rescue NoMethodError
175:       
176:       user, roles, privileges = user_roles_privleges_from_options(privilege, options)
177: 
178:       return true if roles.is_a?(Array) and not (roles & omnipotent_roles).empty?
179: 
180:       # find a authorization rule that matches for at least one of the roles and 
181:       # at least one of the given privileges
182:       attr_validator = AttributeValidator.new(self, user, options[:object], privilege, options[:context])
183:       rules = matching_auth_rules(roles, privileges, options[:context])
184:       
185:       # Test each rule in turn to see whether any one of them is satisfied.
186:       rules.each do |rule|
187:         return true if rule.validate?(attr_validator, options[:skip_attribute_test])
188:       end
189: 
190:       if options[:bang]
191:         if rules.empty?
192:           raise NotAuthorized, "No matching rules found for #{privilege} for #{user.inspect} " +
193:             "(roles #{roles.inspect}, privileges #{privileges.inspect}, " +
194:             "context #{options[:context].inspect})."
195:         else
196:           raise AttributeAuthorizationError, "#{privilege} not allowed for #{user.inspect} on #{(options[:object] || options[:context]).inspect}."
197:         end
198:       else
199:         false
200:       end
201:     end

Calls permit! but doesn‘t raise authorization errors. If no exception is raised, permit? returns true and yields to the optional block.

[Source]

     # File lib/declarative_authorization/authorization.rb, line 205
205:     def permit? (privilege, options = {}) # :yields:
206:       if permit!(privilege, options.merge(:bang=> false))
207:         yield if block_given?
208:         true
209:       else
210:         false
211:       end
212:     end

{[priv, ctx] => [priv, …]}

[Source]

     # File lib/declarative_authorization/authorization.rb, line 97
 97:     def rev_priv_hierarchy
 98:       if @rev_priv_hierarchy.nil?
 99:         @rev_priv_hierarchy = {}
100:         privilege_hierarchy.each do |key, value|
101:           value.each do |val| 
102:             @rev_priv_hierarchy[val] ||= []
103:             @rev_priv_hierarchy[val] << key
104:           end
105:         end
106:       end
107:       @rev_priv_hierarchy
108:     end

{[priv, ctx] => [priv, …]}

[Source]

     # File lib/declarative_authorization/authorization.rb, line 111
111:     def rev_role_hierarchy  
112:       if @rev_role_hierarchy.nil?
113:         @rev_role_hierarchy = {}
114:         role_hierarchy.each do |higher_role, lower_roles|
115:           lower_roles.each do |role|
116:             (@rev_role_hierarchy[role] ||= []) << higher_role
117:           end
118:         end
119:       end
120:       @rev_role_hierarchy
121:     end

Returns the role symbols of the given user.

[Source]

     # File lib/declarative_authorization/authorization.rb, line 259
259:     def roles_for (user)
260:       user ||= Authorization.current_user
261:       raise AuthorizationUsageError, "User object doesn't respond to roles (#{user.inspect})" \
262:         if !user.respond_to?(:role_symbols) and !user.respond_to?(:roles)
263: 
264:       Rails.logger.info("The use of user.roles is deprecated.  Please add a method " +
265:           "role_symbols to your User model.") if defined?(Rails) and Rails.respond_to?(:logger) and !user.respond_to?(:role_symbols)
266: 
267:       roles = user.respond_to?(:role_symbols) ? user.role_symbols : user.roles
268: 
269:       raise AuthorizationUsageError, "User.#{user.respond_to?(:role_symbols) ? 'role_symbols' : 'roles'} " +
270:         "doesn't return an Array of Symbols (#{roles.inspect})" \
271:             if !roles.is_a?(Array) or (!roles.empty? and !roles[0].is_a?(Symbol))
272: 
273:       (roles.empty? ? [Authorization.default_role] : roles)
274:     end

Returns the role symbols and inherritted role symbols for the given user

[Source]

     # File lib/declarative_authorization/authorization.rb, line 277
277:     def roles_with_hierarchy_for(user)
278:       flatten_roles(roles_for(user))
279:     end

Returns the title for the given role. The title may be specified with the authorization rules. Returns nil if none was given.

[Source]

     # File lib/declarative_authorization/authorization.rb, line 254
254:     def title_for (role)
255:       role_titles[role]
256:     end

[Validate]