Пароль, возвращаемый Rails API, не может быть пустым с помощью has_secure_password

Я создал новое приложение Rails, используя rails new recruiter --api -S -C -T -d postgresql, чтобы получить простой API. Затем я раскомментировал gem 'bcrypt', '~> 3.1.7' и запустил bundle install. Затем я создал пользовательский каркас с rails g scaffold User email:string:uniq password_digest:string is_admin:boolean is_agent:boolean и добавил в модель has_secure_password. Когда я запускаю POST-запрос к /users, я получаю "password": "can't be blank" обратно.


# user.rb

class User < ApplicationRecord
  has_secure_password
end

# users_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]

  # GET /users
  def index
    @users = User.all

    render json: @users
  end

  # GET /users/1
  def show
    render json: @user
  end

  # POST /users
  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, status: :created, location: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /users/1
  def update
    if @user.update(user_params)
      render json: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  # DELETE /users/1
  def destroy
    @user.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def user_params
      params.require(:user).permit(:email, :password_digest, :is_admin, :is_agent)
    end
end

Вот мой JSON-запрос POST от Postman: JSON POST-запрос от почтальона

Что я делаю не так? Я ожидал, что это создаст нового пользователя с зашифрованным паролем, сохраненным в password_digest. Я попытался повторно запустить миграцию и перезапустить сервер. Я попытался добавить запись для password_confirmation в запрос JSON POST. Те же результаты. Я даже создал тестовое приложение, выполнив все те же шаги, за исключением bcrypt и has_secure_password, и POST возвращает нового пользователя, поэтому проблема должна быть связана с тем, как я использую bcrypt. Я вижу в консоли Rails, что пароль не передается вместе с пользователем, но я не знаю, почему.

Parameters: {"email"=>"[email protected]", "password"=>"[FILTERED]", "is_admin"=>true, "is_agent"=>true, "user"=>{"email"=>"[email protected]", "is_admin"=>true, "is_agent"=>true}}
   (0.2ms)  BEGIN
  ↳ app/controllers/users_controller.rb:20
   (0.2ms)  ROLLBACK
  ↳ app/controllers/users_controller.rb:20
Completed 422 Unprocessable Entity in 17ms (Views: 0.2ms | ActiveRecord: 6.2ms)

person Josh    schedule 30.05.2018    source источник


Ответы (2)


Вы не разрешаете пароль в user_params. Может быть что-то вроде следующего может работать

def user_params
      params.require(:user).permit(:email, :password, :is_admin, :is_agent)
end

Подробнее о дайджестах паролей здесь https://medium.com/@tpstar/password-digest-column-in-user-migration-table-871ff9120a5

Кроме того, запрос JSON необходимо обернуть в объект user:

{
  "user":
  {
    "email": "[email protected]",
    "password": "password",
    "is_admin": true,
    "is_agent": true
  }
}
person Umair Abid    schedule 30.05.2018
comment
Да, это была половина проблемы. Я тоже только что понял. Мне нужно было не только разрешить :password, но и обернуть запрос JSON в объект пользователя следующим образом: { "user": { "email": "[email protected]", "password": "password", "is_admin": true, "is_agent": true } } Простого добавления :password к параметрам было недостаточно. Я все же приму ваш ответ. Спасибо. - person Josh; 30.05.2018
comment
Спасибо :) вам нужно сделать это, потому что у вас есть require(:user), но это хорошая практика - person Umair Abid; 30.05.2018

Проблема здесь:

params.require(:user).permit(:email, :password_digest, :is_admin, :is_agent)

вы отправляете :password, но разрешаете :password_digest

person Yaroslav V.    schedule 30.05.2018