cancan 1.5.0 → 1.5.1

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.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,10 @@
1
+ 1.5.1 (January 20, 2011)
2
+
3
+ * Fixing deeply nested conditions in Active Record adapter - see issue #246
4
+
5
+ * Improving Mongoid support for multiple can and cannot definitions (thanks stellard) - see issue #239
6
+
7
+
1
8
  1.5.0 (January 11, 2011)
2
9
 
3
10
  * Added an Ability generator - see issue #170
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ when "data_mapper"
11
11
  gem "dm-migrations", "~> 1.0.2"
12
12
  when "mongoid"
13
13
  gem "bson_ext", "~> 1.1"
14
- gem "mongoid", "~> 2.0.0.beta.19"
14
+ gem "mongoid", "~> 2.0.0.beta.20"
15
15
  else
16
16
  raise "Unknown model adapter: #{ENV["MODEL_ADAPTER"]}"
17
17
  end
data/README.rdoc CHANGED
@@ -7,7 +7,7 @@ CanCan is an authorization library for Ruby on Rails which restricts what resour
7
7
 
8
8
  == Installation
9
9
 
10
- In <b>Rails 3</b>, add this to your Gemfile.
10
+ In <b>Rails 3</b>, add this to your Gemfile and run the +bundle+ command.
11
11
 
12
12
  gem "cancan"
13
13
 
@@ -22,13 +22,19 @@ Alternatively, you can install it as a plugin.
22
22
 
23
23
  == Getting Started
24
24
 
25
- CanCan expects a +current_user+ method to exist in controllers. 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/ryanb/cancan/wiki/changing-defaults] if you need to customize this behavior.
25
+ CanCan 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/ryanb/cancan/wiki/changing-defaults] if you need different behavior.
26
26
 
27
- Next, make an +Ability+ class. CanCan 1.5 includes a generator for this.
27
+
28
+ === 1. Define Abilities
29
+
30
+ User permissions are defined in an +Ability+ class. CanCan 1.5 includes a Rails 3 generator for creating this class.
28
31
 
29
32
  rails g cancan:ability
30
33
 
