Devise, validate current_password if any important fields have been changed - ruby-on-rails

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.

Related

Devise Required Params Not Enforced

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.

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).

How to enforce providing password for devise to delete account

how can I make devise enforce getting correct password before canceling registration (deleting account)
You can either:
Do something along the lines of pst's answer: have a text box for :canceled in a form that when saved, cancels the account. Since it would be part of the user model, devise would force the password check upon the update action.
Do it yourself via a button that warns (similar to the delete buttons often in Rails). The controller that receives the request would simply do something like the following (I seem to remember that Devise uses MD5, maybe it's SHA1, SHA2, unsure- see documentation; the key is to use the same type):
if params[:password] == Digest::MD5.hexdigest(params[:password])
cancel_account(…)
…
end
Yeah, the key here is knowing how to encrypt params[:password] to be able to compare it to the current_user.encrypted_password
Older versions of Devise use a password_salt as well. My advice to you would be to look at how devise does this on sign in, and use the same method in your destroy action, or whatever user-facing page you have for that.

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!

Authlogic: failed_login_count not updating

I'm using Authlogic as the login system. Everything is working correctly except that it never updates the failed_login_count field when I purposely type in the wrong password. I am using the email as the login item. In the database there is no 'login' column. Is there something that I need to change or add to make this feature work?
Remember: When you login, the Failed_count_field set to 0.
Is your User model valid? If it's not, the validation will fail and the column can't be saved.

Resources