canard 0.4.0.pre → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -8,7 +8,17 @@ group :test do
8
8
  end
9
9
 
10
10
  # for CRuby, Rubinius, including Windows and RubyInstaller
11
- gem "sqlite3", :platform => [:ruby, :mswin, :mingw], :group => [:development, :test]
11
+ group :development, :test do
12
+
13
+ gem 'bson', "~> 1.6.4"
14
+
15
+ platform :ruby, :mswin, :mingw do
16
+ gem "sqlite3"
17
+ gem "bson_ext", "~> 1.6.4"
18
+ end
19
+
20
+ platform :jruby do
21
+ gem 'activerecord-jdbcsqlite3-adapter'
22
+ end
23
+ end
12
24
 
13
- # for JRuby
14
- gem 'activerecord-jdbcsqlite3-adapter', :platform => [:jruby], :group => [:development, :test]
@@ -1,28 +1,28 @@
1
1
  = Canard
2
2
  == Overview
3
- Canard brings CanCan and RoleModel together to make role based authorization in Rails easy. Your ability
4
- definitions gain their own folder and a little structure. The easiest way to get started is with the
3
+ Canard brings CanCan and RoleModel together to make role based authorization in Rails easy. Your ability
4
+ definitions gain their own folder and a little structure. The easiest way to get started is with the
5
5
  Canard generator. Canard progressively enhances the abilities of the model by applying role abilities on
6
6
  top of the models base abilities.
7
7
 
8
8
  A User model with :admin and :manger roles would be defined:
9
9
 
10
10
  class User < ActiveRecord::Base
11
-
11
+
12
12
  acts_as_user :roles => :manager, :admin
13
-
13
+
14
14
  end
15
-
15
+
16
16
  If a User has both the :manager and :admin roles Canard will apply the abilities in the following order.
17
17
  First it will look for a users abilities, then it will look for the roles in the order they are defined e.g.
18
18
 
19
19
  app/abilities/users.rb
20
20
  app/abilities/manager.rb
21
21
  app/abilities/admin.rb
22
-
23
- Therefore each the later abilities only need to build on their predecessors.
24
22
 
25
- == Usage
23
+ Therefore each the later abilities only need to build on their predecessors.
24
+
25
+ == Usage
26
26
  To generate some abilities for the User.
27
27
 
28
28
  $ rails g canard:ability user can:[read,create]:[account,statement] cannot:destroy:account
@@ -40,13 +40,13 @@ Generates an ability folder in Rails root and an associated spec;
40
40
  The resulting app/abilities/users.rb will look something like this;
41
41
 
42
42
  Canard::Abilities.for(:user) do
43
-
43
+
44
44
  can [:read, :create], Account
45
45
  cannot [:destroy], Account
46
46
  can [:read, :create], Statement
47
-
47
+
48
48
  end
49
-
49
+
50
50
  And it's associated test spec/abilities/users_spec.rb;
51
51
 
52
52
  require_relative '../spec_helper'
@@ -99,10 +99,10 @@ loading the ability for the User model and then apply the abilities for each rol
99
99
  If there is no user (i.e. logged out) Canard creates a guest and looks for a guest ability to apply so:
100
100
 
101
101
  $ rails g canard:ability guest can:create:user
102
-
102
+
103
103
  Would generate an ability for a not logged in user to signup.
104
104
 
105
- Obviously the generators are just a starting point and should be used only to get you going. I strongly
105
+ Obviously the generators are just a starting point and should be used only to get you going. I strongly
106
106
  suggest that every new model you create you add to the abilities as the specs are easy to write and CanCan
107
107
  definitions are very clear and simple.
108
108
 
@@ -133,9 +133,49 @@ That's it!
133
133
 
134
134
  === Rails 2.x
135
135
 
136
- Sorry you are out of luck with Rails 2.x Canard has only been written and tested with Rails 3.x. I'll be happy
136
+ Sorry you are out of luck with Rails 2.x Canard has only been written and tested with Rails 3.x. I'll be happy
137
137
  to accept pull requests for tested Rails 2.x updates if anybody is game.
