| 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.
| reader | [R] |
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.
# 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.
# 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
Returns the description for the given role. The description may be specified with the authorization rules. Returns nil if none was given.
# 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
# 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:
# 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.
# 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, …]}
# 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, …]}
# 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.
# 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
# File lib/declarative_authorization/authorization.rb, line 277
277: def roles_with_hierarchy_for(user)
278: flatten_roles(roles_for(user))
279: end