cancancan 1.7.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/Appraisals +50 -4
- data/CHANGELOG.rdoc +12 -1
- data/README.rdoc +12 -2
- data/Rakefile +0 -2
- data/cancancan.gemspec +3 -2
- data/gemfiles/activerecord_3.0.gemfile +18 -0
- data/gemfiles/{rails_3.0.gemfile → activerecord_3.1.gemfile} +2 -4
- data/gemfiles/activerecord_3.2.gemfile +16 -0
- data/gemfiles/{rails_3.0_datamapper.gemfile → datamapper_1.x.gemfile} +2 -1
- data/gemfiles/{rails_3.0_mongoid.gemfile → mongoid_2.x.gemfile} +6 -1
- data/gemfiles/sequel_3.x.gemfile +17 -0
- data/lib/cancan.rb +1 -0
- data/lib/cancan/ability.rb +24 -4
- data/lib/cancan/controller_resource.rb +6 -2
- data/lib/cancan/model_adapters/sequel_adapter.rb +87 -0
- data/lib/cancan/rule.rb +29 -24
- data/lib/cancan/version.rb +1 -1
- data/lib/cancancan.rb +3 -0
- data/spec/cancan/ability_spec.rb +26 -0
- data/spec/cancan/controller_resource_spec.rb +520 -447
- data/spec/cancan/inherited_resource_spec.rb +49 -38
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +106 -92
- data/spec/cancan/model_adapters/sequel_adapter_spec.rb +148 -0
- data/spec/spec_helper.rb +6 -61
- data/spec/support/ability.rb +7 -0
- metadata +41 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7079b16052c2f98ebe67d6ce08e390188bca856d
|
4
|
+
data.tar.gz: faa43141ca3124dbe3d40ceb30a76ca78bc56117
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8168024035574501d8bef61033f458facb1b7173ed98d901b9b51aedc0c659470f6210beb308273de9cd437e4d75027eb39321f104a9e8dc8f933593f1a67aa1
|
7
|
+
data.tar.gz: e71e7aa4f2a66f0f660aa9ce224dff3c0de2efc3b0fb85d461113175e5349700bf4475f5f9ca7abf16c56457488a33b3b5d954e753b021f162428c5827e28cd5
|
data/.travis.yml
CHANGED
@@ -8,9 +8,12 @@ rvm:
|
|
8
8
|
- jruby
|
9
9
|
- rbx
|
10
10
|
gemfile:
|
11
|
-
- gemfiles/
|
12
|
-
- gemfiles/
|
13
|
-
- gemfiles/
|
11
|
+
- gemfiles/activerecord_3.0.gemfile
|
12
|
+
- gemfiles/activerecord_3.1.gemfile
|
13
|
+
- gemfiles/activerecord_3.2.gemfile
|
14
|
+
- gemfiles/datamapper_1.x.gemfile
|
15
|
+
- gemfiles/mongoid_2.x.gemfile
|
16
|
+
- gemfiles/sequel_3.x.gemfile
|
14
17
|
services:
|
15
18
|
- mongodb
|
16
19
|
matrix:
|
data/Appraisals
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
appraise "
|
1
|
+
appraise "activerecord_3.0" do
|
2
2
|
gem "activerecord", "~> 3.0.20", :require => "active_record"
|
3
|
-
gem
|
3
|
+
gem 'activesupport', '~> 3.0.20', :require => 'active_support/all'
|
4
4
|
gem "meta_where"
|
5
5
|
|
6
6
|
gemfile.platforms :jruby do
|
@@ -13,16 +13,62 @@ appraise "rails_3.0" do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
appraise "
|
16
|
+
appraise "activerecord_3.1" do
|
17
|
+
gem "activerecord", "~> 3.1.0", :require => "active_record"
|
18
|
+
|
19
|
+
gemfile.platforms :jruby do
|
20
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
21
|
+
gem "jdbc-sqlite3"
|
22
|
+
end
|
23
|
+
|
24
|
+
gemfile.platforms :ruby, :mswin, :mingw do
|
25
|
+
gem "sqlite3"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
appraise "activerecord_3.2" do
|
30
|
+
gem "activerecord", "~> 3.2.0", :require => "active_record"
|
31
|
+
|
32
|
+
gemfile.platforms :jruby do
|
33
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
34
|
+
gem "jdbc-sqlite3"
|
35
|
+
end
|
36
|
+
|
37
|
+
gemfile.platforms :ruby, :mswin, :mingw do
|
38
|
+
gem "sqlite3"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
appraise "datamapper_1.x" do
|
43
|
+
gem 'activesupport', '~> 3.0', :require => 'active_support/all'
|
17
44
|
gem "dm-core", "~> 1.0.2"
|
18
45
|
gem "dm-sqlite-adapter", "~> 1.0.2"
|
19
46
|
gem "dm-migrations", "~> 1.0.2"
|
20
47
|
end
|
21
48
|
|
22
|
-
appraise "
|
49
|
+
appraise "mongoid_2.x" do
|
50
|
+
gem 'activesupport', '~> 3.0', :require => 'active_support/all'
|
23
51
|
gem "mongoid", "~> 2.0.0"
|
24
52
|
|
25
53
|
gemfile.platforms :ruby, :mswin, :mingw do
|
26
54
|
gem "bson_ext", "~> 1.1"
|
27
55
|
end
|
56
|
+
|
57
|
+
gemfile.platforms :jruby do
|
58
|
+
gem "mongo", "~> 1.9.2"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
appraise "sequel_3.x" do
|
63
|
+
gem "sequel", "~> 3.47.0"
|
64
|
+
gem 'activesupport', '~> 3.0', :require => 'active_support/all'
|
65
|
+
|
66
|
+
gemfile.platforms :jruby do
|
67
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
68
|
+
gem "jdbc-sqlite3"
|
69
|
+
end
|
70
|
+
|
71
|
+
gemfile.platforms :ruby, :mswin, :mingw do
|
72
|
+
gem "sqlite3"
|
73
|
+
end
|
28
74
|
end
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
|
1
|
+
Develop
|
2
|
+
|
3
|
+
|
4
|
+
1.8.0 (May 8th, 2014)
|
5
|
+
|
6
|
+
* Feature cancan#884 - Add a Sequel model adapter (szetobo)
|
7
|
+
|
8
|
+
* Feature cancancan#3 - Permit "can?" check multiple subjects (cefigueiredo)
|
9
|
+
|
10
|
+
* Feature cancancan#29 - Add ability to use a String that will get instance_eval'd or a Proc that will get called as the parameter method option for strong_parameter santization (svoop)
|
11
|
+
|
12
|
+
* Feature cancancan#48 - Define a CanCanCan module. Even though it is not used, it is standard practice to define the module, and helpful for determining between CanCanCan and CanCan for external libraries.
|
2
13
|
|
3
14
|
|
4
15
|
1.7.1 (March 19th, 2014)
|
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= CanCanCan
|
2
2
|
{<img src="https://badge.fury.io/rb/cancancan.png" alt="Gem Version" />}[http://badge.fury.io/rb/cancancan]
|
3
3
|
{<img src="https://travis-ci.org/CanCanCommunity/cancancan.png?branch=master" alt="Build Status" />}[https://travis-ci.org/CanCanCommunity/cancancan]
|
4
|
-
{<img src="https://codeclimate.com/github/
|
4
|
+
{<img src="https://codeclimate.com/github/CanCanCommunity/cancancan.png" />}[https://codeclimate.com/github/CanCanCommunity/cancancan]
|
5
5
|
{<img src="http://inch-pages.github.io/github/CanCanCommunity/cancancan.png" alt="Inline docs" />}[http://inch-pages.github.io/github/CanCanCommunity/cancancan]
|
6
6
|
|
7
7
|
Wiki[https://github.com/bryanrite/cancancan/wiki] | RDocs[http://rdoc.info/projects/ryanb/cancan] | Screencast[http://railscasts.com/episodes/192-authorization-with-cancan]
|
@@ -22,7 +22,7 @@ Any help is greatly appreciated, feel free to submit pull-requests or open issue
|
|
22
22
|
|
23
23
|
In <b>Rails 3 and 4</b>, add this to your Gemfile and run the +bundle+ command.
|
24
24
|
|
25
|
-
gem 'cancancan', '~> 1.
|
25
|
+
gem 'cancancan', '~> 1.8'
|
26
26
|
|
27
27
|
In <b>Rails 2</b>, add this to your environment.rb file.
|
28
28
|
|
@@ -98,6 +98,8 @@ By default, CanCan will try to sanitize the input on <tt>:create</tt> and <tt>:u
|
|
98
98
|
|
99
99
|
Additionally, <tt>load_and_authorize_resource</tt> can now take a <tt>param_method</tt> option to specify a custom method in the controller to run to sanitize input.
|
100
100
|
|
101
|
+
You can associate the <tt>param_method</tt> option with a symbol corresponding to the name of a method that will get called:
|
102
|
+
|
101
103
|
class ArticlesController < ApplicationController
|
102
104
|
load_and_authorize_resource param_method: :my_sanitizer
|
103
105
|
|
@@ -116,6 +118,14 @@ Additionally, <tt>load_and_authorize_resource</tt> can now take a <tt>param_meth
|
|
116
118
|
end
|
117
119
|
end
|
118
120
|
|
121
|
+
You can also use a string that will be evaluated in the context of the controller using <tt>instance_eval</tt> and needs to contain valid Ruby code. This does come in handy when using a PermittedParams class as suggested in Railscast 371:
|
122
|
+
|
123
|
+
load_and_authorize_resource param_method: 'permitted_params.article'
|
124
|
+
|
125
|
+
Finally, it's possible to associate <tt>param_method</tt> with a Proc object which will be called with the controller as the only argument:
|
126
|
+
|
127
|
+
load_and_authorize_resource param_method: Proc.new { |c| c.params.require(:article).permit(:name) }
|
128
|
+
|
119
129
|
See {Strong Parameters}[https://github.com/bryanrite/cancancan/wiki/Strong-Parameters] for more information.
|
120
130
|
|
121
131
|
=== 3. Handle Unauthorized Access
|
data/Rakefile
CHANGED
data/cancancan.gemspec
CHANGED
@@ -22,9 +22,10 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
23
23
|
s.required_rubygems_version = ">= 1.3.4"
|
24
24
|
|
25
|
+
s.add_development_dependency 'bundler', '~> 1.3'
|
26
|
+
s.add_development_dependency 'rake', '~> 10.1.1'
|
25
27
|
s.add_development_dependency 'rspec', '~> 2.14'
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency 'appraisal', '>= 1.0.0.beta3'
|
28
|
+
s.add_development_dependency 'appraisal', '>= 1.0.0'
|
28
29
|
|
29
30
|
s.rubyforge_project = s.name
|
30
31
|
end
|
@@ -0,0 +1,18 @@
|
|
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 => "../"
|
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem "activerecord", "~> 3.0
|
6
|
-
gem "with_model", "~> 0.2.5"
|
7
|
-
gem "meta_where"
|
5
|
+
gem "activerecord", "~> 3.1.0", :require => "active_record"
|
8
6
|
|
9
7
|
platforms :jruby do
|
10
8
|
gem "activerecord-jdbcsqlite3-adapter"
|
@@ -15,4 +13,4 @@ platforms :ruby, :mswin, :mingw do
|
|
15
13
|
gem "sqlite3"
|
16
14
|
end
|
17
15
|
|
18
|
-
gemspec :path=>"
|
16
|
+
gemspec :path => "../"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 3.2.0", :require => "active_record"
|
6
|
+
|
7
|
+
platforms :jruby do
|
8
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
9
|
+
gem "jdbc-sqlite3"
|
10
|
+
end
|
11
|
+
|
12
|
+
platforms :ruby, :mswin, :mingw do
|
13
|
+
gem "sqlite3"
|
14
|
+
end
|
15
|
+
|
16
|
+
gemspec :path => "../"
|
@@ -2,10 +2,15 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
+
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
5
6
|
gem "mongoid", "~> 2.0.0"
|
6
7
|
|
7
8
|
platforms :ruby, :mswin, :mingw do
|
8
9
|
gem "bson_ext", "~> 1.1"
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
+
platforms :jruby do
|
13
|
+
gem "mongo", "~> 1.9.2"
|
14
|
+
end
|
15
|
+
|
16
|
+
gemspec :path => "../"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "sequel", "~> 3.47.0"
|
6
|
+
gem "activesupport", "~> 3.0", :require => "active_support/all"
|
7
|
+
|
8
|
+
platforms :jruby do
|
9
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
10
|
+
gem "jdbc-sqlite3"
|
11
|
+
end
|
12
|
+
|
13
|
+
platforms :ruby, :mswin, :mingw do
|
14
|
+
gem "sqlite3"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec :path => "../"
|
data/lib/cancan.rb
CHANGED
@@ -12,3 +12,4 @@ require 'cancan/model_adapters/default_adapter'
|
|
12
12
|
require 'cancan/model_adapters/active_record_adapter' if defined? ActiveRecord
|
13
13
|
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
|
14
14
|
require 'cancan/model_adapters/mongoid_adapter' if defined?(Mongoid) && defined?(Mongoid::Document)
|
15
|
+
require 'cancan/model_adapters/sequel_adapter' if defined? Sequel
|
data/lib/cancan/ability.rb
CHANGED
@@ -29,6 +29,13 @@ module CanCan
|
|
29
29
|
#
|
30
30
|
# can? :create, @category => Project
|
31
31
|
#
|
32
|
+
# You can also pass multiple objects to check. You only need to pass a hash
|
33
|
+
# following the pattern { :any => [many subjects] }. The behaviour is check if
|
34
|
+
# there is a permission on any of the given objects.
|
35
|
+
#
|
36
|
+
# can? :create, {:any => [Project, Rule]}
|
37
|
+
#
|
38
|
+
#
|
32
39
|
# Any additional arguments will be passed into the "can" block definition. This
|
33
40
|
# can be used to pass more information about the user's request for example.
|
34
41
|
#
|
@@ -54,12 +61,16 @@ module CanCan
|
|
54
61
|
#
|
55
62
|
# Also see the RSpec Matchers to aid in testing.
|
56
63
|
def can?(action, subject, *extra_args)
|
57
|
-
|
58
|
-
|
59
|
-
|
64
|
+
subject = extract_subjects(subject)
|
65
|
+
|
66
|
+
match = subject.map do |subject|
|
67
|
+
relevant_rules_for_match(action, subject).detect do |rule|
|
68
|
+
rule.matches_conditions?(action, subject, extra_args)
|
69
|
+
end
|
70
|
+
end.compact.first
|
71
|
+
|
60
72
|
match ? match.base_behavior : false
|
61
73
|
end
|
62
|
-
|
63
74
|
# Convenience method which works the same as "can?" but returns the opposite value.
|
64
75
|
#
|
65
76
|
# cannot? :destroy, @project
|
@@ -272,6 +283,15 @@ module CanCan
|
|
272
283
|
@expanded_actions ||= {}
|
273
284
|
end
|
274
285
|
|
286
|
+
# It translates to an array the subject or the hash with multiple subjects given to can?.
|
287
|
+
def extract_subjects(subject)
|
288
|
+
subject = if subject.respond_to?(:keys) && subject.key?(:any)
|
289
|
+
subject[:any]
|
290
|
+
else
|
291
|
+
[subject]
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
275
295
|
# Given an action, it will try to find all of the actions which are aliased to it.
|
276
296
|
# This does the opposite kind of lookup as expand_actions.
|
277
297
|
def aliases_for_action(action)
|
@@ -221,7 +221,11 @@ module CanCan
|
|
221
221
|
|
222
222
|
def resource_params
|
223
223
|
if param_actions.include?(@params[:action].to_sym) && params_method.present?
|
224
|
-
return
|
224
|
+
return case params_method
|
225
|
+
when Symbol then @controller.send(params_method)
|
226
|
+
when String then @controller.instance_eval(params_method)
|
227
|
+
when Proc then params_method.call(@controller)
|
228
|
+
end
|
225
229
|
elsif @options[:class]
|
226
230
|
params_key = extract_key(@options[:class])
|
227
231
|
return @params[params_key] if @params[params_key]
|
@@ -236,7 +240,7 @@ module CanCan
|
|
236
240
|
|
237
241
|
def params_method
|
238
242
|
params_methods.each do |method|
|
239
|
-
return method if @controller.respond_to?(method, true)
|
243
|
+
return method if (method.is_a?(Symbol) && @controller.respond_to?(method, true)) || method.is_a?(String) || method.is_a?(Proc)
|
240
244
|
end
|
241
245
|
nil
|
242
246
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module CanCan
|
2
|
+
module ModelAdapters
|
3
|
+
class SequelAdapter < AbstractAdapter
|
4
|
+
def self.for_class?(model_class)
|
5
|
+
model_class <= Sequel::Model
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.find(model_class, id)
|
9
|
+
model_class[id]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.override_condition_matching?(subject, name, value)
|
13
|
+
value.kind_of?(Hash)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.matches_condition?(subject, name, value)
|
17
|
+
obj = subject.send(name)
|
18
|
+
if obj.nil?
|
19
|
+
false
|
20
|
+
else
|
21
|
+
value.each do |k, v|
|
22
|
+
if v.kind_of?(Hash)
|
23
|
+
return false unless self.matches_condition?(obj, k, v)
|
24
|
+
elsif obj.send(k) != v
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def database_records
|
32
|
+
if @rules.size == 0
|
33
|
+
@model_class.where('1=0')
|
34
|
+
else
|
35
|
+
# only need to process can rules if there are no can rule with empty conditions
|
36
|
+
rules = @rules.reject { |rule| rule.base_behavior && rule.conditions.empty? }
|
37
|
+
rules.reject! { |rule| rule.base_behavior } if rules.count < @rules.count
|
38
|
+
|
39
|
+
can_condition_added = false
|
40
|
+
rules.reverse.inject(@model_class.dataset) do |records, rule|
|
41
|
+
normalized_conditions = normalize_conditions(rule.conditions)
|
42
|
+
if rule.base_behavior
|
43
|
+
if can_condition_added
|
44
|
+
records.or normalized_conditions
|
45
|
+
else
|
46
|
+
can_condition_added = true
|
47
|
+
records.where normalized_conditions
|
48
|
+
end
|
49
|
+
else
|
50
|
+
records.exclude normalized_conditions
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def normalize_conditions(conditions, model_class = @model_class)
|
59
|
+
return conditions unless conditions.kind_of? Hash
|
60
|
+
conditions.inject({}) do |result_hash, (name, value)|
|
61
|
+
if value.kind_of? Hash
|
62
|
+
value = value.dup
|
63
|
+
association_class = model_class.association_reflection(name).associated_class
|
64
|
+
nested = value.inject({}) do |nested, (k, v)|
|
65
|
+
if v.kind_of?(Hash)
|
66
|
+
value.delete(k)
|
67
|
+
nested_class = association_class.association_reflection(k).associated_class
|
68
|
+
nested[k] = nested_class.where(normalize_conditions(v, association_class))
|
69
|
+
else
|
70
|
+
nested[k] = v
|
71
|
+
end
|
72
|
+
nested
|
73
|
+
end
|
74
|
+
result_hash[name] = association_class.where(nested)
|
75
|
+
else
|
76
|
+
result_hash[name] = value
|
77
|
+
end
|
78
|
+
result_hash
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
Sequel::Model.class_eval do
|
86
|
+
include CanCan::ModelAdditions
|
87
|
+
end
|