Настройка пользователя без пароля
Я хочу обновить атрибуты пользователей без пароля. Дело в том, что, если поля подтверждения пароля и пароля не пустые, мне нужно разработать ошибку, и если они пусты, тогда необходимо обновить другие пользовательские атрибуты. Как я мог сделать это с помощью разработки?
Спасибо заранее!
Ответы
Ответ 1
Это то, что вы ищете? Из вики-устройства Devise
Разрешить пользователям редактировать свою учетную запись без ввода пароля
Здесь показано, как это сделать для рельсов 3 и 4 для рельсов.
=======================
Решение John - более простая альтернатива
Ответ 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
первая строка проверяет "отправляет ли ваш пользователь правильный пароль или нет", а затем мы можем обновить атрибуты без мусора