Skip to content
Browse files

Up to 0.0.3

  • Loading branch information...
1 parent e21880c commit d1ed92f8687c821c8f5e5dc5df6ef72db3d6632a @randx committed
Showing with 237 additions and 69 deletions.
  1. +35 −13 README.markdown
  2. +113 −7 lib/six.rb
  3. +2 −2 six.gemspec
  4. +67 −33 spec/six_rules_packs_spec.rb
  5. +10 −14 spec/six_spec.rb
  6. +1 −0 spec/spec_helper.rb
  7. +9 −0 spec/support/book_and_rules.rb
View
48 README.markdown
@@ -1,4 +1,4 @@
-## Six - is a authorization gem for ruby!
+## Six - is a ultra simple authorization gem for ruby!
### Installation
@@ -12,13 +12,14 @@
class BookRules
# All authorization works on objects with method 'allowed'
# No magic behind the scene
- # You can put this method to any class you want
- # It should always return array
+ # You can put this method to any class or object you want
+ # It should always return array
+ # And be aready to get nil in args
def self.allowed(author, book)
rules = []
# good practice is to check for object type
- return rules unless book.instance_of?(Book)
+ return rules unless book && book.instance_of?(Book)
rules << :read_book if book.published?
rules << :edit_book if author && author.id == book.author_id
@@ -31,7 +32,7 @@ class BookRules
end
# Add rules to namespace ':book' & global namespace
-Six.add_pack(:book, BookRules)
+Six.add_pack(:book, BookRules) # true
Six.allowed? :read_book, nil, nil # false
Six.allowed? :read_book, nil, published_book # true
@@ -80,7 +81,7 @@ class Book < ActiveRecord::Base
def self.allowed(object, subject)
rules = []
- return rules unless book.instance_of?(Book)
+ return rules unless book && book.instance_of?(Book)
rules << :read_book if subject.public?
rules << :edit_book if object && object.id == subject.author_id
rules
@@ -115,19 +116,40 @@ class CarRules
end
end
-Six.add_pack(:book, BookRules)
-Six.add_pack(:car, CarRules)
+# add packs
+Six.add_pack(:book, BookRules) # true
+Six.add_pack(:car, CarRules) # true
+Six.add_pack(:ufo, nil) # false
+Six.add_pack!(:ufo, nil) # raise Six::InvalidPackPassed
-Six.use(:book).allowed? :read_book, nil, nil # true
-Six.use(:car).allowed? :drive, nil, nil # true
-Six.use(:car).allowed? :read_book, nil, nil # false
-Six.use(:book).allowed? :drive, nil, nil # false
+# use specific pack for rules
+Six.use(:book) # true
+Six.allowed? :read_book, nil, nil # true
+Six.allowed? :drive, nil, nil # false
+
+Six.use(:car)
+Six.allowed? :drive, nil, nil # true
+Six.allowed? :read_book, nil, nil # false
+# use reset to return to global usage
Six.reset_use
-Six.allowed? :drive, nil, nil # true
+Six.allowed? :drive, nil, nil # true
Six.allowed? :read_book, nil, nil # true
+# different use methods
+Six.use(:ufo) # false
+Six.use!(:ufo) # raise Six::NoPackError
+
+
+# remove pack
+Six.remove(:book) # true
+Six.remove(:ufo) # false
+Six.remove!(:ufo) # raise Six::NoPackError
+
+Six.use(:car) # true
+Six.current_rule_pack # :car
+
```
View
120 lib/six.rb
@@ -1,4 +1,16 @@
class Six
+ class NoPackError < StandardError
+ def message
+ "No such pack"
+ end
+ end
+
+ class InvalidPackPassed < StandardError
+ def message
+ "Wrong Rule Pack. You must provide correct 'allowed' method"
+ end
+ end
+
class << self
attr_accessor :rules_packs
attr_accessor :current_rule_pack
@@ -7,15 +19,56 @@ def rules_packs
@rules_packs ||= {}
end
+ # Set current pack from stored packs by key
+ #
+ # == Parameters:
+ # name::
+ # A Symbol declaring the key name of stored pack
+ #
+ # == Returns:
+ # self or false
+ #
def use(name)
- @current_rule_pack = rules_packs[name.to_sym] if pack_exist?(name)
- self
+ if pack_exist?(name)
+ @current_rule_pack = name.to_sym
+ self
+ end
+ end
+
+ # Same as use but raise exception if no pack found
+ def use!(name)
+ use(name) ? self : raise_no_such_pack
end
+ # Add pack to authorization class
+ #
+ # == Parameters:
+ # name::
+ # A Symbol declaring the key name of stored pack
+ # pack::
+ # Any kind of object responding to allowed method
+ #
+ # == Returns:
+ # true or false
+ #
def add_pack(name, pack)
rules_packs[name.to_sym] = pack if valid_rules_object?(pack)
end
+ # Same as add_pack but raise exception if pack is invalid
+ def add_pack!(name, pack)
+ add_pack(name, pack) || raise_incorrect_pack_object
+ end
+
+ # Remove pack from authorization class
+ #
+ # == Parameters:
+ # name::
+ # A Symbol declaring the key name of stored pack
+ #
+ # == Returns:
+ # true or false
+ #
def remove_pack(name)
if pack_exist?(name)
@current_rule_pack = nil if rules_packs[name.to_sym] == @current_rule_pack
@@ -23,26 +76,79 @@ def remove_pack(name)
end
end
+ # Same as remove_pack but raise exception if pack wasnt found
+ def remove_pack!(name)
+ remove_pack(name) || raise_no_such_pack
+ end
+
+ # Check if object for rule pack is valid
+ #
+ # == Parameters:
+ # pack::
+ # Any kind of object responding to allowed method
+ #
+ # == Returns:
+ # true or false
+ #
def valid_rules_object?(object)
- object.respond_to?(:allowed) ||
- raise("Wrong Rule Pack. You must provide 'allowed' method")
+ object.respond_to?(:allowed) &&
+ object.send(:allowed, nil, nil).kind_of?(Array)
+ rescue
+ false
end
+ # Check if authorization class has pack with such name
+ #
+ # == Parameters:
+ # name::
+ # A Symbol declaring the key name of stored pack
+ #
+ # == Returns:
+ # true or false
+ #
def pack_exist?(name)
- rules_packs.has_key?(name.to_sym) ||
- raise("No such pack")
+ rules_packs.has_key?(name.to_sym)
end
+ # Check if authorization class allow access for object to subject
+ # using selected pack or all stored.
+ # Basically this method
+ # 1. send :allowed for every stored object in packs and pass object & subject
+ # 2. check if any of results include allowed action
+ #
+ # == Parameters:
+ # action::
+ # Action name to check for access
+ # object::
+ # object trying to access resource
+ # subject::
+ # resource
+ #
+ # == Returns:
+ # true or false
+ #
def allowed?(action, object, subject)
if current_rule_pack
- current_rule_pack.allowed(object, subject).include?(action)
+ 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
+ # Reset current used rule pack so auth class use
+ # global allowed? for new request
def reset_use
@current_rule_pack = nil
end
+
+ protected
+
+ def raise_no_such_pack
+ raise Six::NoPackError.new
+ end
+
+ def raise_incorrect_pack_object
+ raise Six::InvalidPackPassed.new
+ end
end
end
View
4 six.gemspec
@@ -1,7 +1,7 @@
Gem::Specification.new do |s|
s.name = 'six'
- s.version = '0.0.2'
- s.date = '2011-08-13'
+ s.version = '0.0.3'
+ s.date = '2011-08-17'
s.summary = "six"
s.description = "Very simple authorization gem"
s.authors = ["Dmitriy Zaporozhets"]
View
100 spec/six_rules_packs_spec.rb
@@ -3,58 +3,92 @@
describe Six do
describe "Rules Packs" do
- class MyRules
- def allowed(object, subject)
- []
- end
+ let(:rules) { BookRules.new }
+
+ describe :add_pack do
+ it { Six.add_pack(:global, rules).should be_true }
+ it { Six.add_pack(:wrong, nil).should be_false }
+ end
+
+ describe :add_pack! do
+ it { Six.add_pack!(:global, rules).should be_true }
+ it { lambda { Six.add_pack!(:wrong, nil)}.should raise_error(Six::InvalidPackPassed) }
end
-
- describe "namespace usage" do
- before do
- @rules = MyRules.new
- @guard = Six
- @guard.add_pack(:global, @rules)
- end
+
+ describe "namespace(pack) usage" do
+ before { Six.add_pack(:global, rules) }
describe :use do
- before do
- @guard.use(:global)
+ before { Six.use(:global) }
+
+ it "should return class object itself when use existing pack" do
+ Six.use(:global).should == Six
+ end
+
+ describe "should set current role pack with selected" do
+ it { Six.current_rule_pack.should == :global }
end
- it { @guard.current_rule_pack.should_not be_nil }
- it { lambda { @guard.use(:noname)}.should raise_error("No such pack") }
+ it "should return false when trying to use unexisting pack" do
+ Six.use(:noname).should be_false
+ end
end
- describe :reset_use do
- before do
- @guard.use(:global)
- @guard.reset_use
+ describe :use! do
+ it "should not raise error if trying to use existing pack" do
+ lambda { Six.use!(:global)}.should_not raise_error
end
- it { @guard.current_rule_pack.should be_nil }
+ it "should raise error if trying to use unexisting pack" do
+ lambda { Six.use!(:noname)}.should raise_error(Six::NoPackError)
+ end
end
end
-
- describe :add_pack do
+ describe :reset_use do
before do
- @rules = MyRules.new
- @guard = Six
+ Six.use(:global)
+ Six.reset_use
end
- it { @guard.add_pack(:global, @rules).should be_true }
- it { lambda { @guard.add_pack(:wrong, nil)}.should raise_error("Wrong Rule Pack. You must provide 'allowed' method") }
+ it "should set current rule pack variable as nil" do
+ Six.current_rule_pack.should be_nil
+ end
end
- describe :remove_pack do
- before do
- @rules = MyRules.new
- @guard = Six
- @guard.add_pack(:global, @rules)
+ context "removing pack" do
+ before { Six.add_pack(:global, rules) }
+
+ describe :remove_pack do
+ it { Six.remove_pack(:global).should be_true }
+ it { Six.remove_pack(:zzz).should be_false }
+ end
+
+ describe :remove_pack! do
+ it { Six.remove_pack!(:global).should be_true }
+ it { lambda { Six.remove_pack!(:zzz)}.should raise_error(Six::NoPackError) }
+ end
+ end
+
+ describe :valid_rules_object? do
+ let (:invalid_with_allowed) do
+ Class.new { def allowed; nil; end }.new
+ end
+
+ let (:invalid_wo_allowed) do
+ Object.new
end
- it { @guard.remove_pack(:global).should be_true }
- it { lambda { @guard.remove_pack(:zzz)}.should raise_error("No such pack") }
+ it { Six.valid_rules_object?(BookRules.new).should be_true }
+ it { Six.valid_rules_object?(invalid_with_allowed).should be_false }
+ it { Six.valid_rules_object?(invalid_wo_allowed).should be_false }
+ end
+
+ describe :pack_exist? do
+ before { Six.add_pack(:global, rules) }
+
+ it { Six.pack_exist?(:global).should be_true }
+ it { Six.pack_exist?(:ufo).should be_false }
end
end
end
View
24 spec/six_spec.rb
@@ -3,40 +3,36 @@
describe Six do
describe "protection" do
- class BookRules
- def allowed(object, subject)
- rules = []
- rules << :read_book if object == 1 && subject == 2
- rules
- end
- end
+ let (:rules) { BookRules.new }
describe "protect!" do
before do
- @rules = BookRules.new
- @guard = Six
- @guard.add_pack(:myrules, @rules)
+ Six.add_pack(:myrules, rules)
end
describe "global rules" do
it "should allow acceess" do
- @guard.allowed?(:read_book, 1, 2).should be_true
+ Six.allowed?(:read_book, 1, 2).should be_true
end
it "should prevent unauthorized acceess" do
- @guard.use(:myrules).allowed?(:read_book, 2, 2).should be_false
+ Six.use(:myrules).allowed?(:read_book, 2, 2).should be_false
end
end
describe "namespace rules" do
it "should allow acceess" do
- @guard.use(:myrules).allowed?(:read_book, 1, 2).should be_true
+ Six.use(:myrules).allowed?(:read_book, 1, 2).should be_true
end
it "should prevent unauthorized acceess" do
- @guard.use(:myrules).allowed?(:read_book, 2, 2).should be_false
+ Six.use(:myrules).allowed?(:read_book, 2, 2).should be_false
end
end
end
+
+ describe "if no rules passed" do
+ it { Six.allowed?(:read_book, 2, 2).should be_false }
+ end
end
end
View
1 spec/spec_helper.rb
@@ -1,3 +1,4 @@
require "rubygems"
require "bundler"
Bundler.require(:default, :development)
+require "support/book_and_rules"
View
9 spec/support/book_and_rules.rb
@@ -0,0 +1,9 @@
+class BookRules
+ def allowed(object, subject)
+ rules = []
+ rules << :read_book if object == 1 && subject == 2
+ rules << :edit_book if object == 1 && subject == 2
+ rules
+ end
+end
+

0 comments on commit d1ed92f

Please sign in to comment.
Something went wrong with that request. Please try again.