web-dev-qa-db-ja.com

パスワードなしで更新ユーザーを考案する

Deviseでパスワードなしでユーザー属性を更新したい。ケースは、パスワードとパスワードの確認フィールドが空白でない場合、エラーを考案する必要があり、それらが空白の場合、他のユーザー属性を更新する必要があるようなものです。どうすればdeviseでこれを行うことができますか?

前もって感謝します!

73
kriysna

これはあなたが探しているものですか? Devise wikiから

ユーザーがパスワードを入力せずにアカウントを編集できるようにする

Rails 3 and Rails 4

=======================

ジョンのソリューション はより単純な代替手段です

61
Dty

私はこれがはるかに良い解決策だと思う:

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

これにより、空白の場合にフォームの応答からパスワードフィールドを削除するだけで、Deviseコントローラーを変更する必要がなくなります。

必ずこれを使用してくださいbefore@user.attributes = params[:user]またはupdateアクションで使用して、フォームから新しいパラメーターを設定するもの。

85
John

Devise 3.2+では、サブクラス化されたコントローラーのupdate_resourceをオーバーライドすることができると思います。最初に尋ねられた質問の例を次に示します。

class MyRegistrationsController < Devise::RegistrationsController
  protected

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

私はこの問題を次のように解決しました:パスワードで送信するフォームの場合、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
7
Mikhail Grishko

パスワードの変更を引き続きサポートしたいが、オプションにする場合は、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

そうすれば、current_passwordが存在する場合、続行してパスワードを更新できます。それ以外の場合は無視し、パスワードなしで更新します。

3
Sebyddd

私は自分のインターフェースでこの問題を解決します。 2つの方法があります。

フィールドが空の場合は無効にします

この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();
});

どちらの場合でも、アプリ自体の更新は必要ありません。変更したいフィールドを送信するだけです。

3
rb-

代わりに#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またはpassword_confirmation属性のいずれかを入力する場合にのみ、パスワードを指定する必要があります。

詳細については、以下を参照してください: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L

私の実装はオリジナルとほとんど同じです: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L5

存在を確認することを除いて(空白文字列に対してfalseを返します)

この問題に関するプルリクエストについての説明は次のとおりです。 https://github.com/plataformatec/devise/pull/392

3
graudeejs

params [:user] [:password]はRails 6で動作していません

params [:user] [:password]params [:password]に変更する必要があります

すべてのパラメーターの[:user]を削除

私のソースコードは以下です

このコマンドを実行する前に

Railsはdevise:controllersユーザーを生成します-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
1
Changwoo Rhee

Deviseに現在のパスワードをチェックさせたい場合、ユーザーがパスワードを変更しようとした場合のみつまり、can現在のパスワードを指定せずに他の属性を変更します):

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'}

inroutes.rb.

1
Maxim Kachanov

回避策として、ユーザーモデルに入れます

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

上記のコードのこのわずかなバリエーションは、わかりやすいと思います。

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
0
sigvei

上記の可能性を十分に検討した結果、パスワードなしでいくつかの属性を更新できるソリューションと、次のようにいくつかの属性を更新できるソリューションがようやく見つかりました。

次のフォームを含むuser/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 %>

Routes.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)

これは大きな回避策であると認めますが、上記の問題をすべて解決できる単純なソリューションはありません。

0
James Mosier

より良い方法と短い方法:check paramsを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
0

私はまったく同じ問題を抱えていましたが、これは私が思いついた解決策であり、それが機能すると信じています。私がやったのは、2番目のuser_paramsメソッドと名前user_params_no_passとにかく見てみましょう:ここで何が起こっているのかは、パスワードを更新する必要があるときに管理者がパスワードを提供することです。パスワードが空白の場合、user_params_no_passが使用される、そうでなければ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
0
Idriss

それはよりビジネスロジックなので、コントローラーにあまり多くのコードを入れません。モデルでDevise::Models::Validatable#password_required?をオーバーライドすることをお勧めします。

def password_required?
  new_record? || password.present? || password_confirmation.present?
end
0
Artur Bilski

ユーザーの属性を更新するには、: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

最初の行は、「ユーザーが正しいパスワードを送信するかどうか」をチェックし、その後、ゴミを出さずに属性を更新できます