Jul 30 Bypassing declarative authorization in Cucumber steps
tags:
You have set up that groovy declarative authorization plugin in your app, all the way from models, to controllers and views, to keep authorization tidy and out of the way, and everything runs smoothly. Now when you try to create objects in your features Given steps you face the dreadful not authorized exception:
No matching rules found for create for #<Authorization::GuestUser:0xb58904a8 @role_symbols=[:guest]>
(roles [:guest], privileges [:create, :manage], context :jobs). (Authorization::NotAuthorized)
./features/step_definitions/leaves_steps.rb:3
./features/step_definitions/leaves_steps.rb:3:in `/^there exists 5 leaves not of mine$/'
features/leaves.feature:5:in `Given there exists 5 leaves not of mine'
Guest user is the default, non session user in declarative authorization. The solution is to bypass declarative authorization in Cucumber and build the objects needed to set a status to run your features. Let’s see an example:
A typical authorization setup
This is the typical setup, a tree can only manage its leaves:
# config/authorization_rules.rb
authorization do
role :tree do
has_permission_on :leaves, :to => :manage do
if_attribute :tree => is { user }
end
end
end
privileges do
# the distributed ones with declarative authorization
end
the models:
# the tree model
class Tree < ActiveRecord::Base
has_many :leaves
# the tree is declaring itself with role tree
def role_symbols
[:tree]
end
end
# your leaf model
class Leaf < ActiveRecord::Base
# now this requires the leaf belongs to tree so the tree can change it
using_access_control
belongs_to :tree
end
You have to set the controller the typical way, but I’ll leave that to you. Anyway you have to make the session available to the models somewhere like this:
# in some before_filter or so, a tree is user :-) Authorization.current_user = current_tree
Your feature
With that setup, you want to run the feature:
# features/leaves.feature Feature: Leaves authorizations Scenario: A tree can only manage its own leaves Given there exists 5 leaves not of mine When I visit the edit url of a leaf not of mine Then I should see "You are not allowed to access this action."
and the step goes like this, the way you always did:
# features/steps_definitions/leaves.rb
Given /^there exists 5 leaves not of mine$/
5.times { Leaf.make }
end
Here is where the exception comes from, since you have no session, and you’ll never have one :-)
The solution, bypass authorization
Luckily declarative authorization provides a way of bypassing its lock. The trick is to load the Authorization::Maintenance module that lives in declarative_authorization/lib/declarative_authorization/maintenance.rb into the Cucumber World like this:
# features/support/env.rb require File.expand_path(File.dirname(__FILE__) + "/../../vendor/plugins/declarative_authorization/lib/declarative_authorization/maintenance.rb") World(Authorization::Maintenance)
and then in your step, run on non-authorized mode:
# features/steps_definitions/leaves.rb
Given /^there exists 5 leaves not of mine$/
# now World contains the module, and here we run the block unprotected
without_access_control do
5.times { Leaf.make }
end
end
You will always bear with authorization
In other place (like the console) you should do it this way:
>> require File.expand_path("/vendor/plugins/declarative_authorization/lib/declarative_authorization/maintenance.rb")
>> include Authorization::Maintenance
>> without_access_control do ...
TODO maybe you could make an initialization script to be run on start up of script/console and load it with an option.