138
138
 
139
+ == Supported ORM's
140
+
141
+ Canard is ORM agnostic. ActiveRecord and Mongoid (thanks David Butler) adapters are currently implemented.
142
+ New adapters can easily be added, but you'd need to check CanCan can also support your adapter.
143
+
144
+ === Further reading
145
+
146
+ Canard stands on the sholders of Ryan Bates' CanCan and Martin Rehfeld's RoleModel. You can read more
147
+ about defining abilities on the CanCan wiki (https://github.com/ryanb/cancan/wiki). Canard implements
148
+ the Ability class for you so you don't need the boilerplate code from Ryan's example;
149
+
150
+ class Ability
151
+ include CanCan::Ability
152
+
153
+ def initialize(user)
154
+ user ||= User.new # guest user (not logged in)
155
+ if user.admin?
156
+ can :manage, :all
157
+ else
158
+ can :read, :all
159
+ end
160
+ end
161
+ end
162
+
163
+ The Canard equivalent for non admins would be;
164
+
165
+ Canard::Abilities.for(:user) do
166
+ can :read, :all
167
+ end
168
+
169
+ And for Admins;
170
+
171
+ Canard::Abilities.for(:admin) do
172
+ can :manage, :all
173
+ end
174
+
175
+ Under the covers Canard uses RoleModel (https://github.com/martinrehfeld/role_model) to define roles. RoleModel
176
+ is based on Ryan Bates' suggested approach to role based authorization which is documented in the CanCan
177
+ wiki (https://github.com/ryanb/cancan/wiki/role-based-authorization).
178
+
139
179
  == Note on Patches/Pull Request
140
180
 
141
181
  * Fork the project.
@@ -152,10 +192,13 @@ to accept pull requests for tested Rails 2.x updates if anybody is game.
152
192
  * James McCarthy
153
193
  * Joey Geiger
154
194
  * Morton Jonuschat
195
+ * David Butler
196
+
197
+ If you feel like contributing there is a TODO list in the root with a few ideas and opportunities!
155
198
 
156
199
  == Credits
157
200
 
158
- Thanks to Ryan Bates for creating the awesome CanCan (http://wiki.github.com/ryanb/cancan)
201
+ Thanks to Ryan Bates for creating the awesome CanCan (http://wiki.github.com/ryanb/cancan)
159
202
  and Martin Rehfeld for implementing Role Based Authorization in the form of RoleModel (http://github.com/martinrehfeld/role_model).
160
203
 
161
204
  == Copyright
data/TODO CHANGED
@@ -1,9 +1,9 @@
1
- 0.4.0
1
+ 0.5.0
2
2
  * Split the test suite so Rails is only required for Rails integration. http://blog.railsware.com/2012/01/07/testing-gem-integration-with-multiple-ruby-frameworks/
3
3
  * Test the railtie (currently implicity tested in dummy app).
4
- 0.5.0
5
4
  * Expand the generated tests to produce all the standard abilities: index,show,read,new,create,edit,update,destroy.
6
5
  * Test the generators.
7
6
  * Add test unit generator.
8
7
  * Add install generator to allow overriding of the default tests.
9
8
  * Make the Ability user referece configureable in Ability.
9
+ * Add DataMapper support.
@@ -21,6 +21,13 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_development_dependency "minitest", "~> 2"
23
23
  s.add_development_dependency "rails", "~> 3.2.3"
24
+
25
+ if RUBY_VERSION < '1.9'
26
+ s.add_development_dependency "mongoid", "~> 2.0"
27
+ else
28
+ s.add_development_dependency "mongoid", "~> 3.0"
29
+ end
30
+
24
31
  s.add_runtime_dependency "cancan"
25
32
  s.add_runtime_dependency "role_model"
26
33
  end
@@ -7,5 +7,3 @@ require "canard/find_abilities"
7
7
  require "ability"
8
8
 
9
9
  require 'canard/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
10
- require 'canard/adapters/active_record' if defined?(ActiveRecord)
11
-
@@ -0,0 +1,43 @@
1
+ module Canard
2
+ module Adapters
3
+ module Mongoid
4
+
5
+ private
6
+
7
+ def add_role_scopes
8
+ valid_roles.each do |role|
9
+ define_scopes_for_role role
10
+ end
11
+
12
+ def with_any_role(*roles)
13
+ where("(this.#{roles_attribute_name} & #{mask_for(*roles)}) > 0")
14
+ end
15
+
16
+ def with_all_roles(*roles)
17
+ where("(this.#{roles_attribute_name} & #{mask_for(*roles)}) === #{mask_for(*roles)}")
18
+ end
19
+
20
+ def with_only_roles(*roles)
21
+ where("this.#{roles_attribute_name} === #{mask_for(*roles)}")
22
+ end
23
+ end
24
+
25
+ def has_roles_mask_accessors?
26
+ fields.include?(roles_attribute_name.to_s) || super
27
+ end
28
+
29
+ def define_scopes_for_role(role)
30
+ include_scope = role.to_s.pluralize
31
+ exclude_scope = "non_#{include_scope}"
32
+
33
+ scope include_scope, where("(this.#{roles_attribute_name} & #{mask_for(role)}) > 0")
34
+ scope exclude_scope, any_of({roles_attribute_name => { "$exists" => false }}, {roles_attribute_name => nil}, {"$where" => "(this.#{roles_attribute_name} & #{mask_for(role)}) === 0"})
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+
41
+ Mongoid::Document::ClassMethods.send :include, Canard::Adapters::Mongoid
42
+ Mongoid::Document::ClassMethods.send :include, Canard::UserModel
43
+ Canard.find_abilities
@@ -14,11 +14,18 @@ module Canard
14
14
 
15
15
  initializer "canard.active_record" do |app|
16
16
  ActiveSupport.on_load :active_record do
17
+ require 'canard/adapters/active_record'
17
18
  Canard::Abilities.default_path = File.expand_path('app/abilities', Rails.root)
18
19
  extend Canard::UserModel
19
20
  Canard.find_abilities
20
21
  end
21
22
  end
23
+
24
+ initializer "canard.mongoid" do |app|
25
+ if defined?(Mongoid)
26
+ require 'canard/adapters/mongoid'
27
+ end
28
+ end
22
29
 
23
30
  initializer "canard.abilities_reloading", :after => "action_dispatch.configure" do |app|
24
31
  if ActionDispatch::Reloader.respond_to?(:to_prepare)
@@ -59,9 +59,15 @@ module Canard
59
59
  def acts_as_user(*args)
60
60
  include RoleModel
61
61
  include InstanceMethods
62
- extend Adapters::ActiveRecord if defined?(ActiveRecord) && self < ActiveRecord::Base
63
-
62
+
64
63
  options = args.last.is_a?(Hash) ? args.pop : {}
64
+
65
+ if defined?(ActiveRecord) && self < ActiveRecord::Base
66
+ extend Adapters::ActiveRecord
67
+ elsif defined?(Mongoid) && self.included_modules.include?(Mongoid::Document)
68
+ extend Adapters::Mongoid
69
+ field (options[:roles_mask] || :roles_mask), :type => Integer
70
+ end
65
71
 
66
72
  roles_attribute options[:roles_mask] if options.has_key?(:roles_mask)
67
73
 
@@ -1,3 +1,3 @@
1
1
  module Canard
2
- VERSION = "0.4.0.pre"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -0,0 +1,444 @@
1
+ require 'test_helper'
2
+ require 'bson'
3
+
4
+ # Make this test compatible with ruby 1.8.7
5
+ begin
6
+ BSON::ObjectId.new <=> BSON::ObjectId.new
7
+ rescue NoMethodError
8
+ class BSON::ObjectId
9
+ def <=>(other)
10
+ self.to_s <=> other.to_s
11
+ end
12
+ end
13
+ end
14
+
15
+ describe Canard::Adapters::Mongoid do
16
+
17
+ describe 'acts_as_user' do
18
+
19
+ describe 'with a role_mask' do
20
+
21
+ describe 'and :roles => [] specified' do
22
+
23
+ it 'sets the valid_roles for the class' do
24
+ MongoidUser.valid_roles.must_equal [:viewer, :author, :admin]
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ describe "scopes" do
34
+
35
+ describe "on an Mongoid model with roles" do
36
+
37
+ before do
38
+ @no_role = MongoidUser.create
39
+ @admin_author_viewer = MongoidUser.create(:roles => [:admin, :author, :viewer])
40
+ @author_viewer = MongoidUser.create(:roles => [:author, :viewer])
41
+ @viewer = MongoidUser.create(:roles => [:viewer])
42
+ @admin_only = MongoidUser.create(:roles => [:admin])
43
+ @author_only = MongoidUser.create(:roles => [:author])
44
+ end
45
+
46
+ after do
47
+ MongoidUser.delete_all
48
+ end
49
+
50
+ subject { MongoidUser }
51
+
52
+ it "adds a scope to return instances with each role" do
53
+ subject.must_respond_to :admins
54
+ subject.must_respond_to :authors
55
+ subject.must_respond_to :viewers
56
+ end
57
+
58
+ it "adds a scope to return instances without each role" do
59
+ subject.must_respond_to :non_admins
60
+ subject.must_respond_to :non_authors
61
+ subject.must_respond_to :non_viewers
62
+ end
63
+
64
+ describe "finding instances with a role" do
65
+
66
+ describe "admins scope" do
67
+
68
+ subject { MongoidUser.admins.sort_by(&:id) }
69
+
70
+ it "returns only admins" do
71
+ subject.must_equal [@admin_author_viewer, @admin_only].sort_by(&:id)
72
+ end
73
+
74
+ it "doesn't return non admins" do
75
+ subject.wont_include @no_role
76
+ subject.wont_include @author_viewer
77
+ subject.wont_include @author_only
78
+ subject.wont_include @viewer
79
+ end
80
+
81
+ end
82
+
83
+ describe "authors scope" do
84
+
85
+ subject { MongoidUser.authors.sort_by(&:id) }
86
+
87
+ it "returns only authors" do
88
+ subject.must_equal [@admin_author_viewer, @author_viewer, @author_only].sort_by(&:id)
89
+ end
90
+
91
+ it "doesn't return non authors" do
92
+ subject.wont_include @no_role
93
+ subject.wont_include @admin_only
94
+ subject.wont_include @viewer
95
+ end
96
+
97
+ end
98
+
99
+ describe "viewers scope" do
100
+
101
+ subject { MongoidUser.viewers.sort_by(&:id) }
102
+
103
+ it "returns only viewers" do
104
+ subject.must_equal [@admin_author_viewer, @author_viewer, @viewer].sort_by(&:id)
105
+ end
106
+
107
+ it "doesn't return non authors" do
108
+ subject.wont_include @no_role
109
+ subject.wont_include @admin_only
110
+ subject.wont_include @author_only
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ describe "finding instances without a role" do
118
+
119
+ describe "non_admins scope" do
120
+
121
+ subject { MongoidUser.non_admins.sort_by(&:id) }
122
+
123
+ it "returns only non_admins" do
124
+ subject.must_equal [@no_role, @author_viewer, @viewer, @author_only].sort_by(&:id)
125
+ end
126
+
127
+ it "doesn't return admins" do
128
+ subject.wont_include @admin_author_viewer
129
+ subject.wont_include @admin_only
130
+ end
131
+
132
+ end
133
+
134
+ describe "non_authors scope" do
135
+
136
+ subject { MongoidUser.non_authors.sort_by(&:id) }
137
+
138
+ it "returns only non_authors" do
139
+ subject.must_equal [@no_role, @viewer, @admin_only].sort_by(&:id)
140
+ end
141
+
142
+ it "doesn't return authors" do
143
+ subject.wont_include @admin_author_viewer
144
+ subject.wont_include @author_viewer
145
+ subject.wont_include @author_only
146
+ end
147
+
148
+ end
149
+
150
+ describe "non_viewers scope" do
151
+
152
+ subject { MongoidUser.non_viewers.sort_by(&:id) }
153
+
154
+ it "returns only non_viewers" do
155
+ subject.must_equal [@no_role, @admin_only, @author_only].sort_by(&:id)
156
+ end
157
+
158
+ it "doesn't return viewers" do
159
+ subject.wont_include @admin_author_viewer
160
+ subject.wont_include @author_viewer
161
+ subject.wont_include @viewer
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+
168
+ describe "with_any_role" do
169
+
170
+ describe "specifying admin only" do
171
+
172
+ subject { MongoidUser.with_any_role(:admin).sort_by(&:id) }
173
+
174
+ it "returns only admins" do
175
+ subject.must_equal [@admin_author_viewer, @admin_only].sort_by(&:id)
176
+ end
177
+
178
+ it "doesn't return non admins" do
179
+ subject.wont_include @no_role
180
+ subject.wont_include @author_viewer
181
+ subject.wont_include @author_only
182
+ subject.wont_include @viewer
183
+ end
184
+
185
+ end
186
+
187
+ describe "specifying author only" do
188
+
189
+ subject { MongoidUser.with_any_role(:author).sort_by(&:id) }
190
+
191
+ it "returns only authors" do
192
+ subject.must_equal [@admin_author_viewer, @author_viewer, @author_only].sort_by(&:id)
193
+ end
194
+
195
+ it "doesn't return non authors" do
196
+ subject.wont_include @no_role
197
+ subject.wont_include @admin_only
198
+ subject.wont_include @viewer
199
+ end
200
+
201
+ end
202
+
203
+ describe "specifying viewer only" do
204
+
205
+ subject { MongoidUser.with_any_role(:viewer).sort_by(&:id) }
206
+
207
+ it "returns only viewers" do
208
+ subject.must_equal [@admin_author_viewer, @author_viewer, @viewer].sort_by(&:id)
209
+ end
210
+
211
+ it "doesn't return non authors" do
212
+ subject.wont_include @no_role
213
+ subject.wont_include @admin_only
214
+ subject.wont_include @author_only
215
+ end
216
+
217
+ end
218
+
219
+ describe "specifying admin and author" do
220
+
221
+ subject { MongoidUser.with_any_role(:admin, :author).sort_by(&:id) }
222
+
223
+ it "returns only admins and authors" do
224
+ subject.must_equal [@admin_author_viewer, @author_viewer, @admin_only, @author_only].sort_by(&:id)
225
+ end
226
+
227
+ it "doesn't return non admins or authors" do
228
+ subject.wont_include @no_role
229
+ subject.wont_include @viewer
230
+ end
231
+
232
+ end
233
+
234
+ describe "specifying admin and viewer" do
235
+
236
+ subject { MongoidUser.with_any_role(:admin, :viewer).sort_by(&:id) }
237
+
238
+ it "returns only admins and viewers" do
239
+ subject.must_equal [@admin_author_viewer, @author_viewer, @admin_only, @viewer].sort_by(&:id)
240
+ end
241
+
242
+ it "doesn't return non admins or viewers" do
243
+ subject.wont_include @no_role
244
+ subject.wont_include @author_only
245
+ end
246
+
247
+ end
248
+
249
+ describe "specifying author and viewer" do
250
+
251
+ subject { MongoidUser.with_any_role(:author, :viewer).sort_by(&:id) }
252
+
253
+ it "returns only authors and viewers" do
254
+ subject.must_equal [@admin_author_viewer, @author_viewer, @author_only, @viewer].sort_by(&:id)
255
+ end
256
+
257
+ it "doesn't return non authors or viewers" do
258
+ subject.wont_include @no_role
259
+ subject.wont_include @admin_only
260
+ end
261
+
262
+ end
263
+
264
+ describe "specifying admin, author and viewer" do
265
+
266
+ subject { MongoidUser.with_any_role(:admin, :author, :viewer).sort_by(&:id) }
267
+
268
+ it "returns only admins, authors and viewers" do
269
+ subject.must_equal [@admin_author_viewer, @author_viewer, @admin_only, @author_only, @viewer].sort_by(&:id)
270
+ end
271
+
272
+ it "doesn't return non admins, authors or viewers" do
273
+ subject.wont_include @no_role
274
+ end
275
+
276
+ end
277
+
278
+ end
279
+
280
+ describe "with_all_roles" do
281
+
282
+ describe "specifying admin only" do
283
+
284
+ subject { MongoidUser.with_all_roles(:admin).sort_by(&:id) }
285
+
286
+ it "returns only admins" do
287
+ subject.must_equal [@admin_author_viewer, @admin_only].sort_by(&:id)
288
+ end
289
+
290
+ it "doesn't return non admins" do
291
+ subject.wont_include @no_role
292
+ subject.wont_include @author_viewer
293
+ subject.wont_include @author_only
294
+ subject.wont_include @viewer
295
+ end
296
+
297
+ end
298
+
299
+ describe "specifying author only" do
300
+
301
+ subject { MongoidUser.with_all_roles(:author).sort_by(&:id) }
302
+
303
+ it "returns only authors" do
304
+ subject.must_equal [@admin_author_viewer, @author_viewer, @author_only].sort_by(&:id)
305
+ end
306
+
307
+ it "doesn't return non authors" do
308
+ subject.wont_include @no_role
309
+ subject.wont_include @admin_only
310
+ subject.wont_include @viewer
311
+ end
312
+
313
+ end
314
+
315
+ describe "specifying viewer only" do
316
+
317
+ subject { MongoidUser.with_all_roles(:viewer).sort_by(&:id) }
318
+
319
+ it "returns only viewers" do
320
+ subject.must_equal [@admin_author_viewer, @author_viewer, @viewer].sort_by(&:id)
321
+ end
322
+
323
+ it "doesn't return non authors" do
324
+ subject.wont_include @no_role
325
+ subject.wont_include @admin_only
326
+ subject.wont_include @author_only
327
+ end
328
+
329
+ end
330
+
331
+ describe "specifying admin and author" do
332
+
333
+ subject { MongoidUser.with_all_roles(:admin, :author).sort_by(&:id) }
334
+
335
+ it "returns only admins and authors" do
336
+ subject.must_equal [@admin_author_viewer].sort_by(&:id)
337
+ end
338
+
339
+ it "doesn't return non admin and authors" do
340
+ subject.wont_include @no_role
341
+ subject.wont_include @author_viewer
342
+ subject.wont_include @author_only
343
+ subject.wont_include @admin_only
344
+ subject.wont_include @viewer
345
+ end
346
+
347
+ end
348
+
349
+ describe "specifying admin and viewer" do
350
+
351
+ subject { MongoidUser.with_all_roles(:admin, :viewer).sort_by(&:id) }
352
+
353
+ it "returns only admins and viewers" do
354
+ subject.must_equal [@admin_author_viewer].sort_by(&:id)
355
+ end
356
+
357
+ it "doesn't return non admins or viewers" do
358
+ subject.wont_include @no_role
359
+ subject.wont_include @author_viewer
360
+ subject.wont_include @author_only
361
+ subject.wont_include @admin_only
362
+ subject.wont_include @viewer
363
+ end
364
+
365
+ end
366
+
367
+ describe "specifying author and viewer" do
368
+
369
+ subject { MongoidUser.with_all_roles(:author, :viewer).sort_by(&:id) }
370
+
371
+ it "returns only authors and viewers" do
372
+ subject.must_equal [@admin_author_viewer, @author_viewer].sort_by(&:id)
373
+ end
374
+
375
+ it "doesn't return non authors or viewers" do
376
+ subject.wont_include @no_role
377
+ subject.wont_include @admin_only
378
+ subject.wont_include @author_only
379
+ subject.wont_include @viewer
380
+ end
381
+
382
+ end
383
+
384
+ describe "specifying admin, author and viewer" do
385
+
386
+ subject { MongoidUser.with_all_roles(:admin, :author, :viewer).sort_by(&:id) }
387
+
388
+ it "returns only admins, authors and viewers" do
389
+ subject.must_equal [@admin_author_viewer].sort_by(&:id)
390
+ end
391
+
392
+ it "doesn't return non admins, authors or viewers" do
393
+ subject.wont_include @no_role
394
+ subject.wont_include @author_viewer
395
+ subject.wont_include @author_only
396
+ subject.wont_include @admin_only
397
+ subject.wont_include @viewer
398
+ end
399
+
400
+ end
401
+
402
+ end
403
+
404
+ describe "with_only_roles" do
405
+
406
+ describe "specifying one role" do
407
+
408
+ subject { MongoidUser.with_only_roles(:admin).sort_by(&:id) }
409
+
410
+ it "returns users with just that role" do
411
+ subject.must_equal [@admin_only].sort_by(&:id)
412
+ end
413
+
414
+ it "doesn't return any other users" do
415
+ subject.wont_include @no_role
416
+ subject.wont_include @admin_author_viewer
417
+ subject.wont_include @author_viewer
418
+ subject.wont_include @author_only
419
+ subject.wont_include @viewer
420
+ end
421
+
422
+ end
423
+
424
+ describe "specifying multiple roles" do
425
+
426
+ subject { MongoidUser.with_only_roles(:author, :viewer).sort_by(&:id) }
427
+
428
+ it "returns only users with no more or less roles" do
429
+ subject.must_equal [@author_viewer].sort_by(&:id)
430
+ end
431
+
432
+ it "doesn't return any other users" do
433
+ subject.wont_include @no_role
434
+ subject.wont_include @admin_author_viewer
435
+ subject.wont_include @admin_only
436
+ subject.wont_include @author_only
437
+ subject.wont_include @viewer
438
+ end
439
+ end
440
+ end
441
+ end
442
+ end
443
+
444
+ end
@@ -0,0 +1,5 @@
1
+ class MongoidUser
2
+ include Mongoid::Document
3
+
4
+ acts_as_user :roles => [:viewer, :author, :admin]
5
+ end
@@ -0,0 +1,9 @@
1
+ development:
2
+ database: canard_development
3
+ host: localhost
4
+ port: 27017
5
+
6
+ test:
7
+ database: canard_test
8
+ host: localhost
9
+ port: 27017
@@ -0,0 +1,13 @@
1
+ development:
2
+ sessions:
3
+ default:
4
+ database: canard_development
5
+ hosts:
6
+ - localhost:27017
7
+
8
+ test:
9
+ sessions:
10
+ default:
11
+ database: canard_test
12
+ hosts:
13
+ - localhost:27017
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -18,6 +17,7 @@ ActiveRecord::Schema.define(:version => 20120430083231) do
18
17
  end
19
18
 
20
19
  create_table "user_without_role_masks", :force => true do |t|
20
+ t.integer "my_roles_mask"
21
21
  end
22
22
 
23
23
  create_table "user_without_roles", :force => true do |t|
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  gem 'minitest'
3
3
  require 'minitest/autorun'
4
4
  require 'active_record'
5
+ require 'mongoid'
5
6
 
6
7
  # Configure Rails Environment
7
8
  environment = ENV["RAILS_ENV"] = 'test'
@@ -20,6 +21,15 @@ ActiveRecord::Base.connection
20
21
  ActiveRecord::Migration.verbose = false
21
22
  ActiveRecord::Migrator.up File.expand_path('db/migrate', rails_root)
22
23
 
24
+ # Load mongoid config
25
+ if Mongoid::VERSION < '3'
26
+ ENV["MONGOID_ENV"] = "test"
27
+ Mongoid.load!(File.expand_path('config/mongoid2.yml', rails_root))
28
+ else
29
+ Mongoid.load!(File.expand_path('config/mongoid3.yml', rails_root), :test)
30
+ end
31
+ Mongoid.logger.level = :info
32
+
23
33
  # Load dummy rails app
24
34
  require File.expand_path('config/environment.rb', rails_root)
25
35
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre
5
- prerelease: 6
4
+ version: 0.4.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - James McCarthy
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-02 00:00:00.000000000 Z
12
+ date: 2012-08-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 3.2.3
46
+ - !ruby/object:Gem::Dependency
47
+ name: mongoid
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: cancan
48
64
  requirement: !ruby/object:Gem::Requirement
@@ -95,6 +111,7 @@ files:
95
111
  - lib/canard.rb
96
112
  - lib/canard/abilities.rb
97
113
  - lib/canard/adapters/active_record.rb
114
+ - lib/canard/adapters/mongoid.rb
98
115
  - lib/canard/find_abilities.rb
99
116
  - lib/canard/railtie.rb
100
117
  - lib/canard/user_model.rb
@@ -110,6 +127,7 @@ files:
110
127
  - test/canard/abilities_test.rb
111
128
  - test/canard/ability_test.rb
112
129
  - test/canard/adapters/active_record_test.rb
130
+ - test/canard/adapters/mongoid_test.rb
113
131
  - test/canard/canard_test.rb
114
132
  - test/canard/find_abilities_test.rb
115
133
  - test/canard/user_model_test.rb
@@ -121,6 +139,7 @@ files:
121
139
  - test/dummy/app/controllers/application_controller.rb
122
140
  - test/dummy/app/models/activity.rb
123
141
  - test/dummy/app/models/member.rb
142
+ - test/dummy/app/models/mongoid_user.rb
124
143
  - test/dummy/app/models/plain_ruby_non_user.rb
125
144
  - test/dummy/app/models/plain_ruby_user.rb
126
145
  - test/dummy/app/models/post.rb
@@ -138,6 +157,8 @@ files:
138
157
  - test/dummy/config/initializers/session_store.rb
139
158
  - test/dummy/config/initializers/wrap_parameters.rb
140
159
  - test/dummy/config/locales/en.yml
160
+ - test/dummy/config/mongoid2.yml
161
+ - test/dummy/config/mongoid3.yml
141
162
  - test/dummy/config/routes.rb
142
163
  - test/dummy/db/migrate/20120430083231_initialize_db.rb
143
164
  - test/dummy/db/schema.rb
@@ -160,9 +181,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
181
  required_rubygems_version: !ruby/object:Gem::Requirement
161
182
  none: false
162
183
  requirements:
163
- - - ! '>'
184
+ - - ! '>='
164
185
  - !ruby/object:Gem::Version
165
- version: 1.3.1
186
+ version: '0'
166
187
  requirements: []
167
188
  rubyforge_project: canard
168
189
  rubygems_version: 1.8.24
@@ -174,6 +195,7 @@ test_files:
174
195
  - test/canard/abilities_test.rb
175
196
  - test/canard/ability_test.rb
176
197
  - test/canard/adapters/active_record_test.rb
198
+ - test/canard/adapters/mongoid_test.rb
177
199
  - test/canard/canard_test.rb
178
200
  - test/canard/find_abilities_test.rb
179
201
  - test/canard/user_model_test.rb
@@ -185,6 +207,7 @@ test_files:
185
207
  - test/dummy/app/controllers/application_controller.rb
186
208
  - test/dummy/app/models/activity.rb
187
209
  - test/dummy/app/models/member.rb
210
+ - test/dummy/app/models/mongoid_user.rb
188
211
  - test/dummy/app/models/plain_ruby_non_user.rb
189
212
  - test/dummy/app/models/plain_ruby_user.rb
190
213
  - test/dummy/app/models/post.rb
@@ -202,6 +225,8 @@ test_files:
202
225
  - test/dummy/config/initializers/session_store.rb
203
226
  - test/dummy/config/initializers/wrap_parameters.rb
204
227
  - test/dummy/config/locales/en.yml
228
+ - test/dummy/config/mongoid2.yml
229
+ - test/dummy/config/mongoid3.yml
205
230
  - test/dummy/config/routes.rb
206
231
  - test/dummy/db/migrate/20120430083231_initialize_db.rb
207
232
  - test/dummy/db/schema.rb