2

I'm using rails 4.0.2, devise and cancancan. I'm trying to allow an admin to create new users. Admin users are assigned with a boolean field in the users table.

In ability.rb I have the following:

can :manage, :all if user.admin?

Following some of the advise in this question I created a new controller called AdminsController and it looks like so:

class AdminsController < Devise::RegistrationsController
      def create
        build_resource(sign_up_params)
        if resource.save
          redirect_to admin_editors_path
        else
          clean_up_passwords resource
          respond_with resource
        end
      end

      def new
        build_resource({})
      end
end

I've tried to configure the routes as well:

  devise_for :users, :skip => [:registrations]
  as :user do
    get 'user/admin' => 'admins#new'
    post 'user/admin' => 'admins#create'
    get 'users/edit' => 'devise/registrations#edit', :as => :edit_user_registration
    post 'users/' => 'devise/registrations#create', :as => :user_registration
    get 'users/cancel' => 'devise/registrations#cancel', :as => :cancel_user_registration
  end

In devise/registrations/edit.html I'm trying to add a link to allow the user to create a new user like so:

<%= link_to "Create User", user_admin_path %>

The problem is that that link just redirects me to the home page with the message

You are already signed in.

I'm not really sure what I'm getting wrong here so any help at all would be much appreciated.

Community
  • 1
  • 1
SoSimple
  • 701
  • 9
  • 30

1 Answers1

0

The build_resource method in the Devise::RegistrationsController( on github ),

def build_resource(hash=nil)
  self.resource = resource_class.new_with_session(hash || {}, session)
end

builds a new resource by based the session. The user in the session (in this case) are the admin and are signed in.

You want to create a new User based on a new user instance of the user class, not based on a session.

Something like this should work.

class AdminsController < ApplicationController
 def new_user
  authorize! :manage, User
   @user = Users.new
 end
 def create_user
    @user = User.new(permitted_params.user)
    authorize! :manage, User
    if @user.save
     #success
    else
     #error
    end

 end
end

routes.rb

get "admins/new_user" => "admins#new_user", as: :admins_new_user
post "admins/create_user/:id" = "admins/create_user", as: :admins_create_user

link to new user

<%= link_to "Create User", admins_new_user_path %>

Form

  <%= form_for(@user, :url => admins_create_user_path) do |f| %>
  #fields and submit
  <% end %>

permitted_params.user is a method in a PermittedParams class, and it might be handy for you.

By passing current_user into the method you can allow different parameter for different users.

models/permitted_params.rb

class PermittedParams < Struct.new(:params, :current_user)
  def user
    params.require(:user).permit(*user_attributes)
  end
  def user_attributes
    if current_user.admin?
      [:name, :email,:password, :password_confirmation, :role ,:admin]
    else
      [ :name, :email, :remember_me,:password, :password_confirmation, ]
    end
  end
end
Andreas Lyngstad
  • 4,887
  • 2
  • 36
  • 69
  • I still get redirected to the home page with the message "you are already signed in". Do you think there's an issue with my routes? – SoSimple Apr 03 '14 at 12:08
  • Yes. Sorry I overlooked it. You should solve this outside devise. I'll update my answer. – Andreas Lyngstad Apr 03 '14 at 12:23
  • Updated. You should solve this outside devise because you just create users you don't sign them in or send out register mails. Devise only messes simple user creation up. – Andreas Lyngstad Apr 03 '14 at 12:35
  • Thanks this is definitely a huge improvement. I'm getting the new_user form but it's not saving for some reason. My logs look something like this: Started POST "/admins/create_user" for 192.168.1.70 at 2014-04-03 14:00:50 +0100 Processing by AdminsController#create_user as HTML Parameters: {#all_the_params, "commit"=>"Create User"} User Load (4.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1 (0.2ms) begin transaction (0.2ms) rollback transaction – SoSimple Apr 03 '14 at 13:03
  • Are #all_the_params permitted? – Andreas Lyngstad Apr 03 '14 at 13:57
  • Yeah, there's no problem there. I tried to debug a bit and other issues showed up. At first I forgot to change AdminsController > Devise::RegistrationsController to AdminsController::ApplicationController but when I did I got the error 'circular dependancy detected" also the permitted_params call in the controller was giving me a no method error so I left that out for now. It's a great touch and I just thought I'd put it in when the new user functionality was working :) – SoSimple Apr 03 '14 at 14:08
  • You kan learn more about strong parameters in this [railscast](http://railscasts.com/episodes/371-strong-parameters) and on [it's github page](https://github.com/rails/strong_parameters/). Don't forget to accept or/and vote if you like the answer. I am trying to get over 2000 to day ;) – Andreas Lyngstad Apr 03 '14 at 14:18
  • OH sorry! I had a typo. It should be `AdminsController < ApplicationController` not `AdminsController::ApplicationController`. I'll correct it – Andreas Lyngstad Apr 03 '14 at 14:21
  • I haven't tried it on my machine yet because I've run into some problems but a colleague did and it seems to be working perfectly! Thank you, and I hope you get your goal today :) – SoSimple Apr 03 '14 at 14:32
  • 1
    Hi, I have a error message here : undefined local variable or method `permitted_params' for # Can you tell me what is the problem ? – zauzaj Oct 12 '14 at 07:14