0

I am building out an app using ruby 2.3.1 and rails 5, user authentication is Devise 4.

This project, my instructor wants an app with User, AdminUser ClientUser and SupportUser types, he is not allowing DeviseInvitable to be used, this app will never be used in production.

My workflow, at present is as follows, when a user (of any type is created) a password is generated and sent (this works), a user after confirming the account and logging in is forced to change their password (this works for User but not for AdminUser SupportUser and ClientUser)

here is how this is all setup:

#application_controller.rb
  # Force User To Change Password On First Login
  def after_sign_in_path_for(resource)
    if current_user.pw_changed == "false"
      edit_passwords_path
    else
      authenticated_root_path
    end
  end

passwords_controller.rb

class PasswordsController < ApplicationController

  def edit
    @user = current_user
  end

  def update
    if current_user.update_with_password(user_params.merge(pw_changed: "true"))
      flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
      redirect_to authenticated_root_path
    else
      flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
      render :edit
    end
  end

  private
    def user_params
      params.require(:user).permit(:current_password, :password, :password_confirmation)
    end


#views
_form.html.erb
edit.html.erb



# routes.rb
  # Force Password Change Routes and Resources
  resource :passwords

  resources :users, :type => 'User'
  resources :admin_users, :type => 'AdminUser'
  resources :client_users, :type => 'ClientUser'
  resources :support_users, :type => 'SupportUser'

My Models:

class User < ApplicationRecord - This also acts as custom show and user index
end

class AdminUser < User
end

class ClientUser < User
end

class SupportUser < User
end

when I Try to update an AdminUsers Password on first login this is the error and server output I get:

enter image description here

Server Output

Started PATCH "/passwords" for ::1 at 2016-09-26 14:59:28 -0600
Processing by PasswordsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"yEO6cUTLv8x2MU9lf1+bOYrpWTie17wE0TsIDEilbJzMWKSWmlQHC8mC3Bb9bkP3L3OhooY+wuwolFDO6fzxlg==", "admin_user"=>{"current_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Admin user"}
  User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 5], ["LIMIT", 1]]
