walruz 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.rdoc +265 -0
- data/Rakefile +75 -0
- data/VERSION.yml +4 -0
- data/lib/walruz/actor.rb +104 -0
- data/lib/walruz/policy.rb +160 -0
- data/lib/walruz/subject.rb +99 -0
- data/lib/walruz/utils.rb +119 -0
- data/lib/walruz.rb +54 -0
- data/spec/scenario.rb +133 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/walruz/actor_spec.rb +123 -0
- data/spec/walruz/policy_spec.rb +62 -0
- data/spec/walruz/subject_spec.rb +24 -0
- data/spec/walruz/utils_spec.rb +46 -0
- data/spec/walruz/walruz_spec.rb +20 -0
- metadata +78 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
module Walruz
|
2
|
+
module Subject
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
|
7
|
+
def self._walruz_policies=(policies)
|
8
|
+
@_walruz_policies = policies
|
9
|
+
end
|
10
|
+
|
11
|
+
def self._walruz_policies
|
12
|
+
@_walruz_policies
|
13
|
+
end
|
14
|
+
|
15
|
+
extend ClassMethods
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @private
|
20
|
+
def can_be?(action, actor)
|
21
|
+
check_authorization_actions_are_setted(action)
|
22
|
+
action = if self.class._walruz_policies.key?(:default)
|
23
|
+
self.class._walruz_policies.key?(action) ? action : :default
|
24
|
+
else
|
25
|
+
if self.class._walruz_policies.key?(action)
|
26
|
+
action
|
27
|
+
else
|
28
|
+
raise ActionNotFound.new(:subject_action, :subject => self,
|
29
|
+
:action => action)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
result = self.class._walruz_policies[action].
|
34
|
+
return_policy.
|
35
|
+
new.
|
36
|
+
safe_authorized?(actor, self)
|
37
|
+
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
# @private
|
42
|
+
def check_authorization_actions_are_setted(action)
|
43
|
+
if self.class._walruz_policies.nil?
|
44
|
+
message =<<BEGIN
|
45
|
+
You need to invoke `check_authorizations :#{action} => Policies::SomePolicy` on the #{self.class.name} class
|
46
|
+
BEGIN
|
47
|
+
raise AuthorizationActionsNotDefined.new(message)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module ClassMethods
|
52
|
+
|
53
|
+
#
|
54
|
+
# Stablishes the actions that can be made with a subject. You may
|
55
|
+
# specify as many actions as you like, and also you may have a default
|
56
|
+
# policy, that will get execute if a specified flag doesn't exist.
|
57
|
+
# You just have to pass the action :default, or just the policy class.
|
58
|
+
#
|
59
|
+
# Example:
|
60
|
+
# # Without :default key
|
61
|
+
# class UserProfile
|
62
|
+
# check_authorizations :read => Policies::FriendPolicy,
|
63
|
+
# :write => Policies::OwnerPolicy
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# # With :default key
|
67
|
+
# class UserProfile
|
68
|
+
# check_authorizations :read => Policies::FriendPolicy,
|
69
|
+
# :write => Policies::OwnerPolicy,
|
70
|
+
# :default => Policies::AdminPolicy
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# # Without any key at all
|
74
|
+
# class UserProfile
|
75
|
+
# # this policy is the default one
|
76
|
+
# check_authorizations Policies::OwnerPolicy
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# Once you stablish the authorizations policies on a subject, you can
|
80
|
+
# check if an actor is able to interact with it via the Actor#can? method
|
81
|
+
#
|
82
|
+
# Example: current_user.can?(:read, profile)
|
83
|
+
#
|
84
|
+
# It's recommended (but not mandatory) that a policy specified to the action
|
85
|
+
# is inherting from Walruz::Policy
|
86
|
+
#
|
87
|
+
def check_authorizations(policy_map)
|
88
|
+
case policy_map
|
89
|
+
when Hash
|
90
|
+
self._walruz_policies = policy_map
|
91
|
+
else
|
92
|
+
self._walruz_policies = { :default => policy_map }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
data/lib/walruz/utils.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
module Walruz
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
module PolicyCompositionHelper
|
5
|
+
|
6
|
+
# NOTE: Not using cattr_accessor to avoid dependencies with ActiveSupport
|
7
|
+
|
8
|
+
def policies=(policies)
|
9
|
+
@policies = policies
|
10
|
+
end
|
11
|
+
|
12
|
+
def policies
|
13
|
+
@policies
|
14
|
+
end
|
15
|
+
|
16
|
+
def policy=(policy)
|
17
|
+
@policy = policy
|
18
|
+
end
|
19
|
+
|
20
|
+
def policy
|
21
|
+
@policy
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_params(params = {})
|
25
|
+
@params ||= {}
|
26
|
+
@params.merge!(params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def params
|
30
|
+
@params
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def orP(*policies)
|
36
|
+
clazz = Class.new(Walruz::Policy) do
|
37
|
+
extend PolicyCompositionHelper
|
38
|
+
|
39
|
+
def authorized?(actor, subject)
|
40
|
+
result = nil
|
41
|
+
self.class.policies.detect do |policy|
|
42
|
+
result = policy.new.safe_authorized?(actor, subject)
|
43
|
+
result[0]
|
44
|
+
end
|
45
|
+
result[0] ? result : result[0]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
clazz.policies = policies
|
50
|
+
clazz
|
51
|
+
end
|
52
|
+
|
53
|
+
def andP(*policies)
|
54
|
+
clazz = Class.new(Walruz::Policy) do
|
55
|
+
extend PolicyCompositionHelper
|
56
|
+
|
57
|
+
def authorized?(actor, subject)
|
58
|
+
acum = [true, {}]
|
59
|
+
self.class.policies.each do |policy|
|
60
|
+
break unless acum[0]
|
61
|
+
policy_instance = policy.new
|
62
|
+
policy_instance.set_params(acum[1])
|
63
|
+
result = policy_instance.safe_authorized?(actor, subject)
|
64
|
+
acum[0] &&= result[0]
|
65
|
+
acum[1].merge!(result[1])
|
66
|
+
end
|
67
|
+
acum[0] ? acum : acum[0]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.policy_keyword
|
71
|
+
(self.policies.map { |p| p.policy_keyword.to_s[0..-2] }.join('_and_') + "?").to_sym
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
clazz.policies = policies
|
76
|
+
clazz
|
77
|
+
end
|
78
|
+
|
79
|
+
def notP(policy)
|
80
|
+
clazz = Class.new(Walruz::Policy) do
|
81
|
+
extend PolicyCompositionHelper
|
82
|
+
|
83
|
+
def authorized?(actor, subject)
|
84
|
+
result = self.class.policy.new.safe_authorized?(actor, subject)
|
85
|
+
!result[0]
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.policy_keyword
|
89
|
+
keyword = self.policy.policy_keyword.to_s[0..-2]
|
90
|
+
:"not(#{keyword})?"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
clazz.policy = policy
|
95
|
+
clazz
|
96
|
+
end
|
97
|
+
|
98
|
+
def lift_subject(key, policy, &block)
|
99
|
+
clazz = Class.new(Walruz::Policy) do
|
100
|
+
extend PolicyCompositionHelper
|
101
|
+
|
102
|
+
def authorized?(actor, subject)
|
103
|
+
params = self.class.params
|
104
|
+
new_subject = subject.send(params[:key])
|
105
|
+
result = self.class.policy.new.safe_authorized?(actor, new_subject)
|
106
|
+
params[:callback].call(result[0], result[1], actor, subject) if params[:callback]
|
107
|
+
result
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
clazz.policy = policy
|
112
|
+
clazz.set_params(:key => key, :callback => block)
|
113
|
+
clazz
|
114
|
+
end
|
115
|
+
|
116
|
+
module_function(:orP, :andP, :notP, :lift_subject)
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
data/lib/walruz.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Walruz
|
2
|
+
|
3
|
+
class NotAuthorized < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
class AuthorizationActionsNotDefined < Exception
|
7
|
+
end
|
8
|
+
|
9
|
+
class ActionNotFound < Exception
|
10
|
+
|
11
|
+
def initialize(failure, params = {})
|
12
|
+
case failure
|
13
|
+
when :subject_action
|
14
|
+
super("%s class doesn't have an authorization action called :%s nor a :default policy" % [params[:subject].class.name, params[:action]])
|
15
|
+
when :policy_label
|
16
|
+
super("There is no Policy with the label %s" % params[:label])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
base_path = File.dirname(__FILE__)
|
23
|
+
autoload :Actor, base_path + '/walruz/actor'
|
24
|
+
autoload :Subject, base_path + '/walruz/subject'
|
25
|
+
autoload :Policy, base_path + '/walruz/policy'
|
26
|
+
autoload :Utils, base_path + '/walruz/utils'
|
27
|
+
|
28
|
+
def self.setup
|
29
|
+
config = Config.new
|
30
|
+
yield config
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.policies
|
34
|
+
Walruz::Policy.policies
|
35
|
+
end
|
36
|
+
|
37
|
+
class Config
|
38
|
+
|
39
|
+
def actors=(actors)
|
40
|
+
Array(actors).each do |actor|
|
41
|
+
actor.send(:include, Actor)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def subjects=(subjects)
|
46
|
+
Array(subjects).each do |subject|
|
47
|
+
subject.send(:include, Subject)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
data/spec/scenario.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
class Beatle
|
2
|
+
include Walruz::Actor
|
3
|
+
include Walruz::Subject
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
attr_accessor :songs
|
7
|
+
attr_accessor :colaborations
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
@songs = []
|
12
|
+
@colaborations = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def sing_the_song(song)
|
16
|
+
response = can!(:sing, song)
|
17
|
+
case response[:owner]
|
18
|
+
when Colaboration
|
19
|
+
authors = response[:owner].authors.dup
|
20
|
+
authors.delete(self)
|
21
|
+
authors.map! { |author| author.name }
|
22
|
+
"I need %s to play this song properly" % authors.join(', ')
|
23
|
+
when Beatle
|
24
|
+
"I just need myself, Let's Rock! \\m/"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def sing_with_john(song)
|
29
|
+
can!(:sing_with_john, song)
|
30
|
+
"Ok John, Let's Play '%s'" % song.name
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
JOHN = self.new("John")
|
35
|
+
PAUL = self.new("Paul")
|
36
|
+
RINGO = self.new("Ringo")
|
37
|
+
GEORGE = self.new("George")
|
38
|
+
end
|
39
|
+
|
40
|
+
class Colaboration
|
41
|
+
|
42
|
+
attr_accessor :authors
|
43
|
+
attr_accessor :songs
|
44
|
+
|
45
|
+
def initialize(*authors)
|
46
|
+
authors.each do |author|
|
47
|
+
author.colaborations << self
|
48
|
+
end
|
49
|
+
@authors = authors
|
50
|
+
@songs = []
|
51
|
+
end
|
52
|
+
|
53
|
+
JOHN_PAUL = self.new(Beatle::JOHN, Beatle::PAUL)
|
54
|
+
JOHN_PAUL_GEORGE = self.new(Beatle::JOHN, Beatle::PAUL, Beatle::GEORGE)
|
55
|
+
JOHN_GEORGE = self.new(Beatle::JOHN, Beatle::GEORGE)
|
56
|
+
end
|
57
|
+
|
58
|
+
class SubjectIsActorPolicy < Walruz::Policy
|
59
|
+
|
60
|
+
def authorized?(actor, subject)
|
61
|
+
actor == subject
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
# class AuthorPolicy < Walruz::Policy
|
67
|
+
#
|
68
|
+
# def authorized?(beatle, song)
|
69
|
+
# if song.author == beatle
|
70
|
+
# [true, { :owner => beatle }]
|
71
|
+
# else
|
72
|
+
# false
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# end
|
77
|
+
|
78
|
+
AuthorPolicy = Walruz::Utils.lift_subject(:author, SubjectIsActorPolicy) do |authorized, params, actor, subject|
|
79
|
+
params.merge!(:owner => actor) if authorized
|
80
|
+
end
|
81
|
+
|
82
|
+
class AuthorInColaborationPolicy < Walruz::Policy
|
83
|
+
|
84
|
+
def authorized?(beatle, song)
|
85
|
+
return false unless song.colaboration
|
86
|
+
if song.colaboration.authors.include?(beatle)
|
87
|
+
[true, { :owner => song.colaboration }]
|
88
|
+
else
|
89
|
+
false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
class ColaboratingWithJohnPolicy < Walruz::Policy
|
96
|
+
depends_on AuthorInColaborationPolicy
|
97
|
+
|
98
|
+
def authorized?(beatle, song)
|
99
|
+
params[:owner].authors.include?(Beatle::JOHN)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
class Song
|
105
|
+
include Walruz::Subject
|
106
|
+
extend Walruz::Utils
|
107
|
+
|
108
|
+
check_authorizations :sing => orP(AuthorPolicy, AuthorInColaborationPolicy),
|
109
|
+
:sell => andP(AuthorPolicy, notP(AuthorInColaborationPolicy)),
|
110
|
+
:sing_with_john => ColaboratingWithJohnPolicy
|
111
|
+
attr_accessor :name
|
112
|
+
attr_accessor :colaboration
|
113
|
+
attr_accessor :author
|
114
|
+
|
115
|
+
def initialize(name, owner)
|
116
|
+
@name = name
|
117
|
+
case owner
|
118
|
+
when Colaboration
|
119
|
+
@colaboration = owner
|
120
|
+
when Beatle
|
121
|
+
@author = owner
|
122
|
+
end
|
123
|
+
owner.songs << self
|
124
|
+
end
|
125
|
+
|
126
|
+
A_DAY_IN_LIFE = self.new("A Day In Life", Colaboration::JOHN_PAUL)
|
127
|
+
YELLOW_SUBMARINE = self.new("Yellow Submarine", Colaboration::JOHN_PAUL)
|
128
|
+
TAXMAN = self.new("Taxman", Colaboration::JOHN_GEORGE)
|
129
|
+
YESTERDAY = self.new("Yesterday", Beatle::PAUL)
|
130
|
+
ALL_YOU_NEED_IS_LOVE = self.new("All You Need Is Love", Beatle::JOHN)
|
131
|
+
BLUE_JAY_WAY = self.new("Blue Jay Way", Beatle::GEORGE)
|
132
|
+
end
|
133
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
require 'walruz'
|
8
|
+
require File.dirname(__FILE__) + '/scenario'
|
9
|
+
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe 'Walruz::Actor' do
|
4
|
+
|
5
|
+
it "should add an instance method `can!` to included classes" do
|
6
|
+
Beatle::JOHN.should respond_to(:can!)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add an instance method `can?` to included classes" do
|
10
|
+
Beatle::JOHN.should respond_to(:can?)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should add an instance method `satisfies?` to included classes" do
|
14
|
+
Beatle::JOHN.should respond_to(:satisfies?)
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
describe "can!" do
|
19
|
+
|
20
|
+
it "should raise a Walruz::NotAuthorized error when the actor is not authorized" do
|
21
|
+
lambda do
|
22
|
+
Beatle::RINGO.sing_the_song(Song::ALL_YOU_NEED_IS_LOVE)
|
23
|
+
end.should raise_error(Walruz::NotAuthorized)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not raise a Walruz::NotAuthorized error when the actor is authorized" do
|
27
|
+
lambda do
|
28
|
+
Beatle::JOHN.sing_the_song(Song::ALL_YOU_NEED_IS_LOVE)
|
29
|
+
end.should_not raise_error(Walruz::NotAuthorized)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should provide parameteres for the invokator correctly" do
|
33
|
+
Beatle::JOHN.sing_the_song(Song::ALL_YOU_NEED_IS_LOVE).should == "I just need myself, Let's Rock! \\m/"
|
34
|
+
Beatle::JOHN.sing_the_song(Song::YELLOW_SUBMARINE).should == "I need Paul to play this song properly"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#can?' do
|
40
|
+
|
41
|
+
it "should be invoked only the first time and then return a cached solution" do
|
42
|
+
Song::ALL_YOU_NEED_IS_LOVE.should_receive(:can_be?).once.and_return([true, {}])
|
43
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE)
|
44
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @deprecated functionality
|
48
|
+
# WHY: When you execute `can?` you should probably have already executed `can!`
|
49
|
+
# it "should execute a given block if the condition is true" do
|
50
|
+
# proc_called = lambda { raise "Is being called" }
|
51
|
+
# lambda do
|
52
|
+
# Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, &proc_called)
|
53
|
+
# end.should raise_error
|
54
|
+
# end
|
55
|
+
|
56
|
+
it "if a boolean third parameter is received it should not use the cached result" do
|
57
|
+
Beatle::JOHN.stub!(:can_without_caching?).and_return(true)
|
58
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE).should be_true
|
59
|
+
|
60
|
+
Beatle::JOHN.stub!(:can_without_caching?).and_return(false)
|
61
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE).should be_true
|
62
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, true).should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should receive at least 2 parameters" do
|
66
|
+
lambda do
|
67
|
+
Beatle::JOHN.can?(:sing)
|
68
|
+
end.should raise_error(ArgumentError)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should receive at most 3 parameters" do
|
72
|
+
lambda do
|
73
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, true, false)
|
74
|
+
end.should raise_error(ArgumentError)
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
it "should execute a given block that receives a hash of return parameters of the policy" do
|
79
|
+
proc_called = lambda do |params|
|
80
|
+
params.should_not be_nil
|
81
|
+
params.should be_kind_of(Hash)
|
82
|
+
params[:author_policy?].should be_true
|
83
|
+
end
|
84
|
+
Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, &proc_called)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#satisfies?' do
|
90
|
+
|
91
|
+
it "should work with the symbol representation of the policy" do
|
92
|
+
Beatle::PAUL.satisfies?(:colaborating_with_john_policy, Song::TAXMAN).should be_false
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should check only the specified policy" do
|
96
|
+
Beatle::PAUL.satisfies?(:colaborating_with_john_policy, Song::TAXMAN).should be_false
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should raise a Walruz::ActionNotFound error if the policy is not found" do
|
100
|
+
lambda do
|
101
|
+
Beatle::GEORGE.satisfies?(:unknown_policy, Song::TAXMAN)
|
102
|
+
end.should raise_error(Walruz::ActionNotFound)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should execute the block if the condition is true" do
|
106
|
+
proc_called = Proc.new { raise "Is being called" }
|
107
|
+
lambda do
|
108
|
+
Beatle::GEORGE.satisfies?(:colaborating_with_john_policy, Song::TAXMAN, &proc_called)
|
109
|
+
end.should raise_error
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should execute the block that receives a hash of return parameters of the policy" do
|
113
|
+
proc_called = lambda do |params|
|
114
|
+
params.should_not be_nil
|
115
|
+
params.should be_kind_of(Hash)
|
116
|
+
params[:author_in_colaboration_policy?].should be_true
|
117
|
+
end
|
118
|
+
Beatle::GEORGE.satisfies?(:colaborating_with_john_policy, Song::TAXMAN, &proc_called)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Walruz::Policy do
|
4
|
+
|
5
|
+
it "should provide the with_actor utility" do
|
6
|
+
AuthorPolicy.should respond_to(:with_actor)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should generate an indicator that the policy was executed after authorization queries" do
|
10
|
+
policy = Beatle::PAUL.can!(:sing, Song::YESTERDAY)
|
11
|
+
policy[:author_policy?].should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a default label" do
|
15
|
+
AuthorPolicy.policy_label.should == :author_policy
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should prioritize a label that is setted over the default one" do
|
19
|
+
AuthorPolicy.set_policy_label :is_author
|
20
|
+
AuthorPolicy.policy_label.should == :is_author
|
21
|
+
AuthorPolicy.set_policy_label(nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise an Walruz::ActionNotFound exception when the action is not specified, and there is no default one" do
|
25
|
+
lambda do
|
26
|
+
Beatle::RINGO.can!(:sing_drunk, Song::TAXMAN)
|
27
|
+
end.should raise_error(Walruz::ActionNotFound)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "when using the #with_actor method" do
|
31
|
+
|
32
|
+
before(:each) do
|
33
|
+
@songs = [Song::A_DAY_IN_LIFE, Song::YELLOW_SUBMARINE, Song::TAXMAN,
|
34
|
+
Song::YESTERDAY, Song::ALL_YOU_NEED_IS_LOVE, Song::BLUE_JAY_WAY]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should work properly" do
|
38
|
+
george_authorship_songs = @songs.select(&AuthorPolicy.with_actor(Beatle::GEORGE))
|
39
|
+
george_authorship_songs.should have(1).song
|
40
|
+
george_authorship_songs.should == [Song::BLUE_JAY_WAY]
|
41
|
+
|
42
|
+
|
43
|
+
john_and_paul_songs = @songs.select(&AuthorInColaborationPolicy.with_actor(Beatle::JOHN))
|
44
|
+
john_and_paul_songs.should have(3).songs
|
45
|
+
john_and_paul_songs.should == [Song::A_DAY_IN_LIFE, Song::YELLOW_SUBMARINE, Song::TAXMAN]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "when using dependence_on macro" do
|
51
|
+
|
52
|
+
it "should work properly" do
|
53
|
+
lambda do
|
54
|
+
Beatle::PAUL.sing_with_john(Song::YESTERDAY)
|
55
|
+
end.should raise_error(Walruz::NotAuthorized)
|
56
|
+
|
57
|
+
Beatle::PAUL.sing_with_john(Song::A_DAY_IN_LIFE).should == "Ok John, Let's Play 'A Day In Life'"
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Walruz::Subject do
|
4
|
+
|
5
|
+
it "should add a can_be? method" do
|
6
|
+
Song::A_DAY_IN_LIFE.should respond_to(:can_be?)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add a class method called check_authorizations" do
|
10
|
+
Song.should respond_to(:check_authorizations)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
describe "when executing validations on an invalid subject" do
|
15
|
+
|
16
|
+
it "should raise an Walruz::AuthorizationActionsNotDefined error" do
|
17
|
+
lambda do
|
18
|
+
Beatle::JOHN.can_be?(:talk_with, Beatle::PAUL)
|
19
|
+
end.should raise_error(Walruz::AuthorizationActionsNotDefined)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Walruz::Utils do
|
4
|
+
|
5
|
+
def check_actor_can_on_subject(label, actor, subject)
|
6
|
+
lambda do
|
7
|
+
actor.can!(label, subject)
|
8
|
+
end.should_not raise_error(Walruz::NotAuthorized)
|
9
|
+
end
|
10
|
+
|
11
|
+
def check_actor_can_not_on_subject(label, actor, subject)
|
12
|
+
lambda do
|
13
|
+
actor.can!(label, subject)
|
14
|
+
end.should raise_error(Walruz::NotAuthorized)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when using combinators `orP`, `andP` or `notP`" do
|
18
|
+
|
19
|
+
it "should work properly" do
|
20
|
+
check_actor_can_not_on_subject(:sell, Beatle::JOHN, Song::A_DAY_IN_LIFE)
|
21
|
+
check_actor_can_on_subject(:sell, Beatle::JOHN, Song::ALL_YOU_NEED_IS_LOVE)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when using andP" do
|
27
|
+
|
28
|
+
it "should return as policy keyword, the name of the original policies keywords concatenated with `_and_`" do
|
29
|
+
Beatle::JOHN.can?(:sell, Song::ALL_YOU_NEED_IS_LOVE) do |policy_params|
|
30
|
+
policy_params[:"author_policy_and_not(author_in_colaboration_policy)?"].should be_true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "when using notP" do
|
37
|
+
|
38
|
+
it "should return as policy keyword, the name of the original policy keyword with a `not()` around" do
|
39
|
+
Beatle::JOHN.can?(:sell, Song::ALL_YOU_NEED_IS_LOVE) do |policy_params|
|
40
|
+
policy_params[:"not(author_in_colaboration_policy)?"].should be_true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Walruz do
|
4
|
+
|
5
|
+
it "should have a policies method" do
|
6
|
+
Walruz.should respond_to(:policies)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#policies' do
|
10
|
+
|
11
|
+
it "should return all the policies created that have a label" do
|
12
|
+
Walruz.policies.should_not be_nil
|
13
|
+
Walruz.policies[:author_policy].should be_nil
|
14
|
+
Walruz.policies[:author_in_colaboration_policy].should == AuthorInColaborationPolicy
|
15
|
+
Walruz.policies[:colaborating_with_john_policy].should == ColaboratingWithJohnPolicy
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|