Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: ryanb/cancan
base: 1.6.4
...
head fork: ryanb/cancan
compare: 1.6.5
  • 20 commits
  • 15 files changed
  • 0 commit comments
  • 6 contributors
Commits on Apr 01, 2011
Florent Piteau flop Failling test for nested resources with a scope for conditions 81f00f9
Florent Piteau flop When using an existing scope, it should be merged properly to the cla…
…ss. May fix ryanb/cancan#328 :)
a10243a
Mitch Williams thatothermitch Fixed bug where conditions on an optionally associated object would t…
…hrow exceptions if the associated object was not present at the rule match time.
6aaab9e
Ryan Bates Merge branch 'optional-associations' of https://github.com/socialcast…
…/cancan into socialcast-optional-associations
b1424df
Commits on Apr 15, 2011
Ryan Ahearn rahearn Adds ability to use Scope query with Mongoid
Same limitations apply as with active record
* can not be OR'd with other rules for same ability/controller
2b62041
Commits on Apr 25, 2011
Ryan Bates Merged pull request #343 from rahearn/mongoid-scope.
Adds ability to use Scope query with Mongoid
18c1007
Commits on Apr 27, 2011
John Feminella Augments Mongoid adapter by handling case where attribute is an array 17c52a7
Ryan Bates Merged pull request #352 from cardagin/topic/mongoid-adapter-enhancem…
…ents.

Augments Mongoid adapter by handling case where attribute is an array
a6af47d
Commits on Apr 29, 2011
Emmanuel Gomez emmanuel Use dkubb's suggestion for evaluating conditions against a Resource. 6d39b0a
Emmanuel Gomez emmanuel Fix pending spec for DataMapper adapter. d6851de
Emmanuel Gomez emmanuel Return empty set early if no can rules are present.
Thanks dkubb!
16bdb8d
Commits on May 02, 2011
Ryan Bates Merge pull request #355 from emmanuel/issue/245.
DataMapper adapter improvements
ff13a82
Commits on May 10, 2011
Ryan Ahearn rahearn Fixes bug in mongoid_adapter with empty conditions hash
* adds mongoid query that matches every record when
rule.conditions.empty? is true
ad62d60
Commits on May 12, 2011
Ryan Ahearn rahearn Processes can rules only if no empty conditions rules are present
1) remove all empty conditions hashes from the rules, they are included
 in the records through `@model_class.all`
2) only process can rules if the new and old rules lists are the same
  length (meaning there were no empty conditions hashes)
