cancancan 1.12.0 → 1.13.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -31
- data/Appraisals +0 -55
- data/CHANGELOG.rdoc +7 -0
- data/CONTRIBUTING.md +2 -2
- data/README.md +28 -2
- data/cancancan.gemspec +5 -8
- data/gemfiles/activerecord_3.2.gemfile +0 -4
- data/gemfiles/mongoid_2.x.gemfile +0 -4
- data/gemfiles/sequel_3.x.gemfile +0 -4
- data/lib/cancan/ability.rb +43 -8
- data/lib/cancan/matchers.rb +3 -0
- data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -31
- data/lib/cancan/rule.rb +5 -1
- data/lib/cancan/version.rb +1 -1
- data/lib/cancan.rb +0 -1
- data/spec/cancan/ability_spec.rb +7 -0
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -62
- metadata +11 -15
- data/gemfiles/activerecord_3.0.gemfile +0 -18
- data/gemfiles/activerecord_3.1.gemfile +0 -20
- data/gemfiles/datamapper_1.x.gemfile +0 -14
- data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
- data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60da1f3c13774c65e5c622667c2a1472fffa0dbf
|
|
4
|
+
data.tar.gz: 1e3f6fd8446e2560579d313980a7633efe8e8af1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f717a5d3e6c98cb11aad2e1fd38ccfa4d7848d1181f031d0c2e988200f77bda96df6997b9d5c18b8b62d50c0b0ebf0d0c8177b8b6b596443875b52c895820e65
|
|
7
|
+
data.tar.gz: 504adef485e28df04ba9decd2902f38963886e9fe7e047125c15d8505b02fc0bb3f978d99f2306e154be3b8cb64dd1ad4ffdd7e8f0172950817841a67160f31b
|
data/.travis.yml
CHANGED
|
@@ -1,55 +1,28 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
cache: bundler
|
|
3
|
+
sudo: false
|
|
1
4
|
rvm:
|
|
2
|
-
- 1.8.7
|
|
3
|
-
- 1.9.2
|
|
4
|
-
- 1.9.3
|
|
5
5
|
- 2.0.0
|
|
6
6
|
- 2.1.0
|
|
7
7
|
- 2.2.0
|
|
8
|
-
- ree
|
|
9
8
|
- jruby
|
|
10
9
|
- rbx
|
|
11
10
|
gemfile:
|
|
12
|
-
- gemfiles/activerecord_3.0.gemfile
|
|
13
|
-
- gemfiles/activerecord_3.1.gemfile
|
|
14
11
|
- gemfiles/activerecord_3.2.gemfile
|
|
15
12
|
- gemfiles/activerecord_4.0.gemfile
|
|
16
13
|
- gemfiles/activerecord_4.1.gemfile
|
|
17
14
|
- gemfiles/activerecord_4.2.gemfile
|
|
18
|
-
- gemfiles/datamapper_1.x.gemfile
|
|
19
15
|
- gemfiles/mongoid_2.x.gemfile
|
|
20
16
|
- gemfiles/sequel_3.x.gemfile
|
|
21
17
|
services:
|
|
22
18
|
- mongodb
|
|
23
19
|
matrix:
|
|
20
|
+
fast_finish: true
|
|
24
21
|
allow_failures:
|
|
25
22
|
- rvm: rbx
|
|
26
|
-
- rvm: jruby
|
|
27
|
-
gemfile: gemfiles/datamapper_1.x.gemfile
|
|
28
23
|
exclude:
|
|
29
|
-
- rvm: 1.8.7
|
|
30
|
-
gemfile: gemfiles/activerecord_4.0.gemfile
|
|
31
|
-
- rvm: 1.8.7
|
|
32
|
-
gemfile: gemfiles/activerecord_4.1.gemfile
|
|
33
|
-
- rvm: 1.8.7
|
|
34
|
-
gemfile: gemfiles/activerecord_4.2.gemfile
|
|
35
|
-
- rvm: 1.9.2
|
|
36
|
-
gemfile: gemfiles/activerecord_4.0.gemfile
|
|
37
|
-
- rvm: 1.9.2
|
|
38
|
-
gemfile: gemfiles/activerecord_4.1.gemfile
|
|
39
|
-
- rvm: 1.9.2
|
|
40
|
-
gemfile: gemfiles/activerecord_4.2.gemfile
|
|
41
|
-
- rvm: 2.2.0
|
|
42
|
-
gemfile: gemfiles/activerecord_3.0.gemfile
|
|
43
|
-
- rvm: 2.2.0
|
|
44
|
-
gemfile: gemfiles/activerecord_3.1.gemfile
|
|
45
24
|
- rvm: 2.2.0
|
|
46
25
|
gemfile: gemfiles/activerecord_3.2.gemfile
|
|
47
|
-
- rvm: ree
|
|
48
|
-
gemfile: gemfiles/activerecord_4.0.gemfile
|
|
49
|
-
- rvm: ree
|
|
50
|
-
gemfile: gemfiles/activerecord_4.1.gemfile
|
|
51
|
-
- rvm: ree
|
|
52
|
-
gemfile: gemfiles/activerecord_4.2.gemfile
|
|
53
26
|
notifications:
|
|
54
27
|
recipients:
|
|
55
28
|
- bryan@bryanrite.com
|
data/Appraisals
CHANGED
|
@@ -1,42 +1,6 @@
|
|
|
1
|
-
appraise "activerecord_3.0" do
|
|
2
|
-
gem "activerecord", "~> 3.0.20", :require => "active_record"
|
|
3
|
-
gem "activesupport", "~> 3.0.20", :require => "active_support/all"
|
|
4
|
-
gem "meta_where"
|
|
5
|
-
|
|
6
|
-
gemfile.platforms :jruby do
|
|
7
|
-
gem "activerecord-jdbcsqlite3-adapter"
|
|
8
|
-
gem "jdbc-sqlite3"
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
gemfile.platforms :ruby, :mswin, :mingw do
|
|
12
|
-
gem "sqlite3"
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
appraise "activerecord_3.1" do
|
|
17
|
-
gem "activerecord", "~> 3.1.0", :require => "active_record"
|
|
18
|
-
|
|
19
|
-
gemfile.platforms :ruby_18, :ruby_19 do
|
|
20
|
-
gem "i18n", "< 0.7"
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
gemfile.platforms :jruby do
|
|
24
|
-
gem "activerecord-jdbcsqlite3-adapter"
|
|
25
|
-
gem "jdbc-sqlite3"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
gemfile.platforms :ruby, :mswin, :mingw do
|
|
29
|
-
gem "sqlite3"
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
1
|
appraise "activerecord_3.2" do
|
|
34
2
|
gem "activerecord", "~> 3.2.0", :require => "active_record"
|
|
35
3
|
|
|
36
|
-
gemfile.platforms :ruby_18, :ruby_19 do
|
|
37
|
-
gem "i18n", "< 0.7"
|
|
38
|
-
end
|
|
39
|
-
|
|
40
4
|
gemfile.platforms :jruby do
|
|
41
5
|
gem "activerecord-jdbcsqlite3-adapter"
|
|
42
6
|
gem "jdbc-sqlite3"
|
|
@@ -90,25 +54,10 @@ appraise "activerecord_4.2" do
|
|
|
90
54
|
end
|
|
91
55
|
end
|
|
92
56
|
|
|
93
|
-
appraise "datamapper_1.x" do
|
|
94
|
-
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
|
95
|
-
gem "dm-core", "~> 1.0"
|
|
96
|
-
gem "dm-sqlite-adapter", "~> 1.0"
|
|
97
|
-
gem "dm-migrations", "~> 1.0"
|
|
98
|
-
|
|
99
|
-
gemfile.platforms :ruby_18, :ruby_19 do
|
|
100
|
-
gem "i18n", "< 0.7"
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
57
|
appraise "mongoid_2.x" do
|
|
105
58
|
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
|
106
59
|
gem "mongoid", "~> 2.0.0"
|
|
107
60
|
|
|
108
|
-
gemfile.platforms :ruby_18, :ruby_19 do
|
|
109
|
-
gem "i18n", "< 0.7"
|
|
110
|
-
end
|
|
111
|
-
|
|
112
61
|
gemfile.platforms :ruby, :mswin, :mingw do
|
|
113
62
|
gem "bson_ext", "~> 1.1"
|
|
114
63
|
end
|
|
@@ -122,10 +71,6 @@ appraise "sequel_3.x" do
|
|
|
122
71
|
gem "sequel", "~> 3.47.0"
|
|
123
72
|
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
|
124
73
|
|
|
125
|
-
gemfile.platforms :ruby_18, :ruby_19 do
|
|
126
|
-
gem "i18n", "< 0.7"
|
|
127
|
-
end
|
|
128
|
-
|
|
129
74
|
gemfile.platforms :jruby do
|
|
130
75
|
gem "jdbc-sqlite3"
|
|
131
76
|
end
|
data/CHANGELOG.rdoc
CHANGED
data/CONTRIBUTING.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
### Reporting an Issue
|
|
4
4
|
|
|
5
|
-
1. If you have any questions about CanCanCan, search the [Wiki](https://github.com/
|
|
5
|
+
1. If you have any questions about CanCanCan, search the [Wiki](https://github.com/cancancommunity/cancancan/wiki), use [Stack Overflow](http://stackoverflow.com/questions/tagged/cancancan), or [our mailing list](https://groups.google.com/forum/#!forum/cancancan). Do not post questions here.
|
|
6
6
|
|
|
7
|
-
1. If you find a security bug, **DO NOT** submit an issue here. Please send an e-mail to
|
|
7
|
+
1. If you find a security bug, **DO NOT** submit an issue here. Please send an e-mail to the current maintainer instead.
|
|
8
8
|
|
|
9
9
|
1. Do a small search on the issues tracker before submitting your issue to see if it was already reported / fixed.
|
|
10
10
|
|
data/README.md
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
CanCan is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access. All permissions are defined in a single location (the `Ability` class) and not duplicated across controllers, views, and database queries.
|
|
11
11
|
|
|
12
|
+
## This is the master branch!
|
|
13
|
+
This branch represents work towards version 2.0. Please checkout the 1.x branch for the stable release. Use master at your own risk.
|
|
14
|
+
|
|
12
15
|
## Mission
|
|
13
16
|
|
|
14
17
|
This repo is a continuation of the dead [CanCan](https://github.com/ryanb/cancan) project. Our mission is to keep CanCan alive and moving forward, with maintenance fixes and new features. Pull Requests are welcome!
|
|
@@ -28,6 +31,12 @@ In **Rails 3 and 4**, add this to your Gemfile and run the `bundle install` comm
|
|
|
28
31
|
|
|
29
32
|
CanCanCan expects a `current_user` method to exist in the controller. First, set up some authentication (such as [Authlogic](https://github.com/binarylogic/authlogic) or [Devise](https://github.com/plataformatec/devise)). See [Changing Defaults](https://github.com/CanCanCommunity/cancancan/wiki/changing-defaults) if you need different behavior.
|
|
30
33
|
|
|
34
|
+
When using [rails-api](https://github.com/rails-api/rails-api), you have to manually include the controller methods for CanCan:
|
|
35
|
+
```ruby
|
|
36
|
+
class ApplicationController < ActionController::API
|
|
37
|
+
include CanCan::ControllerAdditions
|
|
38
|
+
end
|
|
39
|
+
```
|
|
31
40
|
|
|
32
41
|
### 1. Define Abilities
|
|
33
42
|
|
|
@@ -89,9 +98,26 @@ See [Authorizing Controller Actions](https://github.com/CanCanCommunity/cancanca
|
|
|
89
98
|
|
|
90
99
|
When using `strong_parameters` or Rails 4+, you have to sanitize inputs before saving the record, in actions such as `:create` and `:update`.
|
|
91
100
|
|
|
92
|
-
|
|
101
|
+
For the `:update` action, CanCan will load and authorize the resource but *not* change it automatically, so the typical usage would be something like:
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
def update
|
|
105
|
+
if @article.update_attributes(update_params)
|
|
106
|
+
# hurray
|
|
107
|
+
else
|
|
108
|
+
render :edit
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
def update_params
|
|
114
|
+
params.require(:article).permit(:body)
|
|
115
|
+
end
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
For the `:create` action, CanCan will try to initialize a new instance with sanitized input by seeing if your controller will respond to the following methods (in order):
|
|
93
119
|
|
|
94
|
-
1. `create_params`
|
|
120
|
+
1. `create_params`
|
|
95
121
|
2. `<model_name>_params` such as `article_params` (this is the default convention in rails for naming your param method)
|
|
96
122
|
3. `resource_params` (a generically named method you could specify in each controller)
|
|
97
123
|
|
data/cancancan.gemspec
CHANGED
|
@@ -6,8 +6,8 @@ require 'cancan/version'
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "cancancan"
|
|
8
8
|
s.version = CanCan::VERSION
|
|
9
|
-
s.authors = ["Bryan Rite", "Ryan Bates"]
|
|
10
|
-
s.email = "
|
|
9
|
+
s.authors = ["Bryan Rite", "Ryan Bates", "Richard Wilson"]
|
|
10
|
+
s.email = "r.crawfordwilson@gmail.com"
|
|
11
11
|
s.homepage = "https://github.com/CanCanCommunity/cancancan"
|
|
12
12
|
s.summary = "Simple authorization solution for Rails."
|
|
13
13
|
s.description = "Continuation of the simple authorization solution for Rails which is decoupled from user roles. All permissions are stored in a single location."
|
|
@@ -19,13 +19,10 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split($/).map{ |f| File.basename(f) }
|
|
20
20
|
s.require_paths = ["lib"]
|
|
21
21
|
|
|
22
|
-
s.required_ruby_version =
|
|
23
|
-
s.required_rubygems_version = ">= 1.3.4"
|
|
22
|
+
s.required_ruby_version = ">= 2.0.0"
|
|
24
23
|
|
|
25
24
|
s.add_development_dependency 'bundler', '~> 1.3'
|
|
26
25
|
s.add_development_dependency 'rake', '~> 10.1.1'
|
|
27
|
-
s.add_development_dependency 'rspec', '~> 3.
|
|
28
|
-
s.add_development_dependency 'appraisal', '>=
|
|
29
|
-
|
|
30
|
-
s.rubyforge_project = s.name
|
|
26
|
+
s.add_development_dependency 'rspec', '~> 3.2.0'
|
|
27
|
+
s.add_development_dependency 'appraisal', '>= 2.0.0'
|
|
31
28
|
end
|
|
@@ -5,10 +5,6 @@ source "https://rubygems.org"
|
|
|
5
5
|
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
|
6
6
|
gem "mongoid", "~> 2.0.0"
|
|
7
7
|
|
|
8
|
-
platforms :ruby_18, :ruby_19 do
|
|
9
|
-
gem "i18n", "< 0.7"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
8
|
platforms :ruby, :mswin, :mingw do
|
|
13
9
|
gem "bson_ext", "~> 1.1"
|
|
14
10
|
end
|
data/gemfiles/sequel_3.x.gemfile
CHANGED
data/lib/cancan/ability.rb
CHANGED
|
@@ -119,7 +119,7 @@ module CanCan
|
|
|
119
119
|
# can :read, :stats
|
|
120
120
|
# can? :read, :stats # => true
|
|
121
121
|
#
|
|
122
|
-
# IMPORTANT: Neither a hash of conditions
|
|
122
|
+
# IMPORTANT: Neither a hash of conditions nor a block will be used when checking permission on a class.
|
|
123
123
|
#
|
|
124
124
|
# can :update, Project, :priority => 3
|
|
125
125
|
# can? :update, Project # => true
|
|
@@ -133,7 +133,7 @@ module CanCan
|
|
|
133
133
|
# end
|
|
134
134
|
#
|
|
135
135
|
def can(action = nil, subject = nil, conditions = nil, &block)
|
|
136
|
-
|
|
136
|
+
add_rule(Rule.new(true, action, subject, conditions, block))
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
# Defines an ability which cannot be done. Accepts the same arguments as "can".
|
|
@@ -149,7 +149,7 @@ module CanCan
|
|
|
149
149
|
# end
|
|
150
150
|
#
|
|
151
151
|
def cannot(action = nil, subject = nil, conditions = nil, &block)
|
|
152
|
-
|
|
152
|
+
add_rule(Rule.new(false, action, subject, conditions, block))
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
# Alias one or more actions into another one.
|
|
@@ -246,8 +246,8 @@ module CanCan
|
|
|
246
246
|
end
|
|
247
247
|
|
|
248
248
|
def merge(ability)
|
|
249
|
-
ability.
|
|
250
|
-
|
|
249
|
+
ability.rules.each do |rule|
|
|
250
|
+
add_rule(rule.dup)
|
|
251
251
|
end
|
|
252
252
|
self
|
|
253
253
|
end
|
|
@@ -281,6 +281,12 @@ module CanCan
|
|
|
281
281
|
permissions_list
|
|
282
282
|
end
|
|
283
283
|
|
|
284
|
+
protected
|
|
285
|
+
|
|
286
|
+
# Must be protected as an ability can merge with other abilities.
|
|
287
|
+
# This means that an ability must expose their rules with another ability.
|
|
288
|
+
attr_reader :rules
|
|
289
|
+
|
|
284
290
|
private
|
|
285
291
|
|
|
286
292
|
def unauthorized_message_keys(action, subject)
|
|
@@ -331,21 +337,50 @@ module CanCan
|
|
|
331
337
|
results
|
|
332
338
|
end
|
|
333
339
|
|
|
334
|
-
def
|
|
340
|
+
def add_rule(rule)
|
|
335
341
|
@rules ||= []
|
|
342
|
+
@rules << rule
|
|
343
|
+
add_rule_to_index(rule, @rules.size - 1)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def add_rule_to_index(rule, position)
|
|
347
|
+
@rules_index ||= Hash.new { |h, k| h[k] = [] }
|
|
348
|
+
|
|
349
|
+
subjects = rule.subjects.compact
|
|
350
|
+
subjects << :all if subjects.empty?
|
|
351
|
+
|
|
352
|
+
subjects.each do |subject|
|
|
353
|
+
@rules_index[subject] << position
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def alternative_subjects(subject)
|
|
358
|
+
subject = subject.class unless subject.is_a?(Module)
|
|
359
|
+
[:all, *subject.ancestors, subject.class.to_s]
|
|
336
360
|
end
|
|
337
361
|
|
|
338
362
|
# Returns an array of Rule instances which match the action and subject
|
|
339
363
|
# This does not take into consideration any hash conditions or block statements
|
|
340
364
|
def relevant_rules(action, subject)
|
|
341
|
-
|
|
365
|
+
return [] unless @rules
|
|
366
|
+
relevant = possible_relevant_rules(subject).select do |rule|
|
|
342
367
|
rule.expanded_actions = expand_actions(rule.actions)
|
|
343
368
|
rule.relevant? action, subject
|
|
344
369
|
end
|
|
345
|
-
relevant.reverse!
|
|
370
|
+
relevant.reverse!.uniq!
|
|
346
371
|
relevant
|
|
347
372
|
end
|
|
348
373
|
|
|
374
|
+
def possible_relevant_rules(subject)
|
|
375
|
+
if subject.is_a?(Hash)
|
|
376
|
+
rules
|
|
377
|
+
else
|
|
378
|
+
positions = @rules_index.values_at(subject, *alternative_subjects(subject))
|
|
379
|
+
positions.flatten!.sort!
|
|
380
|
+
positions.map { |i| @rules[i] }
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
349
384
|
def relevant_rules_for_match(action, subject)
|
|
350
385
|
relevant_rules(action, subject).each do |rule|
|
|
351
386
|
if rule.only_raw_sql?
|
data/lib/cancan/matchers.rb
CHANGED
|
@@ -15,6 +15,9 @@ Kernel.const_get(rspec_module)::Matchers.define :be_able_to do |*args|
|
|
|
15
15
|
# Check that RSpec is < 2.99
|
|
16
16
|
if !respond_to?(:failure_message) && respond_to?(:failure_message_for_should)
|
|
17
17
|
alias :failure_message :failure_message_for_should
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if !respond_to?(:failure_message_when_negated) && respond_to?(:failure_message_for_should_not)
|
|
18
21
|
alias :failure_message_when_negated :failure_message_for_should_not
|
|
19
22
|
end
|
|
20
23
|
|
|
@@ -6,37 +6,6 @@ module CanCan
|
|
|
6
6
|
model_class <= ActiveRecord::Base
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def self.override_condition_matching?(subject, name, value)
|
|
10
|
-
name.kind_of?(MetaWhere::Column) if defined? MetaWhere
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.matches_condition?(subject, name, value)
|
|
14
|
-
subject_value = subject.send(name.column)
|
|
15
|
-
if name.method.to_s.ends_with? "_any"
|
|
16
|
-
value.any? { |v| meta_where_match? subject_value, name.method.to_s.sub("_any", ""), v }
|
|
17
|
-
elsif name.method.to_s.ends_with? "_all"
|
|
18
|
-
value.all? { |v| meta_where_match? subject_value, name.method.to_s.sub("_all", ""), v }
|
|
19
|
-
else
|
|
20
|
-
meta_where_match? subject_value, name.method, value
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def self.meta_where_match?(subject_value, method, value)
|
|
25
|
-
case method.to_sym
|
|
26
|
-
when :eq then subject_value == value
|
|
27
|
-
when :not_eq then subject_value != value
|
|
28
|
-
when :in then value.include?(subject_value)
|
|
29
|
-
when :not_in then !value.include?(subject_value)
|
|
30
|
-
when :lt then subject_value < value
|
|
31
|
-
when :lteq then subject_value <= value
|
|
32
|
-
when :gt then subject_value > value
|
|
33
|
-
when :gteq then subject_value >= value
|
|
34
|
-
when :matches then subject_value =~ Regexp.new("^" + Regexp.escape(value).gsub("%", ".*") + "$", true)
|
|
35
|
-
when :does_not_match then !meta_where_match?(subject_value, :matches, value)
|
|
36
|
-
else raise NotImplemented, "The #{method} MetaWhere condition is not supported."
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
9
|
private
|
|
41
10
|
|
|
42
11
|
def build_relation(*where_conditions)
|
data/lib/cancan/rule.rb
CHANGED
|
@@ -91,7 +91,11 @@ module CanCan
|
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
def matches_subject_class?(subject)
|
|
94
|
-
@subjects.any?
|
|
94
|
+
@subjects.any? do |sub|
|
|
95
|
+
sub.kind_of?(Module) && (subject.kind_of?(sub) ||
|
|
96
|
+
subject.class.to_s == sub.to_s ||
|
|
97
|
+
(subject.kind_of?(Module) && subject.ancestors.include?(sub)))
|
|
98
|
+
end
|
|
95
99
|
end
|
|
96
100
|
|
|
97
101
|
# Checks if the given subject matches the given conditions hash.
|
data/lib/cancan/version.rb
CHANGED
data/lib/cancan.rb
CHANGED
|
@@ -20,6 +20,5 @@ if defined? ActiveRecord
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
|
|
24
23
|
require 'cancan/model_adapters/mongoid_adapter' if defined?(Mongoid) && defined?(Mongoid::Document)
|
|
25
24
|
require 'cancan/model_adapters/sequel_adapter' if defined? Sequel
|
data/spec/cancan/ability_spec.rb
CHANGED
|
@@ -45,6 +45,13 @@ describe CanCan::Ability do
|
|
|
45
45
|
expect(@ability.can?(:read, 6)).to be(false)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
it "overrides earlier rules with later ones (even if a different exact subject)" do
|
|
49
|
+
@ability.cannot :read, Numeric
|
|
50
|
+
@ability.can :read, Integer
|
|
51
|
+
|
|
52
|
+
expect(@ability.can?(:read, 6)).to be(true)
|
|
53
|
+
end
|
|
54
|
+
|
|
48
55
|
it "does not pass class with object if :all objects are accepted" do
|
|
49
56
|
@ability.can :preview, :all do |object|
|
|
50
57
|
expect(object).to eq(123)
|
|
@@ -380,67 +380,5 @@ if defined? CanCan::ModelAdapters::ActiveRecordAdapter
|
|
|
380
380
|
expect(Namespace::TableX.accessible_by(ability)).to eq([table_x])
|
|
381
381
|
end
|
|
382
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
383
|
end
|
|
446
384
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cancancan
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bryan Rite
|
|
8
8
|
- Ryan Bates
|
|
9
|
+
- Richard Wilson
|
|
9
10
|
autorequire:
|
|
10
11
|
bindir: bin
|
|
11
12
|
cert_chain: []
|
|
12
|
-
date: 2015-
|
|
13
|
+
date: 2015-10-08 00:00:00.000000000 Z
|
|
13
14
|
dependencies:
|
|
14
15
|
- !ruby/object:Gem::Dependency
|
|
15
16
|
name: bundler
|
|
@@ -45,31 +46,31 @@ dependencies:
|
|
|
45
46
|
requirements:
|
|
46
47
|
- - "~>"
|
|
47
48
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: 3.
|
|
49
|
+
version: 3.2.0
|
|
49
50
|
type: :development
|
|
50
51
|
prerelease: false
|
|
51
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
52
53
|
requirements:
|
|
53
54
|
- - "~>"
|
|
54
55
|
- !ruby/object:Gem::Version
|
|
55
|
-
version: 3.
|
|
56
|
+
version: 3.2.0
|
|
56
57
|
- !ruby/object:Gem::Dependency
|
|
57
58
|
name: appraisal
|
|
58
59
|
requirement: !ruby/object:Gem::Requirement
|
|
59
60
|
requirements:
|
|
60
61
|
- - ">="
|
|
61
62
|
- !ruby/object:Gem::Version
|
|
62
|
-
version:
|
|
63
|
+
version: 2.0.0
|
|
63
64
|
type: :development
|
|
64
65
|
prerelease: false
|
|
65
66
|
version_requirements: !ruby/object:Gem::Requirement
|
|
66
67
|
requirements:
|
|
67
68
|
- - ">="
|
|
68
69
|
- !ruby/object:Gem::Version
|
|
69
|
-
version:
|
|
70
|
+
version: 2.0.0
|
|
70
71
|
description: Continuation of the simple authorization solution for Rails which is
|
|
71
72
|
decoupled from user roles. All permissions are stored in a single location.
|
|
72
|
-
email:
|
|
73
|
+
email: r.crawfordwilson@gmail.com
|
|
73
74
|
executables: []
|
|
74
75
|
extensions: []
|
|
75
76
|
extra_rdoc_files: []
|
|
@@ -85,13 +86,10 @@ files:
|
|
|
85
86
|
- README.md
|
|
86
87
|
- Rakefile
|
|
87
88
|
- cancancan.gemspec
|
|
88
|
-
- gemfiles/activerecord_3.0.gemfile
|
|
89
|
-
- gemfiles/activerecord_3.1.gemfile
|
|
90
89
|
- gemfiles/activerecord_3.2.gemfile
|
|
91
90
|
- gemfiles/activerecord_4.0.gemfile
|
|
92
91
|
- gemfiles/activerecord_4.1.gemfile
|
|
93
92
|
- gemfiles/activerecord_4.2.gemfile
|
|
94
|
-
- gemfiles/datamapper_1.x.gemfile
|
|
95
93
|
- gemfiles/mongoid_2.x.gemfile
|
|
96
94
|
- gemfiles/sequel_3.x.gemfile
|
|
97
95
|
- init.rb
|
|
@@ -106,7 +104,6 @@ files:
|
|
|
106
104
|
- lib/cancan/model_adapters/active_record_3_adapter.rb
|
|
107
105
|
- lib/cancan/model_adapters/active_record_4_adapter.rb
|
|
108
106
|
- lib/cancan/model_adapters/active_record_adapter.rb
|
|
109
|
-
- lib/cancan/model_adapters/data_mapper_adapter.rb
|
|
110
107
|
- lib/cancan/model_adapters/default_adapter.rb
|
|
111
108
|
- lib/cancan/model_adapters/mongoid_adapter.rb
|
|
112
109
|
- lib/cancan/model_adapters/sequel_adapter.rb
|
|
@@ -126,7 +123,6 @@ files:
|
|
|
126
123
|
- spec/cancan/matchers_spec.rb
|
|
127
124
|
- spec/cancan/model_adapters/active_record_4_adapter_spec.rb
|
|
128
125
|
- spec/cancan/model_adapters/active_record_adapter_spec.rb
|
|
129
|
-
- spec/cancan/model_adapters/data_mapper_adapter_spec.rb
|
|
130
126
|
- spec/cancan/model_adapters/default_adapter_spec.rb
|
|
131
127
|
- spec/cancan/model_adapters/mongoid_adapter_spec.rb
|
|
132
128
|
- spec/cancan/model_adapters/sequel_adapter_spec.rb
|
|
@@ -147,14 +143,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
147
143
|
requirements:
|
|
148
144
|
- - ">="
|
|
149
145
|
- !ruby/object:Gem::Version
|
|
150
|
-
version:
|
|
146
|
+
version: 2.0.0
|
|
151
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
148
|
requirements:
|
|
153
149
|
- - ">="
|
|
154
150
|
- !ruby/object:Gem::Version
|
|
155
|
-
version:
|
|
151
|
+
version: '0'
|
|
156
152
|
requirements: []
|
|
157
|
-
rubyforge_project:
|
|
153
|
+
rubyforge_project:
|
|
158
154
|
rubygems_version: 2.2.3
|
|
159
155
|
signing_key:
|
|
160
156
|
specification_version: 4
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# This file was generated by Appraisal
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
gem "activerecord", "~> 3.0.20", :require => "active_record"
|
|
6
|
-
gem "activesupport", "~> 3.0.20", :require => "active_support/all"
|
|
7
|
-
gem "meta_where"
|
|
8
|
-
|
|
9
|
-
platforms :jruby do
|
|
10
|
-
gem "activerecord-jdbcsqlite3-adapter"
|
|
11
|
-
gem "jdbc-sqlite3"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
platforms :ruby, :mswin, :mingw do
|
|
15
|
-
gem "sqlite3"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
gemspec :path => "../"
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# This file was generated by Appraisal
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
gem "activerecord", "~> 3.1.0", :require => "active_record"
|
|
6
|
-
|
|
7
|
-
platforms :ruby_18, :ruby_19 do
|
|
8
|
-
gem "i18n", "< 0.7"
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
platforms :jruby do
|
|
12
|
-
gem "activerecord-jdbcsqlite3-adapter"
|
|
13
|
-
gem "jdbc-sqlite3"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
platforms :ruby, :mswin, :mingw do
|
|
17
|
-
gem "sqlite3"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
gemspec :path => "../"
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# This file was generated by Appraisal
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
|
6
|
-
gem "dm-core", "~> 1.0"
|
|
7
|
-
gem "dm-sqlite-adapter", "~> 1.0"
|
|
8
|
-
gem "dm-migrations", "~> 1.0"
|
|
9
|
-
|
|
10
|
-
platforms :ruby_18, :ruby_19 do
|
|
11
|
-
gem "i18n", "< 0.7"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
gemspec :path => "../"
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
module CanCan
|
|
2
|
-
module ModelAdapters
|
|
3
|
-
class DataMapperAdapter < AbstractAdapter
|
|
4
|
-
def self.for_class?(model_class)
|
|
5
|
-
model_class <= DataMapper::Resource
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def self.find(model_class, id)
|
|
9
|
-
model_class.get(id)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def self.override_conditions_hash_matching?(subject, conditions)
|
|
13
|
-
conditions.any? { |k,v| !k.kind_of?(Symbol) }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def self.matches_conditions_hash?(subject, conditions)
|
|
17
|
-
collection = DataMapper::Collection.new(subject.query, [ subject ])
|
|
18
|
-
!!collection.first(conditions)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def database_records
|
|
22
|
-
scope = @model_class.all(:conditions => ["0 = 1"])
|
|
23
|
-
cans, cannots = @rules.partition { |r| r.base_behavior }
|
|
24
|
-
return scope if cans.empty?
|
|
25
|
-
# apply unions first, then differences. this mean cannot overrides can
|
|
26
|
-
cans.each { |r| scope += @model_class.all(:conditions => r.conditions) }
|
|
27
|
-
cannots.each { |r| scope -= @model_class.all(:conditions => r.conditions) }
|
|
28
|
-
scope
|
|
29
|
-
end
|
|
30
|
-
end # class DataMapper
|
|
31
|
-
end # module ModelAdapters
|
|
32
|
-
end # module CanCan
|
|
33
|
-
|
|
34
|
-
DataMapper::Model.append_extensions(CanCan::ModelAdditions::ClassMethods)
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
if defined? CanCan::ModelAdapters::DataMapperAdapter
|
|
4
|
-
|
|
5
|
-
DataMapper.setup(:default, 'sqlite::memory:')
|
|
6
|
-
|
|
7
|
-
class Article
|
|
8
|
-
include DataMapper::Resource
|
|
9
|
-
property :id, Serial
|
|
10
|
-
property :published, Boolean, :default => false
|
|
11
|
-
property :secret, Boolean, :default => false
|
|
12
|
-
property :priority, Integer
|
|
13
|
-
has n, :comments
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class Comment
|
|
17
|
-
include DataMapper::Resource
|
|
18
|
-
property :id, Serial
|
|
19
|
-
property :spam, Boolean, :default => false
|
|
20
|
-
belongs_to :article
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
DataMapper.finalize
|
|
24
|
-
DataMapper.auto_migrate!
|
|
25
|
-
|
|
26
|
-
describe CanCan::ModelAdapters::DataMapperAdapter do
|
|
27
|
-
before(:each) do
|
|
28
|
-
Article.destroy
|
|
29
|
-
Comment.destroy
|
|
30
|
-
(@ability = double).extend(CanCan::Ability)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "is for only data mapper classes" do
|
|
34
|
-
expect(CanCan::ModelAdapters::DataMapperAdapter).not_to be_for_class(Object)
|
|
35
|
-
expect(CanCan::ModelAdapters::DataMapperAdapter).to be_for_class(Article)
|
|
36
|
-
expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)).to eq(CanCan::ModelAdapters::DataMapperAdapter)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "finds record" do
|
|
40
|
-
article = Article.create
|
|
41
|
-
expect(CanCan::ModelAdapters::DataMapperAdapter.find(Article, article.id)).to eq(article)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it "does not fetch any records when no abilities are defined" do
|
|
45
|
-
Article.create
|
|
46
|
-
expect(Article.accessible_by(@ability)).to be_empty
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "fetches all articles when one can read all" do
|
|
50
|
-
@ability.can :read, Article
|
|
51
|
-
article = Article.create
|
|
52
|
-
expect(Article.accessible_by(@ability)).to eq([article])
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it "fetches only the articles that are published" do
|
|
56
|
-
@ability.can :read, Article, :published => true
|
|
57
|
-
article1 = Article.create(:published => true)
|
|
58
|
-
article2 = Article.create(:published => false)
|
|
59
|
-
expect(Article.accessible_by(@ability)).to eq([article1])
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "fetches any articles which are published or secret" do
|
|
63
|
-
@ability.can :read, Article, :published => true
|
|
64
|
-
@ability.can :read, Article, :secret => true
|
|
65
|
-
article1 = Article.create(:published => true, :secret => false)
|
|
66
|
-
article2 = Article.create(:published => true, :secret => true)
|
|
67
|
-
article3 = Article.create(:published => false, :secret => true)
|
|
68
|
-
article4 = Article.create(:published => false, :secret => false)
|
|
69
|
-
expect(Article.accessible_by(@ability)).to eq([article1, article2, article3])
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
it "fetches only the articles that are published and not secret" do
|
|
73
|
-
@ability.can :read, Article, :published => true
|
|
74
|
-
@ability.cannot :read, Article, :secret => true
|
|
75
|
-
article1 = Article.create(:published => true, :secret => false)
|
|
76
|
-
article2 = Article.create(:published => true, :secret => true)
|
|
77
|
-
article3 = Article.create(:published => false, :secret => true)
|
|
78
|
-
article4 = Article.create(:published => false, :secret => false)
|
|
79
|
-
expect(Article.accessible_by(@ability)).to eq([article1])
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it "only reads comments for articles which are published" do
|
|
83
|
-
@ability.can :read, Comment, :article => { :published => true }
|
|
84
|
-
comment1 = Comment.create(:article => Article.create!(:published => true))
|
|
85
|
-
comment2 = Comment.create(:article => Article.create!(:published => false))
|
|
86
|
-
expect(Comment.accessible_by(@ability)).to eq([comment1])
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "allows conditions in SQL and merge with hash conditions" do
|
|
90
|
-
@ability.can :read, Article, :published => true
|
|
91
|
-
@ability.can :read, Article, ["secret=?", true]
|
|
92
|
-
article1 = Article.create(:published => true, :secret => false)
|
|
93
|
-
article4 = Article.create(:published => false, :secret => false)
|
|
94
|
-
expect(Article.accessible_by(@ability)).to eq([article1])
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it "matches gt comparison" do
|
|
98
|
-
@ability.can :read, Article, :priority.gt => 3
|
|
99
|
-
article1 = Article.create(:priority => 4)
|
|
100
|
-
article2 = Article.create(:priority => 3)
|
|
101
|
-
expect(Article.accessible_by(@ability)).to eq([article1])
|
|
102
|
-
expect(@ability).to be_able_to(:read, article1)
|
|
103
|
-
expect(@ability).not_to be_able_to(:read, article2)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
it "matches gte comparison" do
|
|
107
|
-
@ability.can :read, Article, :priority.gte => 3
|
|
108
|
-
article1 = Article.create(:priority => 4)
|
|
109
|
-
article2 = Article.create(:priority => 3)
|
|
110
|
-
article3 = Article.create(:priority => 2)
|
|
111
|
-
expect(Article.accessible_by(@ability)).to eq([article1, article2])
|
|
112
|
-
expect(@ability).to be_able_to(:read, article1)
|
|
113
|
-
expect(@ability).to be_able_to(:read, article2)
|
|
114
|
-
expect(@ability).not_to be_able_to(:read, article3)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# TODO: add more comparison specs
|
|
118
|
-
end
|
|
119
|
-
end
|