Password Reset Link doesn't work using Devise in rails - ruby-on-rails

I have overridden the Devise' password controller in my rails application. But it's not working properly. On click of 'reset password link', sometimes call to password#create goes into the gem or sometimes it goes into the overridden controller. My controller looks like:
class Users::PasswordsController < Devise::PasswordsController
layout 'lunchbox/lunchbox', only: [:lunchbox_forgot, :lunchbox_recover]
def create
self.resource = resource_class.send_reset_password_instructions(resource_params)
if successfully_sent?(resource)
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
else
flash[:error] = "Email not found"
redirect_path = params[:user][:lunchbox] ? lunchbox_forgot_password_path : new_user_password_path
redirect_to redirect_path
end
end
end

Related

Devise find by username or email

after setup devise
i would like to get the user by username or email with in a api session
I passed login to parameters but rails spits out a error
User.find_for_database_authentication(:login => params[:username][:email])
the overwrite of find_for_database_authentication on model is already done.
def self.find_for_database_authentication(warden_conditions)
Someone has any hint to spare?
Devise
class Api::SessionsController < Devise::SessionsController
respond_to :json
def create
resource = User.find_for_database_authentication(:login => params[:username][:email])
if resource.valid_password?(params[:login][:password])
sign_in(:user, resource)
render :json=> {:auth_token=>resource.authentication_token, :email=>resource.email}, :status => :ok
return
end
invalid_login_attempt
end
end
I did this by overriding find_for_database_authentication like this:
class User
def self.find_for_database_authentication(auth_hash)
self.where("username = :query OR email = :query", query: auth_hash[:email]).first
end
end
Nothing more was needed.
Try this: User.find_by(username: 'username') or User.find_by(email: 'your#email.com')

How to sign_in user after devise email confirmation in Rails

I am trying from last 7 hours to auto signin the user after email confirmation but when I click the confirmation link then it says "Your email address has been successfully confirmed." but not sign in the user. I have written this code in my confirmations controller and route
devise_for :users, controllers: {confirmations: 'users/confirmations'}
class ConfirmationsController < Devise::ConfirmationsController
#private
def after_confirmation_path_for(resource_name, resource)
sign_in(resource)
render plain: "here"
redirect_to "/admins/view_account", notice: "User deleted."
end
end
Any help would be highly appreciated Thanks.
Notice that automatically sign in after e-mail confirmation used to be Devise's default behavior and was then changed (after 3.1) due to security measures as you can see more here and here.
If you still want to do it, depending on the Devise's version make sure to set the line below on the config/initializers/devise.rb file within your project:
config.allow_insecure_sign_in_after_confirmation=true
If you are using latest Devise version, you may have to instead of that, extend the default controller with this code on app/controllers/users/confirmations_controller.rb as a replacement of what you have mentioned above for controller code (please mind the namespaces and path mentioned):
class Users::ConfirmationsController < Devise::ConfirmationsController
def show
super do |resource|
sign_in(resource) if resource.errors.empty?
end
end
end
And make sure the code you pasted in the beginning of the question belongs in config/routes.rb:
devise_for :users, controllers: { confirmations: 'users/confirmations' }
Hope it helps!
I have solved it myself.
routes should be like this
devise_for :users, controllers: {confirmations: 'confirmations'} do
#put "confirm_user", to: "confirmations#confirm_user"
get "confirmation", to: "confirmations#after_confirmation_path_for"
end
Controller is like this
class ConfirmationsController < Devise::ConfirmationsController
#private
def after_confirmation_path_for(resource_name, resource)
sign_in(resource)
#render plain: "here"
#redirect_to "/admins/"
end
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_flashing_format?
sign_in(resource) # <= THIS LINE ADDED
redirect_to "/your path/"
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end
end

Refactoring sessions_controller in Ruby On Rails

