Rails 4.2.7 & Devise 4.1.1 - Change password with current password required in user preferences page with AJAX -


my application has 3 different user types (i.e. devise models): superadminuser, adminuser , standarduser. every user, regardless of type, has preferences page able update number of attributes (e.g. :email, :password, :username, etc.), 2 of attributes requiring user enter current password update (:email, :password), while remaining attributes not require current password update.

now, in ideal world, preference updates utilize ajax attribute changed refresh in page rather entire page reload. have working of attributes don't require user enter current password, i've been unable work :email , :password. oddly enough, have working in previous prototype, had 1 devise user model, not three, , single model didn't have it's own registration controller overriding devise registration controller, 3 user models in current app do, although don't see in these overriding registration controllers impacting issue here.

the error message i'm getting own, on preferences page:

sorry, unable update password. 

the problem appears :current_password param value not being captured form. console log statement shows blank string, while :new_password , :new_password_confirmation values captured without problem. haven't been able determine why happening. alternate approach, tried mimic closely change password example in devise wiki (the last example) (here: https://github.com/plataformatec/devise/wiki/how-to:-allow-users-to-edit-their-password), no avail. suggestions appreciated.

additionally, guess important question ask if should using ajax password attribute. is, inherently insecure passing these password values via ajax? if so, there way securely (e.g. encrypted)?

here relevant code:

app/controllers/super_admin_users/preferences_controller.rb

class superadminusers::preferencescontroller < applicationcontroller    include applicationhelper   before_action :authenticate_super_admin_user!   .   .   .   def change_password     @super_admin_user = superadminuser.find_by(id: current_super_admin_user.id)     if resource.update_with_password(params.permit(:password,                                                    :password_confirmation,                                                    :current_password))       sign_in resource_name, self.resource, bypass: true       status_message = 'your password has been updated successfully!'     else       status_message = 'sorry, unable update password.'     end     respond_to |format|       format.json { render json: { status_message: status_message } }     end   end    def password_section_partial     @change_password_status_message = params[:change_password_status_message] || ""     render 'super_admin_users/preferences/password/password_section_partial'   end   .   .   .     end end 

app/views/super_admin_users/preferences/password/_change_password_form.html.haml

= form_tag super_admin_user_prefs_change_password_path, id: 'prefs-change-password-form'   .prefs-label-and-input-wrapper     #prefs-new-password-label-wrapper.prefs-input-label-wrapper       = label_tag 'password', 'new password', id:           'prefs-new-password-label',                                               class:        'prefs-input-label'     #prefs-new-password-input-wrapper.prefs-input-wrapper       = password_field_tag 'password', nil,   autofocus:     true,                                               autocomplete: 'off',                                               id:           'prefs-new-password-input',                                               class:        'prefs-input'   .prefs-label-and-input-wrapper     #prefs-new-password-confirmation-label-wrapper.prefs-input-label-wrapper       = label_tag 'password_confirmation', 'new password confirmation', id:           'prefs-new-confirmation-password-label',                                                                         class:        'prefs-input-label'     #prefs-new-password-confirmation-input-wrapper.prefs-input-wrapper       = password_field_tag 'password_confirmation', nil,                autocomplete: 'off',                                                                         id:           'prefs-new-password-confirmation-input',                                                                         class:        'prefs-input'   .prefs-label-and-input-wrapper     #prefs-current-password-label-wrapper.prefs-input-label-wrapper       = label_tag 'current_password', 'current password', id:           'prefs-current-password-label',                                                           class:        'prefs-input-label'     #prefs-current-password-input-wrapper.prefs-input-wrapper       = password_field_tag 'current_password', nil,       autocomplete: 'off',                                                           id:           'prefs-current-password-input',                                                           class:        'prefs-input'   #prefs-change-password-form-buttons-wrapper     #prefs-change-password-form-submit-btn-wrapper       = link_to 'update', 'javascript:;', id: 'prefs-change-password-form-submit-btn', class: 'btn btn-sm btn-success btn-submit'       -#%input{ id: 'prefs-change-password-form-submit-btn', class: 'btn btn-sm btn-success', type: 'submit', value: 'update' }     #prefs-change-password-form-cancel-btn-wrapper       = link_to 'cancel', 'javascript:;', id: 'prefs-change-password-form-cancel-btn', class: 'btn btn-sm btn-secondary btn-cancel' 

app/views/super_admin_users/preferences/password/_change_password_status_message.html.haml

#prefs-change-password-status-message.prefs-status-message= change_password_status_message 

app/views/super_admin_users/preferences/password/_password_section.html.haml

#prefs-password-section-header.prefs-section-header   #prefs-password-headline-wrapper     .prefs-section-headline password   #prefs-password-edit-btn-wrapper     = link_to 'edit', 'javascript:;', id: 'prefs-password-edit-btn', class: 'btn btn-sm btn-primary btn-edit' #prefs-change-password-form-wrapper.prefs-form-wrapper.no-display   = render partial: 'super_admin_users/preferences/password/change_password_form' #prefs-change-password-status-message-wrapper.prefs-status-message-wrapper.no-display 

app/views/super_admin_users/preferences/password/password_section_partial.js.haml

$('#prefs-change-password-status-message-wrapper').empty(); $('#prefs-change-password-form-wrapper').addclass('no-display'); $('#prefs-change-password-form').trigger('reset');  - if @change_password_status_message.present?   $('#prefs-change-password-status-message-wrapper').append("#{ escape_javascript(render(partial: 'super_admin_users/preferences/password/change_password_status_message', locals: { change_password_status_message: @change_password_status_message })) }");   $('#prefs-change-password-status-message-wrapper').removeclass('no-display');  $('#prefs-password-edit-btn').removeclass('no-display'); 

app/controllers/application_controller.rb

