Permalink
Browse files

multiple actions check, << method, preparing to 0.2.0

  • Loading branch information...
1 parent 49068ca commit 0a5d9148b8f19ba3e778629469e3c71838ccf32b @randx committed Sep 2, 2011
Showing with 73 additions and 10 deletions.
  1. +7 −0 CHANGELOG
  2. +6 −4 README.markdown
  3. +38 −5 lib/six.rb
  4. +1 −0 spec/six_initialize_spec.rb
  5. +12 −0 spec/six_rules_packs_spec.rb
  6. +1 −0 spec/six_spec.rb
  7. +8 −1 spec/support/valid_abilities_example.rb
View
@@ -1,3 +1,10 @@
+v 0.2.0
+ - '<<' method for quick pack add w/o specifing namespace
+ Ex. Six.new << BookRules.new
+ - allowed? method can accept array of actions and return true only if all granted
+ Ex. allowed?(:author, [:read, :write, :publish], :book ) # true
+ Ex. allowed?(:author, [:read, :write, :publish, :admin], :book ) # false
+
v 0.1.3
- initialization with pack as args
Ex. Six.new(:book => BookRules.new)
View
@@ -30,7 +30,7 @@
3. Add object with your rules to abilities
```ruby
- abilities.add(:book, BookRules) # true
+ abilities << BookRules # true
```
4. Thats all. Now you can check abilites. In difference to CanCan it doesnt use current_user method. you manually pass object & subject.
@@ -72,6 +72,8 @@ abilites = Six.new
# Add rules to namespace ':book' & global namespace
abilities.add(:book, BookRules) # true
+# OR simple syntax w/o namespaces
+abilities << BookRules # true
# thats all - now we can use it!
@@ -125,7 +127,7 @@ class BooksController < ApplicationController
protected
def add_abilities
- abilities.add(:book, Book)
+ abilities << Book
end
def load_author
@@ -196,14 +198,14 @@ end
# init object
abilities = Six.new
-# add packs
+# add packs with namespace support
abilities.add(:book, BookRules) # true
abilities.add(:car, CarRules) # true
abilities.add(:ufo, nil) # false
abilities.add!(:ufo, nil) # raise Six::InvalidPackPassed
-# use specific pack for rules
+# use specific pack for rules (namespace)
abilities.use(:book) # true
abilities.allowed? :anyone, :read_book, book # true
abilities.allowed? :anyone, :drive, car # false
View
@@ -20,6 +20,15 @@ def message
attr_reader :rules_packs
attr_reader :current_rule_pack
+ # Initialize ability object
+ #
+ # == Parameters:
+ # packs::
+ # A Hash or rules to add with initializtion
+ #
+ # == Returns:
+ # self
+ #
def initialize(packs={})
raise InitializeArgumentError.new unless packs.kind_of?(Hash)
@@ -70,6 +79,19 @@ def add_pack!(name, pack)
add_pack(name, pack) || raise_incorrect_pack_object
end
+ # Add pack to authorization class w/o key
+ #
+ # == Parameters:
+ # pack::
+ # Any kind of object responding to allowed method
+ #
+ # == Returns:
+ # true or raise exception
+ #
+ def <<(pack)
+ add_pack!(pack.object_id.to_s, pack)
+ end
+
# Remove pack from authorization class
#
# == Parameters:
@@ -137,11 +159,14 @@ def pack_exist?(name)
# == Returns:
# true or false
#
- def allowed?(object, action, subject)
- if current_rule_pack
- rules_packs[current_rule_pack].allowed(object, subject).include?(action)
- else
- rules_packs.values.map { |rp| rp.allowed(object, subject) }.flatten.include?(action)
+ def allowed?(object, actions, subject)
+ # if multiple actions passed
+ # check all actions to be allowed
+ if actions.respond_to?(:each)
+ actions.all? { |action| action_included?(object, action, subject) }
+ else
+ # single action check
+ action_included?(object, actions, subject)
end
end
@@ -153,6 +178,14 @@ def reset_use
protected
+ def action_included?(object, action, subject)
+ if current_rule_pack
+ rules_packs[current_rule_pack].allowed(object, subject).include?(action)
+ else
+ rules_packs.values.map { |rp| rp.allowed(object, subject) }.flatten.include?(action)
+ end
+ end
+
def raise_no_such_pack
raise Six::NoPackError.new
end
@@ -30,6 +30,7 @@
describe "passing rules on initialization" do
it_should_behave_like :valid_abilities do
let(:abilities) { Six.new(:book_rules => BookRules.new) }
+ let(:rules_key) { :book_rules }
end
end
end
@@ -8,6 +8,18 @@
describe "Rules Packs" do
let(:rules) { BookRules.new }
+ describe "<<" do
+ it { (abilities << rules).should be_true }
+ it { lambda { abilities << nil }.should raise_error(Six::InvalidPackPassed) }
+
+ it_should_behave_like :valid_abilities do
+ let (:abilities) { Six.new }
+ let (:rules) { BookRules.new }
+ let (:rules_key) { rules.object_id.to_s }
+ before { abilities << rules }
+ end
+ end
+
describe :add do
it { abilities.add(:global, rules).should be_true }
it { abilities.add(:wrong, nil).should be_false }
View
@@ -5,6 +5,7 @@
it_should_behave_like :valid_abilities do
let (:abilities) { Six.new }
let (:rules) { BookRules.new }
+ let (:rules_key) { :book_rules }
before { abilities.add(:book_rules, rules) }
end
end
@@ -14,7 +14,7 @@ def allowed?(action, object, subject)
# validate work of both global & local namespaces
abilities.allowed?(action, object, subject) &&
- abilities.use(:book_rules).allowed?(action, object, subject)
+ abilities.use(rules_key).allowed?(action, object, subject)
end
describe "should return true or false depend on access" do
@@ -45,6 +45,13 @@ def allowed?(action, object, subject)
it { allowed?(@jim, :publish_book, @mikes_book).should be_false }
it { allowed?(@mike,:publish_book, @jims_book).should be_false }
end
+
+ context 'passing multiple actions' do
+ it { allowed?(@jim, [:read_book, :edit_book], @jims_book).should be_true }
+ it { allowed?(@jim, [:ead_book, :publish_book, :edit_book], @jims_book).should be_false }
+ it { allowed?(@mike, [:read_book, :edit_book], @mikes_book).should be_true }
+ it { allowed?(@mike, [:rate_book, :publish_book, :edit_book], @mikes_book).should be_false }
+ end
end
end
end

0 comments on commit 0a5d914

Please sign in to comment.