3

I've been fiddling with CanCanCan gem to limit a regular user's actions, but so far I only managed to limit authorizations to a whole model, and what I really need is to limit access to some of its attributes.

For example, on my User model, besides the user/password/email stuff, I have a boolean for admin, which I use to validate the status of the logged user, in which case if user.admin?, it can access/manage everything, else, it should be able to read all, and can only update its own record if the user.id matches.

I've read the documentation through and through for many times, the closest I got was adding this to app/models/ability.rb

can :update, :users, [:name, :password, :email]

which doesn't do anything .

So,

The problem: The user can either :update the whole model, or just :read it, I can't set it to :update or :read on specific attributes.

What I need: The user to able to :edit only specific attributes.

The question: What is the correct syntax to limit attributes? Is there any other configuration I must set on some other files?

My Ability.rb file:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new
    if user.admin?
      can :manage, :all
      can :import, [User, Enclosure, Blade, Component]
    else
      can :access, :rails_admin
      can :dashboard
      can :read, :all
      can :history, :all
      # Allows user to only edit an enclosure, if it's allocated to itself, or not allocated at all
      can :update, Enclosure do |enclosure|
        can :update, Enclosure if (enclosure.allocated_to == user.email && enclosure.allocation == true) || enclosure.allocation == false
      end 
    end    
  end
end

Gems I'm using (besides the default Rails 4 gems):

# Administration Panel Gems
gem 'rails_admin'                    # Rails Administration Panel Gem
gem 'rails_admin_history_rollback'   # Enables users to visualize and revert history
gem 'rails_admin_import', "~> 1.0.0" # Enables importing
gem 'devise'                         # Authentication Gem
gem 'cancancan'                      # Authorization Gem
gem 'paper_trail', '~> 4.0.0.rc'     # Auditing Gem (History)

Thank you!

1 Answers1

6

I think you should use strong parameters. This gem lets you choose which parameters do you want to be updated. If you are using Rails 4, the gem is already installed, otherwise you can install it.

class UsersController < ApplicationController
  load_and_authorize_resource

  def update
    if @user.update_attributes(update_params)
      # hurray
    else
      render :edit
    end
  end

  private

  def update_params
    if current_user.admin?
      params.require(:user).permit(:user, :email, :password, :admin)
    else
      params.require(:user).permit(:user, :email, :password)
    end
  end
end
Andrici Cezar
  • 603
  • 1
  • 9
  • 15