简体   繁体   中英

Admin Change Approval Status of User - Rails + Devise + Cancancan

I followed this link to figure out how to have an admin approve a new user. I have an approved attribute on my User model that is a boolean.

2 problems - 1) when I'm logged in as admin and go to the edit user via the link_to "Edit", edit_user_path(user) to change approved user - the url is for the correct user but then the update action tries to update the current admin user.

2) I would prefer to have the override of the needed current password so I've put a method in the Registrations controller to do this below but get this error:

error: unknown attribute 'current_password' for User.

So it won't override the current_password and it won't update the correct non-admin user - Where am I going wrong?

class Ability
      include CanCan::Ability

      def initialize(user)

       current_user ||= User.new # guest user (not logged in)
        if current_user.admin == true
          can :manage, :all
        else
          can :manage, User, id: user.id
        end       
      end
    end

Routes

Rails.application.routes.draw do
  devise_for :users, controllers: { registrations: 'registrations' }
  resources :users
end

Controller

class RegistrationsController < Devise::RegistrationsController

  def update_resource(resource, params)
    resource.update_without_password(params) if current_user.admin == true
  end
end

I spent a lot of time trying to solve this and didn't find any definitive, end-to-end complete examples online so I'm putting everything below so any new users to RoR/Devise hopefully won't have same problems.

Assuming Devise is on the User model. Ensure your Cancancan is setup accordingly. Something similar to this:

models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    # Define abilities for the passed in user here. For example:
    #
    current_user ||= User.new # guest user (not logged in)
    if current_user.admin
      can :manage, :all
    else
      can :manage, User, id: user.id
    end
 end
end

Follow the steps in here

He mentions have an 'admin-accessible only' page. In case someone's not sure how to do this:

class UsersController < ApplicationController
  before_action :admin?, only: :index

  def index
    if params[:approved] == false
      @users = User.where(approved: false)
    else
      @users = User.all
    end
  end

private
  def admin?
    redirect_to '/login' unless current_user.admin == true
  end

end

Replace this line (I use .erb not .haml as he does in the link) %td= link_to "Edit", edit_user_path(user) with this: <%= User.approved %>

          <td>
            <% if !User.approved %>
              <%= link_to "Approve User", user_path(:id => user.id, "user[approved]" => true), :method => :patch, class: "btn btn-success" %>
            <% else %>
              <%= link_to "Unapprove User", user_path(:id => user.id, "user[approved]" => false), :method => :patch, class: "btn btn-danger" %>
            <% end %>
          </td>

This essentially gives you a button that when clicked, will approve the user and visa-versa. The key here that tripped me up for days is that a) You have to ensure that your form (in this case, the link_to hits the Users controller and NOT the RegistrationsController#update method.

I know some online links gave instructions to create a Registrations model and changing routes, overriding models, etc.

Honestly, my final solution didn't need any of that. Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM