cancan 1.6.5 → 1.6.7

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.
@@ -1,3 +1,27 @@
1
+ 1.6.7 (October 4, 2011)
2
+
3
+ * fixing nested resource problem caused by namespace addition - issue #482
4
+
5
+
6
+ 1.6.6 (September 28, 2011)
7
+
8
+ * correct "return cant jump across threads" error when using check_authorization (thanks codeprimate) - issues #463, #469
9
+
10
+ * fixing tests in development by specifying with_model version (thanks kirkconnell) - issue #476
11
+
12
+ * added travis.yml file for TravisCI support (thanks bai) - issue #427
13
+
14
+ * better support for namespaced models (thanks whilefalse) - issues #424
15
+
16
+ * adding :id_param option to load_and_authorize_resource (thanks skhisma) - issue #425
17
+
18
+ * make default unauthorized message translatable text (thanks nhocki) - issue #409
19
+
20
+ * improving DataMapper behavior (thanks psanford, maxsum-corin) - issue #410, #373
21
+
22
+ * allow :find_by option to be full find method name - issue #335
23
+
24
+
1
25
  1.6.5 (May 18, 2011)
2
26
 
3
27
  * pass action and subject through AccessDenied exception when :through isn't found - issue #366
@@ -15,7 +39,6 @@
15
39
  * improve scope merging - issue #328
16
40
 
17
41
 
18
-
19
42
  1.6.4 (March 29, 2011)
20
43
 
21
44
  * Fixed mongoid 'or' error - see issue #322
data/Gemfile CHANGED
@@ -3,8 +3,8 @@ source "http://rubygems.org"
3
3
  case ENV["MODEL_ADAPTER"]
4
4
  when nil, "active_record"
5
5
  gem "sqlite3"
6
- gem "activerecord", :require => "active_record"
7
- gem "with_model"
6
+ gem "activerecord", '~> 3.0.9', :require => "active_record"
7
+ gem "with_model", '~> 0.1.5'
8
8
  gem "meta_where"
9
9
  when "data_mapper"
10
10
  gem "dm-core", "~> 1.0.2"
@@ -186,7 +186,7 @@ module CanCan
186
186
  skip_authorize_resource(*args)
187
187
  end
188
188
 
189
- # Skip both the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
189
+ # Skip the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
190
190
  # only do authorization on certain actions. You can pass :only and :except options to specify which actions to
191
191
  # skip the effects on. It will apply to all actions by default.
192
192
  #
@@ -202,7 +202,7 @@ module CanCan
202
202
  cancan_skipper[:load][name] = options
203
203
  end
204
204
 
205
- # Skip both the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
205
+ # Skip the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
206
206
  # only do loading on certain actions. You can pass :only and :except options to specify which actions to
207
207
  # skip the effects on. It will apply to all actions by default.
208
208
  #
@@ -247,9 +247,9 @@ module CanCan
247
247
  #
248
248
  def check_authorization(options = {})
249
249
  self.after_filter(options.slice(:only, :except)) do |controller|
250
- return if controller.instance_variable_defined?(:@_authorized)
251
- return if options[:if] && !controller.send(options[:if])
252
- return if options[:unless] && controller.send(options[:unless])
250
+ next if controller.instance_variable_defined?(:@_authorized)
251
+ next if options[:if] && !controller.send(options[:if])
252
+ next if options[:unless] && controller.send(options[:unless])
253
253
  raise AuthorizationNotPerformed, "This action failed the check_authorization because it does not authorize_resource. Add skip_authorization_check to bypass this check."
254
254
  end
255
255
  end
@@ -100,20 +100,36 @@ module CanCan
100
100
  if @options[:singleton] && parent_resource.respond_to?(name)
101
101
  parent_resource.send(name)
102
102
  else
103
- @options[:find_by] ? resource_base.send("find_by_#{@options[:find_by]}!", id_param) : resource_base.find(id_param)
103
+ if @options[:find_by]
104
+ if resource_base.respond_to? "find_by_#{@options[:find_by]}!"
105
+ resource_base.send("find_by_#{@options[:find_by]}!", id_param)
106
+ else
107
+ resource_base.send(@options[:find_by], id_param)
108
+ end
109
+ else
110
+ adapter.find(resource_base, id_param)
111
+ end
104
112
  end
