I'm using code identical to my password_reset code for my email change code.
User wants change their email address so they type in their email address click a button and they're logged out.
An email is sent to them containing a link they click containing a code as id which is then matched up with the one stored in the db to confirm they are in fact the accounts owner. Any way when I click the I get the error shown below.
Problem is I'm getting this error:
ArgumentError in EmailsController#edit
comparison of String with ActiveSupport::TimeWithZone failed
Rails.root: /Users/greg/site
Application Trace | Framework Trace | Full Trace
app/controllers/emails_controller.rb:19:in `<'
app/controllers/emails_controller.rb:19:in `edit'
Request
Parameters:
{"id"=>"KdFTTeWuOGqpDm6F_iY7aw"}
Show session dump
Show env dump
Response
Headers:
None
Emails controller create:
def create
#user = User.find_by_email(params[:email_change][:email])
logout if logged_in?
#user.generate_and_store_email_change_token && UserMailer.email_change(#user).deliver if #user
flash[:success] = "Email sent with email reset instructions."
redirect_to root_url
end
Emails controller edit:
def edit
#user = User.find_by_email_change_token(params[:id])
if #user.nil?
flash[:error] = "The email change link you clicked has been used."
redirect_to root_url
elsif #user.email_change_sent_at < 2.hours.ago
flash[:error] = "Email change token has expired."
redirect_to email_change_url
end
end
User model:
def generate_and_store_email_change_token
self.email_change_token = SecureRandom.urlsafe_base64
self.email_change_sent_at = Time.zone.now
save!(:validate => false)
end
def remove_used_email_change_token
self.email_change_token = nil
save!(:validate => false)
end
This is strange because the exact same code works for my password reset. I tested again and I don't get the error the email version giving me.
Kind regards
Seems like email_change_sent_at type is a string. You should change it to datetime
Related
working on a Passwords_Controller that allows the password to be changed, also validates if the user is using same password, or if they are trying to use different password, and another password to confirm. I have it set to "redirect_to" to my dashboard controller that lands them back to be the page to enter the password again before user is updated with new password.
currently I am getting a DoubleRenderError. I have some "puts" with extrapolation see if the logic is passing through the controller and rendering I'm new to rails, so i'm not exactly sure if its my redirect statements that are stopping the validation of old pw, new password - confirm password logic in my controller, or I have too many if statements that is forcing the controller to do double render.
(output of on the terminal with statements for error)
Redirected to http://127.0.0.1:3000/dashboard
true
is this working asdf <~~ test username
is this also working $2a$12$d5WadQunMyww2r4lnmqgveoXaq6WO6hNXvsG/h3RxqUxGFCp6tnWm
Redirected to
Completed 500 Internal Server Error in 738ms (ActiveRecord: 9.1ms | Allocations: 6474)
AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".):
this is my password controller
require 'bcrypt'
class PasswordsController < ApplicationController
include BCrypt
def passwordchanged
end
def update
user = current_user;
#user entered correct password
if user.authenticate(params[:password])
helpers.flash_message :danger, "current password doesnt match"
redirect_to '/dashboard'
end
puts "#{user.authenticate(params[:password])}"
puts "is this working #{params[:new_password]}"
puts "is this also working #{Password.new(user.password)}"
#if new password is the same as new password, doesnt not save
if Password.new(user.password) == params[:new_password]
helpers.flash_message :danger, "new password can't match current password, please try again"
redirect_to '/login'
end
puts "#{redirect_to '/login'}"
#if new password doesnt match confirm password
if params[:new_password] != params[:new_password_confirm]
helpers.flash_message :danger, "password, password confirm needs to match"
redirect_to '/dashboard'
end
puts "#{params[:new_password] != params[:new_password_confirm]}"
#create a new password and save the user ID
user.password = params[:new_password]
user.save
helpers.flash_message :success, "change successful, logout for new session"
redirect_to '/passwordchangesuccess'
end
end
this is my Application Controller
class ApplicationController < ActionController::Base
helper_method :current_user
def current_user
User.find_by(id: session[:user_id])
end
def authenticate_user!
redirect_to '/login' unless current_user
end
end
I get this error when I try to sign in a user, and can't figure out why. It's weird because when I run the following code I get the BCrypt Error, however when I change the find_by line (line 7) from can_email (candidate's email) to can_name (candidate's first name) I don't get the error at all, it just doesn't sign in the user presenting an "invalid password/email combination" error message on the webpage regardless if the combination is right or not. It's something to do with the password but I can't pin point it.
class SessionsController < ApplicationController
def new
end
def create
candidate = Candidate.find_by_can_email(params[:can_email])
if candidate && candidate.authenticate(params[:password]) **Error highlights this line**
session[:candidate_id] = candidate.id
redirect_to candidate
else
flash.now[:error]="Invalid email/password combination"
render 'new'
end
end
def destroy
if signed_in?
session[:candidate_id] = nil
else
flash[:notice] = "You need to log in first"
end
redirect_to login_path
end
end
Having the SessionController i am assuming you have a route as follows
# This is just a sample
post 'login' => "sessions#create" # gives login_path
Since there will be no session model i assume you have the form as follows
form_for(:session, url: login_path)
Now if you are collecting eg can_email and password you get
{session: {password: 'foo', can_email: 'foo#bar.com'}}
Accessing params[:session] returns the hash containing email and passowrd
So i think you should obtain them as follows
def create
candidate = Candidate.find_by(can_email: params[:session][:can_email])
if candidate && candidate.authenticate(params[:session][:password])
# login the user
else
# whatever
end
end
I got this error too, but in my case it was the result of myself having changed the encrypted_password value of my user in the database a while back and then forgetting about it.
This was easily fixed just by updating the password :)
I have been trying to solve the following problem for a couple of days. Forgive me if this is a common problem as I am new to rails and probably couldn't query the right question/keyword in stackoverflow or google.
I am building a system where a user will get an invite via email, click on a unique link, be taken to a page where he/she can accept or decline the invitation. I am getting stuck at the part where the user accepts or declines the invitation.
I've built it around two controllers: an invitations controller and a confirmations controller.The invitations controller creates a record containing a name, an email, and a uniquely generated token. The controller then emails a link with the token to the defined email. The link points to the confirmations controller and passes the unique token from the invitation. However, when clicking on the link and accepting the invitation, I get the following error:
NoMethodError in ConfirmationController#confirm
undefined method `update_attribute' for nil:NilClass
Here is some of the code for solving this issue:
Confirmation_controller.rb
class ConfirmationController < ApplicationController
def new
#confirmation = Invitation.find_by_invite_token(params[:invite_token])
end
def confirm
if #confirmation.update_attribute(:accepted, true)
flash[:success] = "Invitation confirmed!"
redirect_to 'static_pages/home'
else
flash[:notice] = "Failed :("
redirect_to 'static_pages/home'
end
end
end
routes.rb
match '/confirmation/:invite_token', to: 'confirmation#new'
match '/confirmation/:invite_token/confirm', to: 'confirmation#confirm'
app/views/confirmation/new.html.erb
Click here to accept:
<%= link_to "Confirm", :controller => "confirmation", :action => "confirm" %>
You need to get your Invitation in the confirm method too.
If you want rails to raise an exception if no invitation was found
def confirm
#confirmation = Invitation.find_by_invite_token!(params[:invite_token])
#confirmation.update_...
end
No exception will be raise. You may want to check manually with a condition in the following case.
def confirm
#confirmation = Invitation.find_by_invite_token(params[:invite_token])
if #confirmation
#confirmation.update_...
else
# do something
end
end
You should find confirmation record before calling update_attribute on it, like you did it in new action:
#confirmation = Invitation.find_by_invite_token(params[:invite_token])
Or, to throw exception when the record is not found and to render 404 page to the user:
#ocnfirmation = Invitation.find_by_invite_token!(params[:invite_token])
The problem is that you never told the program what #confirmation is. What you should do is find it first then run the update. Note this is different from the different answers, just thought I would throw in some variety.
def confirm
# You're missing this line below. Basic search for the confirmation.
# Note too that you will have to pass in the parameter `invite_token` for it to work
# I'm also assuming invite_token is unique among each invitation
confirmation = Invitation.where(invite_token: params[:invite_token])
# Notice that I'm first checking to see if the confirmation record exists, then doing an update
if confirmation and confirmation.update_attribute(:accepted, true)
flash[:success] = "Invitation confirmed!"
redirect_to 'static_pages/home'
else
flash[:notice] = "Failed :("
redirect_to 'static_pages/home'
end
end
In my application I have a user confirmation process. When a user signs up four things happen:
An account_status_id is set to 1 (unconfirmed)
The user is signed in (now current_user exists)
A new_account_confirmation_token is generated
A confirmation email is sent to the new user with a link that includes the new_account_confirmation_token
I initially tried to handle the confirmation link with this method. It finds the user without issue and the code flows through the update_attributes! method, however it wasn't updating the account_status. From what I can tell it is due to the fact that the current_user object exists, therefore the user Im trying to update is already "in memory". Is that correct?
def new_account_confirmation
#title = "Account Confirmation"
logger.info("User is not logged in")
#user = User.find_by_new_account_confirmation_token(params[:confirm_id])
if #user
#user.update_attributes!(:account_status_id => 2)
else
redirect_to root_path
end
end
My work around is as follows. The code below works but I'd like to know why the code above doesn't work. Why won't it update the account_status?
def new_account_confirmation
#title = "Account Confirmation"
if current_user
logger.info("User is logged in")
current_user.update_attributes!(:account_status_id => 2)
else
logger.info("User is not logged in")
#user = User.find_by_new_account_confirmation_token(params[:confirm_id])
if #user
#user.update_attributes!(:account_status_id => 2)
else
redirect_to root_path
end
end
end
Even if your user is "in memory" as you say, that's no reason for it not to update. I believe your update IS happening but you're just not seeing it because current_user is not in sync with #user.
I don't know how you're verifying that #user is not being updated but if update_attributes! is not throwing an error then it's being saved.
i already have the crm_member_list table and also can successfully login ,now i want to add a column to crm_member_list table called "failed_times" to record the failed times.when the failed_times more than 5 times.user account is locked.
i define a method called add_failed_times in the crm_member_list model.
def self.add_failed_times(mbr_id)
member = find_by_mbr_id(mbr_id)
failed_times = member.failed_times.to_i+1
end
in the session controller,
def create
member = CrmMemberList.authenticate(params[:session][:mbr_id],params[:session][:password])
if member.nil?
user= CrmMemberList.find_by_mbr_id(params[:session][:mbr_id])
if user.nil?
flash.now[:error] = "Invalid passport/password combination."
#title = "User nil"
render 'new'
else
times = CrmMemberList.add_failed_times(params[:session][:mbr_id])
if times.to_i=1
user.failed_times=times
user.save
flash.now[:error] = "Invalid passport/password combination."
#title = "Less than 6"
render 'new'
else
#title ="Locked"
render 'failed'
end
end
else
sign_in member
redirect_to member
end
end
How can i resolve this problem?
thanks
the save is false.
I'm guessing the save is false due to some validation error. Probably the password and password confirmation don't match. You can call
user.save(:validates => false)
which bypasses the validation.
If you're unsure what the error is, after you've called user.save, you can output
user.errors
To get the errors that are stopping your save.
What about using a gem to handle the whole authentication stuff (including account locking) automagically : https://github.com/binarylogic/authlogic ?