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

CanCan ActiveModel::ForbiddenAttributesError with rails 4 #835

Open
Crystark opened this issue Mar 11, 2013 · 80 comments
Open

CanCan ActiveModel::ForbiddenAttributesError with rails 4 #835

Crystark opened this issue Mar 11, 2013 · 80 comments

Comments

@Crystark
Copy link

Hi,

I'm quite new to rails and i'm going for a Devise-CanCan-SimpleRoles approach on my project. I'm using CanCan 1.6.9.
It seems that since i rebuilt the project from scratch on rails4 beta1, i'm getting a ActiveModel::ForbiddenAttributesError when i try to create any entity using a controller wich extends my ApplicationController.

This seems to come from :

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  # load_and_authorize_resource
  before_filter do |controller|
    controller.class.cancan_resource_class.new(controller).load_and_authorize_resource unless controller.devise_controller?
  end
  before_filter :authenticate_user!

  private

  # Catching exceptions from Cancan
  rescue_from CanCan::AccessDenied do |exception|
    redirect_to :home, alert: exception.message
  end

end

I've tried using load_and_authorize_resource instead but it does the same error.

I think this might have to do with #763 and #571 but as i'm still quite new to rails, i'd rather be sure this issue is reported.

Thanks

Here's the full stacktrace of the error:

