lib/authority/controller.rb in authority-2.7.0 vs lib/authority/controller.rb in authority-2.8.0
- old
+ new
@@ -5,21 +5,34 @@
extend ActiveSupport::Concern
include ActiveSupport::Rescuable unless defined?(Rails)
def self.security_violation_callback
Proc.new do |exception|
- # Through the magic of ActiveSupport's `Proc#bind`, `ActionController::Base#rescue_from`
+ # Through the magic of `instance_exec` `ActionController::Base#rescue_from`
# can call this proc and make `self` the actual controller instance
self.send(Authority.configuration.security_violation_handler, exception)
end
end
included do
rescue_from(Authority::SecurityViolation, :with => Authority::Controller.security_violation_callback)
class_attribute :authority_resource, :instance_reader => false
end
+ attr_writer :authorization_performed
+
+ def authorization_performed?
+ !!@authorization_performed
+ end
+
+ def ensure_authorization_performed(options = {})
+ return if authorization_performed?
+ return if options[:if] && !send(options[:if])
+ return if options[:unless] && send(options[:unless])
+ raise AuthorizationNotPerformed, "No authorization was performed for #{self.class.to_s}##{self.action_name}"
+ end
+
module ClassMethods
# Sets up before_filter to ensure user is allowed to perform a given controller action
#
# @param [Class OR Symbol] resource_or_finder - class whose authorizer
@@ -47,10 +60,17 @@
set multiple actions in one shot. Please update your controllers \
accordingly. (called from #{caller.first})".squeeze(' ')
authority_actions(action_map)
end
+ # Convenience wrapper for instance method
+ def ensure_authorization_performed(options = {})
+ after_filter(options.slice(:only, :except)) do |controller_instance|
+ controller_instance.ensure_authorization_performed(options)
+ end
+ end
+
# The controller action to authority action map used for determining
# which Rails actions map to which authority actions (ex: index to read)
#
# @return [Hash] A duplicated copy of the configured controller_action_map
def authority_action_map
@@ -72,11 +92,13 @@
# `action_name` comes from ActionController
authority_action = self.class.authority_action_map[action_name.to_sym]
if authority_action.nil?
raise MissingAction.new("No authority action defined for #{action_name}")
end
+
Authority.enforce(authority_action, authority_resource, authority_user, *options)
+ self.authorization_performed = true
end
# Renders a static file to minimize the chances of further errors.
#
# @param [Exception] error, an error that indicates the user tried to perform a forbidden action.
@@ -110,9 +132,10 @@
# @return [Object] the user object returned from sending the user_method
def authority_user
send(Authority.configuration.user_method)
end
- class MissingAction < StandardError ; end
- class MissingResource < StandardError ; end
+ class MissingAction < StandardError ; end
+ class MissingResource < StandardError ; end
+ class AuthorizationNotPerformed < StandardError ; end
end
end