105
113
  end
106
114
 
115
+ def adapter
116
+ ModelAdapters::AbstractAdapter.adapter_class(resource_class)
117
+ end
118
+
107
119
  def authorization_action
108
120
  parent? ? :show : @params[:action].to_sym
109
121
  end
110
122
 
111
123
  def id_param
112
- @params[parent? ? :"#{name}_id" : :id]
124
+ if @options[:id_param]
125
+ @params[@options[:id_param]]
126
+ else
127
+ @params[parent? ? :"#{name}_id" : :id]
128
+ end
113
129
  end
114
130
 
115
131
  def member_action?
116
- new_actions.include?(@params[:action].to_sym) || @options[:singleton] || (@params[:id] && !collection_actions.include?(@params[:action].to_sym))
132
+ new_actions.include?(@params[:action].to_sym) || @options[:singleton] || ( (@params[:id] || @params[@options[:id_param]]) && !collection_actions.include?(@params[:action].to_sym))
117
133
  end
118
134
 
119
135
  # Returns the class used for this resource. This can be overriden by the :class option.
@@ -122,7 +138,7 @@ module CanCan
122
138
  def resource_class
123
139
  case @options[:class]
124
140
  when false then name.to_sym
125
- when nil then name.to_s.camelize.constantize
141
+ when nil then namespaced_name.to_s.camelize.constantize
126
142
  when String then @options[:class].constantize
127
143
  else @options[:class]
128
144
  end
@@ -191,6 +207,12 @@ module CanCan
191
207
  @name || name_from_controller
192
208
  end
193
209
 
210
+ def namespaced_name
211
+ @name || @params[:controller].sub("Controller", "").singularize.camelize.constantize
212
+ rescue NameError
213
+ name
214
+ end
215
+
194
216
  def name_from_controller
195
217
  @params[:controller].sub("Controller", "").underscore.split('/').last.singularize
196
218
  end
@@ -40,7 +40,7 @@ module CanCan
40
40
  @message = message
41
41
  @action = action
42
42
  @subject = subject
43
- @default_message = "You are not authorized to access this page."
43
+ @default_message = I18n.t(:"unauthorized.default", :default => "You are not authorized to access this page.")
44
44
  end
45
45
 
46
46
  def to_s
@@ -1,5 +1,5 @@
1
- RSpec = Spec unless defined? RSpec # for RSpec 1 compatability
2
- RSpec::Matchers.define :be_able_to do |*args|
1
+ rspec_module = defined?(RSpec::Core) ? 'RSpec' : 'Spec' # for RSpec 1 compatability
2
+ Kernel.const_get(rspec_module)::Matchers.define :be_able_to do |*args|
3
3
  match do |ability|
4
4
  ability.can?(*args)
5
5
  end
@@ -15,6 +15,11 @@ module CanCan
15
15
  false # override in subclass
16
16
  end
17
17
 
18
+ # Override if you need custom find behavior
19
+ def self.find(model_class, id)
20
+ model_class.find(id)
21
+ end
22
+
18
23
  # Used to determine if this model adapter will override the matching behavior for a hash of conditions.
19
24
  # If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash
20
25
  def self.override_conditions_hash_matching?(subject, conditions)
@@ -5,6 +5,10 @@ module CanCan
5
5
  model_class <= DataMapper::Resource
6
6
  end
7
7
 
8
+ def self.find(model_class, id)
9
+ model_class.get(id)
10
+ end
11
+
8
12
  def self.override_conditions_hash_matching?(subject, conditions)
9
13
  conditions.any? { |k,v| !k.kind_of?(Symbol) }
10
14
  end
@@ -27,6 +31,4 @@ module CanCan
27
31
  end # module ModelAdapters
28
32
  end # module CanCan
29
33
 
30
- DataMapper::Model.class_eval do
31
- include CanCan::ModelAdditions::ClassMethods
32
- end
34
+ DataMapper::Model.append_extensions(CanCan::ModelAdditions::ClassMethods)
@@ -35,6 +35,18 @@ describe CanCan::ControllerResource do
35
35
  @controller.instance_variable_get(:@project).should == project
