canard 0.4.0.pre → 0.4.0
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/Gemfile +13 -3
- data/README.rdoc +58 -15
- data/TODO +2 -2
- data/canard.gemspec +7 -0
- data/lib/canard.rb +0 -2
- data/lib/canard/adapters/mongoid.rb +43 -0
- data/lib/canard/railtie.rb +7 -0
- data/lib/canard/user_model.rb +8 -2
- data/lib/canard/version.rb +1 -1
- data/test/canard/adapters/mongoid_test.rb +444 -0
- data/test/dummy/app/models/mongoid_user.rb +5 -0
- data/test/dummy/config/mongoid2.yml +9 -0
- data/test/dummy/config/mongoid3.yml +13 -0
- data/test/dummy/db/schema.rb +1 -1
- data/test/test_helper.rb +10 -0
- metadata +30 -5
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
|
-
|
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]
|
data/README.rdoc
CHANGED
@@ -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
|
-
|
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.
|
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.
|
data/canard.gemspec
CHANGED
@@ -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
|
data/lib/canard.rb
CHANGED
@@ -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
|
data/lib/canard/railtie.rb
CHANGED
@@ -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)
|
data/lib/canard/user_model.rb
CHANGED
@@ -59,9 +59,15 @@ module Canard
|
|
59
59
|
def acts_as_user(*args)
|
60
60
|
include RoleModel
|
61
61
|
include InstanceMethods
|
62
|
-
|
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
|
|
data/lib/canard/version.rb
CHANGED
@@ -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
|
data/test/dummy/db/schema.rb
CHANGED
@@ -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|
|
data/test/test_helper.rb
CHANGED
@@ -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
|
5
|
-
prerelease:
|
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-
|
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:
|
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
|