Rails 3.0 Devise reset Password by answering a question - ruby-on-rails

I am using devise with rails 3. In user model I have created fields for the question and answer to that question.
I want to know How I can implement forget password in following logic:
On forget password page User enters the Username
On Next step application should displays the question stored in db.
User answers the question and app matches the answer if answer is matched with values stored in db.
It redirects to edit password page where password can updated.
I tried to override password controller of devise but got stuck.
Thanks for help in advance.
Note: I am new to rails and its my first project

I've actually not used Devise before, however assuming you have a befor_filter on your controller to route to Devise authentication, you could possibly do something like:
skip_before_filter :authenticate_with_devise if user_answered_question_correctly?

this gem has a security_questionable feature which would do the trick, amongst other things https://github.com/phatworx/devise_security_extension

You don't need to override Devise for this.
make your own forget_password routes:
in routes.rb:
get "forgot_password" => "passwords#forgot"
get "forgot_password/verify_question" => "passwords#verify_question"
post "forgot_password/verify_answer" => "passwords#verify_answer"
post "forgot_password/reset_password" => "passwords#reset"
Create app/controller/passwords_controller.rb and fill out logic you want via forms / render.
Create views.
Change forgot password link to your own.
Profit

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

Rails basic authentication [duplicate]

I am relatively new to rails and right now I am developing a simple log in log out system.
In my app when I log in the URL generated is:
localhost:3000/user/index/7
When I log out I get back to the root. But if copy this URL and paste it in another browser window i get instantly logged in without being directed to the log in form. How to correct this issue.
I tried to store user id in session hash and then upon logout i have set user id in session to be nil. But that does not work. Help needed.
Edited:
In my Home controller
class HomeController < ApplicationController
def signin
user=User.find(:all,:conditions=>["user_login=? AND user_password=?",params[:user] [:username],params[:user][:password]);
if user!=nil
session[:user_id]=user.user_id;
redirect_to({:controller=>'user'})
end
end
end
In User controller i have a logout method:
def logout
session[:user_id]=nil;
redirect_to({:controller=>'home'});
end
My routes.rb file looks like this:
ActionController::Routing::Routes.draw do |map|
map.root :controller => "home",:action => "index"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Edited:
I have solved this issue I was not checking id value in session hash in User controller index method. But I have another question If i have an app in rails 2.3.17 and I want to shift it to latest version how much changes will I have to make
You can set before_filter for those actions in the controller. using that before_filter you can check session is nil or value is present.
Otherwise you can follow this railscasts video
http://railscasts.com/episodes/250-authentication-from-scratch
This is the default behavior of the basic authentication. Once you get logged in, all your credentials are stored in the session headers which is maintained by the browser. If your clear your cache, then it should prompt for the password again....
I really recommend to use an existing authentication systems, like https://github.com/plataformatec/devise
On this site you can easily get an overview about other existing systems, and of there popularity and development activity.
https://www.ruby-toolbox.com/categories/rails_authentication
You really donĀ“t have to program such stuff by yourself, but if you really like to do it, maybe this could also helps you: http://railscasts.com/episodes/250-authentication-from-scratch-revised. But I recommend devise absolutely.
I think you are trying to reinvent the wheel here. You can use has_secure_password inside your User model and generate a sessions_controller to handle the create and destroy. the methods are basically the same, but with the has_secure_password flag. You should then take care of destroying the session properly.

Rails 3 + Devise: How do I change other user's passwords from an admin role?

I've developed a Rails 3 application with Devise for registration and login control. I want to be able to modify any user's password to one I provide.
The solution I've come up with (I haven't had the chance to test it yet) is to make a fake new registration with the password I choose, copy the password from the table record to the user's record in question, and then delete the fake record I generated in the DB. It's not the most elegant thing to do, but it is all I've got. I wait for better suggestions.
I might be misunderstanding the question but it should be as simple as;
#user = User.find(<some id>)
#user.update_attributes(:password => 'anewpassword', :password_confirmation => 'anewpassword')
then their password will be 'anewpassword'

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!

Rails 3 + Devise: user_signed_in? for a different user in the database?

I'm building an app where I want to add an online status for a given user.
I know that Devise has a method user_signed_in? built in to check if the user who is using the app is signed in or not. But when I try to use it for a different user like this:
user_signed_in?(user)
user.user_signed_in?
I obviously get an undefined method error.
Does Devise have a method for this or do I have to write my own?
One approach was to store the online status of a given user in the user model.
What's the best solution to this?
I have used Devise on my applications and experienced some of the same problems as you when I first began working with it. You are merely using the helper methods incorrectly. If you'd like to check if the current user has a session and is signed in, you use the helper as such:
if user_signed_in?
which is essentially the same statement as:
if !current_user.nil? && current_user.signed_in
If you'd like to check if a user object is signed in, then you call this: (where user is a User Model Object)
if user.signed_in?
I'm not the author of Devise, but from what I can tell of Warden / Devise neither keep track of who is logged in.
The problem with having an is_online column in the User table is that it is difficult to see who is active on the website. I would add a column to your User model called last_seen as a date-time, and update that with Devise every time the user requests a page. You could then easily add a User.online_count method or also see if a user has been seen at the website in the last 5 minutes.
Use devise_for :user in your routes.rb.

Resources