Подтвердить что ты не робот

Настройка пользователя без пароля

Я хочу обновить атрибуты пользователей без пароля. Дело в том, что, если поля подтверждения пароля и пароля не пустые, мне нужно разработать ошибку, и если они пусты, тогда необходимо обновить другие пользовательские атрибуты. Как я мог сделать это с помощью разработки?

Спасибо заранее!

4b9b3361

Ответ 2

Я думаю, что это гораздо лучшее решение:

if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
    params[:user].delete(:password)
    params[:user].delete(:password_confirmation)
end

Это не позволяет вам изменить контроллер Devise, просто удалив поле пароля из ответа формы, если оно пустое.

Просто используйте это до @user.attributes = params[:user] или все, что вы используете в своем действии update, чтобы установить новые параметры из формы.

Ответ 3

Я думаю, что с помощью Devise 3.2+ вы можете просто переопределить update_resource в своем подклассовом контроллере. Вот пример изначально заданного вопроса:

class MyRegistrationsController < Devise::RegistrationsController
  protected

  def update_resource(resource, params)
    resource.update_without_password(params)
  end
end

Ответ 4

Я решил эту проблему следующим образом: если форма отправляется с паролем, то нужно заполнить поле current_password или обновить форму без пароля и current_password

в модели:

class User
  devise: bla-bla-bla

  attr_accessor :current_password
end

В контроллере:

class Users::RegistrationsController <  Devise::RegistrationsController
  layout 'application'


   def update
    self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)


    # custom logic
    if params[:user][:password].present?
      result = resource.update_with_password(params[resource_name])
    else
      result = resource.update_without_password(params[resource_name])
    end

    # standart devise behaviour
    if result
      if is_navigational_format?
        if resource.respond_to?(:pending_reconfirmation?) && resource.pending_reconfirmation?
          flash_key = :update_needs_confirmation
        end
        set_flash_message :notice, flash_key || :updated
      end
      sign_in resource_name, resource, :bypass => true
      respond_with resource, :location => after_update_path_for(resource)
    else
      clean_up_passwords resource
      respond_with resource
    end
  end
end

Ответ 5

Я решаю эту проблему с моим интерфейсом. Есть два способа, которыми это может пойти.

Отключите поля, если они пусты

Этот бит jQuery отключает поля перед тем, как форма отправляется в том случае, если они пусты. Для этого требуется определенный шаблон разметки, проверьте демонстрацию на Codepen.

$(".password-fields").each(function() {
  var $fields, $form;
  $form = $(this).parents("form");
  $fields = $(this).find("input");
  $form.on("submit", function() {
    $fields.each(function() {
      if ($(this).val() === "") {
        $(this).attr("disabled", "disabled");
      }
    });
  });
});

Дайте пользователю флажок, чтобы выбрать, хотите ли они обновить

Другой вариант - удалить поля пароля из формы, если пользователь не указал, что они хотят обновить свой пароль. Вот пример в CodePen.

$(".password-fields").each(function () {
  var $fields, $button, html;
  $fields = $(this);
  $button = $fields.prev(".update-password").find("input");
  html = $fields.html();

  $button
    .on("change", function () {
      if ( $(this).is(":checked") ) {
        $fields.html(html);
      }
      else {
        $fields.html("");
      }
    })
    .prop("checked", "checked")
    .click();
});

В любом случае он не требует обновления для самого приложения. Вы просто отправляете поля, которые хотите изменить.

Ответ 6

Вместо этого вместо #password_required? метод внутри пользовательской модели.

class User < ActiveRecord::Base
  devise :database_authenticatable, :validatable #, ...

  def password_required?
    if respond_to?(:reset_password_token)
      return true if reset_password_token.present?
    end
    return true if new_record?
    password.present? || password_confirmation.present?
  end
end

Итак, если пользователь новый, ему потребуется указать пароль. Однако пользователю необходимо указать пароль только в том случае, если он заполняет либо пароль, либо атрибуты password_confirmation.

Подробнее см.: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L33

Моя реализация почти идентична оригинальной: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L53

за исключением того, что я проверяю наличие (которое возвращает false для пустых строк)

Здесь обсуждается мой запрос на растяжение по этому вопросу: https://github.com/plataformatec/devise/pull/3920

Ответ 7

Если вы все еще хотите поддерживать смену пароля, но делаете его необязательным, проверьте наличие current_password как такового:

class MyRegistrationsController < Devise::RegistrationsController
  protected

  def update_resource(resource, params)
    if params[:current_password].blank?
     resource.update_without_password(params.except(:current_password))
    else
      resource.update_with_password(params)
    end
  end
end

Таким образом, если присутствует текущий_память, вы можете продолжить и обновить пароль, иначе проигнорировать его и обновить без пароля.

Ответ 8

Если вы хотите, чтобы Devise проверял текущий пароль только при попытке пользователя сменить пароль (это означает, что может изменять другие атрибуты без предоставления текущего пароля):

class RegistrationsController < Devise::RegistrationsController

  protected

    def update_resource(resource, params)
      if params[:password].blank? && params[:password_confirmation].blank?
      resource.update_without_password(params)
    else
     super
    end
  end
end

Также в вашей модели:

attr_accessor :current_password

И не забывайте о

devise_for :users, controllers: {registrations: 'registrations'}

в routes.rb.

Ответ 9

Как обходное решение, введенное в модель пользователя

def password_required?
  encrypted_password.blank? || encrypted_password_changed?
end

Ответ 10

params [: user] [: password] не работает в rails 6