class applicationcontroller < actioncontroller::base   # prevent csrf attacks raising exception.   # apis, may want use :null_session instead.   protect_from_forgery with: :exception    include applicationhelper   include deviseparamsanitizeroverrides    def get_current_user_type     respond_to |format|       format.json { render json: { current_user_type: resource_name.to_s } }     end   end    def get_current_environment      respond_to |format|       format.json { render json: { current_environment: rails.env } }     end   end    protected      def devise_parameter_sanitizer       if resource_class.to_s == 'superadminuser'         superadminuser::parametersanitizer.new(superadminuser, :super_admin_user, params)       elsif resource_class.to_s == 'adminuser'         adminuser::parametersanitizer.new(adminuser, :admin_user, params)       elsif resource_class.to_s == 'standarduser'         standarduser::parametersanitizer.new(standarduser, :standard_user, params)       end     end  end 

app/controllers/concerns/devise_param_sanitizer_overrides.rb

module deviseparamsanitizeroverrides    extend activesupport::concern    class superadminuser::parametersanitizer < devise::parametersanitizer     def initialize(*)       super       permit(:sign_up,        keys: [:email, :first_name, :last_name, :username])       permit(:sign_in,        keys: [:email, :username])       permit(:account_update, keys: [:current_password, :email, :first_name, :last_name, :time_zone, :username])     end   end . . . end 

app/helpers/application_helper.rb

module applicationhelper      def resource       if super_admin_user_signed_in?         @super_admin_user ||= superadminuser.new       elsif admin_user_signed_in?         @admin_user       ||= adminuser.new       elsif standard_user_signed_in?         @standard_user    ||= standarduser.new       end     end      def resource_name       if super_admin_user_signed_in?         :super_admin_user       elsif admin_user_signed_in?         :admin_user       elsif standard_user_signed_in?         :standard_user       end     end      def resource_class       if super_admin_user_signed_in?         superadminuser       elsif admin_user_signed_in?         adminuser       elsif standard_user_signed_in?         standarduser       end     end      def devise_mapping       if super_admin_user_signed_in?         @devise_mapping ||= devise.mappings[:super_admin_user]       elsif admin_user_signed_in?         @devise_mapping ||= devise.mappings[:admin_user]       elsif standard_user_signed_in?         @devise_mapping ||= devise.mappings[:standard_user]       end     end      def resource_authenticated_root       if super_admin_user_signed_in?         authenticated_super_admin_user_root       elsif admin_user_signed_in?         authenticated_admin_user_root       elsif standard_user_signed_in?         authenticated_standard_user_root       end     end  end 

app/assets/javascripts/preferences.js

var currentusertype; var currentenvironment;  getcurrentusertype('/get_current_user_type' ).done(function(getcurrentusertyperesponse) {   currentusertype = getcurrentusertyperesponse.current_user_type; });  getcurrentenvironment('/get_current_environment' ).done(function(getcurrentenvironmentresponse) {   currentenvironment = getcurrentenvironmentresponse.current_environment; });   $(document).ready(function() {    $('#prefs-password-edit-btn').click(function (e) {     $('#prefs-password-edit-btn').addclass('no-display');     $('#prefs-change-password-form').trigger('reset');     $('#prefs-change-password-form-wrapper').removeclass('no-display');   });    $(function() {     return $('body').on('click', '#prefs-change-password-form-submit-btn', function() {       $('#prefs-change-password-form-wrapper').addclass('no-display');       changepassword('/' + currentusertype + 's/preferences/change_password?password='              + $('#prefs-new-password-input').val() +                                                                           '&password_confirmation=' + $('#prefs-new-password-confirmation-input').val() +                                                                           '&current_password='      + $('#prefs-current-password-input').val()       ).done(function(changepasswordresponse) {         $.ajax({url: '/' + currentusertype + 's/preferences/password_section_partial?change_password_status_message=' + changepasswordresponse.status_message});       });     });   });    $(function() {     return $('body').on('click', '#prefs-change-password-form-cancel-btn', function() {       $('#prefs-change-password-form-wrapper').addclass('no-display');       $('#prefs-change-password-form').trigger('reset');       $('#prefs-password-edit-btn').removeclass('no-display');     });   });   function getcurrentusertype(url) {   return $.ajax({     url: url,     type: 'get',     datatype: 'json'   })   .fail(function() {     if (currentenvironment === 'development') {       alert('ajax current user type error');     }   }) }  function getcurrentenvironment(url) {   return $.ajax({     url: url,     type: 'get',     datatype: 'json'   })   .fail(function() {     alert('ajax current environment error');   }) }  function changepassword(url) {   return $.ajax({     url: url,     type: 'get',     datatype: 'json'   })   .fail(function() {     if (currentenvironment === 'development') {       alert('ajax change password error');     }   }) } 

config/routes.rb

rails.application.routes.draw    '/get_current_user_type',   to: 'application#get_current_user_type'   '/get_current_environment', to: 'application#get_current_environment'   .   .   .   devise_for :super_admin_users, controllers: { registrations: 'super_admin_users/registrations' }    authenticated :super_admin_user     root to: 'super_admin_users/dashboard#index', as: 'authenticated_super_admin_user_root'   end    :super_admin_user      'super_admin_users/preferences/password_section_partial', to: 'super_admin_users/preferences#password_section_partial',                                                                    as: :super_admin_user_password_section_partial      'super_admin_users/preferences/change_password',          to: 'super_admin_users/preferences#change_password',                                                                    as: :super_admin_user_prefs_change_password   end  end 


Comments

Popular posts from this blog

javascript - Thinglink image not visible until browser resize -

firebird - Error "invalid transaction handle (expecting explicit transaction start)" executing script from Delphi -

mongodb - How to keep track of users making Stripe Payments -