3) always process cannot rules
0882450
Commits on May 17, 2011
Ryan Bates ensure Mongoid::Document is defined before loading Mongoid adapter - …
…closes #359
cb9777b
Ryan Bates allow :through option to work with private controller methods - closes dde88c9
Ryan Bates adding current_ability to helper methods - closes #361 4e4c5a9
Ryan Bates Merge pull request #363 from rahearn/mongoid-conditions-empty
Fixes bug in mongoid_adapter with empty conditions hash
74c9d58
Commits on May 18, 2011
Ryan Bates pass action and subject through AccessDenied exception when :through …
…isn't found - closes #366
843fe89
Ryan Bates releasing 1.6.5 6a01427
18 CHANGELOG.rdoc
View
@@ -1,3 +1,21 @@
+1.6.5 (May 18, 2011)
+
+* pass action and subject through AccessDenied exception when :through isn't found - issue #366
+
+* many Mongoid adapter improvements (thanks rahearn, cardagin) - issues #363, #352, #343
+
+* allow :through option to work with private controller methods - issue #360
+
+* ensure Mongoid::Document is defined before loading Mongoid adapter - issue #359
+
+* many DataMapper adapter improvements (thanks emmanuel) - issue #355
+
+* handle checking nil attributes through associations (thanks thatothermitch) - issue #330
+
+* improve scope merging - issue #328
+
+
+
1.6.4 (March 29, 2011)
* Fixed mongoid 'or' error - see issue #322
2  cancan.gemspec
View
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "cancan"
- s.version = "1.6.4"
+ s.version = "1.6.5"
s.author = "Ryan Bates"
s.email = "ryan@railscasts.com"
s.homepage = "http://github.com/ryanb/cancan"
2  lib/cancan.rb
View
@@ -10,4 +10,4 @@
require 'cancan/model_adapters/default_adapter'
require 'cancan/model_adapters/active_record_adapter' if defined? ActiveRecord
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
-require 'cancan/model_adapters/mongoid_adapter' if defined? Mongoid
+require 'cancan/model_adapters/mongoid_adapter' if defined?(Mongoid) && defined?(Mongoid::Document)
2  lib/cancan/controller_additions.rb
View
@@ -286,7 +286,7 @@ def cancan_skipper
def self.included(base)
base.extend ClassMethods
- base.helper_method :can?, :cannot?
+ base.helper_method :can?, :cannot?, :current_ability
end
# Raises a CanCan::AccessDenied exception if the current_ability cannot
4 lib/cancan/controller_resource.rb
View
@@ -159,7 +159,7 @@ def resource_base
elsif @options[:shallow]
resource_class
else
- raise AccessDenied # maybe this should be a record not found error instead?
+ raise AccessDenied.new(nil, authorization_action, resource_class) # maybe this should be a record not found error instead?
end
else
resource_class
@@ -178,7 +178,7 @@ def parent_resource
def fetch_parent(name)
if @controller.instance_variable_defined? "@#{name}"
@controller.instance_variable_get("@#{name}")
- elsif @controller.respond_to? name
+ elsif @controller.respond_to?(name, true)
@controller.send(name)
end
end
2  lib/cancan/model_adapters/active_record_adapter.rb
View
@@ -87,7 +87,7 @@ def joins
def database_records
if override_scope
- override_scope
+ @model_class.scoped.merge(override_scope)
elsif @model_class.respond_to?(:where) && @model_class.respond_to?(:joins)
@model_class.where(conditions).joins(joins)
else
23 lib/cancan/model_adapters/data_mapper_adapter.rb
View
@@ -10,23 +10,22 @@ def self.override_conditions_hash_matching?(subject, conditions)
end
def self.matches_conditions_hash?(subject, conditions)
- subject.class.all(:conditions => conditions).include?(subject) # TODO don't use a database query here for performance and other instances
+ collection = DataMapper::Collection.new(subject.query, [ subject ])
+ !!collection.first(conditions)
end
def database_records
- scope = @model_class.all(:conditions => ["0=1"])
- conditions.each do |condition|
- scope += @model_class.all(:conditions => condition)
- end
+ scope = @model_class.all(:conditions => ["0 = 1"])
+ cans, cannots = @rules.partition { |r| r.base_behavior }
+ return scope if cans.empty?
+ # apply unions first, then differences. this mean cannot overrides can
+ cans.each { |r| scope += @model_class.all(:conditions => r.conditions) }
+ cannots.each { |r| scope -= @model_class.all(:conditions => r.conditions) }
scope
end
-
- def conditions
- @rules.map(&:conditions)
- end
- end
- end
-end
+ end # class DataMapper
+ end # module ModelAdapters
+end # module CanCan
DataMapper::Model.class_eval do
include CanCan::ModelAdditions::ClassMethods
31 lib/cancan/model_adapters/mongoid_adapter.rb
View
@@ -6,7 +6,14 @@ def self.for_class?(model_class)
end
def self.override_conditions_hash_matching?(subject, conditions)
- conditions.any? { |k,v| !k.kind_of?(Symbol) }
+ conditions.any? do |k,v|
+ key_is_not_symbol = lambda { !k.kind_of?(Symbol) }
+ subject_value_is_array = lambda do
+ subject.respond_to?(k) && subject.send(k).is_a?(Array)
+ end
+
+ key_is_not_symbol.call || subject_value_is_array.call
+ end
end
def self.matches_conditions_hash?(subject, conditions)
@@ -16,16 +23,22 @@ def self.matches_conditions_hash?(subject, conditions)
end
def database_records
- if @rules.size == 0
+ if @rules.size == 0
@model_class.where(:_id => {'$exists' => false, '$type' => 7}) # return no records in Mongoid
+ elsif @rules.size == 1 && @rules[0].conditions.is_a?(Mongoid::Criteria)
+ @rules[0].conditions
else
- @rules.inject(@model_class.all) do |records, rule|
- if rule.conditions.empty?
- records
- elsif rule.base_behavior
- records.or(rule.conditions)
+ # we only need to process can rules if
+ # there are no rules with empty conditions
+ rules = @rules.reject { |rule| rule.conditions.empty? }
+ process_can_rules = @rules.count == rules.count
+ rules.inject(@model_class.all) do |records, rule|
+ if process_can_rules && rule.base_behavior
+ records.or rule.conditions
+ elsif !rule.base_behavior
+ records.excludes rule.conditions
else
- records.excludes(rule.conditions)
+ records
end
end
end
@@ -37,4 +50,4 @@ def database_records
# simplest way to add `accessible_by` to all Mongoid Documents
module Mongoid::Document::ClassMethods
include CanCan::ModelAdditions::ClassMethods
-end
+end
2  lib/cancan/rule.rb
View
@@ -109,7 +109,7 @@ def matches_conditions_hash?(subject, conditions = @conditions)
if attribute.kind_of? Array
attribute.any? { |element| matches_conditions_hash? element, value }
else
- matches_conditions_hash? attribute, value
+ !attribute.nil? && matches_conditions_hash?(attribute, value)
end
elsif value.kind_of?(Array) || value.kind_of?(Range)
value.include? attribute
7 spec/cancan/ability_spec.rb
View
@@ -249,6 +249,13 @@
@ability.can?(:read, 1..5).should be_true
@ability.can?(:read, 4..6).should be_false
end
+
+ it "should not match subjects return nil for methods that must match nested a nested conditions hash" do
+ mock(object_with_foo = Object.new).foo { :bar }
+ @ability.can :read, Array, :first => { :foo => :bar }
+ @ability.can?(:read, [object_with_foo]).should be_true
+ @ability.can?(:read, []).should be_false
+ end
it "should not stop at cannot definition when comparing class" do
@ability.can :read, Range
2  spec/cancan/controller_additions_spec.rb
View
@@ -6,7 +6,7 @@
@controller = @controller_class.new
stub(@controller).params { {} }
stub(@controller).current_user { :current_user }
- mock(@controller_class).helper_method(:can?, :cannot?)
+ mock(@controller_class).helper_method(:can?, :cannot?, :current_ability)
@controller_class.send(:include, CanCan::ControllerAdditions)
end
5 spec/cancan/controller_resource_spec.rb
View
@@ -235,7 +235,10 @@
resource = CanCan::ControllerResource.new(@controller, :through => :category)
lambda {
resource.load_resource
- }.should raise_error(CanCan::AccessDenied)
+ }.should raise_error(CanCan::AccessDenied) { |exception|
+ exception.action.should == :show
+ exception.subject.should == Project
+ }
@controller.instance_variable_get(:@project).should be_nil
end
9 spec/cancan/model_adapters/active_record_adapter_spec.rb
View
@@ -125,6 +125,15 @@
Article.accessible_by(@ability).should == [article1]
end
+ it "should fetch only associated records when using with a scope for conditions" do
+ @ability.can :read, Article, Article.where(:secret => true)
+ category1 = Category.create!(:visible => false)
+ category2 = Category.create!(:visible => true)
+ article1 = Article.create!(:secret => true, :category => category1)
+ article2 = Article.create!(:secret => true, :category => category2)
+ category1.articles.accessible_by(@ability).should == [article1]
+ end
+
it "should raise an exception when trying to merge scope with other conditions" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, Article.where(:secret => true)
1  spec/cancan/model_adapters/data_mapper_adapter_spec.rb
View
@@ -65,7 +65,6 @@ class Comment
end
it "should fetch only the articles that are published and not secret" do
- pending "the `cannot` may require some custom SQL, maybe abstract out from Active Record adapter"
@ability.can :read, Article, :published => true
@ability.cannot :read, Article, :secret => true
article1 = Article.create(:published => true, :secret => false)
26 spec/cancan/model_adapters/mongoid_adapter_spec.rb
View
@@ -42,6 +42,15 @@ class MongoidProject
@ability.should be_able_to(:read, model)
end
+ it "should be able to read hashes when field is array" do
+ one_to_three = MongoidProject.create(:numbers => ['one', 'two', 'three'])
+ two_to_five = MongoidProject.create(:numbers => ['two', 'three', 'four', 'five'])
+
+ @ability.can :foo, MongoidProject, :numbers => 'one'
+ @ability.should be_able_to(:foo, one_to_three)
+ @ability.should_not be_able_to(:foo, two_to_five)
+ end
+
it "should return [] when no ability is defined so no records are found" do
MongoidProject.create(:title => 'Sir')
MongoidProject.create(:title => 'Lord')
@@ -59,6 +68,15 @@ class MongoidProject
MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
end
+ it "should be able to mix empty conditions and hashes" do
+ @ability.can :read, MongoidProject
+ @ability.can :read, MongoidProject, :title => 'Sir'
+ sir = MongoidProject.create(:title => 'Sir')
+ lord = MongoidProject.create(:title => 'Lord')
+
+ MongoidProject.accessible_by(@ability, :read).count.should == 2
+ end
+
it "should return everything when the defined ability is manage all" do
@ability.can :manage, :all
sir = MongoidProject.create(:title => 'Sir')
@@ -68,6 +86,14 @@ class MongoidProject
MongoidProject.accessible_by(@ability, :read).entries.should == [sir, lord, dude]
end
+ it "should allow a scope for conditions" do
+ @ability.can :read, MongoidProject, MongoidProject.where(:title => 'Sir')
+ sir = MongoidProject.create(:title => 'Sir')
+ lord = MongoidProject.create(:title => 'Lord')
+ dude = MongoidProject.create(:title => 'Dude')
+
+ MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
+ end
describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do
it "should handle :field.in" do

No commit comments for this range

Something went wrong with that request. Please try again.