webentwicklung-frage-antwort-db.com.de

Update-Benutzer ohne Passwort erstellen

Ich möchte Benutzerattribute ohne Passwort in devise aktualisieren. Der Fall ist wie, wenn Kennwort und Kennwortbestätigungsfelder nicht leer sind, dann brauche ich einen Fehler und wenn sie leer sind, müssen andere Benutzerattribute aktualisiert werden. Wie könnte ich das mit devise machen?

Danke im Voraus! 

70
kriysna

Ist es das, wonach du suchst? Aus dem Devise-Wiki

Benutzern erlauben, ihr Konto zu bearbeiten, ohne ein Passwort anzugeben

Es zeigt, wie es für Rails 3 und Rails 4 geht

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

Johns Lösung ist eine einfachere Alternative

61
Dty

Ich denke, das ist eine viel bessere Lösung:

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

Dies verhindert, dass Sie den Devise-Controller ändern müssen, indem Sie einfach das Kennwortfeld aus der Formularantwort entfernen, wenn es leer ist.

Stellen Sie sicher, dass Sie diese before @user.attributes = params[:user] oder was auch immer Sie in Ihrer update-Aktion verwenden, um die neuen Parameter aus dem Formular festzulegen.

83
John

Ich denke, mit Devise 3.2+ können Sie einfach update_resource in Ihrem untergeordneten Controller überschreiben. Hier ist ein Beispiel für die ursprünglich gestellte Frage:

class MyRegistrationsController < Devise::RegistrationsController
  protected

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

Ich habe dieses Problem wie folgt gelöst: Wenn das Formular mit Kennwort übermittelt wird, müssen Sie das Feld current_password oder das Formular ohne Kennwort und current_password aktualisieren

im Modell:

class User
  devise: bla-bla-bla

  attr_accessor :current_password
end

Im Controller:

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

Ich löse dieses Problem mit meiner Schnittstelle. Es gibt zwei Möglichkeiten, wie es gehen kann.

Deaktivieren Sie die Felder, wenn sie leer sind

Dieses jQuery-Bit deaktiviert die Felder, bevor das Formular übermittelt wird, falls sie leer sind. Es erfordert ein bestimmtes Auszeichnungsmuster, überprüfen Sie die Demo auf 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");
      }
    });
  });
});

Geben Sie dem Benutzer ein Kontrollkästchen, um auszuwählen, ob er eine Aktualisierung durchführen möchte

Eine weitere Option ist das Entfernen der Kennwortfelder aus dem Formular, wenn der Benutzer nicht angegeben hat, dass er sein Kennwort aktualisieren möchte. Hier ist das Beispiel auf 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();
});

In beiden Fällen ist keine Aktualisierung der App selbst erforderlich. Sie übermitteln nur die Felder, die Sie ändern möchten.

3
rb-

Ich überschreibe stattdessen #password_required? Methode innerhalb des Benutzermodells.

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

Wenn der Benutzer neu ist, muss er das Kennwort angeben. Ein vorhandener Benutzer muss das Kennwort jedoch nur angeben, wenn er entweder das Kennwort oder die Kennwortbestätigungsattribute eingibt.

Weitere Informationen finden Sie unter: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L33

Meine Implementierung ist fast identisch mit dem Original: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L53

außer dass ich auf Präsenz prüfe (was für leere Zeichenfolgen falsch ist)

Hier ist eine Diskussion über meine Pull-Anfrage in dieser Angelegenheit: https://github.com/plataformatec/devise/pull/3920

3
graudeejs

Wenn Sie die Kennwortänderung weiterhin unterstützen möchten, dies jedoch optional machen, überprüfen Sie die Verfügbarkeit von 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

Auf diese Weise können Sie, wenn das aktuelle_Kennwort vorhanden ist, das Kennwort aktualisieren und es sonst ignorieren und ohne Kennwort aktualisieren.

2
Sebyddd

params [: user] [: password] funktioniert nicht in Rails 6

Sie müssen params [: user] [: password] in params [: password] ändern

Entferne [: user] in allen Parametern

mein Quellcode ist unten

bevor Sie diesen Befehl ausführen

Schienen erzeugen Geräte: Controller-Benutzer -c = Registrierungen

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

Wenn Sie möchten, dass Devise das aktuelle Passwort überprüft nur wenn der Benutzer versucht, das Passwort zu ändern (, bedeutet dies, dass Sie können andere Attribute ändern, ohne das aktuelle Passwort anzugeben ):

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

Auch in Ihrem Modell:

attr_accessor :current_password

Und nicht vergessen

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

in routes.rb.

1
Maxim Kachanov

Ich finde, dass diese geringfügige Variation des obigen Codes leichter zu folgen ist:

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

Nach eingehender Erkundung der oben genannten Möglichkeiten habe ich endlich eine Lösung gefunden, mit der Sie einige Attribute ohne Passwort aktualisieren können und einige mit:

Ich habe eine Ansicht für user/edit.html.erb mit dem folgenden Formular erstellt.

<%= 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 %>

Ich setze Routen in routen.rb

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

Ich habe Bearbeitungs- und Aktualisierungsmethoden in users_controller.rb erstellt

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

Ich habe diese Bearbeitungsansicht für Änderungen verwendet, für die kein Kennwort erforderlich war. Es wird der Geräteregistrierungscontroller vollständig übersprungen, da ich ihn mit verlinke

edit_user_path(current_user)

Ich habe auch die Parameter so eingestellt, dass E-Mail und Passwort hier nicht geändert werden können. Um das Passwort und die E-Mail-Adresse zu aktualisieren, verweise ich auf die erstellte Inventaransicht:

edit_user_registration_path(current_user)

Ich gebe zu, dass dies eine enorme Arbeit ist, aber keine der einfacheren Lösungen löste alle oben genannten Probleme.

0
James Mosier

Besser und kurzer Weg: Fügen Sie check params in den Block user_params ein. Zum Beispiel:

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

Ich hatte genau das gleiche Problem und dies ist die Lösung, die ich mir ausgedacht habe, und glaubt mir, dass es funktioniert. Was ich getan habe, ist, eine zweite user_params-Methode zu erstellen und sie user_params_no_pass zu nennen Geben Sie ein Kennwort ein, wenn das Kennwort aktualisiert werden muss. Andernfalls lassen Sie das Kennwort leer. Wenn das Passwort leer ist, wird der user_params_no_pass verwendet, ansonsten user_params. Ich hoffe das hilft

    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

Es ist mehr Geschäftslogik, daher würde ich nicht zu viel Code in den Controller einfügen. Ich schlage vor, Devise::Models::Validatable#password_required? in Ihrem Modell zu überschreiben:

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

um die Benutzerattribute zu aktualisieren, müssen Sie Folgendes verwenden: aktuelles_kennwort, um zu überprüfen, ob Ihr Benutzer das richtige aktuelle_kennwort verwendet oder ob jemand Ihren Benutzer auflösen möchte.

also in form:

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

im Controller:

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

in der ersten Zeile wird überprüft, ob Ihr Benutzer das richtige Kennwort sendet oder nicht. Anschließend können wir die Attribute ohne Datenverlust aktualisieren

Als Workaround fügen Sie Ihr Benutzermodell hinzu

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