31
- This is where the user permission will be defined. See the comments in models/ability.rb and {Defining Abilities}[https://github.com/ryanb/cancan/wiki/defining-abilities] for details.
34
+ See {Defining Abilities}[https://github.com/ryanb/cancan/wiki/defining-abilities] for details.
35
+
36
+
37
+ === 2. Check Abilities & Authorization
32
38
 
33
39
  The current user's permissions can then be checked using the <tt>can?</tt> and <tt>cannot?</tt> methods in the view and controller.
34
40
 
@@ -38,14 +44,14 @@ The current user's permissions can then be checked using the <tt>can?</tt> and <
38
44
 
39
45
  See {Checking Abilities}[https://github.com/ryanb/cancan/wiki/checking-abilities] for more information
40
46
 
41
- The "authorize!" method in the controller will raise an exception if the user is not able to perform the given action.
47
+ The <tt>authorize!</tt> method in the controller will raise an exception if the user is not able to perform the given action.
42
48
 
43
49
  def show
44
50
  @article = Article.find(params[:id])
45
51
  authorize! :read, @article
46
52
  end
47
53
 
48
- Setting this for every action can be tedious, therefore the +load_and_authorize_resource+ method is provided to automatically authorize all actions in a RESTful style resource controller. It will use a before filter to load the resource into an instance variable and authorize it for each action.
54
+ Setting this for every action can be tedious, therefore the +load_and_authorize_resource+ method is provided to automatically authorize all actions in a RESTful style resource controller. It will use a before filter to load the resource into an instance variable and authorize it for every action.
49
55
 
50
56
  class ArticlesController < ApplicationController
51
57
  load_and_authorize_resource
@@ -57,6 +63,9 @@ Setting this for every action can be tedious, therefore the +load_and_authorize_
57
63
 
58
64
  See {Authorizing Controller Actions}[https://github.com/ryanb/cancan/wiki/authorizing-controller-actions] for more information.
59
65
 
66
+
67
+ === 3. Handle Unauthorized Access
68
+
60
69
  If the user authorization fails, a <tt>CanCan::AccessDenied</tt> exception will be raised. You can catch this and modify its behavior in the +ApplicationController+.
61
70
 
62
71
  class ApplicationController < ActionController::Base
@@ -82,9 +91,9 @@ See {Exception Handling}[https://github.com/ryanb/cancan/wiki/exception-handling
82
91
 
83
92
  == Questions or Problems?
84
93
 
85
- If you have any issues with CanCan which you cannot find the solution to in the documentation, please add an {issue on GitHub}[https://github.com/ryanb/cancan/issues] or fork the project and send a pull request.
94
+ If you have any issues with CanCan which you cannot find the solution to in the documentation[https://github.com/ryanb/cancan/wiki], please add an {issue on GitHub}[https://github.com/ryanb/cancan/issues] or fork the project and send a pull request.
86
95
 
87
- To get the specs running you should call +bundle+ and then +rake+. Specs currently do not work in Ruby 1.9 due to the RR mocking framework. See the {spec/README}[https://github.com/ryanb/cancan/blob/master/spec/README.rdoc] for more information.
96
+ To get the specs running you should call +bundle+ and then +rake+. See the {spec/README}[https://github.com/ryanb/cancan/blob/master/spec/README.rdoc] for more information.
88
97
 
89
98
 
90
99
  == Special Thanks
@@ -294,7 +294,7 @@ module CanCan
294
294
  #
295
295
  # class ApplicationController < ActionController::Base
296
296
  # rescue_from CanCan::AccessDenied do |exception|
297
- # flash[:error] = exception.message
297
+ # flash[:alert] = exception.message
298
298
  # redirect_to root_url
299
299
  # end
300
300
  # end
@@ -31,12 +31,13 @@ module CanCan
31
31
  end
32
32
  end
33
33
 
34
- def tableized_conditions(conditions)
34
+ def tableized_conditions(conditions, model_class = @model_class)
35
35
  return conditions unless conditions.kind_of? Hash
36
36
  conditions.inject({}) do |result_hash, (name, value)|
37
37
  if value.kind_of? Hash
38
- name = @model_class.reflect_on_association(name).table_name
39
- value = tableized_conditions(value)
38
+ association_class = model_class.reflect_on_association(name).class_name.constantize
39
+ name = model_class.reflect_on_association(name).table_name
40
+ value = tableized_conditions(value, association_class)
40
41
  end
41
42
  result_hash[name] = value
42
43
  result_hash
@@ -16,21 +16,18 @@ module CanCan
16
16
  end
17
17
 
18
18
  def database_records
19
- @model_class.where(conditions)
20
- end
21
-
22
- def conditions
23
- if @rules.size == 0
24
- false_query
19
+ if @rules.size == 0
20
+ @model_class.where(:_id => {'$exists' => false, '$type' => 7}) # return no records in Mongoid
25
21
  else
26
- @rules.first.conditions
22
+ @rules.inject(@model_class.all) do |records, rule|
23
+ if rule.base_behavior
24
+ records.or(rule.conditions)
25
+ else
26
+ records.excludes(rule.conditions)
27
+ end
28
+ end
27
29
  end
28
30
  end
29
-
30
- def false_query
31
- # this query is sure to return no results
32
- {:_id => {'$exists' => false, '$type' => 7}} # type 7 is an ObjectID (default for _id)
33
- end
34
31
  end
35
32
  end
36
33
  end
@@ -8,12 +8,23 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
8
8
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
9
 
10
10
  describe CanCan::ModelAdapters::ActiveRecordAdapter do
11
+ with_model :category do
12
+ table do |t|
13
+ t.boolean "visible"
14
+ end
15
+ model do
16
+ has_many :articles
17
+ end
18
+ end
19
+
11
20
  with_model :article do
12
21
  table do |t|
13
22
  t.boolean "published"
14
23
  t.boolean "secret"
24
+ t.integer "category_id"
15
25
  end
16
26
  model do
27
+ belongs_to :category
17
28
  has_many :comments
18
29
  end
19
30
  end
@@ -88,6 +99,13 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
88
99
  Comment.accessible_by(@ability).should == [comment1]
89
100
  end
90
101
 
102
+ it "should only read comments for visible categories through articles" do
103
+ @ability.can :read, Comment, :article => { :category => { :visible => true } }
104
+ comment1 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => true)))
105
+ comment2 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => false)))
106
+ Comment.accessible_by(@ability).should == [comment1]
107
+ end
108
+
91
109
  it "should allow conditions in SQL and merge with hash conditions" do
92
110
  @ability.can :read, Article, :published => true
93
111
  @ability.can :read, Article, ["secret=?", true]
@@ -56,7 +56,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
56
56
  lord = MongoidProject.create(:title => 'Lord')
57
57
  dude = MongoidProject.create(:title => 'Dude')
58
58
 
59
- MongoidProject.accessible_by(@ability, :read).should == [sir]
59
+ MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
60
60
  end
61
61
 
62
62
  it "should return everything when the defined ability is manage all" do
@@ -154,7 +154,24 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
154
154
  @ability.can :read, MongoidProject, :foo => {:bar => 1}
155
155
  MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
156
156
  end
157
+
158
+ it "should exclude from the result if set to cannot" do
159
+ obj = MongoidProject.create(:bar => 1)
160
+ obj2 = MongoidProject.create(:bar => 2)
161
+ @ability.can :read, MongoidProject
162
+ @ability.cannot :read, MongoidProject, :bar => 2
163
+ MongoidProject.accessible_by(@ability, :read).entries.should == [obj]
164
+ end
157
165
 
166
+ it "should combine the rules" do
167
+ obj = MongoidProject.create(:bar => 1)
168
+ obj2 = MongoidProject.create(:bar => 2)
169
+ obj3 = MongoidProject.create(:bar => 3)
170
+ @ability.can :read, MongoidProject, :bar => 1
171
+ @ability.can :read, MongoidProject, :bar => 2
172
+ MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
173
+ end
174
+
158
175
  it "should not allow to fetch records when ability with just block present" do
159
176
  @ability.can :read, MongoidProject do
160
177
  false
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: 3
4
+ hash: 1
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- - 0
10
- version: 1.5.0
9
+ - 1
10
+ version: 1.5.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Bates
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-11 00:00:00 -08:00
18
+ date: 2011-01-20 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency