Devise Required Params Not Enforced - ruby-on-rails

I've added the first_name, last_name and username fields to my user table and I want to ensure they are set when a user signs up. After some searching it seems the common consensus on how to do this is to extend the registrations controller and use the #permit method to add the params.
This can be seen in https://gist.github.com/jamesrwhite/6a53cccd9284fb3be9f8.
The problem is I can still sign up and leave the first_name, last_name and username fields empty and no errors are shown. I've tried multiple different ways of doing this but none seem to work. I'm using Rails 4.1.1 and Devise 3.2.4.
Any ideas?

It seems you have missed validation line for 3 fields in your User Model. Could you please try that too.

Related

rails 4 how to add custom form fields

How can we add custom form fields in rails 4.
For ex:
User (model)
username
email
hashed_password
Now in the form field for password I would like to have fields like password and password confirm.
But due to the introduction of strong parameters in rails 4, I cannot simply send those fields .
It throws error.
It used to be a piece of cake in prior versions of rails i.e in the model we would add our custom form fields to attr_accessor and we could play with them.
NOTE: I tried this thing few weeks ago and it did'nt work, and I don't remember the exact error but was something like 'no method password on user'.
I know it is very stupid of me to not provide you with the exact error messages.
My apologies, can't help I deleted the application.
I was following this tutorial (it's for rails 3) http://www.sitepoint.com/rails-userpassword-authentication-from-scratch-part-i/
Check out How is attr_accessible used in Rails 4? for using strong parameters in rails 4
Protecting attributes is now done in the Controller.
I'm using attr_accessor in model in Rails 4.
In forms I have
<%= text_field_tag 'param_name' %>
And in controller
#model.param_name = params[:param_name]
It works ok and can solve your problem, I think. BUT! I'm not sure it is secure to use it this way. If someone can explain, why it is not appropriate for security reasons and suggest a better way, I'll appreciate it (as the author, I think).

Devise, validate current_password if any important fields have been changed

Specifically, I'm using Devise with Typus. But, I think my misunderstanding resides in my knowledge of Devise.
I'm trying to achieve the functionality of when you want to change an important model via form, you have to provide your current password to confirm you can change it, a la google.
Right now, I can log in and change any of the fields of my User model. Including the password, without having to confirm my password prior. Not good. So, I've added current_password to the form. But that didn't do anything. Then I tried to validate presence on current_password. Then it doesn't seem to accept any value for it.
Google didn't help me. All of the relevant posts were about removing current_password instead of confirming it. Which makes me think I'm misunderstanding the use of current_password.
Anyone care to share some insight? Thanks.
You should add the password field to the form, and then in your controller's action you can validate the password using:
user.valid_password?(params[:user][:password])
Note that probably you should change params[:user][:password] to the the name of the param for your password's field in the form (perhaps just params[:password]).
Hope it helps.
Actually, devise has a builtin method for this:
user.update_with_password(params, *options) you can read the rdoc here.
Update record attributes when :current_password matches, otherwise returns error on :current_password. It also automatically rejects :password and :password_confirmation if they are blank.

How to override the Devise Passwords Controller?

How to override the Devise Passwords Controller:
https://github.com/plataformatec/devise/blob/master/app/controllers/devise/passwords_controller.rb
I want to do the following:
downcase all emails submitted for password reset. All the emails in the DB as lowercase. If a user tried to reset a valid email with any characters uppercase, the reset fails to find a user. And devise doesn't even give a error message saying no user found
If no user is found in def create, I want to add a flash that says, no user found, did you enter the right email?
How can I accomplish the 2 items above? I believe that required overriding the devise password controller. How do I do that? Or if you have a better solution that's even cleaner, I would like to hear it.
Thanks
the devise initializer has a option to make any field case insensitive:
config.case_insensitive_keys = [ :email ]
If I remember correctly it was added in the newer version and if you don't see some related comments in you initializer then you should upgrade your devise gem using bundle upgrade devise. I am using version 1.3.3.
And this version also shows an error "Email not found" if an invalid email is entered.
If you not getting the error message add <%= devise_error_messages! %> to your view. You can customize the error messages by editing config/locales/devise.en.yml

Is there a way in Rails to say "run all the validates EXCEPT :password"?

I am using Devise for my authentication. If a hashed_password isn't set, Rails/Devise's validations will require a password to be set, as well as the password_confirmation.
When I invite new users, I obviously don't want to set their password, so when I create the invitation in my system, it fails because user.password is blank.
I can set a temporary hashed_password on the user, but when they enter their own password, the validation checks for :password and :password_confirmation will not happen because hashed_password is set, which is a real problem.
Is there any way to tell Rails that I want to run all the validations except for the ones associated with :password?
I know Rails has :if conditions, which might fix my problem, but Devise declares the :password validation on my behalf, so that essentially is hidden.
How can I get the desired result here?, hopefully in a way that is not a hack.
My current hypothetical solution that is somewhat messy: The only thing I can think of is to create a new Invitation model that is not the User model, and use the Invitation model for the form. When the invitation is submitted I can validate that Invitation and copy over all the values to the new User model. I can save that User without any validations at all.
That's the best solution I dreamed up.
It seems like my solution will be a lot more work than saying something simple like:
user.save(validations => {:except => :password})
EDIT: I have found one part of the solution, but I am still having problems. In our user model, we can override a Devise method to prevent the validation of the password for invitations with this bit of code:
#protected
def password_required?
!is_invited && super
end
The is_invited attribute is just a column I added to the users table/model.
However, there is one gotcha here. When a user accepts an invitation and they arrive to the form where they need to set their password/password_confirmation, valid? will always return true.
This one has me deeply perplexed. I don't see how requires_password? and valid? can be true at the same time. If it requires the password, it should do a validation check and cause the validations to fail.
I'm starting to hate Devise - or just the idea of using gems to build parts of your application in a blackbox. I think the real solution probably is to rip out Devise and just do it all from scratch. That way your app has total control of how all of this works :(
I recently started using this great devise add-on: devise_invitable
It's commonly used so users (or any model) can invite other users to join.
But I adapt it for manually (via an admin panel) invite new potential users to my app.
Hope this helps!

Migrating existing user model to Devise

I'm trying to migrate a legacy app to Rails 3 and change the authentication to use Devise. I've created the model and migrations and imported all the user data.
I don't plan to migrate the passwords over as the existing scheme is not one we'd like to use going forward, but I want to be able to present users with a simple experience.
Ideally I'd like to catch a login error and then check the password with the legacy field and then update the Devise password with it if it matches.
I can see that Warden gives me a callback that can trap errors so I expect I can trap a login error.
However because all the passwords (in Devise) are blank I get errors relating to the hash as the encrypted_password fields are empty.
Is there a way I can update all the user accounts with a random password?
I've seen in Devise::Models::DatabaseAuthenticatable that there is a method 'password=' but if I call that, e.g. in rails console for the app:
User.find(1).password=('new')
=> "new"
I just get the same plain text string back ('new') and saving the user record post this doesn't populate the encrypted_password field.
I've searched around but can't seem to be able to find it. Any suggestions much appreciated!
Ok just in case anyone else is as cloth headed as I have been the last 24 hours, here's how you set the password:
user = User.find(id)
user.password = 'new-password'
user.save
Simple really :)

Resources