Вы должны изменить параметры [: пользователь] [: пароль] на параметры [: пароль]

Удалить [: user] во всех параметрах

мой исходный код ниже

перед запуском этой команды

rails generate devise:controllers users -c=registrations

class Users::RegistrationsController < Devise::RegistrationsController
  # before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  protected

  def update_resource(resource, params)
    puts "params ===> #{params}"
    if params[:password].blank? && params[:password_confirmation].blank?
      params.delete(:password)
      params.delete(:password_confirmation)
      params.delete(:current_password)
      resource.update_without_password(params)
    else
      super
    end
  end
end

Ответ 11

Это больше бизнес-логики, поэтому я бы не поставил слишком много кода в контроллер. Я предлагаю переопределить Devise::Models::Validatable#password_required? в вашей модели:

def password_required?
  new_record? || password.present? || password_confirmation.present?
end

Ответ 12

У меня была такая же проблема, и это решение, с которым я столкнулся, и считаю, что это работает. То, что я сделал, это создать второй метод user_params и назвал его user_params_no_pass в любом случае: посмотрите, что происходит здесь, так это то, что администратор предоставит пароль, когда пароль нужно обновить, иначе оставить пароль пустым. когда пароль пуст, используется user_params_no_pass else user_params. Надеюсь, что это поможет

    def update

    if @user.valid_password?(params[:user][:password])
          respond_to do |format|

            if @user.update(user_params)
              format.html { redirect_to @user, notice: 'User profile was successfully updated.' }
              format.json { render :show, status: :ok, location: @user }
            else
             format.html { render :new }
             format.json { render json: @user.errors, status: :unprocessable_entity }
            end
          end
    else
      respond_to do |format|

            if @user.update(user_params_no_pass)
              format.html { redirect_to @user, notice: 'User profile was successfully updated without password.' }
              format.json { render :show, status: :ok, location: @user }
            else
              format.html { render :edit }
              format.json { render json: @user.errors, status: :unprocessable_entity }
            end
          end
    end
  end

  def destroy
     @user.destroy
      respond_to do |format|
        format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
        format.json { head :no_content }
      end
  end
  private

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

    def user_params
      params.require(:user).permit(:user_name, :first_name, :middle_name, :last_name, :dob, :gender, :race, :hispanic, :leader, :mentor, :student, :email, :organization_id, :password, :opus,
  :release_date, :days_to_release, :current_level, :is_active)
    end


    def user_params_no_pass
      params.require(:user).permit(:user_name, :first_name, :middle_name, :last_name, :dob, :gender, :race, :hispanic, :leader, :mentor, :student, :email, :organization_id, :opus,
  :release_date, :days_to_release, :current_level, :is_active)
    end

Ответ 13

Я считаю, что это небольшое изменение в коде выше проще:

def update
  @user = User.find(params[:id])

  method = if user_params[:password].blank?
             :update_without_password
           else
             :update_with_password

  if @user.send(method, user_params)
    redirect_to @user, notice: 'User settings were saved.'
  else
    render :edit
  end
end

Ответ 14

После долгих исследований вышеуказанных возможностей я наконец-то нашел решение, позволяющее обновлять некоторые атрибуты без пароля, а некоторые с помощью:

Я создал представление для пользователя /edit.html.erb со следующей формой.

<%= form_for(@user) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <%= f.label :name %>
  <%= f.text_field :name, class: 'form-control' %>

  <%= f.submit "Save changes"%>
<% end %>

Я устанавливаю маршруты в route.rb

resources :users, only: [:show, :index, :edit, :update]

Я сделал редактирование и обновление методов в users_controller.rb

def edit
  @user = current_user
end

def update
  @user = current_user
  if @user.update_attributes(user_params)
    flash[:success] = "Profile updated"
    redirect_to root_url
  else
    render 'edit'
  end
end


def user_params
  params.require(:user).permit(:name, :avatar, :whatsup)
end

Я использовал этот вид редактирования для изменений, для которых не требовался пароль. Он полностью пропускает регистрационный контроллер устройства, потому что я ссылаюсь на него с помощью

edit_user_path(current_user)

Я также установил параметры, чтобы здесь нельзя было изменить электронную почту и пароль. Чтобы обновить пароль и адрес электронной почты, я ссылаюсь на созданный на складе вид устройства:

edit_user_registration_path(current_user)

Я признаю, что это огромная работа, но ни одно из более простых решений не решило все вышеперечисленные проблемы.

Ответ 15

Лучший и короткий путь: добавьте контрольные параметры в блок user_params. Например:

def user_params
    up = params.require(:user).permit(
      %i[first_name last_name role_id email encrypted_password
         reset_password_token reset_password_sent_at remember_created_at
         password password_confirmation]
    )

    if up[:password].blank? && up[:password_confirmation].blank?
      up.delete(:password)
      up.delete(:password_confirmation)
    end
    up
end

Ответ 16

чтобы обновить атрибуты для пользователя, вам нужно будет использовать: current_password, чтобы проверить "использует ли ваш пользователь правильный current_password или кто-то хочет взломать вашего пользователя"

так по форме:

= f.input :current_password,
          hint: "we need your current password to confirm your changes",
          required: true,
          input_html: { autocomplete: "current-password" }

в контроллере:

    if your_user.valid_password?(params[:user][:current_password])
        your_user.update_attributes(user_params.except(:current_password, :password, :password_confirmation))
    end

первая строка проверяет "отправляет ли ваш пользователь правильный пароль или нет", а затем мы можем обновить атрибуты без мусора