Firstly, you probably want to clean up your abilities, as things seem a little confused at the moment. Ignoring everything else, it's probably a good idea to specify a custom action for modifying passwords, for clarity's sake. For example:
# ability.rb
def initialize(user)
...
cannot :manage_roles, :user
if user.has_role? :admin
can :manage_roles, :user
else
end
(What exactly are you trying to achieve with the rest of the rules? Currently if seems you're letting moderators read, edit and delete themselves only, is this what you intended?)
You'll probably want to hide or disable the roles section of your form for anyone that can't actually do anything with it:
#_form.html.erb
<%= simple_form_for @user do |f| %>
<%= f.association :roles, as: :check_boxes if can? :manage_roles, @user %>
<%= f.button :submit %>
<% end %>
(Note that can?
only takes two arguments, the action, and the object/class.)
If you want to be extra secure, you could also use the following check in the controller:
# users_controller.rb
def update
@user = User.find(params[:id])
user_params = params[:user]
if cannot? :manage_roles, @user
user_params.delete_if { |k, v| k.to_sym == :role_ids }
end
if @user.update_without_password(user_params)
redirect_to @user
else
render :action => "edit"
end
end
(You will need to double check what the correct key to remove from the params hash is, I'm assuming it's :role_ids
based on your attr_accessible
, but I don't really know simple_form that well.)