-
Notifications
You must be signed in to change notification settings - Fork 111
Description
Some people expect ACL block in derived controller to extend its counterpart from the base controller. So they put rather restrictive rules to the base (e.g. deny all), trynig to loosen the restrictions in descendant controllers.
Unfortunately this doesn't work. Each access_control call with a block results in a filter being appended to the "before" filter chain. Now add more filters, get more restrictive behavior.
skip_before_filter comes to the rescue when you need to circumvent ACL block from the base controller, but how could we truly inherit ACL rules?
I see several possibilities.
-
Declare "virtual" ACL blocks, which are used only for inheritance. Something like:
class BaseController < ApplicationController # ... access_control :base, :virtual => true do deny anonymous end # ... end class DerivedController < BaseController access_control do extends :base allow anonymous, :to => [:show, :index] allow logged_in end end
Here :base block doesn't get installed in BaseController as a filter.
- Modification of (1).
Install the filter, but also save the rules into inheritable array. Each derived controller will append its rules, calling skip_before_filter against the inherited filter.
class BaseController < ApplicationController
# ...
access_control :base, :virtual => true do
deny anonymous
end
# ...
end
class DerivedController < BaseController
access_control :base do
allow anonymous, :to => [:show, :index]
allow logged_in
end
end
class DerivedDerivedController < DerivedController
access_control :base do
allow anonymous, :to => [:custom]
end
end
We get 3 blocks here. The 3rd block is used to match first (both for allow and for deny). If it doesn't bring a match, the 2nd block is tried and then the 1st.