0

How do I enable the Superadmin to actually create Users? Do I need a policy CreateusersPolicy? My code currently takes me to a page/form where I can create a user, but it doesn't actually create the user.

Please let me know if I need to include more information!

config/routes.rb

Rails.application.routes.draw do
  devise_for :users
  resources :users, except: :create
  root "pages#home"

  get "index" => "users#index"
  get 'create_user' => 'users#create', as: :create_user 

controllers/application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  include Pundit
  protect_from_forgery 

  def authorize_superadmin
    redirect_to root_path, alert: 'Access Denied' unless current_user.superadmin?
  end
end

I also don't know what to put here in the create section.

controllers/users_controller.rb

class UsersController < ApplicationController
  before_filter :authenticate_user!
  #before_filter :authorize_superadmin, except [:show]
  #after_action :verify_authorized


  def create
    # user create code (can't get here if not admin)
  end

  def index
    @users = User.all
    authorize User
  end

  def show
   @user = User.find(params[:id])
   authorize @user
  end

  def update
    @user = User.find(params[:id])
    authorize @user
    if @user.update_attributes(secure_params)
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end

  def destroy
    user = User.find(params[:id])
    authorize user
    user.destroy
    redirect_to users_path, :notice => "User deleted."
  end

  private

  def secure_params
    params.require(:user).permit(:role)
  end

end

views/users/create.html.erb

<%= form_for User.new, url: create_user_path do |f| %>

  <div><%= f.label :first_name %><br />
  <%= f.text_field :first_name, autofocus: true %></div>

  <div><%= f.label :last_name %><br />
  <%= f.text_field :last_name, autofocus: true %></div>

  <div><%= f.label :email %><br />
  <%= f.email_field :email, autofocus: true %></div>

  <div><%= f.label :phone_number%><br />
  <%= f.phone_field :phone_number, autofocus: true %></div>

  <div><%= f.label :street %><br />
  <%= f.text_field :street, autofocus: true %></div>

  <div><%= f.label :city %><br />
  <%= f.text_field :city, autofocus: true %></div>

  <div><%= f.label :state %><br />
  <%= f.text_field :state, autofocus: true %></div>

  <div><%= f.label :zip %><br />
  <%= f.text_field :zip, autofocus: true %></div>

  <div><%= f.label :password %> <% if @validatable %><i>(<%= @minimum_password_length %> characters minimum)</i><% end %><br />
    <%= f.password_field :password, autocomplete: "off" %></div>

  <div><%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation, autocomplete: "off" %></div>

  <div><%= f.submit "Create" %></div>

<% end %>

app/polices/user_policy.rb

class UserPolicy
  attr_reader :current_user, :model

  def initialize(current_user, model)
    @current_user = current_user
    @user = model
  end

  def index?
    @current_user.superadmin?
  end

  def show?
    @current_user.superadmin? or @current_user == @user
  end

 def update?
    @current_user.superadmin?
 end

 def destroy?
   return false if @current_user == @user
    @current_user.superadmin?
 end

 def permitted_attributes
    if @current_user.superadmin?
      [:role]
    else
      [:name, :email]
    end
  end

end
rogue0137
  • 21
  • 5

1 Answers1

1

You don't have a create? method in the UserPolicy file so you aren't actually authorizing anything (as far as I can tell).

It should read like this:

# app/policies/user_policy.rb
def create?
  @current_user.superadmin?
end

# app/controllers/users_controller.rb
def create
  authorize User
  # rest of method to create user
end

Also, you don't need to (or want to IMO) have the authorize_superadmin method (you do have the before_filter commented out in the controller, so you aren't calling it) because a) you will call the authorize method in your action and this would be redundant and b) you want to keep your authorization logic in one location: the UserPolicy class. If the authorization fails, it will raise an exception and will not call the rest of the action.

The Pundit documentation is a great resource to get everything setup, but it does take a little bit of trial and error.

I also highly suggest that you create an ApplicationPolicy that you inherit all of your model specific authorization from so that you can catch things that you may not have defined. It is all in the documentation.

nikkon226
  • 998
  • 6
  • 11