moulin_rouge 0.0.1.beta1 → 0.0.1.beta2
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/CHANGELOG.md +5 -0
- data/MIT-LICENSE +1 -1
- data/README.md +72 -51
- data/lib/generators/moulin_rouge/auth_generator.rb +18 -0
- data/lib/generators/moulin_rouge/install_generator.rb +3 -3
- data/lib/generators/moulin_rouge/templates/authorization.rb +21 -0
- data/lib/generators/moulin_rouge/templates/initializer.rb +14 -0
- data/lib/moulin_rouge.rb +2 -2
- data/lib/moulin_rouge/{permission.rb → ability.rb} +35 -62
- data/lib/moulin_rouge/authorization.rb +46 -0
- data/lib/moulin_rouge/cancan/ability.rb +6 -6
- data/lib/moulin_rouge/version.rb +1 -1
- data/spec/fixtures/fixture_authorization.rb +5 -0
- data/spec/moulin_rouge/ability_spec.rb +229 -0
- data/spec/moulin_rouge/authorization_spec.rb +120 -0
- data/spec/moulin_rouge/cancan/ability_spec.rb +5 -5
- data/spec/moulin_rouge_spec.rb +9 -19
- data/spec/spec_helper.rb +9 -9
- metadata +51 -38
- data/lib/generators/moulin_rouge/permission_generator.rb +0 -18
- data/lib/generators/moulin_rouge/templates/install/config/initializers/moulin_rouge.rb +0 -15
- data/lib/generators/moulin_rouge/templates/permission.rb +0 -19
- data/spec/fixtures/role.rb +0 -3
- data/spec/moulin_rouge/permission_spec.rb +0 -316
@@ -0,0 +1,46 @@
|
|
1
|
+
module MoulinRouge
|
2
|
+
# Creates a common scope to register roles and abilities
|
3
|
+
class Authorization
|
4
|
+
# Avoid direct initialization, just act as a singleton
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Delegates the missing method for the main ability
|
9
|
+
def method_missing(name, *args, &block)
|
10
|
+
main.send(name, *args, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
# The instance of the main ability
|
14
|
+
def main
|
15
|
+
@@main ||= MoulinRouge::Ability.new(:main)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns an array with the name of all roles created
|
19
|
+
def roles
|
20
|
+
@@roles ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns an hash with all permissions defined
|
24
|
+
def abilities
|
25
|
+
@@abilities ||= {}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Register an ability in the singleton
|
29
|
+
def register(instance)
|
30
|
+
name = instance.name
|
31
|
+
self.abilities[name] = instance
|
32
|
+
self.roles << name unless self.roles.include?(name)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Load and initialize all authorization files in the configuration path
|
36
|
+
def compile!
|
37
|
+
Dir[MoulinRouge.configuration.path].each { |file| Kernel.load(file) }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Reset all constants
|
41
|
+
def reset! #:nodoc:
|
42
|
+
@@main, @@roles, @@abilities = nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -9,14 +9,14 @@ module MoulinRouge
|
|
9
9
|
model = MoulinRouge.configuration.model.new if model.nil? and not MoulinRouge.configuration.model.nil?
|
10
10
|
# Reload all permissions if cache is disabled
|
11
11
|
MoulinRouge.reload! unless MoulinRouge.configuration.cache
|
12
|
-
# Set all
|
13
|
-
MoulinRouge::
|
12
|
+
# Set all abilities in main
|
13
|
+
MoulinRouge::Authorization.main.abilities.each do |ability|
|
14
14
|
ability.send_to(self, model)
|
15
15
|
end
|
16
|
-
# Set all
|
17
|
-
MoulinRouge::
|
18
|
-
|
19
|
-
|
16
|
+
# Set all abilities by role
|
17
|
+
MoulinRouge::Authorization.abilities.each do |role, ability|
|
18
|
+
ability.abilities.each do |cancan_ability|
|
19
|
+
cancan_ability.send_to(self, model)
|
20
20
|
end if model.send(MoulinRouge.configuration.test_method, role)
|
21
21
|
end
|
22
22
|
end
|
data/lib/moulin_rouge/version.rb
CHANGED
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoulinRouge::Ability do
|
4
|
+
let(:ability) { MoulinRouge::Ability.new(:name) }
|
5
|
+
|
6
|
+
describe "#initialize" do
|
7
|
+
it "evaluate the groups and authorizations to the class scope" do
|
8
|
+
ability = MoulinRouge::Ability.new(:scope) do
|
9
|
+
self.class.should == MoulinRouge::Ability
|
10
|
+
can :do, :something
|
11
|
+
role :for
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "registers the ability instance into authorization" do
|
16
|
+
MoulinRouge::Authorization.should_receive(:register).at_least(:once)
|
17
|
+
MoulinRouge::Ability.new(:main) do
|
18
|
+
role(:one)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "inherits all abilities from parent if this is a group" do
|
23
|
+
role = nil
|
24
|
+
MoulinRouge::Ability.new(:main) do
|
25
|
+
group(:group) do
|
26
|
+
can :do, :this
|
27
|
+
role = role(:role)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
role.abilities.first.args.should include(:do, :this)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#name" do
|
35
|
+
it "returns the given name on class initialization" do
|
36
|
+
ability.name.should be(:name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#parent" do
|
41
|
+
it "returns nil when for main" do
|
42
|
+
ability.parent.should be_nil
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns a instance of the MoulinRouge::Ability" do
|
46
|
+
another = MoulinRouge::Ability.new(:another, :parent => ability)
|
47
|
+
another.parent.should be_a(MoulinRouge::Ability)
|
48
|
+
another.parent.should be(ability)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#childrens" do
|
53
|
+
it "returns an array" do
|
54
|
+
ability.childrens.should be_an(Array)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#abilities" do
|
59
|
+
it "returns an array" do
|
60
|
+
ability.abilities.should be_a(Array)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#inherithed_abilities" do
|
65
|
+
it "returns all abilities from self and their childrens" do
|
66
|
+
ability.can :do, :this
|
67
|
+
# First nested level
|
68
|
+
one = ability.role(:one) do
|
69
|
+
can :do, :one
|
70
|
+
end
|
71
|
+
# Second nested level
|
72
|
+
two = one.role(:two) do
|
73
|
+
can :do, :two
|
74
|
+
end
|
75
|
+
ability.inherithed_abilities.should be_an(Array)
|
76
|
+
ability.inherithed_abilities.length.should be(3)
|
77
|
+
one.inherithed_abilities.length.should be(2)
|
78
|
+
two.inherithed_abilities.length.should be(1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#role" do
|
83
|
+
it "returns a new ability with the parent setted to the class that are calling" do
|
84
|
+
role = ability.role(:test)
|
85
|
+
role.should be_a(MoulinRouge::Ability)
|
86
|
+
role.parent.should be(ability)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "adds a new instance on children" do
|
90
|
+
ability.childrens.should be_empty
|
91
|
+
ability.role(:name)
|
92
|
+
ability.childrens.should_not be_empty
|
93
|
+
end
|
94
|
+
|
95
|
+
it "appends the content if the name is already present" do
|
96
|
+
ability.role(:test) { can :do, :this }
|
97
|
+
# should create one children ...
|
98
|
+
ability.childrens.length.should be(1)
|
99
|
+
# ... and one ability
|
100
|
+
ability.childrens.first.abilities.length.should be(1)
|
101
|
+
|
102
|
+
ability.role(:test) { can :do, :this }
|
103
|
+
# should not create other children ...
|
104
|
+
ability.childrens.length.should be(1)
|
105
|
+
# ... and append the new ability
|
106
|
+
ability.childrens.first.abilities.length.should be(2)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#group" do
|
111
|
+
it "not add the group name to ability list" do
|
112
|
+
ability.group(:test)
|
113
|
+
MoulinRouge::Authorization.abilities.should_not include(:test)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#group?" do
|
118
|
+
it "returns true if is a group and false otherwise" do
|
119
|
+
role = ability.role(:role)
|
120
|
+
group = ability.group(:group)
|
121
|
+
role.group?.should be_false
|
122
|
+
group.group?.should be_true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#role?" do
|
127
|
+
it "returns true if is a group and false otherwise" do
|
128
|
+
role = ability.role(:role)
|
129
|
+
group = ability.group(:group)
|
130
|
+
role.role?.should be_true
|
131
|
+
group.role?.should be_false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#method_missing" do
|
136
|
+
let(:args) { [:one, :two] }
|
137
|
+
let(:proc) { Proc.new { :block } }
|
138
|
+
|
139
|
+
context "collect all cancan methods and store under abilities" do
|
140
|
+
MoulinRouge::Ability::CANCAN_METHODS.each do |method_name|
|
141
|
+
describe "##{method_name}" do
|
142
|
+
it "adds a new ability to this ability" do
|
143
|
+
ability.abilities.should be_empty
|
144
|
+
ability.send(method_name, *args, &proc)
|
145
|
+
ability.abilities.should_not be_empty
|
146
|
+
end
|
147
|
+
|
148
|
+
it "stores nil on block attribute when no block is given" do
|
149
|
+
ability.send(method_name, *args)
|
150
|
+
ability.abilities.first.block.should be_nil
|
151
|
+
end
|
152
|
+
|
153
|
+
it "stores the method" do
|
154
|
+
ability.abilities.should be_empty
|
155
|
+
ability.send(method_name, *args, &proc)
|
156
|
+
ability.abilities.should_not be_empty
|
157
|
+
|
158
|
+
method = ability.abilities.first
|
159
|
+
method.should be_a(MoulinRouge::CanCan::Method)
|
160
|
+
# Evaluate the class of the arguments and block
|
161
|
+
method.args.should be_a(Array)
|
162
|
+
method.block.should be_a(Proc)
|
163
|
+
# Just check the value
|
164
|
+
method.args.should eq(args)
|
165
|
+
method.block.call.should be(:block)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
it "receives and stores in a proc calls on the model object" do
|
172
|
+
cancan_ability = nil
|
173
|
+
ability.role(:test) do
|
174
|
+
cancan_ability = can :do, :this, :user_id => current_user.id
|
175
|
+
end
|
176
|
+
cancan_ability.args.last[:user_id].should be_a(Proc)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "raise an error if the method is not registered has a cancan method" do
|
180
|
+
lambda { ability.send(:abcdefg, *args, &proc) }.should raise_error(NoMethodError)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#find" do
|
185
|
+
it "returns the instance of the ability if there is children with this name and nil otherwise" do
|
186
|
+
role = ability.role(:test)
|
187
|
+
ability.find(:test).should be(role)
|
188
|
+
ability.find(:bad).should be_nil
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "#name" do
|
193
|
+
it "returns an symbol containing the name with the parents separeted by a underscore" do
|
194
|
+
first_children, second_children = nil
|
195
|
+
MoulinRouge::Ability.new(:main) do
|
196
|
+
first_children = role(:one) do
|
197
|
+
second_children = role(:two)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
first_children.name.should be(:one)
|
201
|
+
second_children.name.should be(:one_two)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#include" do
|
206
|
+
it "appends all childrens and abilities from one object to another" do
|
207
|
+
one, another = nil
|
208
|
+
one = ability.role(:one) do
|
209
|
+
role(:nested)
|
210
|
+
can :do, :something
|
211
|
+
end
|
212
|
+
another = ability.role(:another) do
|
213
|
+
include :one
|
214
|
+
end
|
215
|
+
another.childrens.should_not be_empty
|
216
|
+
another.abilities.should_not be_empty
|
217
|
+
another.childrens.first.singular_name.should be(:nested)
|
218
|
+
another.abilities.first.args.should include(:do, :something)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "raises an error if could not find the requested ability" do
|
222
|
+
lambda {
|
223
|
+
ability.role(:name) do
|
224
|
+
include :not_found
|
225
|
+
end
|
226
|
+
}.should raise_error(MoulinRouge::RoleNotFound)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoulinRouge::Authorization do
|
4
|
+
let(:ability) { MoulinRouge::Ability.new(:name) }
|
5
|
+
|
6
|
+
context "self" do
|
7
|
+
describe "#method_missing" do
|
8
|
+
it "delegates any missing method to the main ability class" do
|
9
|
+
MoulinRouge::Authorization.main.should_receive(:role).with(:test)
|
10
|
+
MoulinRouge::Authorization.main.should_receive(:can).with(:test)
|
11
|
+
MoulinRouge::Authorization.role(:test)
|
12
|
+
MoulinRouge::Authorization.can(:test)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#main" do
|
17
|
+
it "returns the main MoulinRouge::Authorization instance" do
|
18
|
+
MoulinRouge::Authorization.main.should be_instance_of(ability.class)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#roles" do
|
23
|
+
it "returns an array" do
|
24
|
+
MoulinRouge::Authorization.roles.should be_a(Array)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#abilities" do
|
29
|
+
it "returns a hash with all registered roles with assigned abilities" do
|
30
|
+
MoulinRouge::Authorization.abilities.should be_a(Hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "store all abilities instantiated unless the main one" do
|
34
|
+
hello_world = ability.role(:hello_world) do
|
35
|
+
can :do
|
36
|
+
end
|
37
|
+
MoulinRouge::Authorization.abilities[hello_world.name].should be(hello_world)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#register" do
|
42
|
+
it "should append the object instance on Authorization.all and Authorization.names" do
|
43
|
+
object = double(:name => :foo)
|
44
|
+
MoulinRouge::Authorization.abilities.should_receive(:'[]=').with(object.name, object)
|
45
|
+
MoulinRouge::Authorization.roles.should_receive(:'<<').with(object.name)
|
46
|
+
MoulinRouge::Authorization.register(object)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#compile!" do
|
51
|
+
let(:files_loaded) { [] }
|
52
|
+
|
53
|
+
it "load all files in the configuration path" do
|
54
|
+
Kernel.stub(:load) { |file| files_loaded << file }
|
55
|
+
MoulinRouge::Authorization.compile!
|
56
|
+
files_loaded.should include(*Dir[MoulinRouge.configuration.path])
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should load all roles defined into the Authorization abilities" do
|
60
|
+
MoulinRouge::Authorization.roles.should be_empty
|
61
|
+
MoulinRouge::Authorization.compile!
|
62
|
+
MoulinRouge::Authorization.roles.should_not be_empty
|
63
|
+
MoulinRouge::Authorization.roles.should include(:fixture)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "let raise exceptions when there are syntax errors" do
|
67
|
+
tests = []
|
68
|
+
tests << %|
|
69
|
+
# Wrong method name
|
70
|
+
roe :name do
|
71
|
+
end
|
72
|
+
|
|
73
|
+
tests << %|
|
74
|
+
# Wrong method name
|
75
|
+
groups :name do
|
76
|
+
end
|
77
|
+
|
|
78
|
+
tests << %|
|
79
|
+
# Wrong method name
|
80
|
+
cn :
|
81
|
+
|
|
82
|
+
tests << %|
|
83
|
+
# Wrong method name
|
84
|
+
role do
|
85
|
+
end
|
86
|
+
|
|
87
|
+
# Execute them all
|
88
|
+
tests.each do |test|
|
89
|
+
create_authorization test
|
90
|
+
lambda { ability.import(MoulinRouge.configuration.path) }.should raise_error
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#reset!" do
|
96
|
+
it "sets to nil the main, role and abilities instance variables" do
|
97
|
+
# Create some
|
98
|
+
ability.role(:one)
|
99
|
+
ability.role(:two)
|
100
|
+
MoulinRouge::Authorization.abilities.should_not be_empty
|
101
|
+
MoulinRouge::Authorization.roles.should_not be_empty
|
102
|
+
# Apply
|
103
|
+
MoulinRouge::Authorization.reset!
|
104
|
+
# Evaluate constants
|
105
|
+
MoulinRouge::Authorization.class_variable_get(:'@@main').should be_nil
|
106
|
+
MoulinRouge::Authorization.class_variable_get(:'@@abilities').should be_nil
|
107
|
+
MoulinRouge::Authorization.class_variable_get(:'@@roles').should be_nil
|
108
|
+
# Evaluate has arrays
|
109
|
+
MoulinRouge::Authorization.abilities.should be_empty
|
110
|
+
MoulinRouge::Authorization.roles.should be_empty
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#new" do
|
115
|
+
it "raises an error because the class only act as a singleton" do
|
116
|
+
lambda { MoulinRouge::Authorization.new }.should raise_error(NoMethodError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -4,7 +4,7 @@ describe MoulinRouge::CanCan::Ability do
|
|
4
4
|
let(:test_method) { MoulinRouge.configuration.test_method.to_sym }
|
5
5
|
let(:model) { double("model", test_method => true) }
|
6
6
|
let(:ability) { MoulinRouge::CanCan::Ability.new(model) }
|
7
|
-
let(:permission) { MoulinRouge::
|
7
|
+
let(:permission) { MoulinRouge::Authorization.main }
|
8
8
|
|
9
9
|
before(:each) do
|
10
10
|
MoulinRouge::CanCan::Ability.any_instance.stub(:can) { true }
|
@@ -56,7 +56,7 @@ describe MoulinRouge::CanCan::Ability do
|
|
56
56
|
|
57
57
|
it "executes the can method with exactly the same arguments and block that was stored" do
|
58
58
|
# Concat permissions from main and from all defined classes
|
59
|
-
abilities = permission.abilities + MoulinRouge::
|
59
|
+
abilities = permission.abilities + MoulinRouge::Authorization.abilities.values.map(&:abilities)
|
60
60
|
abilities.flatten.each do |ability|
|
61
61
|
MoulinRouge::CanCan::Ability.any_instance.should_receive(:can).with(*ability.args, &ability.block).at_least(:once)
|
62
62
|
end
|
@@ -65,7 +65,7 @@ describe MoulinRouge::CanCan::Ability do
|
|
65
65
|
|
66
66
|
it "reloads all permissions when cache is set to false" do
|
67
67
|
MoulinRouge.configuration.cache = false
|
68
|
-
MoulinRouge.should_receive(:reload!).
|
68
|
+
MoulinRouge.should_receive(:reload!).twice # Here and inside spec_helpe.rb before(:each)
|
69
69
|
ability # Execute
|
70
70
|
end
|
71
71
|
|
@@ -79,9 +79,9 @@ describe MoulinRouge::CanCan::Ability do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
it "executes any proc on the model object" do
|
82
|
-
MoulinRouge::
|
82
|
+
MoulinRouge::Authorization.reset!
|
83
83
|
####
|
84
|
-
MoulinRouge::
|
84
|
+
MoulinRouge::Authorization.main.can(:do, :this, :user_id => MoulinRouge::ModelDouble.new.id)
|
85
85
|
model.should_receive(:id)
|
86
86
|
ability # Execute
|
87
87
|
end
|