How to let user activate account through devise confirmations email link locally - ruby-on-rails

I am trying to confirm user accounts in test mode while using devise and rails. Here's the scenario. I changed the devise confirmation email that is sent into a partial that is rendered after a user has successfully signed up. Problem is it shows the following error "undefined method email". Here's my confirmation partial.Welcome <%= #resource.email %>!
You can confirm your account through the link below:
<%= link_to 'Confirm my account', confirmation_url(#resource, :confirmation_token => #resource.confirmation_token) %>. And below is my application_helper in order to access the resource details. def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end</pre>

Is #resource actually the user in application_helper? I know if it is nil it will be assigned a new User, but what is it before it assigns it?
I suspect #resource isn't a User, but something else (a something that doesn't have an email field).

Related

no responce when using devise in other controller

I'm not so long in Rails development and now am working with checkout login logic. I ended up with finding this kind of solution in order to pass user as the resource for using Devise in other controllers
def resource_name
:user
end
def resource
#resource ||= User.new
end
def resource_class
User
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
Though I now can use resourse in my controller, when I'm trying to login/sign up Devise doesn't work properly. I get error of incorrect email/password when I'm trying to log in and get no response trying to sign up. Even if I leave email field empty I don't receive error which should appear due to resource.errors.
My code is:
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= render 'devise/shared/error_messages', resource: resource
= f.label :email, 'Enter Email'
= f.email_field :email, placeholder: 'Enter Email'
= resource.errors.messages[:email].to_sentence
= f.submit ''
Maybe anyone else had the same problem or saw any solution in such situation, I'll be grateful for any help.
If you are trying to create a user and then pass them to other functions, if they successfully log in, you can use current_user as per the Devise documentation
But I'm not sure what exactly you are trying to do. The user should be #user or :user, depending on your setup. What exactly are you trying to achieve? What are the other controllers like?

How to redirect to login page/ or making user login successful after confirm email in devise token auth

I am using devise token auth with React frontend and now I am making user confirmable through email. Email is being sent but somehow it generates a wrong URL.
The URL that is generated is.
http://localhost:3001/auth/confirmation.4?confirmation_token=AoWH2yYxuHHnBzJRF746
My routes.
new_user_confirmation GET /auth/confirmation/new(.:format) users/confirmations#new
user_confirmation GET /auth/confirmation(.:format) users/confirmations#show
POST /auth/confirmation(.:format) users/confirmations#create
My app/views/devise/mailer/confirmation_instructions.html.erb
<p>Welcome <%= #email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', user_confirmation_url(confirmation_token: #token) %></p>
After clicking confirm my account, it takes me to my application successfully, but with the wrong URL. I will be happy if I achieve one of the following.
User is automatically logged in after confirming.
It goes to login page after confirm account and after that he gives thee credentials and login.
For 1, I have overridden the confirmations_controller.rb like.
# frozen_string_literal: true
class Users::ConfirmationsController < Devise::ConfirmationsController
# The path used after confirmation.
def after_confirmation_path_for(resource_name, resource)
sign_in(resource) # In case you want to sign in the user
root_path
end
end
In routes.rb
mount_devise_token_auth_for 'User', at: 'auth', controllers: { confirmations: 'users/confirmations' }
First, the url helper that you use in the email doesn't need to receive the #resource - this is why it generates the url with the .4. It should rather be
<p><%= link_to 'Confirm my account', user_confirmation_url(confirmation_token: #token) %></p
Second, according to this tutorial, you can redirect the user after confirmation, like you tried already.
https://github.com/heartcombo/devise/wiki/How-To:-Add-:confirmable-to-Users#redirecting-user
Just give a path in your app after you signed in the user
def after_confirmation_path_for(resource_name, resource)
sign_in(resource) # In case you want to sign in the user
your_new_after_confirmation_path
end
So no need to go to session_new again after signing in.

1 error prohibited this user from being saved: Reset password token is invalid

I am currently doing a project that using devise gem.. The sign up,confirmation email and also the login is working well. But in forgot password, I am encountering this error.. I tried to check the token in http://localhost:3000/rails/mailers/user_mailer/reset_password_instructions by hovering the "change my password" text the token that received is the same in my table
Note: I followed the instruction that i have search regarding to the reset_password file
Reset Password Instruction
<p>Hello <%= #resource.email %>!</p>
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(#resource, reset_password_token: #token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
User Mailer preview
# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailerPreview < ActionMailer::Preview
def confirmation_instructions
#user = User.last
#getUser = User.find(#user)
#token = #getUser.confirmation_token
Devise::Mailer.confirmation_instructions(#user, #token)
end
def reset_password_instructions
#user = User.last
#getUser = User.find(#user)
#token = #getUser.reset_password_token
Devise::Mailer.reset_password_instructions(#user,#token)
end
end
Question: How can I fix this kind of error?
In file of user_mailer_preview and to the method of reset_password_instructions try to add this
def reset_password_instructions
query = "SELECT * FROM users
WHERE reset_password_token IS NOT NULL
ORDER by reset_password_sent_at DESC"
user = User.find_by_sql(query).first
token = user.send(:set_reset_password_token)
Devise::Mailer.reset_password_instructions(user, token)
end

Login a User via email - Devise

Within my application a User is created after a successful transaction
def create_real_user
return unless current_or_guest_user.is_guest?
generated_password = Devise.friendly_token.first(8)
#user = User.new(
is_guest: false,
first_name: params[:first_name],
last_name: params[:last_name],
email: params[:email],
password: generated_password,
password_confirmation: generated_password,
braintree_id: #result.transaction.customer_details.id
)
#user.save(validate: false)
RegistrationMailer.welcome(#user, generated_password).deliver_now
end
And as you can see an email is sent out and it advises that a password has been set for them but if they wish to change it then visit a link
Your current password is <%= #password %> but if you would like to change it then please visit <%= link_to 'Change my password', edit_user_registration_path(#user.id) %>
So when clicking this i get to the login screen but i would like to have the user automatically signed in and taken straight to the page where they can edit their password.
How would i go about this?
Thanks
There isn't a quick fix for this but it's possible.
Include a route for this special login case...
resources :users do
member do
get 'token_link'
end
end
This gives you a new helper method `token_link_user_path
You would need to create a token field in your User table when you create the record, and set it to some random value via a before_create
class User
before_create :generate_token
def generate_token
user.token = SecureRandom.urlsafe_base64(nil, false)
end
...
end
In your email include the link...
link_to 'access your account', token_link_user_path(#user.token)
In your User controller...
def token_link
#user = User.find_by(token: params[:id])
#user = nil if #user && #user.created_at < Time.now - 1.day
unless #user
flash[:error] = 'Invalid log in'
redirect_to root_path
end
#user.update_attribute(:token, nil)
... do here any processing, renders, or redirects you'd like
end
Note how we wipe out the token_link after it's been used, to prevent it from beign used twice. Along the same lines, we check that it's not older than a day since the record's been created.

Editing Users With Devise and Omniauth

I'm working through the Railscast on implementing Devise and OmniAuth (along with the Devise documentation) -- currently, I've got a site going where visitors can sign up using their facebook accounts or by filling out a form.
I'm running into trouble when users that sign up via OmniAuth try to edit their profiles, though. Devise looks for the user's current password when they submit changes to their profiles, but those that logged in with facebook don't know their passwords (they're set automatically in the user model):
def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
unless user
user = User.create(first_name:auth.extra.raw_info.first_name,
last_name:auth.extra.raw_info.last_name,
provider:auth.provider,
uid:auth.uid,
email:auth.info.email,
password:Devise.friendly_token[0,20]
)
end
user
end
When a user edits his information, the app should not require password confirmation if he set up his account through OmniAuth. The tutorial suggests that the handy password_required? method will help me achieve this outcome. Specifically, adding this method to the user model means that it should only return true if the user didn't sign up through OmniAuth (the provider attribute would be nil in that case):
def password_required?
super && provider.blank?
end
Thus, a piece of code like:
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<%= render :partial => "essential_user_info_inputs", :locals => { :f => f } %>
<%= render :partial => "inessential_user_info_inputs", :locals => { :f => f } %>
<% if f.object.password_required? %>
<%= render :partial => "password_inputs", :locals => { :f => f } %>
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
<% end %>
<%= f.submit "Update" %>
<% end %>
would theoretically only display password inputs when needed. It also suggests that Devise has built in logic saying that OmniAuth users don't need to use passwords to edit their accounts. I have no idea if this is true, but the tutorial kind of makes it look like that. But when an OmniAuth user tries to edit his account, I get "Current password can't be blank." Same thing with non-OmniAuth users (this makes sense, since the password fields don't show up on those users' edit pages either).
Some poking around confirms that the password_required? method is returning false, both when the user signed up through OmniAuth and through the site's regular user signup. Even when I change it to simply run the superclass method, it returns false.
Any ideas of what's going on with the password_required method? I can't find anything about it anywhere, but I feel like that's what's tripping things up right now.
Update:
This is now working, but not using the method outlined in the Railscast, which relies on requires_password? method, a topic that I still know nothing about. Instead, I implemented the solution outlined here, as suggested here. So I am now only requiring passwords to update non-OmniAuth accounts with the code:
class Users::RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
email_changed = #user.email != params[:user][:email]
is_facebook_account = !#user.provider.blank?
successfully_updated = if !is_facebook_account
#user.update_with_password(params[:user])
else
#user.update_without_password(params[:user])
end
if successfully_updated
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
end
The easiest way is to overwrite the update_resource method in your RegistrationsController. This is advised by devise in their own implementation of the controller:
# By default we want to require a password checks on update.
# You can overwrite this method in your own RegistrationsController.
def update_resource(resource, params)
resource.update_with_password(params)
end
So the solution is to overwrite this method in your own controller like this:
class Users::RegistrationsController < Devise::RegistrationsController
# Overwrite update_resource to let users to update their user without giving their password
def update_resource(resource, params)
if current_user.provider == "facebook"
params.delete("current_password")
resource.update_without_password(params)
else
resource.update_with_password(params)
end
end
end
I've added an update to the link below that includes my solution to the Devise/ OmniAuth change user profile/password issue and collected some helpful links:
stackoverflow - Allowing users to edit accounts without saving passwords in devise
I saw this used somewhere.
def update
params[:user].delete(:current_password)
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
if current_user.update_without_password(params[:user])
redirect_to somewhere_wicked_path, notice => "You rock"
else
render 'edit', :alert => 'you roll'
end
end
use something like this in your update method in your controller. Pretty sure that method is in Devise too.

Resources