Skip to content

Commit

Permalink
Redo :query_method with extending BooleanMethod generator.
Browse files Browse the repository at this point in the history
Now it's supported in both method and lambda cases and can look into the
passed hash for objects.

Side-effect: all boolean methods now support action override!
Pass it as the optional first argument.
  • Loading branch information
be9 committed Jun 25, 2009
1 parent 73fe443 commit 00f3094
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 21 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.textile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* Fix namespaced models in roles backend (thanks goes to Tomas Jogin)
* Action name override in boolean methods.
* @:query_method@ option for @access_control@.

h2. 0.10.0 (03-May-2009)

* Use context+matchy combo for testing
Expand Down
24 changes: 22 additions & 2 deletions lib/acl9/controller_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ def access_control(*args, &block)
end

method = opts[:as_method]
query_method = opts[:query_method]

query_method_available = true
generator = case
when method && filter
Acl9::Dsl::Generators::FilterMethod.new(subject_method, method, query_method)
Acl9::Dsl::Generators::FilterMethod.new(subject_method, method)
when method && !filter
query_method_available = false
Acl9::Dsl::Generators::BooleanMethod.new(subject_method, method)
else
Acl9::Dsl::Generators::FilterLambda.new(subject_method)
Expand All @@ -59,6 +60,25 @@ def access_control(*args, &block)
generator.acl_block!(&block)

generator.install_on(self, opts)

if query_method_available && (query_method = opts.delete(:query_method))
case query_method
when true
if method
query_method = "#{method}?"
else
raise ArgumentError, "You must specify :query_method as Symbol"
end
when Symbol, String
# okay here
else
raise ArgumentError, "Invalid value for :query_method"
end

second_generator = Acl9::Dsl::Generators::BooleanMethod.new(subject_method, query_method)
second_generator.acl_block!(&block)
second_generator.install_on(self, opts)
end
end
end
end
Expand Down
28 changes: 12 additions & 16 deletions lib/acl9/controller_extensions/generators.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,11 @@ def to_proc
################################################################

class FilterMethod < BaseGenerator
def initialize(subject_method, method_name, query_meth = nil)
def initialize(subject_method, method_name)
super

@method_name = method_name
@controller = nil
@query_method = (query_meth == true) ? "#{method_name}?" : query_meth
end

def install_on(controller_class, options)
Expand All @@ -138,24 +137,13 @@ def _add_method(controller_class)
end

def to_method_code
code = <<-RUBY
<<-RUBY
def #{@method_name}
unless #{allowance_expression}
#{_access_denied}
end
end
RUBY

if @query_method
code += <<-RUBY
def #{@query_method}(action)
action_name = action.to_s
return #{allowance_expression}
end
RUBY
end

code
end
end

Expand All @@ -176,8 +164,16 @@ def install_on(controller_class, opts)

def to_method_code
<<-RUBY
def #{@method_name}(options = {})
#{allowance_expression}
def #{@method_name}(*args)
options = args.extract_options!
unless args.size <= 1
raise ArgumentError, "call #{@method_name} with 0, 1 or 2 arguments"
end
action_name = args.empty? ? self.action_name : args.first.to_s
return #{allowance_expression}
end
RUBY
end
Expand Down
49 changes: 48 additions & 1 deletion test/access_control_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,32 @@ class ACLObjectsHashTest < ActionController::TestCase
end
end

class ACLActionOverrideTest < ActionController::TestCase
tests ACLActionOverride

it "should allow index action to anonymous" do
get :check_allow, :_action => :index
@response.body.should == 'OK'
end

it "should deny show action to anonymous" do
get :check_allow, :_action => :show
@response.body.should == 'AccessDenied'
end

it "should deny edit action to regular user" do
get :check_allow_with_foo, :_action => :edit, :user => TheOnlyUser.instance

@response.body.should == 'AccessDenied'
end

it "should allow edit action to owner of foo" do
get :check_allow_with_foo, :_action => :edit, :user => OwnerOfFoo.new

@response.body.should == 'OK'
end
end

class ACLHelperMethodTest < ActionController::TestCase
tests ACLHelperMethod

Expand All @@ -183,6 +209,7 @@ def self.included(base)
before do
@editor = Beholder.new(:editor)
@viewer = Beholder.new(:viewer)
@owneroffoo = OwnerOfFoo.new
end

[:edit, :update, :destroy].each do |meth|
Expand Down Expand Up @@ -212,6 +239,16 @@ def self.included(base)
@controller.acl?(meth.to_s).should == true
end
end

it "should return false for editor/fooize" do
@controller.current_user = @editor
@controller.acl?(:fooize).should == false
end

it "should return true for foo owner" do
@controller.current_user = @owneroffoo
@controller.acl?(:fooize, :foo => MyDearFoo.instance).should == true
end
end
end
end
Expand All @@ -221,7 +258,17 @@ class ACLQueryMethodTest < ActionController::TestCase
tests ACLQueryMethod

it "should respond to :acl?" do
@controller.should respond_to(:acl)
@controller.should respond_to(:acl?)
end

include ACLQueryMixin
end

class ACLQueryMethodWithLambdaTest < ActionController::TestCase
tests ACLQueryMethodWithLambda

it "should respond to :acl?" do
@controller.should respond_to(:acl?)
end

include ACLQueryMixin
Expand Down
37 changes: 35 additions & 2 deletions test/support/controllers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class ACLArguments < EmptyController
access_control :except => [:index, :show] do
allow :admin, :if => :true_meth, :unless => :false_meth
end

include TrueFalse
end

Expand Down Expand Up @@ -129,12 +129,33 @@ def allow
@foo = nil
render :text => (allowed?(:foo => MyDearFoo.instance) ? 'OK' : 'AccessDenied')
end


def current_user
params[:user]
end
end

class ACLActionOverride < ApplicationController
access_control :allowed?, :filter => false do
allow all, :to => :index
deny all, :to => :show
allow :owner, :of => :foo, :to => :edit
end

def check_allow
render :text => (allowed?(params[:_action]) ? 'OK' : 'AccessDenied')
end

def check_allow_with_foo
render :text => (allowed?(params[:_action], :foo => MyDearFoo.instance) ? 'OK' : 'AccessDenied')
end

def current_user
params[:user]
end
end


class ACLHelperMethod < ApplicationController
access_control :helper => :foo? do
allow :owner, :of => :foo
Expand All @@ -157,6 +178,17 @@ class ACLQueryMethod < ApplicationController
access_control :acl, :query_method => true do
allow :editor, :to => [:edit, :update, :destroy]
allow :viewer, :to => [:index, :show]
allow :owner, :of => :foo, :to => :fooize
end
end

class ACLQueryMethodWithLambda < ApplicationController
attr_accessor :current_user

access_control :query_method => :acl? do
allow :editor, :to => [:edit, :update, :destroy]
allow :viewer, :to => [:index, :show]
allow :owner, :of => :foo, :to => :fooize
end
end

Expand All @@ -166,6 +198,7 @@ class ACLNamedQueryMethod < ApplicationController
access_control :acl, :query_method => 'allow_ay' do
allow :editor, :to => [:edit, :update, :destroy]
allow :viewer, :to => [:index, :show]
allow :owner, :of => :foo, :to => :fooize
end

def acl?(*args)
Expand Down

0 comments on commit 00f3094

Please sign in to comment.