Skip to content
This repository has been archived by the owner on Dec 12, 2021. It is now read-only.

While we wait for 1.6.11... #989

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2ea73a9
Fixes nested ability conditions in issue #859
ricec May 23, 2013
e87464b
FIX: Variable collision prevents defining permissions with multiple n…
knoopx Nov 21, 2013
c8aec29
Use scoped to avoid sql query execution
Dec 11, 2013
5155f63
Avoid deprecation warning with AR 4
Dec 12, 2013
375c012
Update to pass specs
Dec 12, 2013
a1ba470
Changing [].flatten to array wrapper method
ralbt Dec 29, 2013
d3e4fd7
Do not execute the scope condition on class permission checks.
matt-glover Dec 7, 2013
ba5294d
id_param now returns nil when the param is nil
francocatena May 8, 2013
44c2ca7
treat ActiveRecord::Relation as Array
francocatena Dec 2, 2013
d5a0732
Fix typo
francocatena Dec 2, 2013
bd755e2
Remove .rvmrc, use .ruby-version, and move to 1.9.3
bryanrite Jan 27, 2014
8976293
Allow multiple abilities with associations
Aug 22, 2012
cd04d23
removed rr, bump rspec version to 2.14, expect syntax, ruby 1.9.3/2.0…
ogerman Jul 23, 2013
a30dfb2
ruby 1.8 style hash syntax
ogerman Jul 23, 2013
be24a2c
use expect syntax for Mongoid and DataMappper specs
ogerman Jul 25, 2013
b5bfda6
removed should spec wording, same as on the 2nd branch
ryanb Apr 22, 2012
04acbdc
Reduce object allocations
Aug 22, 2013
3c97fb3
Fixes to specs for spec update.
bryanrite Jan 27, 2014
23b2ed6
Support for strong_parameters
bryanrite Jan 28, 2014
535e5db
Merge pull request #1 from bryanrite/yet_another_strong_params_support
bryanrite Jan 28, 2014
d76b2b0
Run against modern rubies.
bryanrite Jan 28, 2014
8e70203
Add back in 1.8.7 support.
bryanrite Jan 28, 2014
014f513
add jruby and rubinus to travis
bryanrite Jan 29, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .rbenv-version

This file was deleted.

1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.9.3
1 change: 0 additions & 1 deletion .rvmrc

This file was deleted.

9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- 2.0.0
- 2.1.0
- ree
- jruby
- rbx
matrix:
allow_failures:
- rvm: rbx
notifications:
recipients:
- [email protected]
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.rdoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Master

* Adds support for strong_parameters (bryanrite)

1.6.10 (May 7, 2013)

* fix matches_conditons_hash for string values on 1.8 (thanks rrosen)
Expand Down
5 changes: 4 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ source "https://rubygems.org"

