1

Using Rails 3.1.3 with Devise 1.5.3. My app has accounts and users. Each account can have multiple users. A user can have one role, "user" or "account_admin". Devise signup routes to accounts#new. The account and an initial account_admin user are created simultaneously. Got this working as described here (although things have evolved some since then).

An account_admin signs should be able to create additional users in that account. That's where I'm running into trouble: instead of creating new users, it's just redirecting to the user_path (users#show) page with the message "You are already signed in." (user_path is my overridden after_sign_in_path.)

This article asks a similar question. The answer suggests a separate namespace for admins, but since admins are part of my regular app I don't think that applies.

I've defined a complete UsersController. According to the log, GET "/users/new" renders from my "UsersController#new". However POST "/users" is intercepted by Devise and rendered from "Devise::RegistrationsController#create".

config/routes.rb

devise_for :users
devise_scope :user do
  get "signup",   :to => "accounts#new"
  get "signin",   :to => "devise/sessions#new"
  get "signout",  :to => "devise/sessions#destroy"
end
resources :users
resources :accounts

app/controllers/users_controller.rb

class UsersController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource # CanCan
  ...
  def new
    # CanCan:  @user = User.new
  end

  def create
    # CanCan:  @user = User.new(params[:user])
    @user.skip_confirmation! # confirm immediately--don't require email confirmation
    if @user.save
      flash[:success] = "User added and activated."
      redirect_to users_path # list of all users
    else
      render 'new'
    end
  end
  ...
end    

I've tried overriding the Devise controller, thinking I could tell it to use my users#create action if the user is already signed in. The log tells me it is using my controller ("Processing by RegistrationsController#create as HTML"), but it doesn't seem to execute its code. I've commented out my custom actions and just left in the logger lines, but I don't get my logging messages. And in spite of super being commented out, the behavior doesn't change--it still redirects with "You are already signed in."

config/routes.rb

devise_for :users, :controllers => {:registrations => "registrations"}

app/controllers/registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
  def new
    logger.info "Custom RegistrationsController:  new"
    super
  end

  def create
    logger.info "Custom RegistrationsController:  create"
#    super unless user_signed_in?
#    render "users#create"
  end

  def update
    super
  end
end 

What am I missing? How can I let the account_admin user create additional users?

Community
  • 1
  • 1
Mark Berry
  • 17,843
  • 4
  • 58
  • 88

2 Answers2

1

The main issue is that Devise was intercepting the POST "/users" (and a few other routes). Found this workaround to allow my Users controller handle those routes: change the devise_for to skip registrations, then add back in the routes for which Devise normally defines aliases:

routes.rb

devise_for :users, :skip => [:registrations]
devise_scope :user do
  get "signup",   :to => "accounts#new"
  get "signin",   :to => "devise/sessions#new"
  get "signout",  :to => "devise/sessions#destroy"
  get "cancel_user_registration", :to => "devise/registrations#cancel"
  post "user_registration",       :to => "users#create"
  get "new_user_registration",    :to => "accounts#new"
  get "edit_user_registration",   :to => "users#edit"
end
resources :users
resources :accounts

Never figured out why the Devise controller override wasn't working.

A user on this thread pointed out the devise_invitable gem which might be an interesting alternative.

Mark Berry
  • 17,843
  • 4
  • 58
  • 88
0

This is how I ended up getting this to work with my setup (Devise tied to my User model -- no separate Editor/Admin model):

class UsermakersController < ApplicationController
before_action :authenticate_user!

def new
    @user = User.new
end

def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to users_path, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render users_path }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
end

private
    def user_params
      userParams = params.require(:user).permit(:name, :email)
    end
end

From here, when you want to add a new User as another User, simply call the Usermakers#new url in your form, e.g., I have this at the bottom of my Users index page:

 <%= link_to 'Add User', new_usermaker_path, id: 'new_user_link' %>

And the Usermakers form looks like:

= simple_form_for @user, url: usermakers_path, html: {multipart: true} do |f|
=f.error_notification errors: true

= f.input :name
= f.input :email

%p
= f.button :submit, 'Create User', class: 'button'

Of course, you'd need to add a dummy new.html.erb file which simply renders _form.html.erb to use this.

Just add the new and create methods to your routes.rb file (whether by resources :usermakers, or more specific routes) and you should be good to go. Hope this helps!

Q A
  • 200
  • 2
  • 11