Completed 400 Bad Request in 3ms (ActiveRecord: 0.9ms)



    ActionController::ParameterMissing - param is missing or the value is empty: user:
      actionpack (5.0.0.1) lib/action_controller/metal/strong_parameters.rb:308:in `require'
      app/controllers/passwords_controller.rb:19:in `user_params'
      app/controllers/passwords_controller.rb:8:in `update'
      actionpack (5.0.0.1) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
      actionpack (5.0.0.1) lib/abstract_controller/base.rb:188:in `process_action'
      actionpack (5.0.0.1) lib/action_controller/metal/rendering.rb:30:in `process_action'
      actionpack (5.0.0.1) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:126:in `call'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:455:in `call'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:448:in `block (2 levels) in around'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:267:in `block (2 levels) in halting_and_conditional'
      activesupport (5.0.0.1) lib/active_support/core_ext/time/zones.rb:64:in `use_zone'
      app/controllers/application_controller.rb:20:in `user_time_zone'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:382:in `block in make_lambda'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:266:in `block in halting_and_conditional'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:447:in `block in around'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:455:in `call'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:101:in `__run_callbacks__'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:750:in `_run_process_action_callbacks'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
      actionpack (5.0.0.1) lib/abstract_controller/callbacks.rb:19:in `process_action'
      actionpack (5.0.0.1) lib/action_controller/metal/rescue.rb:20:in `process_action'
      actionpack (5.0.0.1) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
      activesupport (5.0.0.1) lib/active_support/notifications.rb:164:in `block in instrument'
      activesupport (5.0.0.1) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
      activesupport (5.0.0.1) lib/active_support/notifications.rb:164:in `instrument'
      actionpack (5.0.0.1) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
      actionpack (5.0.0.1) lib/action_controller/metal/params_wrapper.rb:248:in `process_action'
      activerecord (5.0.0.1) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
      actionpack (5.0.0.1) lib/abstract_controller/base.rb:126:in `process'
      actionview (5.0.0.1) lib/action_view/rendering.rb:30:in `process'
      actionpack (5.0.0.1) lib/action_controller/metal.rb:190:in `dispatch'
      actionpack (5.0.0.1) lib/action_controller/metal.rb:262:in `dispatch'
      actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
      actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb:32:in `serve'
      actionpack (5.0.0.1) lib/action_dispatch/journey/router.rb:39:in `block in serve'
      actionpack (5.0.0.1) lib/action_dispatch/journey/router.rb:26:in `each'
      actionpack (5.0.0.1) lib/action_dispatch/journey/router.rb:26:in `serve'
      actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb:725:in `call'
      warden (1.2.6) lib/warden/manager.rb:35:in `block in call'
      warden (1.2.6) lib/warden/manager.rb:34:in `catch'
      warden (1.2.6) lib/warden/manager.rb:34:in `call'
      rack (2.0.1) lib/rack/etag.rb:25:in `call'
      rack (2.0.1) lib/rack/conditional_get.rb:38:in `call'
      rack (2.0.1) lib/rack/head.rb:12:in `call'
      rack (2.0.1) lib/rack/session/abstract/id.rb:222:in `context'
      rack (2.0.1) lib/rack/session/abstract/id.rb:216:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/cookies.rb:613:in `call'
      activerecord (5.0.0.1) lib/active_record/migration.rb:552:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
      activesupport (5.0.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
      better_errors (2.1.1) lib/better_errors/middleware.rb:84:in `protected_app_call'
      better_errors (2.1.1) lib/better_errors/middleware.rb:79:in `better_errors_call'
      better_errors (2.1.1) lib/better_errors/middleware.rb:57:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
      web-console (3.3.1) lib/web_console/middleware.rb:131:in `call_app'
      web-console (3.3.1) lib/web_console/middleware.rb:28:in `block in call'
      web-console (3.3.1) lib/web_console/middleware.rb:18:in `catch'
      web-console (3.3.1) lib/web_console/middleware.rb:18:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
      railties (5.0.0.1) lib/rails/rack/logger.rb:36:in `call_app'
      railties (5.0.0.1) lib/rails/rack/logger.rb:24:in `block in call'
      activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:70:in `block in tagged'
      activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:26:in `tagged'
      activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:70:in `tagged'
      railties (5.0.0.1) lib/rails/rack/logger.rb:24:in `call'
      sprockets-rails (3.2.0) lib/sprockets/rails/quiet_assets.rb:13:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/request_id.rb:24:in `call'
      rack (2.0.1) lib/rack/method_override.rb:22:in `call'
      rack (2.0.1) lib/rack/runtime.rb:22:in `call'
      activesupport (5.0.0.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
      actionpack (5.0.0.1) lib/action_dispatch/middleware/static.rb:136:in `call'
      rack (2.0.1) lib/rack/sendfile.rb:111:in `call'
      railties (5.0.0.1) lib/rails/engine.rb:522:in `call'
      puma (3.6.0) lib/puma/configuration.rb:225:in `call'
      puma (3.6.0) lib/puma/server.rb:578:in `handle_request'
      puma (3.6.0) lib/puma/server.rb:415:in `process_client'
      puma (3.6.0) lib/puma/server.rb:275:in `block in run'
      puma (3.6.0) lib/puma/thread_pool.rb:116:in `block in spawn_thread'

    Started POST "/__better_errors/462cce3c438acc05/variables" for ::1 at 2016-09-26 14:59:28 -0600
Shawn Wilson
  • 1,311
  • 14
  • 40

2 Answers2

1

You can use ActiveModel::Naming to get param keys, I18n keys or humanized versions of the names of any of your models.

class PasswordsController < ApplicationController

  def edit
  end

  def update
    if current_user.update_with_password(user_params.merge(pw_changed: "true"))
      flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
      redirect_to authenticated_root_path
    else
      flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
      render :edit
    end
  end

  private
    def user_params
      param_key = current_user.class.model_name.param_key
      params.require(param_key)
            .permit(:current_password, :password, :password_confirmation)
    end
end

You should also learn how to use the case statement (the Ruby equivalent of switch)

max
  • 96,212
  • 14
  • 104
  • 165
  • Thanks for the advice on case statements! im reading into it as we speak! Thanks for the assistance in the PasswordsController issue aswell worked like a charm! Really appreciated! – Shawn Wilson Sep 27 '16 at 02:27
0

So I think i have found a fix, probably not the most orthodox solution, but its working.. I made the following changes to the passwords controller:

class PasswordsController < ApplicationController

  def edit
  end

  def update
    if current_user.type == "User"
      if current_user.update_with_password(user_params.merge(pw_changed: "true"))
        flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
        redirect_to authenticated_root_path
      else
        flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
        render :edit
      end
    elsif current_user.type == "AdminUser"
      if current_user.update_with_password(user_params.merge(pw_changed: "true"))
        flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
        redirect_to authenticated_root_path
      else
        flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
        render :edit
      end
    elsif current_user.type == "ClientUser"
      if current_user.update_with_password(user_params.merge(pw_changed: "true"))
        flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
        redirect_to authenticated_root_path
      else
        flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
        render :edit
      end
    elsif current_user.type == "SupportUser"
      if current_user.update_with_password(user_params.merge(pw_changed: "true"))
        flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
        redirect_to authenticated_root_path
      else
        flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
        render :edit
      end
    end
  end

  private
    def user_params
      if current_user.type == "User"
        params.require(:user).permit(:current_password, :password, :password_confirmation)
      elsif current_user.type == "AdminUser"
        params.require(:admin_user).permit(:current_password, :password, :password_confirmation)
      elsif current_user.type == "ClientUser"
        params.require(:client_user).permit(:current_password, :password, :password_confirmation)
      elsif current_user.type == "SupportUser"
        params.require(:support_user).permit(:current_password, :password, :password_confirmation)
      end
    end

end
Shawn Wilson
  • 1,311
  • 14
  • 40