I'm using Bcrypt with has_secure_password in my User class, and trying to create a new User with username and password, but the password param, although permitted in my strong params, is not coming through.
This is my User class:
class User < ApplicationRecord
has_secure_password
has_many :journals
end
This is the User Controller:
class Api::V1::UsersController < ActionController::API
def index
@users = User.all
render json: @users.to_json(:include => :journals)
end
def create
byebug
@user = User.create(user_params)
end
private
def user_params
params.require(:user).permit(:username, :password)
end
end
I'm trying to post a new user with:
fetch('http://localhost:3001/api/v1/users', {
method: 'POST',
headers: {Accept: 'application/json', "Content-Type":
'application/json'},
body: JSON.stringify({username: 'Name', password: 'test'})})
and the result, inside the byebug in 'create', is:
(byebug) params
<ActionController::Parameters {"username"=>"Name", "password"=>"test",
"controller"=>"api/v1/users", "action"=>"create", "user"=> .
{"username"=>"Name"}} permitted: false>
(byebug) user_params
<ActionController::Parameters {"username"=>"Name"} permitted: true>
No matter what I try, I cannot access the password param in user_params to create a user with a hashed password.
In terminal, in rails console, I can create a user and the password gets hashed as expected, I can then fetch that user information from the API with a normal fetch request, but I cannot use strong params to create a User with a Post request, and I don't know why.
but I cannot use strong params to create a User with a Post request, and I don't know why.
Mainly because you're not using strong params correctly.
params.require(:user).permit(:username, :password)
This means that you need to pass {user: {username: 'foo', password: 'bar'}}
instead of {username: 'foo', password: 'bar'}
(see the nesting?).
But even though you don't pass params[:user][:username]
, it is somehow magically there. How? ParamsWrapper
, that's how.
If you enable ParamsWrapper for :json format, instead of having to send JSON parameters like this:
{"user": {"name": "Konata"}}
You can send parameters like this:
{"name": "Konata"}
Yes, but why password
doesn't get the same treatment? We find out a few lines below:
On Active Record models with no
:include
or:exclude
option set, it will only wrap the parameters returned by the class methodattribute_names
.
password
is not an attribute/column in your model, so params wrapper ignores it.