36
36
  end
37
37
 
38
+ it "should attempt to load a resource with the same namespace as the controller when using :: for namespace" do
39
+ module MyEngine
40
+ class Project < ::Project; end
41
+ end
42
+
43
+ project = MyEngine::Project.create!
44
+ @params.merge!(:controller => "MyEngine::ProjectsController", :action => "show", :id => project.id)
45
+ resource = CanCan::ControllerResource.new(@controller)
46
+ resource.load_resource
47
+ @controller.instance_variable_get(:@project).should == project
48
+ end
49
+
38
50
  it "should properly load resource for namespaced controller when using '::' for namespace" do
39
51
  project = Project.create!
40
52
  @params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id)
@@ -185,8 +197,8 @@ describe CanCan::ControllerResource do
185
197
 
186
198
  it "should load parent resource through proper id parameter" do
187
199
  project = Project.create!
188
- @params.merge!(:action => "index", :project_id => project.id)
189
- resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
200
+ @params.merge!(:controller => "categories", :action => "index", :project_id => project.id)
201
+ resource = CanCan::ControllerResource.new(@controller, :project)
190
202
  resource.load_resource
191
203
  @controller.instance_variable_get(:@project).should == project
192
204
  end
@@ -327,7 +339,15 @@ describe CanCan::ControllerResource do
327
339
  lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
328
340
  @controller.instance_variable_get(:@custom_project).should == project
329
341
  end
330
-
342
+
343
+ it "should load resource using custom ID param" do
344
+ project = Project.create!
345
+ @params.merge!(:action => "show", :the_project => project.id)
346
+ resource = CanCan::ControllerResource.new(@controller, :id_param => :the_project)
347
+ resource.load_resource
348
+ @controller.instance_variable_get(:@project).should == project
349
+ end
350
+
331
351
  it "should load resource using custom find_by attribute" do
332
352
  project = Project.create!(:name => "foo")
333
353
  @params.merge!(:action => "show", :id => "foo")
@@ -336,6 +356,14 @@ describe CanCan::ControllerResource do
336
356
  @controller.instance_variable_get(:@project).should == project
337
357
  end
338
358
 
359
+ it "should allow full find method to be passed into find_by option" do
360
+ project = Project.create!(:name => "foo")
361
+ @params.merge!(:action => "show", :id => "foo")
362
+ resource = CanCan::ControllerResource.new(@controller, :find_by => :find_by_name)
363
+ resource.load_resource
364
+ @controller.instance_variable_get(:@project).should == project
365
+ end
366
+
339
367
  it "should raise ImplementationRemoved when adding :name option" do
