use I18n for unauthorization messages - closes #103
This commit is contained in:
parent
66314a89f8
commit
a5f838a964
|
@ -49,7 +49,6 @@ module CanCan
|
|||
#
|
||||
# Also see the RSpec Matchers to aid in testing.
|
||||
def can?(action, subject, *extra_args)
|
||||
raise Error, "Nom nom nom. I eated it." if action == :has && subject == :cheezburger
|
||||
match = relevant_can_definitions(action, subject).detect do |can_definition|
|
||||
can_definition.matches_conditions?(action, subject, extra_args)
|
||||
end
|
||||
|
@ -189,9 +188,36 @@ module CanCan
|
|||
Query.new(subject, relevant_can_definitions_for_query(action, subject))
|
||||
end
|
||||
|
||||
# See ControllerAdditions#authorize! for documentation.
|
||||
def authorize!(action, subject, *args)
|
||||
message = nil
|
||||
if args.last.kind_of?(Hash) && args.last.has_key?(:message)
|
||||
message = args.pop[:message]
|
||||
end
|
||||
if cannot?(action, subject, *args)
|
||||
message ||= unauthorized_message(action, subject)
|
||||
raise AccessDenied.new(message, action, subject)
|
||||
end
|
||||
end
|
||||
|
||||
def unauthorized_message(action, subject)
|
||||
keys = unauthorized_message_keys(action, subject)
|
||||
message = I18n.translate(nil, :scope => :unauthorized, :default => keys + [""])
|
||||
message.blank? ? nil : message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Accepts a hash of aliased actions and returns an array of actions which match.
|
||||
def unauthorized_message_keys(action, subject)
|
||||
subject = (subject.class == Class ? subject : subject.class).name.underscore unless subject.kind_of? Symbol
|
||||
[subject, :all].map do |try_subject|
|
||||
[aliases_for_action(action), :manage].flatten.map do |try_action|
|
||||
:"#{try_action}.#{try_subject}"
|
||||
end
|
||||
end.flatten
|
||||
end
|
||||
|
||||
# Accepts an array of actions and returns an array of actions which match.
|
||||
# This should be called before "matches?" and other checking methods since they
|
||||
# rely on the actions to be expanded.
|
||||
def expand_actions(actions)
|
||||
|
@ -200,6 +226,16 @@ module CanCan
|
|||
end.flatten
|
||||
end
|
||||
|
||||
# Given an action, it will try to find all of the actions which are aliased to it.
|
||||
# This does the opposite kind of lookup as expand_actions.
|
||||
def aliases_for_action(action)
|
||||
results = [action]
|
||||
aliased_actions.each do |aliased_action, actions|
|
||||
results += aliases_for_action(aliased_action) if actions.include? action
|
||||
end
|
||||
results
|
||||
end
|
||||
|
||||
def can_definitions
|
||||
@can_definitions ||= []
|
||||
end
|
||||
|
|
|
@ -185,12 +185,8 @@ module CanCan
|
|||
#
|
||||
# See the load_and_authorize_resource method to automatically add the authorize! behavior
|
||||
# to the default RESTful actions.
|
||||
def authorize!(action, subject, *args)
|
||||
message = nil
|
||||
if args.last.kind_of?(Hash) && args.last.has_key?(:message)
|
||||
message = args.pop[:message]
|
||||
end
|
||||
raise AccessDenied.new(message, action, subject) if cannot?(action, subject, *args)
|
||||
def authorize!(*args)
|
||||
current_ability.authorize!(*args)
|
||||
end
|
||||
|
||||
def unauthorized!(message = nil)
|
||||
|
|
|
@ -157,18 +157,7 @@ describe CanCan::Ability do
|
|||
@ability.can?(:read, 123).should be_false
|
||||
end
|
||||
|
||||
it "should support block on 'cannot' method" do
|
||||
@ability.can :read, :all
|
||||
@ability.cannot :read, Integer do |int|
|
||||
int > 5
|
||||
end
|
||||
@ability.can?(:read, "foo").should be_true
|
||||
@ability.can?(:read, 3).should be_true
|
||||
@ability.can?(:read, 123).should be_false
|
||||
end
|
||||
|
||||
it "should pass to previous can definition, if block returns false or nil" do
|
||||
#same as previous
|
||||
@ability.can :read, :all
|
||||
@ability.cannot :read, Integer do |int|
|
||||
int > 10 ? nil : ( int > 5 )
|
||||
|
@ -177,7 +166,6 @@ describe CanCan::Ability do
|
|||
@ability.can?(:read, 3).should be_true
|
||||
@ability.can?(:read, 8).should be_false
|
||||
@ability.can?(:read, 123).should be_true
|
||||
|
||||
end
|
||||
|
||||
it "should always return `false` for single cannot definition" do
|
||||
|
@ -262,9 +250,39 @@ describe CanCan::Ability do
|
|||
@ability.can?(:read, Array).should be_true
|
||||
end
|
||||
|
||||
it "should has eated cheezburger" do
|
||||
lambda {
|
||||
@ability.can? :has, :cheezburger
|
||||
}.should raise_error(CanCan::Error, "Nom nom nom. I eated it.")
|
||||
describe "unauthorized message" do
|
||||
after(:each) do
|
||||
I18n.backend = nil
|
||||
end
|
||||
|
||||
it "should use action/subject in i18n" do
|
||||
I18n.backend.store_translations :en, :unauthorized => {:update => {:array => "foo"}}
|
||||
@ability.unauthorized_message(:update, Array).should == "foo"
|
||||
@ability.unauthorized_message(:update, [1, 2, 3]).should == "foo"
|
||||
@ability.unauthorized_message(:update, :missing).should be_nil
|
||||
end
|
||||
|
||||
it "should use symbol as subject directly" do
|
||||
I18n.backend.store_translations :en, :unauthorized => {:has => {:cheezburger => "Nom nom nom. I eated it."}}
|
||||
@ability.unauthorized_message(:has, :cheezburger).should == "Nom nom nom. I eated it."
|
||||
end
|
||||
|
||||
it "should fall back to 'manage' and 'all'" do
|
||||
I18n.backend.store_translations :en, :unauthorized => {
|
||||
:manage => {:all => "manage all", :array => "manage array"},
|
||||
:update => {:all => "update all", :array => "update array"}
|
||||
}
|
||||
@ability.unauthorized_message(:update, Array).should == "update array"
|
||||
@ability.unauthorized_message(:update, Hash).should == "update all"
|
||||
@ability.unauthorized_message(:foo, Array).should == "manage array"
|
||||
@ability.unauthorized_message(:foo, Hash).should == "manage all"
|
||||
end
|
||||
|
||||
it "should follow aliased actions" do
|
||||
I18n.backend.store_translations :en, :unauthorized => {:modify => {:array => "modify array"}}
|
||||
@ability.alias_action :update, :to => :modify
|
||||
@ability.unauthorized_message(:update, Array).should == "modify array"
|
||||
@ability.unauthorized_message(:edit, Array).should == "modify array"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,7 @@ describe CanCan::ControllerAdditions do
|
|||
end
|
||||
|
||||
it "should raise access denied exception if ability us unauthorized to perform a certain action" do
|
||||
# TODO this should probably be moved into Ability spec
|
||||
begin
|
||||
@controller.authorize! :read, :foo, 1, 2, 3, :message => "Access denied!"
|
||||
rescue CanCan::AccessDenied => e
|
||||
|
|
Loading…
Reference in New Issue
Block a user