case ENV["MODEL_ADAPTER"]
when nil, "active_record"
gem "sqlite3"
# Sqlite for CRuby, Rubinius, including Windows and RubyInstaller
gem "sqlite3", :platform => [:ruby, :mswin, :mingw]
# Sqlite for JRuby
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
gem "activerecord", '~> 3.0.9', :require => "active_record"
gem "with_model", "~> 0.2.5"
gem "meta_where"
Expand Down
36 changes: 33 additions & 3 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= CanCan
{<img src="https://fury-badge.herokuapp.com/rb/cancan.png" alt="Gem Version" />}[http://badge.fury.io/rb/cancan]
{<img src="https://secure.travis-ci.org/ryanb/cancan.png?branch=master" />}[http://travis-ci.org/ryanb/cancan]
{<img src="https://fury-badge.herokuapp.com/rb/cancan.png" alt="Gem Version" />}[http://badge.fury.io/rb/cancan]
{<img src="https://secure.travis-ci.org/ryanb/cancan.png?branch=master" />}[http://travis-ci.org/ryanb/cancan]
{<img src="https://codeclimate.com/github/ryanb/cancan.png" />}[https://codeclimate.com/github/ryanb/cancan]

Wiki[https://github.com/ryanb/cancan/wiki] | RDocs[http://rdoc.info/projects/ryanb/cancan] | Screencast[http://railscasts.com/episodes/192-authorization-with-cancan]
Expand Down Expand Up @@ -34,7 +34,7 @@ User permissions are defined in an +Ability+ class. CanCan 1.5 includes a Rails

rails g cancan:ability

In Rails 2.3, just add a new class in `app/models/ability.rb` with the following contents:
In Rails 2.3, just add a new class in <tt>app/models/ability.rb</tt> with the following contents:

class Ability
include CanCan::Ability
Expand Down Expand Up @@ -76,6 +76,36 @@ Setting this for every action can be tedious, therefore the +load_and_authorize_
See {Authorizing Controller Actions}[https://github.com/ryanb/cancan/wiki/authorizing-controller-actions] for more information.


==== Strong Parameters

When using <tt>strong_parameters</tt> or Rails 4+, you have to sanitize inputs before saving the record, in actions such as <tt>:create</tt> and <tt>:update</tt>.

By default, CanCan will try to sanitize the input on <tt>:create</tt> and <tt>:update</tt> routes by seeing if your controller will respond to the following methods (in order):

* <tt>create_params</tt> or <tt>update_params</tt> (depending on the action you are performing)
* <tt><model_name>_params</tt> such as <tt>article_params</tt> (this is the default convention in rails for naming your param method)
* <tt>resource_params</tt> (a generically named method you could specify in each controller)

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.

class ArticlesController < ApplicationController
load_and_authorize_resource param_method: :my_sanitizer

def create
if @article.save
# hurray
else
render :new
end
end

private

def my_sanitizer
params.require(:article).permit(:name)
end
end

=== 3. Handle Unauthorized Access

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+.
Expand Down
3 changes: 1 addition & 2 deletions cancan.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ Gem::Specification.new do |s|
s.files = Dir["{lib,spec}/**/*", "[A-Z]*", "init.rb"] - ["Gemfile.lock"]
s.require_path = "lib"

s.add_development_dependency 'rspec', '~> 2.6.0'
s.add_development_dependency 'rspec', '~> 2.14.0'
s.add_development_dependency 'rails', '~> 3.0.9'
s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43
s.add_development_dependency 'supermodel', '~> 0.1.4'

s.rubyforge_project = s.name
Expand Down
21 changes: 17 additions & 4 deletions lib/cancan/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,20 @@ def unauthorized_message_keys(action, subject)
# This should be called before "matches?" and other checking methods since they
# rely on the actions to be expanded.
def expand_actions(actions)
actions.map do |action|
aliased_actions[action] ? [action, *expand_actions(aliased_actions[action])] : action
end.flatten
expanded_actions[actions] ||= begin
expanded = []
actions.each do |action|
expanded << action
if aliases = aliased_actions[action]
expanded += expand_actions(aliases)
end
end
expanded
end
end

def expanded_actions
@expanded_actions ||= {}
end

# Given an action, it will try to find all of the actions which are aliased to it.
Expand All @@ -278,10 +289,12 @@ def rules
# Returns an array of Rule instances which match the action and subject
# This does not take into consideration any hash conditions or block statements
def relevant_rules(action, subject)
rules.reverse.select do |rule|
relevant = rules.select do |rule|
rule.expanded_actions = expand_actions(rule.actions)
rule.relevant? action, subject
end
relevant.reverse!
relevant
end

def relevant_rules_for_match(action, subject)
Expand Down
39 changes: 32 additions & 7 deletions lib/cancan/controller_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,15 @@ def authorization_action
end

def id_param
@params[id_param_key].to_s if @params[id_param_key]
end

def id_param_key
if @options[:id_param]
@params[@options[:id_param]]
@options[:id_param]
else
@params[parent? ? :"#{name}_id" : :id]
end.to_s
parent? ? :"#{name}_id" : :id
end
end

def member_action?
Expand Down Expand Up @@ -177,7 +181,9 @@ def collection_instance
def resource_base
if @options[:through]
if parent_resource
@options[:singleton] ? resource_class : parent_resource.send(@options[:through_association] || name.to_s.pluralize)
base = @options[:singleton] ? resource_class : parent_resource.send(@options[:through_association] || name.to_s.pluralize)
base = base.scoped if base.respond_to?(:scoped) && defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR == 3
base
elsif @options[:shallow]
resource_class
else
Expand Down Expand Up @@ -214,7 +220,9 @@ def name
end

def resource_params
if @options[:class]
if param_actions.include?(@params[:action].to_sym) && params_method.present?
return @controller.send(params_method)
elsif @options[:class]
params_key = extract_key(@options[:class])
return @params[params_key] if @params[params_key]
end
Expand All @@ -226,6 +234,19 @@ def resource_params_by_namespaced_name
@params[extract_key(namespaced_name)]
end

def params_method
params_methods.each do |method|
return method if @controller.respond_to?(method, true)
end
nil
end

def params_methods
methods = ["#{@params[:action]}_params".to_sym, "#{name}_params".to_sym, :resource_params]
methods.unshift(@options[:param_method]) if @options[:param_method].present?
methods
end

def namespace
@params[:controller].split(/::|\//)[0..-2]
end
Expand All @@ -245,11 +266,15 @@ def instance_name
end

def collection_actions
[:index] + [@options[:collection]].flatten
[:index] + Array(@options[:collection])
end

def new_actions
[:new, :create] + [@options[:new]].flatten
[:new, :create] + Array(@options[:new])
end

def param_actions
[:create, :update]
end

private
Expand Down
7 changes: 3 additions & 4 deletions lib/cancan/model_adapters/active_record_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ def tableized_conditions(conditions, model_class = @model_class)
value.delete(k)
nested[k] = v
else
name = model_class.reflect_on_association(name).table_name.to_sym
result_hash[name] = value
result_hash[model_class.reflect_on_association(name).table_name.to_sym] = value
end
nested
end
Expand Down Expand Up @@ -102,9 +101,9 @@ def database_records
elsif @model_class.respond_to?(:where) && @model_class.respond_to?(:joins)
mergeable_conditions = @rules.select {|rule| rule.unmergeable? }.blank?
if mergeable_conditions
@model_class.where(conditions).joins(joins)
@model_class.where(conditions).includes(joins)
else
@model_class.where(*(@rules.map(&:conditions))).joins(joins)
@model_class.where(*(@rules.map(&:conditions))).includes(joins)
end
else
@model_class.scoped(:conditions => conditions, :joins => joins)
Expand Down
4 changes: 2 additions & 2 deletions lib/cancan/rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def matches_conditions?(action, subject, extra_args)
matches_conditions_hash?(subject)
else
# Don't stop at "cannot" definitions when there are conditions.
@conditions.empty? ? true : @base_behavior
conditions_empty? ? true : @base_behavior
end
end

Expand Down Expand Up @@ -111,7 +111,7 @@ def matches_conditions_hash?(subject, conditions = @conditions)
else
attribute = subject.send(name)
if value.kind_of?(Hash)
if attribute.kind_of? Array
if attribute.kind_of?(Array) || attribute.kind_of?(ActiveRecord::Relation)
attribute.any? { |element| matches_conditions_hash? element, value }
else
!attribute.nil? && matches_conditions_hash?(attribute, value)
Expand Down
Loading