cancancan 1.11.0 → 2.3.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.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/cancancan.gemspec +15 -19
  3. data/lib/cancan/ability/actions.rb +91 -0
  4. data/lib/cancan/ability/rules.rb +85 -0
  5. data/lib/cancan/ability.rb +74 -136
  6. data/lib/cancan/conditions_matcher.rb +93 -0
  7. data/lib/cancan/controller_additions.rb +34 -40
  8. data/lib/cancan/controller_resource.rb +47 -212
  9. data/lib/cancan/controller_resource_builder.rb +24 -0
  10. data/lib/cancan/controller_resource_finder.rb +40 -0
  11. data/lib/cancan/controller_resource_loader.rb +116 -0
  12. data/lib/cancan/controller_resource_name_finder.rb +21 -0
  13. data/lib/cancan/controller_resource_sanitizer.rb +30 -0
  14. data/lib/cancan/exceptions.rb +7 -3
  15. data/lib/cancan/matchers.rb +12 -3
  16. data/lib/cancan/model_adapters/abstract_adapter.rb +8 -8
  17. data/lib/cancan/model_adapters/active_record_4_adapter.rb +33 -10
  18. data/lib/cancan/model_adapters/active_record_5_adapter.rb +70 -0
  19. data/lib/cancan/model_adapters/active_record_adapter.rb +41 -81
  20. data/lib/cancan/model_adapters/can_can/model_adapters/active_record_adapter/joins.rb +39 -0
  21. data/lib/cancan/model_adapters/conditions_extractor.rb +75 -0
  22. data/lib/cancan/model_additions.rb +0 -1
  23. data/lib/cancan/rule.rb +36 -92
  24. data/lib/cancan/rules_compressor.rb +20 -0
  25. data/lib/cancan/version.rb +1 -1
  26. data/lib/cancan.rb +5 -12
  27. data/lib/generators/cancan/ability/ability_generator.rb +1 -1
  28. metadata +54 -65
  29. data/.gitignore +0 -15
  30. data/.rspec +0 -1
  31. data/.travis.yml +0 -55
  32. data/Appraisals +0 -136
  33. data/CHANGELOG.rdoc +0 -503
  34. data/CONTRIBUTING.md +0 -23
  35. data/Gemfile +0 -3
  36. data/LICENSE +0 -22
  37. data/README.md +0 -188
  38. data/Rakefile +0 -9
  39. data/gemfiles/activerecord_3.0.gemfile +0 -18
  40. data/gemfiles/activerecord_3.1.gemfile +0 -20
  41. data/gemfiles/activerecord_3.2.gemfile +0 -20
  42. data/gemfiles/activerecord_4.0.gemfile +0 -17
  43. data/gemfiles/activerecord_4.1.gemfile +0 -17
  44. data/gemfiles/activerecord_4.2.gemfile +0 -18
  45. data/gemfiles/datamapper_1.x.gemfile +0 -14
  46. data/gemfiles/mongoid_2.x.gemfile +0 -20
  47. data/gemfiles/sequel_3.x.gemfile +0 -20
  48. data/lib/cancan/inherited_resource.rb +0 -20
  49. data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -47
  50. data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
  51. data/lib/cancan/model_adapters/mongoid_adapter.rb +0 -54
  52. data/lib/cancan/model_adapters/sequel_adapter.rb +0 -87
  53. data/spec/README.rdoc +0 -27
  54. data/spec/cancan/ability_spec.rb +0 -487
  55. data/spec/cancan/controller_additions_spec.rb +0 -141
  56. data/spec/cancan/controller_resource_spec.rb +0 -632
  57. data/spec/cancan/exceptions_spec.rb +0 -58
  58. data/spec/cancan/inherited_resource_spec.rb +0 -71
  59. data/spec/cancan/matchers_spec.rb +0 -29
  60. data/spec/cancan/model_adapters/active_record_4_adapter_spec.rb +0 -85
  61. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -446
  62. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
  63. data/spec/cancan/model_adapters/default_adapter_spec.rb +0 -7
  64. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +0 -227
  65. data/spec/cancan/model_adapters/sequel_adapter_spec.rb +0 -132
  66. data/spec/cancan/rule_spec.rb +0 -52
  67. data/spec/matchers.rb +0 -13
  68. data/spec/spec.opts +0 -2
  69. data/spec/spec_helper.rb +0 -28
  70. data/spec/support/ability.rb +0 -7
@@ -1,71 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe CanCan::InheritedResource do
4
- let(:ability) { Ability.new(nil) }
5
- let(:params) { HashWithIndifferentAccess.new(:controller => "models") }
6
- let(:controller_class) { Class.new }
7
- let(:controller) { controller_class.new }
8
-
9
- before(:each) do
10
- class Model
11
- attr_accessor :name
12
-
13
- def initialize(attributes={})
14
- attributes.each do |attribute, value|
15
- send("#{attribute}=", value)
16
- end
17
- end
18
- end
19
-
20
- allow(controller).to receive(:params) { params }
21
- allow(controller).to receive(:current_ability) { ability }
22
- allow(controller_class).to receive(:cancan_skipper) { {:authorize => {}, :load => {}} }
23
- end
24
-
25
- it "show loads resource through controller.resource" do
26
- params.merge!(:action => "show", :id => 123)
27
- allow(controller).to receive(:resource) { :model_resource }
28
- CanCan::InheritedResource.new(controller).load_resource
29
- expect(controller.instance_variable_get(:@model)).to eq(:model_resource)
30
- end
31
-
32
- it "new loads through controller.build_resource" do
33
- params[:action] = "new"
34
- allow(controller).to receive(:build_resource) { :model_resource }
35
- CanCan::InheritedResource.new(controller).load_resource
36
- expect(controller.instance_variable_get(:@model)).to eq(:model_resource)
37
- end
38
-
39
- it "index loads through controller.association_chain when parent" do
40
- params[:action] = "index"
41
- allow(controller).to receive(:association_chain) { controller.instance_variable_set(:@model, :model_resource) }
42
- CanCan::InheritedResource.new(controller, :parent => true).load_resource
43
- expect(controller.instance_variable_get(:@model)).to eq(:model_resource)
44
- end
45
-
46
- it "index loads through controller.end_of_association_chain" do
47
- params[:action] = "index"
48
- allow(Model).to receive(:accessible_by).with(ability, :index) { :projects }
49
- allow(controller).to receive(:end_of_association_chain) { Model }
50
- CanCan::InheritedResource.new(controller).load_resource
51
- expect(controller.instance_variable_get(:@models)).to eq(:projects)
52
- end
53
-
54
- it "builds a new resource with attributes from current ability" do
55
- params[:action] = "new"
56
- ability.can(:create, Model, :name => "from conditions")
57
- allow(controller).to receive(:build_resource) { Struct.new(:name).new }
58
- resource = CanCan::InheritedResource.new(controller)
59
- resource.load_resource
60
- expect(controller.instance_variable_get(:@model).name).to eq("from conditions")
61
- end
62
-
63
- it "overrides initial attributes with params" do
64
- params.merge!(:action => "new", :model => {:name => "from params"})
65
- ability.can(:create, Model, :name => "from conditions")
66
- allow(controller).to receive(:build_resource) { Struct.new(:name).new }
67
- resource = CanCan::ControllerResource.new(controller)
68
- resource.load_resource
69
- expect(controller.instance_variable_get(:@model).name).to eq("from params")
70
- end
71
- end
@@ -1,29 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe "be_able_to" do
4
- it "delegates to can?" do
5
- expect(object = double).to receive(:can?).with(:read, 123) { true }
6
- expect(object).to be_able_to(:read, 123)
7
- end
8
-
9
- it "reports a nice failure message for should" do
10
- expect(object = double).to receive(:can?).with(:read, 123) { false }
11
- expect {
12
- expect(object).to be_able_to(:read, 123)
13
- }.to raise_error('expected to be able to :read 123')
14
- end
15
-
16
- it "reports a nice failure message for should not" do
17
- expect(object = double).to receive(:can?).with(:read, 123) { true }
18
- expect {
19
- expect(object).to_not be_able_to(:read, 123)
20
- }.to raise_error('expected not to be able to :read 123')
21
- end
22
-
23
- it "delegates additional arguments to can? and reports in failure message" do
24
- expect(object = double).to receive(:can?).with(:read, 123, 456) { false }
25
- expect {
26
- expect(object).to be_able_to(:read, 123, 456)
27
- }.to raise_error('expected to be able to :read 123 456')
28
- end
29
- end
@@ -1,85 +0,0 @@
1
- require "spec_helper"
2
-
3
- if defined? CanCan::ModelAdapters::ActiveRecord4Adapter
4
- describe CanCan::ModelAdapters::ActiveRecord4Adapter do
5
- context 'with sqlite3' do
6
- before :each do
7
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
8
- ActiveRecord::Migration.verbose = false
9
- ActiveRecord::Schema.define do
10
- create_table(:parents) do |t|
11
- t.timestamps :null => false
12
- end
13
-
14
- create_table(:children) do |t|
15
- t.timestamps :null => false
16
- t.integer :parent_id
17
- end
18
- end
19
-
20
- class Parent < ActiveRecord::Base
21
- has_many :children, lambda { order(:id => :desc) }
22
- end
23
-
24
- class Child < ActiveRecord::Base
25
- belongs_to :parent
26
- end
27
-
28
- (@ability = double).extend(CanCan::Ability)
29
- end
30
-
31
- it "respects scope on included associations" do
32
- @ability.can :read, [Parent, Child]
33
-
34
- parent = Parent.create!
35
- child1 = Child.create!(:parent => parent, :created_at => 1.hours.ago)
36
- child2 = Child.create!(:parent => parent, :created_at => 2.hours.ago)
37
-
38
- expect(Parent.accessible_by(@ability).order(:created_at => :asc).includes(:children).first.children).to eq [child2, child1]
39
- end
40
- end
41
-
42
- if Gem::Specification.find_all_by_name('pg').any?
43
- context 'with postgresql' do
44
- before :each do
45
- ActiveRecord::Base.establish_connection(:adapter => "postgresql", :database => "postgres", :schema_search_path => 'public')
46
- ActiveRecord::Base.connection.drop_database('cancan_postgresql_spec')
47
- ActiveRecord::Base.connection.create_database 'cancan_postgresql_spec', 'encoding' => 'utf-8', 'adapter' => 'postgresql'
48
- ActiveRecord::Base.establish_connection(:adapter => "postgresql", :database => "cancan_postgresql_spec")
49
- ActiveRecord::Migration.verbose = false
50
- ActiveRecord::Schema.define do
51
- create_table(:parents) do |t|
52
- t.timestamps :null => false
53
- end
54
-
55
- create_table(:children) do |t|
56
- t.timestamps :null => false
57
- t.integer :parent_id
58
- end
59
- end
60
-
61
- class Parent < ActiveRecord::Base
62
- has_many :children, lambda { order(:id => :desc) }
63
- end
64
-
65
- class Child < ActiveRecord::Base
66
- belongs_to :parent
67
- end
68
-
69
- (@ability = double).extend(CanCan::Ability)
70
- end
71
-
72
- it "allows overlapping conditions in SQL and merge with hash conditions" do
73
- @ability.can :read, Parent, :children => {:parent_id => 1}
74
- @ability.can :read, Parent, :children => {:parent_id => 1}
75
-
76
- parent = Parent.create!
77
- child1 = Child.create!(:parent => parent, :created_at => 1.hours.ago)
78
- child2 = Child.create!(:parent => parent, :created_at => 2.hours.ago)
79
-
80
- expect(Parent.accessible_by(@ability)).to eq([parent])
81
- end
82
- end
83
- end
84
- end
85
- end
@@ -1,446 +0,0 @@
1
- require "spec_helper"
2
-
3
- if defined? CanCan::ModelAdapters::ActiveRecordAdapter
4
-
5
- describe CanCan::ModelAdapters::ActiveRecordAdapter do
6
-
7
- before :each do
8
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
- ActiveRecord::Migration.verbose = false
10
- ActiveRecord::Schema.define do
11
- create_table(:categories) do |t|
12
- t.string :name
13
- t.boolean :visible
14
- t.timestamps :null => false
15
- end
16
-
17
- create_table(:projects) do |t|
18
- t.string :name
19
- t.timestamps :null => false
20
- end
21
-
22
- create_table(:articles) do |t|
23
- t.string :name
24
- t.timestamps :null => false
25
- t.boolean :published
26
- t.boolean :secret
27
- t.integer :priority
28
- t.integer :category_id
29
- t.integer :user_id
30
- end
31
-
32
- create_table(:comments) do |t|
33
- t.boolean :spam
34
- t.integer :article_id
35
- t.timestamps :null => false
36
- end
37
-
38
- create_table(:legacy_mentions) do |t|
39
- t.integer :user_id
40
- t.integer :article_id
41
- t.timestamps :null => false
42
- end
43
-
44
- create_table(:users) do |t|
45
- t.timestamps :null => false
46
- end
47
- end
48
-
49
- class Project < ActiveRecord::Base
50
- end
51
-
52
- class Category < ActiveRecord::Base
53
- has_many :articles
54
- end
55
-
56
- class Article < ActiveRecord::Base
57
- belongs_to :category
58
- has_many :comments
59
- has_many :mentions
60
- has_many :mentioned_users, :through => :mentions, :source => :user
61
- belongs_to :user
62
- end
63
-
64
- class Mention < ActiveRecord::Base
65
- self.table_name = 'legacy_mentions'
66
- belongs_to :user
67
- belongs_to :article
68
- end
69
-
70
- class Comment < ActiveRecord::Base
71
- belongs_to :article
72
- end
73
-
74
- class User < ActiveRecord::Base
75
- has_many :articles
76
- end
77
-
78
- (@ability = double).extend(CanCan::Ability)
79
- @article_table = Article.table_name
80
- @comment_table = Comment.table_name
81
- end
82
-
83
- it "is for only active record classes" do
84
- if ActiveRecord.respond_to?(:version) &&
85
- ActiveRecord.version > Gem::Version.new("4")
86
- expect(CanCan::ModelAdapters::ActiveRecord4Adapter).to_not be_for_class(Object)
87
- expect(CanCan::ModelAdapters::ActiveRecord4Adapter).to be_for_class(Article)
88
- expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)).to eq(CanCan::ModelAdapters::ActiveRecord4Adapter)
89
- else
90
- expect(CanCan::ModelAdapters::ActiveRecord3Adapter).to_not be_for_class(Object)
91
- expect(CanCan::ModelAdapters::ActiveRecord3Adapter).to be_for_class(Article)
92
- expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)).to eq(CanCan::ModelAdapters::ActiveRecord3Adapter)
93
- end
94
- end
95
-
96
- it "finds record" do
97
- article = Article.create!
98
- adapter = CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)
99
- expect(adapter.find(Article, article.id)).to eq(article)
100
- end
101
-
102
- it "does not fetch any records when no abilities are defined" do
103
- Article.create!
104
- expect(Article.accessible_by(@ability)).to be_empty
105
- end
106
-
107
- it "fetches all articles when one can read all" do
108
- @ability.can :read, Article
109
- article = Article.create!
110
- expect(Article.accessible_by(@ability)).to eq([article])
111
- end
112
-
113
- it "fetches only the articles that are published" do
114
- @ability.can :read, Article, :published => true
115
- article1 = Article.create!(:published => true)
116
- article2 = Article.create!(:published => false)
117
- expect(Article.accessible_by(@ability)).to eq([article1])
118
- end
119
-
120
- it "fetches any articles which are published or secret" do
121
- @ability.can :read, Article, :published => true
122
- @ability.can :read, Article, :secret => true
123
- article1 = Article.create!(:published => true, :secret => false)
124
- article2 = Article.create!(:published => true, :secret => true)
125
- article3 = Article.create!(:published => false, :secret => true)
126
- article4 = Article.create!(:published => false, :secret => false)
127
- expect(Article.accessible_by(@ability)).to eq([article1, article2, article3])
128
- end
129
-
130
- it "fetches any articles which we are cited in" do
131
- user = User.create!
132
- cited = Article.create!
133
- not_cited = Article.create!
134
- cited.mentioned_users << user
135
- @ability.can :read, Article, { :mentioned_users => { :id => user.id } }
136
- @ability.can :read, Article, { :mentions => { :user_id => user.id } }
137
- expect(Article.accessible_by(@ability)).to eq([cited])
138
- end
139
-
140
- it "fetches only the articles that are published and not secret" do
141
- @ability.can :read, Article, :published => true
142
- @ability.cannot :read, Article, :secret => true
143
- article1 = Article.create!(:published => true, :secret => false)
144
- article2 = Article.create!(:published => true, :secret => true)
145
- article3 = Article.create!(:published => false, :secret => true)
146
- article4 = Article.create!(:published => false, :secret => false)
147
- expect(Article.accessible_by(@ability)).to eq([article1])
148
- end
149
-
150
- it "only reads comments for articles which are published" do
151
- @ability.can :read, Comment, :article => { :published => true }
152
- comment1 = Comment.create!(:article => Article.create!(:published => true))
153
- comment2 = Comment.create!(:article => Article.create!(:published => false))
154
- expect(Comment.accessible_by(@ability)).to eq([comment1])
155
- end
156
-
157
- it "should only read articles which are published or in visible categories" do
158
- @ability.can :read, Article, :category => { :visible => true }
159
- @ability.can :read, Article, :published => true
160
- article1 = Article.create!(:published => true)
161
- article2 = Article.create!(:published => false)
162
- article3 = Article.create!(:published => false, :category => Category.create!(:visible => true))
163
- expect(Article.accessible_by(@ability)).to eq([article1, article3])
164
- end
165
-
166
- it "should only read categories once even if they have multiple articles" do
167
- @ability.can :read, Category, :articles => { :published => true }
168
- @ability.can :read, Article, :published => true
169
- category = Category.create!
170
- Article.create!(:published => true, :category => category)
171
- Article.create!(:published => true, :category => category)
172
- expect(Category.accessible_by(@ability)).to eq([category])
173
- end
174
-
175
- it "only reads comments for visible categories through articles" do
176
- @ability.can :read, Comment, :article => { :category => { :visible => true } }
177
- comment1 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => true)))
178
- comment2 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => false)))
179
- expect(Comment.accessible_by(@ability)).to eq([comment1])
180
- end
181
-
182
- it "allows conditions in SQL and merge with hash conditions" do
183
- @ability.can :read, Article, :published => true
184
- @ability.can :read, Article, ["secret=?", true]
185
- article1 = Article.create!(:published => true, :secret => false)
186
- article2 = Article.create!(:published => true, :secret => true)
187
- article3 = Article.create!(:published => false, :secret => true)
188
- article4 = Article.create!(:published => false, :secret => false)
189
- expect(Article.accessible_by(@ability)).to eq([article1, article2, article3])
190
- end
191
-
192
- it "allows a scope for conditions" do
193
- @ability.can :read, Article, Article.where(:secret => true)
194
- article1 = Article.create!(:secret => true)
195
- article2 = Article.create!(:secret => false)
196
- expect(Article.accessible_by(@ability)).to eq([article1])
197
- end
198
-
199
- it "fetches only associated records when using with a scope for conditions" do
200
- @ability.can :read, Article, Article.where(:secret => true)
201
- category1 = Category.create!(:visible => false)
202
- category2 = Category.create!(:visible => true)
203
- article1 = Article.create!(:secret => true, :category => category1)
204
- article2 = Article.create!(:secret => true, :category => category2)
205
- expect(category1.articles.accessible_by(@ability)).to eq([article1])
206
- end
207
-
208
- it "raises an exception when trying to merge scope with other conditions" do
209
- @ability.can :read, Article, :published => true
210
- @ability.can :read, Article, Article.where(:secret => true)
211
- expect(lambda { Article.accessible_by(@ability) }).to raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Article ability.")
212
- end
213
-
214
- it "does not allow to fetch records when ability with just block present" do
215
- @ability.can :read, Article do
216
- false
217
- end
218
- expect(lambda { Article.accessible_by(@ability) }).to raise_error(CanCan::Error)
219
- end
220
-
221
- it "should support more than one deeply nested conditions" do
222
- @ability.can :read, Comment, :article => {
223
- :category => {
224
- :name => 'foo', :visible => true
225
- }
226
- }
227
- expect { Comment.accessible_by(@ability) }.to_not raise_error
228
- end
229
-
230
- it "does not allow to check ability on object against SQL conditions without block" do
231
- @ability.can :read, Article, ["secret=?", true]
232
- expect(lambda { @ability.can? :read, Article.new }).to raise_error(CanCan::Error)
233
- end
234
-
235
- it "has false conditions if no abilities match" do
236
- expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'")
237
- end
238
-
239
- it "returns false conditions for cannot clause" do
240
- @ability.cannot :read, Article
241
- expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'")
242
- end
243
-
244
- it "returns SQL for single `can` definition in front of default `cannot` condition" do
245
- @ability.cannot :read, Article
246
- @ability.can :read, Article, :published => false, :secret => true
247
- expect(@ability.model_adapter(Article, :read).conditions).to orderlessly_match(%Q["#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't'])
248
- end
249
-
250
- it "returns true condition for single `can` definition in front of default `can` condition" do
251
- @ability.can :read, Article
252
- @ability.can :read, Article, :published => false, :secret => true
253
- expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='t'")
254
- end
255
-
256
- it "returns `false condition` for single `cannot` definition in front of default `cannot` condition" do
257
- @ability.cannot :read, Article
258
- @ability.cannot :read, Article, :published => false, :secret => true
259
- expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'")
260
- end
261
-
262
- it "returns `not (sql)` for single `cannot` definition in front of default `can` condition" do
263
- @ability.can :read, Article
264
- @ability.cannot :read, Article, :published => false, :secret => true
265
- expect(@ability.model_adapter(Article, :read).conditions).to orderlessly_match(%Q["not (#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't')])
266
- end
267
-
268
- it "returns appropriate sql conditions in complex case" do
269
- @ability.can :read, Article
270
- @ability.can :manage, Article, :id => 1
271
- @ability.can :update, Article, :published => true
272
- @ability.cannot :update, Article, :secret => true
273
- expect(@ability.model_adapter(Article, :update).conditions).to eq(%Q[not ("#{@article_table}"."secret" = 't') AND (("#{@article_table}"."published" = 't') OR ("#{@article_table}"."id" = 1))])
274
- expect(@ability.model_adapter(Article, :manage).conditions).to eq({:id => 1})
275
- expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='t'")
276
- end
277
-
278
- it "returns appropriate sql conditions in complex case with nested joins" do
279
- @ability.can :read, Comment, :article => { :category => { :visible => true } }
280
- expect(@ability.model_adapter(Comment, :read).conditions).to eq({ Category.table_name.to_sym => { :visible => true } })
281
- end
282
-
283
- it "returns appropriate sql conditions in complex case with nested joins of different depth" do
284
- @ability.can :read, Comment, :article => { :published => true, :category => { :visible => true } }
285
- expect(@ability.model_adapter(Comment, :read).conditions).to eq({ Article.table_name.to_sym => { :published => true }, Category.table_name.to_sym => { :visible => true } })
286
- end
287
-
288
- it "does not forget conditions when calling with SQL string" do
289
- @ability.can :read, Article, :published => true
290
- @ability.can :read, Article, ['secret=?', false]
291
- adapter = @ability.model_adapter(Article, :read)
292
- 2.times do
293
- expect(adapter.conditions).to eq(%Q[(secret='f') OR ("#{@article_table}"."published" = 't')])
294
- end
295
- end
296
-
297
- it "has nil joins if no rules" do
298
- expect(@ability.model_adapter(Article, :read).joins).to be_nil
299
- end
300
-
301
- it "has nil joins if no nested hashes specified in conditions" do
302
- @ability.can :read, Article, :published => false
303
- @ability.can :read, Article, :secret => true
304
- expect(@ability.model_adapter(Article, :read).joins).to be_nil
305
- end
306
-
307
- it "merges separate joins into a single array" do
308
- @ability.can :read, Article, :project => { :blocked => false }
309
- @ability.can :read, Article, :company => { :admin => true }
310
- expect(@ability.model_adapter(Article, :read).joins.inspect).to orderlessly_match([:company, :project].inspect)
311
- end
312
-
313
- it "merges same joins into a single array" do
314
- @ability.can :read, Article, :project => { :blocked => false }
315
- @ability.can :read, Article, :project => { :admin => true }
316
- expect(@ability.model_adapter(Article, :read).joins).to eq([:project])
317
- end
318
-
319
- it "merges nested and non-nested joins" do
320
- @ability.can :read, Article, :project => { :blocked => false }
321
- @ability.can :read, Article, :project => { :comments => { :spam => true } }
322
- expect(@ability.model_adapter(Article, :read).joins).to eq([{:project=>[:comments]}])
323
- end
324
-
325
- it "merges :all conditions with other conditions" do
326
- user = User.create!
327
- article = Article.create!(:user => user)
328
- ability = Ability.new(user)
329
- ability.can :manage, :all
330
- ability.can :manage, Article, :user_id => user.id
331
- expect(Article.accessible_by(ability)).to eq([article])
332
- end
333
-
334
- it 'should not execute a scope when checking ability on the class' do
335
- relation = Article.where(:secret => true)
336
- @ability.can :read, Article, relation do |article|
337
- article.secret == true
338
- end
339
-
340
- allow(relation).to receive(:count).and_raise('Unexpected scope execution.')
341
-
342
- expect { @ability.can? :read, Article }.not_to raise_error
343
- end
344
-
345
- context "with namespaced models" do
346
- before :each do
347
- ActiveRecord::Schema.define do
348
- create_table( :table_xes ) do |t|
349
- t.timestamps :null => false
350
- end
351
-
352
- create_table( :table_zs ) do |t|
353
- t.integer :table_x_id
354
- t.integer :user_id
355
- t.timestamps :null => false
356
- end
357
- end
358
-
359
- module Namespace
360
- end
361
-
362
- class Namespace::TableX < ActiveRecord::Base
363
- has_many :table_zs
364
- end
365
-
366
- class Namespace::TableZ < ActiveRecord::Base
367
- belongs_to :table_x
368
- belongs_to :user
369
- end
370
- end
371
-
372
- it "fetches all namespace::table_x when one is related by table_y" do
373
- user = User.create!
374
-
375
- ability = Ability.new(user)
376
- ability.can :read, Namespace::TableX, :table_zs => { :user_id => user.id }
377
-
378
- table_x = Namespace::TableX.create!
379
- table_z = table_x.table_zs.create( :user => user )
380
- expect(Namespace::TableX.accessible_by(ability)).to eq([table_x])
381
- end
382
- end
383
-
384
- context "when MetaWhere is defined" do
385
- before :each do
386
- pending "[Deprecated] MetaWhere support is being removed" unless defined? MetaWhere
387
- end
388
-
389
- it "restricts articles given a MetaWhere condition" do
390
- # pending "[Deprecated] MetaWhere support is being removed" unless defined? MetaWhere
391
- @ability.can :read, Article, :priority.lt => 2
392
- article1 = Article.create!(:priority => 1)
393
- article2 = Article.create!(:priority => 3)
394
- expect(Article.accessible_by(@ability)).to eq([article1])
395
- expect(@ability).to be_able_to(:read, article1)
396
- expect(@ability).to_not be_able_to(:read, article2)
397
- end
398
-
399
- it "merges MetaWhere and non-MetaWhere conditions" do
400
- # pending "[Deprecated] MetaWhere support is being removed" unless defined? MetaWhere
401
- @ability.can :read, Article, :priority.lt => 2
402
- @ability.can :read, Article, :priority => 1
403
- article1 = Article.create!(:priority => 1)
404
- article2 = Article.create!(:priority => 3)
405
- expect(Article.accessible_by(@ability)).to eq([article1])
406
- expect(@ability).to be_able_to(:read, article1)
407
- expect(@ability).to_not be_able_to(:read, article2)
408
- end
409
-
410
- it "matches any MetaWhere condition" do
411
- adapter = CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)
412
- article1 = Article.new(:priority => 1, :name => "Hello World")
413
- expect(adapter.matches_condition?(article1, :priority.eq, 1)).to be(true)
414
- expect(adapter.matches_condition?(article1, :priority.eq, 2)).to be(false)
415
- expect(adapter.matches_condition?(article1, :priority.eq_any, [1, 2])).to be(true)
416
- expect(adapter.matches_condition?(article1, :priority.eq_any, [2, 3])).to be(false)
417
- expect(adapter.matches_condition?(article1, :priority.eq_all, [1, 1])).to be(true)
418
- expect(adapter.matches_condition?(article1, :priority.eq_all, [1, 2])).to be(false)
419
- expect(adapter.matches_condition?(article1, :priority.ne, 2)).to be(true)
420
- expect(adapter.matches_condition?(article1, :priority.ne, 1)).to be(false)
421
- expect(adapter.matches_condition?(article1, :priority.in, [1, 2])).to be(true)
422
- expect(adapter.matches_condition?(article1, :priority.in, [2, 3])).to be(false)
423
- expect(adapter.matches_condition?(article1, :priority.nin, [2, 3])).to be(true)
424
- expect(adapter.matches_condition?(article1, :priority.nin, [1, 2])).to be(false)
425
- expect(adapter.matches_condition?(article1, :priority.lt, 2)).to be(true)
426
- expect(adapter.matches_condition?(article1, :priority.lt, 1)).to be(false)
427
- expect(adapter.matches_condition?(article1, :priority.lteq, 1)).to be(true)
428
- expect(adapter.matches_condition?(article1, :priority.lteq, 0)).to be(false)
429
- expect(adapter.matches_condition?(article1, :priority.gt, 0)).to be(true)
430
- expect(adapter.matches_condition?(article1, :priority.gt, 1)).to be(false)
431
- expect(adapter.matches_condition?(article1, :priority.gteq, 1)).to be(true)
432
- expect(adapter.matches_condition?(article1, :priority.gteq, 2)).to be(false)
433
- expect(adapter.matches_condition?(article1, :name.like, "%ello worl%")).to be_truthy
434
- expect(adapter.matches_condition?(article1, :name.like, "hello world")).to be_truthy
435
- expect(adapter.matches_condition?(article1, :name.like, "hello%")).to be_truthy
436
- expect(adapter.matches_condition?(article1, :name.like, "h%d")).to be_truthy
437
- expect(adapter.matches_condition?(article1, :name.like, "%helo%")).to be_falsey
438
- expect(adapter.matches_condition?(article1, :name.like, "hello")).to be_falsey
439
- expect(adapter.matches_condition?(article1, :name.like, "hello.world")).to be_falsey
440
- # For some reason this is reporting "The not_matches MetaWhere condition is not supported."
441
- # expect(adapter.matches_condition?(article1, :name.nlike, "%helo%")).to be(true)
442
- # expect(adapter.matches_condition?(article1, :name.nlike, "%ello worl%")).to be(false)
443
- end
444
- end
445
- end
446
- end