I am learning to refactor my code but I am having trouble refactoring a sessions_controller I have in my application.It is violating the "tell don't ask" principle.I am thinking of extracting some logic to its own class but not sure how that would work.Here is the code from the controller.
class SessionsController < ApplicationController
def create
admin = Admin.find_by(email: params[:sessions][:email])
if admin && admin.authenticate(params[:sessions][:password])
sign_in admin
redirect_to anasayfa_path
flash[:success] = 'Başarılı şekilde giriş yapıldı'
else
redirect_to root_path
flash[:error] = 'Giriş bilgilerinde bir hata var'
end
end
end
How would I refactor this?I thought of extracting
admin && admin.authenticate(params[:sessions][:password])
from this method but would that be the best way?Where would I put the class if I extracted this?
First, you could extract admin lookup, as it may be reused in other actions.
Also, you could standardize your flash keys : notice and alert are two standard keys that #redirect_to understands.
class SessionsController < ApplicationController
before_filter :find_admin
def create
if #admin.authenticate(params[:sessions][:password])
sign_in #admin
redirect_to anasayfa_path, notice: 'Başarılı şekilde giriş yapıldı'
else
redirect_to root_path, alert: 'Giriş bilgilerinde bir hata var'
end
end
private
def find_admin
#admin = Admin.where(email: params[:sessions][:email]).first or redirect_to( root_path, alert: 'not logged in' )
end
end
You have to use #where instead of #find_by to avoid exception if admin is not found.
If you want to keep your current flash keys, you can add in an initializer :
ActionController::Flash.add_flash_types( :success, :error )
Path in #redirect_to from #find_admin and when authentication fail should probably points to log in url.
Try this
class SessionsController < ApplicationController
def create
admin = Admin.find_by(email: params[:sessions][:email])
login_status = false
if admin && admin.authenticate(params[:sessions][:password])
sign_in admin
login_status = true
end
login_status ? redirect_to(anasayfa_path, :flash => {:success => 'Başarılı şekilde giriş yapıldı'}) : redirect_to(root_path, :flash => {:error => 'Giriş bilgilerinde bir hata var'})
end
end

RoR : Are devise controllers generated automatically or should we write on our own?

I am new to ruby on rails. I am trying to use devise gem for authentication. i am going through the tutorials in github. I have created devise views using rails generate devise:views. But i dont find any controllers. Do i need to create on my own or is there any command to generate controllers for it?
Plz help
Devise already creates the required controllers for you behind the scenes. Few of these controllers are: RegistrationController, SessionController.
To customize or override any controller, say RegistrationController; you can do following (snippet from my one application):
class RegistrationsController < Devise::RegistrationsController
before_filter :admin_user, :only => [:destroy]
def new
super
end
def create
if simple_captcha_valid? #verifying user registration by captcha
super
else
build_resource
clean_up_passwords(resource)
flash.now[:alert] = "There was an error with the captcha code below. Please re-enter the code."
render :new
end
end
def update
# required for settings form to submit when password is left blank
if params[:user][:password].blank?
params[:user].delete("password")
params[:user].delete("password_confirmation")
end
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to after_update_path_for(#user)
else
render "edit"
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to rooth_path
end
end
For more you can follow: https://github.com/plataformatec/devise#configuring-controllers

overriding password controller in devise not working

I have problems when overriding passwords controller in devise. I do not want to sign in the user after password is changed so i thought of overriding the password controller and i tried as follows and got an error. I could not identify what the problem is, so please help me. The following is the passwords_controller.rb
class PasswordsController < Devise::PasswordsController
prepend_before_filter :require_no_authentication
# Render the #edit only if coming from a reset password email link
append_before_filter :assert_reset_token_passed, :only => :edit
def new
super
end
def create
super
end
def edit
self.resource = resource_class.new
resource.reset_password_token = params[:reset_password_token]
end
def update
self.resource = resource_class.reset_password_by_token(resource_params)
if resource.errors.empty?
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message(:notice, "New password has been saved")
redirect_to new_user_session_path
else
respond_with resource
end
end
protected
# The path used after sending reset password instructions
def after_sending_reset_password_instructions_path_for(resource_name)
new_session_path(resource_name)
end
# Check if a reset_password_token is provided in the request
def assert_reset_token_passed
if params[:reset_password_token].blank?
set_flash_message(:error, :no_token)
redirect_to new_session_path(resource_name)
end
end
# Check if proper Lockable module methods are present & unlock strategy
# allows to unlock resource on password reset
def unlockable?(resource)
resource.respond_to?(:unlock_access!) &&
resource.respond_to?(:unlock_strategy_enabled?) &&
resource.unlock_strategy_enabled?(:email)
end
end
and my routes is
devise_for :users, :controllers => { :passwords => 'passwords' }
and the error i get is
NameError in PasswordsController#update
undefined local variable or method `resource_params' for #<PasswordsController:0x000001008231c8>
Your 'resource_params' is undefined. May be you should get it as a parameter :
def update
self.resource = resource_class.reset_password_by_token(params[:resource_params])
....
Finally it works. I am using devise version 1.5.3 and it does not provide resource_params method so i copied the following from devise version 1.5.3 and it works.
self.resource =
resource_class.reset_password_by_token(params[resource_name])

Resources