Devise 3 (рельсы 4) не может обновлять пользователя без пароля
Я пытаюсь обновить пользователя, не предоставляя пароль, но подходы, которые работали над более старыми версиями devise/rails, больше не работают с конструкцией 3 и 4-мя сильными параметрами.
Я использую мой user_controller для обновления, но я также попытался использовать специальный контроллер регистрации разработки с devise_parameter_sanitizer без успеха.
Форма не требует пароля (не имеет поля пароля), а user_controller, обрабатывающий обновление, выглядит так:
# PATCH/PUT /users/1
def update
if user_params[:password].blank?
Rails.logger.info "entered if statement"
user_params.delete :password
user_params.delete :password_confirmation
Rails.logger.info(user_params.inspect)
end
@user = current_user
if @user.update(user_params)
redirect_to @user, notice: 'User was successfully updated.'
else
Rails.logger.info(@user.errors.inspect)
render action: 'edit'
end
end
private
def user_params
params.require(:user).permit(:screen_name, :full_name, :email, :about,
:location, :profile_pic, :password, :password_confirmation, :current_password)
end
.. журнал после представления выглядит следующим образом:
Started PATCH "/users/13" for 127.0.0.1 at 2013-05-29 11:18:18 +0100
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"20avah2OzaOVubAiam/SgvbYEQ4iijEWQqmNo7xD4rY=", "user"=>{"screen_name"=>"Darcbar", "full_name"=>"Barry Darcy", "about"=>"", "location"=>"", "website_url"=>"", "twitter_username"=>"", "email"=>"[email protected]"}, "commit"=>"Save changes", "id"=>"13"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 13 ORDER BY "users"."id" ASC LIMIT 1
Entered if statement...
{"screen_name"=>"Darcbar", "full_name"=>"Barry Darcy", "email"=>"[email protected]", "about"=>"", "location"=>"", "twitter_username"=>"", "website_url"=>""}
(0.2ms) BEGIN
User Exists (0.8ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = '[email protected]' AND "users"."id" != 13) LIMIT 1
(0.2ms) ROLLBACK
#<ActiveModel::Errors:0x007fedf45bb640 @base=#<User id: 13, username: "darcbar", full_name: "Barry Darcy", about: "", location: "", email: "[email protected]", encrypted_password: "$2a$10$Mb4zsRPPqZ9CYz0zdLMBU.62NyIk/T8s6Zw/uRTwWov3...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 9, current_sign_in_at: "2013-05-28 17:51:20", last_sign_in_at: "2013-05-28 16:42:52", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", authentication_token: nil, created_at: "2013-05-27 14:03:41", updated_at: "2013-05-28 17:51:20", screen_name: "Darcbar", profile_pic_file_name: nil, profile_pic_content_type: nil, profile_pic_file_size: nil, profile_pic_updated_at: nil>,
@messages={:password=>["please enter a password with at least 5 characters", "please enter a password with at least 5 characters"]}>
Rendered users/edit.html.haml within layouts/application (3.0ms)
Rendered partials/head/_user_options.haml (1.8ms)
Completed 200 OK in 74ms (Views: 12.1ms | ActiveRecord: 1.7ms)
Кто-нибудь знает, почему ошибки пароля присутствуют?
Ответы
Ответ 1
Проверка пароля происходит из пользовательской модели:
validates :password, presence: true
Решение состоит в том, чтобы проверять наличие при создании и allow_blank при обновлении:
validates :password, presence: true, length: {minimum: 5, maximum: 120}, on: :create
validates :password, length: {minimum: 5, maximum: 120}, on: :update, allow_blank: true
Ответ 2
Начиная с 2014 года вы можете просто переопределить защищенный метод и выполнить:
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
resource.update_without_password(params)
end
end
Ответ 3
Вы можете использовать метод @user.update_without_password(user_params)
для обновления других полей.
Например, у меня это есть в моих пользовательских users_controller.rb. Я обновляюсь с помощью удаленного вызова (ajax).
#users_controller.rb
def update
respond_to do |format|
if needs_password?(@user, user_params)
if @user.update_with_password(user_params_password_update)
flash[:success] = 'User was successfully updated. Password was successfully updated'
format.js {render 'update'}
else
error = true
end
else
if @user.update_without_password(user_params)
flash[:success] = 'User was successfully updated.'
format.js {render 'update'}
else
error = true
end
end
if error
flash[:error] = @user.errors.full_messages.join(', ')
format.js {render json: @user.errors.full_messages, status: :unprocessable_entity}
end
end
end
private
def needs_password?(user, user_params)
!user_params[:password].blank?
end
def user_params
params[:user].permit(:email, :password, :password_confirmation, :username, :full_name)
end
#Need :current_password for password update
def user_params_password_update
params[:user].permit(:email, :password, :password_confirmation, :current_password, :username, :full_name)
end
Ответ 4
Ключ находится в этом "user_params [: password].blank?". Следующий пример кода:
def update
if user_params[:password].blank?
params = user_params_without_password
else
params = user_params
end
respond_to do |format|
if @user.update(params)
format.html { redirect_to @user, notice: t(:user_update) }
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
private
def set_user
@user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:email, :username, :first_name, :last_name, :admin, :locked, :password)
end
def user_params_without_password
params.require(:user).permit(:email, :username, :first_name, :last_name, :admin, :locked)
end
Надеемся, что вы поможете
Ответ 5
Я много лет обходил круги. Ответы все можно утверждать, как указано выше mrstif. Если вы используете модуль validatable, Devise работает из коробки (с параметрами конфигурации), позволяя вам обновлять данные пользователя, не указывая пароль, поэтому будьте очень осторожны при проверке собственных паролей.
Ответ 6
просто переопределите конструкцию, создав приложение/контроллер/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
resource.update(params.except(:current_password))
end
end
этот код будет непосредственно обновлять параметры пользователя, кроме: current_password
и обновить config/routes.rb
devise_for :users, controllers: {registrations: 'registrations'}
Ответ 7
Моя цель состояла в том, чтобы разрешить редактирование пользовательских атрибутов, не требуя пароля, если только это не изменяет адрес электронной почты, пароль или не удаляет учетную запись. И вот, что сработало для меня:
приложение/контроллеры/registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters
...
def update
params[:user][:team_attributes][:id] = current_user.team.id
account_update_params = devise_parameter_sanitizer.sanitize(:account_update)
if password_required?
successfully_updated = resource.update_with_password(account_update_params)
else
account_update_params.delete(:current_password)
successfully_updated = resource.update_without_password(account_update_params)
end
if successfully_updated
sign_in resource, bypass: true
redirect_to '/'
else
render :edit
end
end
def destroy
current_password = devise_parameter_sanitizer.sanitize(:account_update)[:current_password]
resource.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
error_messages = 'Current password ' + resource.errors[:current_password].join
if resource.destroy_with_password(current_password)
redirect_to '/'
else
redirect_to delete_account_path, notice: error_messages
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update) do |user_params|
user_params.permit(:username, :email, :password, :password_confirmation, :current_password, :name, :phone_number
end
end
private
def password_required?
(resource.email != params[:user][:email] if params[:user][:email].present?) || params[:user][:password].present?
end
end
Обновить config/routes.rb:
devise_for :users, controllers: { registrations: 'registrations' }
В представлениях/разработке/регистрации/edit.html.haml
# edit form
...
= simple_nested_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: 'mo-form' }, defaults: { placeholder: false, hint: false }) do |f|
...
# delete form
...
= simple_form_for(resource, as: resource_name, url: user_registration_path(resource_name), method: :delete, html: { class: 'mo-form' }, defaults: { placeholder: false, hint: false }) do |f|
...