# Authorization::Maintenance require File.dirname(__FILE__) + '/authorization.rb' module Authorization # Provides a few maintenance methods for modifying data without enforcing # authorization. module Maintenance # Disables access control for the given block. Appropriate for # maintenance operation at the Rails console or in test case setup. # # For use in the Rails console: # require "vendor/plugins/declarative_authorization/lib/maintenance" # include Authorization::Maintenance # # without_access_control do # SomeModel.find(:first).save # end def without_access_control Authorization::Maintenance.without_access_control() do yield if block_given? end end # A class method variant of without_access_control. Thus, one can call # Authorization::Maintenance::without_access_control do # ... # end def self.without_access_control previous_state = Authorization.ignore_access_control begin Authorization.ignore_access_control(true) yield ensure Authorization.ignore_access_control(previous_state) end end # Sets the current user for the declarative authorization plugin to the # given one for the execution of the supplied block. Suitable for tests # on certain users. def with_user(user) Authorization::Maintenance.with_user(user) do yield if block_given? end end def self.with_user(user) prev_user = Authorization.current_user Authorization.current_user = user yield ensure Authorization.current_user = prev_user end # Module for grouping usage-related helper methods module Usage # Delivers a hash of {ControllerClass => usage_info_hash}, # where usage_info_hash has the form of def self.usages_by_controller # load each application controller begin Dir.glob(File.join(::Rails.root, 'app', 'controllers', '**', '*_controller\.rb')) do |entry| require entry end rescue Errno::ENOENT end controllers = ObjectSpace.each_object(Class).select do |obj| obj.ancestors.include?(ActionController::Base) && obj != ActionController::Base && (!obj.name || obj.name.demodulize != 'ApplicationController') end controllers.inject({}) do |memo, controller| catchall_permissions = [] permission_by_action = {} controller.all_filter_access_permissions.each do |controller_permissions| catchall_permissions << controller_permissions if controller_permissions.actions.include?(:all) controller_permissions.actions.reject {|action| action == :all}.each do |action| permission_by_action[action] = controller_permissions end end actions = controller.public_instance_methods(false) - controller.private_methods memo[controller] = actions.inject({}) do |actions_memo, action| action_sym = action.to_sym actions_memo[action_sym] = if permission_by_action[action_sym] { :privilege => permission_by_action[action_sym].privilege, :context => permission_by_action[action_sym].context, :controller_permissions => [permission_by_action[action_sym]] } elsif !catchall_permissions.empty? { :privilege => catchall_permissions[0].privilege, :context => catchall_permissions[0].context, :controller_permissions => catchall_permissions } else {} end actions_memo end memo end end end end # TestHelper provides assert methods and controller request methods which # take authorization into account and set the current user to a specific # one. # # Defines get_with, post_with, get_by_xhr_with etc. for methods # get, post, put, delete each with the signature # get_with(user, action, params = {}, session = {}, flash = {}) # # Use it by including it in your TestHelper: # require File.expand_path(File.dirname(__FILE__) + # "/../vendor/plugins/declarative_authorization/lib/maintenance") # class Test::Unit::TestCase # include Authorization::TestHelper # ... # # def admin # # create admin user # end # end # # class SomeControllerTest < ActionController::TestCase # def test_should_get_index # ... # get_with admin, :index, :param_1 => "param value" # ... # end # end # # Note: get_with etc. do two things to set the user for the request: # Authorization.current_user is set and session[:user], session[:user_id] # are set appropriately. If you determine the current user in a different # way, these methods might not work for you. module TestHelper include Authorization::Maintenance # Analogue to the Ruby's assert_raise method, only executing the block # in the context of the given user. def assert_raise_with_user(user, *args) assert_raise(*args) do with_user(user) do yield if block_given? end end end # Test helper to test authorization rules. # with_user a_normal_user do # should_not_be_allowed_to :update, :conferences # should_not_be_allowed_to :read, an_unpublished_conference # should_be_allowed_to :read, a_published_conference # end # # If the objects class name does not match the controller name, you can set the object and context manually # should_be_allowed_to :create, :object => car, :context => :vehicles # # If you use specify the object and context manually, you can also specify the user manually, skipping the with_user block: # should_be_allowed_to :create, :object => car, :context => :vehicles, :user => a_normal_user def should_be_allowed_to(privilege, *args) options = {} if(args.first.class == Hash) options = args.extract_options! else options[args[0].is_a?(Symbol) ? :context : :object] = args[0] end assert_nothing_raised do Authorization::Engine.instance.permit!(privilege, options) end end # See should_be_allowed_to def should_not_be_allowed_to(privilege, *args) options = {} if(args.first.class == Hash) options = args.extract_options! else options[args[0].is_a?(Symbol) ? :context : :object] = args[0] end assert !Authorization::Engine.instance.permit?(privilege, options) end def request_with(user, method, xhr, action, params = {}, session = {}, flash = {}) session = session.merge({:user => user, :user_id => user && user.id}) with_user(user) do if xhr xhr method, action, params, session, flash else send method, action, params, session, flash end end end def self.included(base) [:get, :post, :put, :delete].each do |method| base.class_eval <<-EOV, __FILE__, __LINE__ def #{method}_with(user, *args) request_with(user, #{method.inspect}, false, *args) end def #{method}_by_xhr_with(user, *args) request_with(user, #{method.inspect}, true, *args) end EOV end end end end