Search code examples
ruby-on-railsruby-on-rails-3activerecordmass-assignment

ActiveRecord roles with user permissions


Fairly new to rails so forgive me if I've misunderstood anything. I have a user model that looks like the below. Ideally what I'd like to do is have regular users only able to update their password, but have administrators able to change their username, email, etc...

class User < ActiveRecord::Base
  # Default auths
  attr_accessible :password, :password_confirmation, :remember_me
  # Admin auths
  attr_accessible :login, :username, :email, :password, :password_confirmation, :remember_me, :role_ids, :as => :admin
end

To update the record as an admin I do the following:

@user.update_attributes(params[:user], :as => :admin)

But lets say I want to update the user record as a non-admin:

@user.update_attributes(params[:user])

I receive the following exception:

ActiveModel::MassAssignmentSecurity::Error in UsersController#update
Can't mass-assign protected attributes: email, username

What I'd like to happen is for the non-accessible params to be ignored and for only accessible attributes to be update, whereas currently the whole update fails. Is this possible and more importantly is this the recommended way to do things? Would it be better to manually strip out the inaccessible parameters before calling update_attributes?


Solution

  • One thing you can do is set

    config.active_record.mass_assignment_sanitizer = :logger
    

    This will log the filtered attributes instead of throwing ActiveModel::MassAssignmentSecurity::Error.

    Alternatively, you can write your own sanitizer extending ActiveModel::MassAssignmentSecurity::Sanitizer, customizing process_removed_attributes to fail silently.

    As for your other questions

    ... is this the recommended way to do things? Would it be better to manually strip out the inaccessible parameters before calling update_attributes?

    I think you should be looking into why you're allowing a form to be submitted containing fields which will be rejected by Rails when submitted for some roles and not others. For example, it doesn't make sense to let a regular user see/change a Username text field in the form if attr_accessible for their role omits that attribute.

    You should instead hide the non-admin fields for users who are not admins, and leave the :strict sanitizer in place. The only time the ActiveModel::MassAssignmentSecurity::Error would be raised is if someone was modifying the DOM, trying to submit fields which they were not provided and thus not allowed to modify for the related model.