340
368
  lambda {
341
369
  CanCan::ControllerResource.new(@controller, :name => :foo)
@@ -32,4 +32,27 @@ describe CanCan::AccessDenied do
32
32
  @exception.message.should == "Access denied!"
33
33
  end
34
34
  end
35
+
36
+ describe "i18n in the default message" do
37
+ after(:each) do
38
+ I18n.backend = nil
39
+ end
40
+
41
+ it "uses i18n for the default message" do
42
+ I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"}
43
+ @exception = CanCan::AccessDenied.new
44
+ @exception.message.should == "This is a different message"
45
+ end
46
+
47
+ it "defaults to a nice message" do
48
+ @exception = CanCan::AccessDenied.new
49
+ @exception.message.should == "You are not authorized to access this page."
50
+ end
51
+
52
+ it "does not use translation if a message is given" do
53
+ @exception = CanCan::AccessDenied.new("Hey! You're not welcome here")
54
+ @exception.message.should == "Hey! You're not welcome here"
55
+ @exception.message.should_not == "You are not authorized to access this page."
56
+ end
57
+ end
35
58
  end
@@ -1,10 +1,6 @@
1
1
  if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
2
2
  require "spec_helper"
3
3
 
4
- RSpec.configure do |config|
5
- config.extend WithModel
6
- end
7
-
8
4
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
5
 
10
6
  describe CanCan::ModelAdapters::ActiveRecordAdapter do
@@ -56,6 +52,11 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
56
52
  CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter
57
53
  end
58
54
 
55
+ it "should find record" do
56
+ article = Article.create!
57
+ CanCan::ModelAdapters::ActiveRecordAdapter.find(Article, article.id).should == article
58
+ end
59
+
59
60
  it "should not fetch any records when no abilities are defined" do
60
61
  Article.create!
61
62
  Article.accessible_by(@ability).should be_empty
@@ -36,6 +36,11 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
36
36
  CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter
37
37
  end
38
38
 
39
+ it "should find record" do
40
+ article = Article.create
41
+ CanCan::ModelAdapters::DataMapperAdapter.find(Article, article.id).should == article
42
+ end
43
+
39
44
  it "should not fetch any records when no abilities are defined" do
40
45
  Article.create
41
46
  Article.accessible_by(@ability).should be_empty
@@ -36,6 +36,11 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
36
36
  CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter
37
37
  end
38
38
 
39
+ it "should find record" do
40
+ project = MongoidProject.create
41
+ CanCan::ModelAdapters::MongoidAdapter.find(MongoidProject, project.id).should == project
42
+ end
43
+
39
44
  it "should compare properties on mongoid documents with the conditions hash" do
40
45
  model = MongoidProject.new
41
46
  @ability.can :read, MongoidProject, :id => model.id
@@ -9,11 +9,15 @@ require 'matchers'
9
9
  require 'cancan/matchers'
10
10
 
11
11
  RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.filter_run :focus => true
14
+ config.run_all_when_everything_filtered = true
12
15
  config.mock_with :rr
13
16
  config.before(:each) do
14
17
  Project.delete_all
15
18
  Category.delete_all
16
19
  end
20
+ config.extend WithModel
17
21
  end
18
22
 
19
23
  class Ability
@@ -30,4 +34,12 @@ end
30
34
  class Project < SuperModel::Base
31
35
  belongs_to :category
32
36
  attr_accessor :category # why doesn't SuperModel do this automatically?
37
+
38
+ def self.respond_to?(method, include_private = false)
39
+ if method.to_s == "find_by_name!" # hack to simulate ActiveRecord
40
+ true
41
+ else
42
+ super
43
+ end
44
+ end
33
45
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cancan
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 6
9
- - 5
10
- version: 1.6.5
9
+ - 7
10
+ version: 1.6.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Bates
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-18 00:00:00 -04:00
19
- default_executable:
18
+ date: 2011-10-04 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: rspec
@@ -26,12 +25,12 @@ dependencies:
26
25
  requirements:
27
26
  - - ~>
28
27
  - !ruby/object:Gem::Version
29
- hash: 11
28
+ hash: 23
30
29
  segments:
31
30
  - 2
32
- - 1
31
+ - 6
33
32
  - 0
34
- version: 2.1.0
33
+ version: 2.6.0
35
34
  type: :development
36
35
  version_requirements: *id001
37
36
  - !ruby/object:Gem::Dependency
@@ -42,12 +41,12 @@ dependencies:
42
41
  requirements:
43
42
  - - ~>
44
43
  - !ruby/object:Gem::Version
45
- hash: 7
44
+ hash: 21
46
45
  segments:
47
46
  - 3
48
47
  - 0
49
- - 0
50
- version: 3.0.0
48
+ - 9
49
+ version: 3.0.9
51
50
  type: :development
52
51
  version_requirements: *id002
53
52
  - !ruby/object:Gem::Dependency
@@ -129,7 +128,6 @@ files:
129
128
  - Rakefile
130
129
  - README.rdoc
131
130
  - init.rb
132
- has_rdoc: true
133
131
  homepage: http://github.com/ryanb/cancan
134
132
  licenses: []
135
133
 
@@ -161,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
159
  requirements: []
162
160
 
163
161
  rubyforge_project: cancan
164
- rubygems_version: 1.5.3
162
+ rubygems_version: 1.8.6
165
163
  signing_key:
166
164
  specification_version: 3
167
165
  summary: Simple authorization solution for Rails.