walruz 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|