/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activemodel/lib/active_model/forbidden_attributes_protection.rb:21:in `sanitize_for_mass_assignment'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/attribute_assignment.rb:21:in `assign_attributes'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/core.rb:174:in `initialize'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/inheritance.rb:24:in `new'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/inheritance.rb:24:in `new'
cancan (1.6.9) lib/cancan/controller_resource.rb:85:in `build_resource'
cancan (1.6.9) lib/cancan/controller_resource.rb:66:in `load_resource_instance'
cancan (1.6.9) lib/cancan/controller_resource.rb:32:in `load_resource'
cancan (1.6.9) lib/cancan/controller_resource.rb:25:in `load_and_authorize_resource'
app/controllers/application_controller.rb:6:in `block in <class:ApplicationController>'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/callbacks.rb:408:in `_run__4520472595650506565__process_action__callbacks'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/callbacks.rb:78:in `run_callbacks'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/abstract_controller/callbacks.rb:17:in `process_action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal/rescue.rb:29:in `process_action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/notifications.rb:158:in `block in instrument'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/notifications.rb:158:in `instrument'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/abstract_controller/base.rb:136:in `process'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/abstract_controller/rendering.rb:44:in `process'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal.rb:196:in `dispatch'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_controller/metal.rb:232:in `block in action'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/routing/route_set.rb:80:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/routing/route_set.rb:80:in `dispatch'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/routing/route_set.rb:48:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/journey/router.rb:69:in `block in call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/journey/router.rb:57:in `each'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/journey/router.rb:57:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/routing/route_set.rb:645:in `call'
lib/my/middleware/locale.rb:20:in `call'
warden (1.2.1) lib/warden/manager.rb:35:in `block in call'
warden (1.2.1) lib/warden/manager.rb:34:in `catch'
warden (1.2.1) lib/warden/manager.rb:34:in `call'
rack (1.5.2) lib/rack/etag.rb:23:in `call'
rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
rack (1.5.2) lib/rack/head.rb:11:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/params_parser.rb:27:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/flash.rb:241:in `call'
rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/cookies.rb:452:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/query_cache.rb:36:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:632:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activerecord/lib/active_record/migration.rb:348:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/callbacks.rb:374:in `_run__2034566760718777775__call__callbacks'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/callbacks.rb:78:in `run_callbacks'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/callbacks.rb:27:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/reloader.rb:64:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
better_errors (0.7.0) lib/better_errors/middleware.rb:58:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/railties/lib/rails/rack/logger.rb:38:in `call_app'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/railties/lib/rails/rack/logger.rb:21:in `block in call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/tagged_logging.rb:67:in `block in tagged'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/tagged_logging.rb:25:in `tagged'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/tagged_logging.rb:67:in `tagged'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/railties/lib/rails/rack/logger.rb:21:in `call'
quiet_assets (1.0.2) lib/quiet_assets.rb:18:in `call_with_quiet_assets'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/request_id.rb:21:in `call'
rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
rack (1.5.2) lib/rack/runtime.rb:17:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/activesupport/lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.5.2) lib/rack/lock.rb:17:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/actionpack/lib/action_dispatch/middleware/static.rb:64:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/railties/lib/rails/engine.rb:511:in `call'
/data/home/mainuser/.bundler/ruby/2.0.0/rails-12f785fdc7c2/railties/lib/rails/application.rb:96:in `call'
rack (1.5.2) lib/rack/lock.rb:17:in `call'
rack (1.5.2) lib/rack/content_length.rb:14:in `call'
rack (1.5.2) lib/rack/handler/webrick.rb:60:in `service'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:138:in `service'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:94:in `run'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/server.rb:295:in `block in start_thread'
@natebird
Copy link

Hi @Crystark, welcome Rails and CanCan. The error you are running into (ActiveModel::ForbiddenAttributesError) is actually part of Rails 4 and the strong_parameters feature for model attributes. You can read more about how it works here: Edge Guides - Strong Parameters.

Basically this is a way of saying that CanCan isn't ready out of the box for Rails 4. There are a number of work arounds in the issues you referenced. I'd play around with those and see if those work well for you. The other option is to create an authorization system from scratch. @ryanb shows how in the Railscast about strong_parameters Authorization from scratch - Part I Authorization from scratch - Part II (PRO episodes require a subscription).

@Crystark
Copy link
Author

Thanks @natebird

I will try to see those workarounds. Any ideas on if and when CanCan will support strong_parameters ?
Thanks again

Edit: As stated in #571 one of the workarounds worked for me.

@natebird
Copy link

@Crystark there are a few pull requests waiting to be merged in that help support strong_parameters. Just waiting for @ryanb to pull them in.

@natebird
Copy link

Oh, and if the issue is resolved can you close it?

@miharekar
Copy link

I'm using Rails 4 rc1 and CanCan 1.6.10 and I'm still getting this error when creating. Is there some additional work I must do to get it going?

@tonytonyjan
Copy link

+1 for this. I'm having the same problem.

@LorandLorincz
Copy link

+1, Using Rails 4 rc and cancan 1.6.1

@ryanb ryanb reopened this May 26, 2013
@AntonTrapp
Copy link

+1, 4.0.0.rc1 + 1.6.10 - any workaround for this configuration?

@miharekar
Copy link

I use: load_and_authorize_resource except: [:create] just so I got it working but that shouldn't be used on production I guess.

@AntonTrapp
Copy link

Thanks, if someone has the same problem: #571 describes a workaround. In short:

In the ApplicationController:

before_filter do
  resource = controller_name.singularize.to_sym
  method = "#{resource}_params"
  params[resource] &&= send(method) if respond_to?(method, true)
end

and in the resource controller (for example NoteController):

def note_params
  params.require(:note).permit(:what, :ever)
end

@thenickcox
Copy link

Hey, @AntonTrapp! This fixed my issue. CanCan 1.6.10 and Rails 4.0.0.rc1. Thanks.

@ashleydw
Copy link

+1, 4.0.0.rc2 and 1.6.10. @AntonTrapp's fixs works here as well

@jirikolarik
Copy link

Thanks @AntonTrapp and I made some changes, now it's compatible with namespaces

  before_filter do
    resource = controller_path.singularize.gsub('/', '_').to_sym
    method = "#{resource}_params"
    params[resource] &&= send(method) if respond_to?(method, true)
  end

@leckylao
Copy link

Here's my workaround:
As load_resource will only load if resource is not there. So my approach is simply add a before_action before the load_and_authorize_resource to load the instance_resource in the strong_parameter way.

  # before_action :set_company, only: [:show, :edit, :update, :destroy]
  before_action :load_company, only: :create
  load_and_authorize_resource

  private
    # Use callbacks to share common setup or constraints between actions.
    # def set_company
    #   @company = Company.find(params[:id])
    # end

    def load_company
      @company = Company.new(company_params)
    end

So it's cleaner and dryer without double loading the resource

@amoose
Copy link

amoose commented Jul 25, 2013

+1 on rails 4.0.0.rc2 and cancan 1.6.10

@AntonTrapp / @jirikolarik workaround is working for me.

@chronosafe
Copy link

@AntonTrapp / @jirikolarik worked for me with Rails 4 release and cancan 1.6.10. Thanks for the short-term fix.

@Sovietaced
Copy link

Work around worked for me as well, thanks!

@jziggas
Copy link

jziggas commented Jul 31, 2013

Using cancan 1.6.1, ruby 2.0.0p247 and rails 4, and @AntonTrapp worked for me. Thank you.

@obelich
Copy link

obelich commented Aug 5, 2013

i get that error in Rails 4 and cancan (1.6.10) :(

but if i use
load_and_authorize_resource except: [:create]

it work thanks for @mrfoto

@alagos
Copy link

alagos commented Aug 5, 2013

@obelich the problem with that workaround is that any authenticated user will create your used model

@socketwiz
Copy link

+1 @AntonTrapp workaround fixes problem for me as well on 4.0.0.

@danawoodman
Copy link

👍 Thanks @AntonTrapp for the workaround!

@AntonTrapp
Copy link

Not my workaround, see #571 - credits go to mcbsys

@miharekar
Copy link

@obelich @alagos yeah, DON'T use my "solution". As I've said, it's just to get it going but shouldn't be used on production. It was a temp fix I used so I could work without going in depth about this issue. I would suggest either the solution @AntonTrapp reposted or the one from @lecky which is even nicer IMHO.

@burmjohn
Copy link

Thanks @AntonTrapp and @jirikolarik hopefully we will see a perm fix soon.

@rafaelcgo
Copy link

👍 for solution proposed by @AntonTrapp / @jirikolarik

@bman917
Copy link

bman917 commented Mar 29, 2014

Here is what worked for me....

  • create file under config/initializers/cancan.rb
module CanCan
  class ControllerResource
    alias_method :original_resource_params_by_namespaced, :resource_params_by_namespaced_name

    def resource_params_by_namespaced_name
      if (@controller && @params && @params[:action] == "create")
        strong_params =  @controller.method("#{namespaced_name.name.downcase}_params".to_sym)
        params = strong_params.call if defined? strong_params
      end
      params ||=  original_resource_params_by_namespaced
    end
  end
end
  • Restart your rails app.

Note:
This fix/workaround only works if your controller has the usual strong params method. For example, in FooController there should be:

def foo_params
  params.require(:foo).permit(:what, :ever)
end

@miharekar
Copy link

Just FYI we now have CanCanCan which fixes this and many other issues on the original CanCan repo 😉

@AntonTrapp
Copy link

WARNING: before you all run to CanCanCan, it is 1.x only!

@miharekar
Copy link

Well 2.x isn't usable yet anyway, right? And they say they will start working on 2.x when they figure out what exactly @ryanb had in mind building it. What I'm trying to say is that their 2.x is the same as CanCan 2.x - there is no work being done anywhere 😄

@AntonTrapp
Copy link

It is for some, just don't want them to be disappointed (like me, rushed to your site immediately lol).

@Crystark
Copy link
Author

I changed for Cancancan and did not have to change even one line of code for it to work. And FYI the fix I talked about in my first post has always been working.

@eljaydub
Copy link

eljaydub commented Apr 9, 2014

I just switched to CanCanCan and can also confirm that it is working without changing any code. I was able to remove the fix_cancan_forbidden_attr_error work-around in my application_controller.rb with any problems after switching to CanCanCan.

@Feuda
Copy link

Feuda commented Jun 17, 2014

@AntonTrapp +1 Cool, thanks

@xhoy
Copy link

xhoy commented Jul 1, 2014

Thanks for your submission! The ryanb/cancan repository has been inactive since Sep 06, 2013.
Since only Ryan himself has commit permissions, the CanCan project is on a standstill.

CanCan has many open issues, including missing support for Rails 4. To keep CanCan alive, an active fork exists at cancancommunity/cancancan. The new gem is cancancan. More info is available at #994.

If your pull request or issue is still applicable, it would be really appreciated if you resubmit it to CanCanCan.

We hope to see you on the other side!

@candidosales
Copy link

I lost 2 hours trying to find this bug ... Thank you!

@ombr
Copy link

ombr commented Jul 28, 2014

If you are getting the same error on new ( giving default params from the url) you can do this 👍

module CanCan
  class ControllerResource
    alias_method :original_resource_params_by_namespaced, :resource_params_by_namespaced_name

    def resource_params_by_namespaced_name
      if (@controller && @params && (@params[:action] == 'create' || (@params[namespaced_name.name.downcase] && @params[:action] == 'new')))
        strong_params =  @controller.method("#{namespaced_name.name.downcase}_params".to_sym)
        params = strong_params.call if defined? strong_params
      end
      params ||=  original_resource_params_by_namespaced
    end
  end
end

@karanahuja-android
Copy link

Hi guys

i started rails in this week only.
(i am working with piggyback demo and getting this error)
I am getting this error in rails admin.
any idea where i can apply the fix given by @AntonTrapp or by @bman917

Please help.

tc cheers,
karan

i cannot find where i can apply the workaround in rails admin

@miharekar
Copy link

@kodeycom switch to cancancan

@jirikolarik
Copy link

Switch to cancancan

On Sep 6, 2014, at 12:05, kodeycom [email protected] wrote:

Hi guys

i started rails in this week only.
(i am working with piggyback demo and getting this error)
I am getting this error in rails admin.
any idea where i can apply the fix given by @AntonTrapp https://github.com/AntonTrapp or by @bman917 https://github.com/bman917
Please help.

tc cheers,
karan

i cannot find where i can apply the workaround in rails admin


Reply to this email directly or view it on GitHub #835 (comment).

@CarlosRoque
Copy link

I spent an hour trying to figure out this problem
I just switched to CanCanCan and it worked without having to modify anything

Great work

@mitogh
Copy link

mitogh commented Nov 12, 2014

Thank you @AntonTrapp 👍

@xacaxulu
Copy link

+1

@xacaxulu
Copy link

Merci @ombr , ça marche bien~

module CanCan
  class ControllerResource
    alias_method :original_resource_params_by_namespaced, :resource_params_by_namespaced_name

    def resource_params_by_namespaced_name
      if (@controller && @params && @params[:action] == "create")
        strong_params =  @controller.method("#{namespaced_name.name.downcase}_params".to_sym)
        params = strong_params.call if defined? strong_params
      end
      params ||=  original_resource_params_by_namespaced
    end
  end
end

@ombr
Copy link

ombr commented Jan 12, 2015

De rien !

It works, but on my projects I moved to cancancan.

vmarquet added a commit to vmarquet/bartendr-server that referenced this issue Jan 12, 2015
* quand on n'a pas les droits, on a un message d'erreur propre
  pour dire que c'est interdit, et on est redirigé
* par contre, quand on a les droits pour faire un CREATE sur une table,
  on a une erreur ActiveModel::ForbiddenAttributesError
  qui d'après recherches, serait dûe au fait que CanCan n'a pas été
  mis à jour pour Rails 4 (cf ryanb/cancan#835)
  Il est donc conseillé d'utiliser la nouvelle version de CanCan,
  à savoir CanCanCan: https://github.com/CanCanCommunity/cancancan
atamis added a commit to fearlessandloathing/forum that referenced this issue Aug 25, 2015
… user info without specifying a "new" password

ryanb/cancan#835 , see this for new info on other solutions to the problem.
@MaksimPW
Copy link

@AntonTrapp,Thank you for help!

@PedroPauloML
Copy link

Thanks, @AntonTrapp, your solution fixed my issue. 👍

emcoding added a commit to rails-girls-summer-of-code/rgsoc-teams that referenced this issue May 26, 2018
Solved in cancancan Fixed in cancancan: ryanb/cancan#835 (comment)
@Thaisia
Copy link

Thaisia commented Feb 10, 2021

i had AdjustmentTask model and adj_task_params in its controller
it starts to work after renaming params method like model name: tcfto_adjustment_params

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests