How to set Devise confirmable link on Mandrill template? - ruby-on-rails

I know that with the Mandrill syntax that I can send in user specific info by doing something like this:
def confirmation_instructions(record, token, opts={})
options = {
:subject => 'Email confirmation',
:email => record.email,
:name => record.first_name,
:global_merge_vars => [
{
name: 'email',
content: record.email
},
{
name: 'confirmation_link',
content: record.confirmation_token
}
],
:template => 'confirm_email'
}
mandrill_send(options)
end
but how do I send the actual confirmation link that is in the devise confirmation instructions html.erb?
views/confirmable/mailer/confirmation_instructions.html.erb
<p><%= link_to 'Confirm my account', confirmation_url(#resource, confirmation_token: #token) %></p>
UPDATE
I edited so I send this link:
content: 'http://localhost:3000/users/confirmation?confirmation_token=' + record.confirmation_token
It still doesn't work, I think because the token is actually encrypted. I'm thinking this is the case because when I use the default mailer the token is a lot shorter than the token I get from record.confirmation_token.
Can someone let me know how to pass the correct token to Mandrill?

I had the same issue, what worked for me was using 'token' instead of 'record.confirmation_token'. It seems that Devise's latests updates changed some Mailer's methods config.
Instead of:
http://domain.com/users/confirmation?confirmation_token=' + record.confirmation_token
Use:
http://domain.com/users/confirmation?confirmation_token=' + token
Let me know if it helps you.

Related

Devise edit_password_url missing /

I've write a RoR application and I use Devise for some user management.
I've already configure my application to send email for password recovery and I use the following code in my reset_password_instruction.html.erb:
<p><%= link_to 'Modify password', edit_password_url(#resource, reset_password_token: #token) %></p>
In my config environment files I have defined: config.action_mailer.default_url_options = { :host => 'app_url.com' }.
When the application send a recovery email, it attach an url like this:
app_url.comuser insted of app_url.com/user.
What did I miss?
From the rails console, I see the url like it is suppposed to be.
<p><a href=3D"http://app_url.com/users/password/edit?reset_password_=token=3D47da8a08bd3d4asdfadfasdfa3eb9422388467adccfe095f058ca2a3352b12"=>Modify password</a></p>

Post a hash using HTTParty to an api

I'm trying to send a POST request to an api with a hash as the parameters of the request. The api in question is freshdesk's api. I'm using rails 4.
They require that i send a request in this form:
Code
{
"helpdesk_ticket":{
"description":"Some details on the issue ...",
"subject":"Support needed..",
"email":"hulk#outerspace.com",
"priority":1, "status":2
},
"cc_emails":"superman#marvel.com,avengers#marvel.com"
}
Sample Curl
curl -u user#yourcompany.com:test -H "Content-Type: application/json"
-d '{ "helpdesk_ticket": { "description": "Details about the issue...", "subject": "Support Needed...", "email":
"hulk#outerspace.com", "priority": 1, "status": 2 }, "cc_emails":
"superman#marvel.com,avengers#marvel.com" }' -X POST
http://domain.freshdesk.com/helpdesk/tickets.json
This is currently what I have
Controller
def create
email = params[:email]
description = params[:description]
subject = params[:subject]
payload = [{"helpdesk_ticket" => { 'email' => email, 'description' => description, 'subject' => subject, 'priority' => 1, 'status' => 2}}].to_json
trololol = Freshdesk.post('/helpdesk/tickets.json',
:body => payload
)
debugger
redirect_to "/support"
end
class Freshdesk
include HTTParty
#apikey = "Somethingladida"
format :json
base_uri "http://genericname.freshdesk.com/"
basic_auth #apikey, ""
end
View
=form_tag support_index_path do
=label_tag :email
=text_field_tag :email,params[:email]
=label_tag :description
=text_field_tag :description
=label_tag :subject
=text_field_tag :subject
=submit_tag "Submit", class:"button"
The main problem is this: I'm getting a 500 internal server error, so I'm presuming that the request that i'm trying to craft is not in the format that the freshdesk api requires
Cheers! :)
You can mirror that structure exactly by doing something like this:
def freshdesk_hash
{
"helpdesk_ticket":{
"description":"Some details on the issue ...",
"subject":"Support needed..",
"email":"hulk#outerspace.com",
"priority":1, "status":2
},
"cc_emails":"superman#marvel.com,avengers#marvel.com"
}
end
But to me it looks like you're putting the hash into an array ([{...).

Devise - How to translate auto generated links

I'm finishing the different localizations of my site and i got a little issue in Devise email templates.
In confirmation email for instance, i have translated it all, but the link to confirm the account is auto generated using this snippet:
<%= link_to t('devise.mailer.confirmation_instructions.confirm_link'), confirmation_url(#resource, :confirmation_token => #token) %>
This auto generated link points always to my .com web version and i want it to be conditional depending on the domain (.com/.es). When the link is not auto generated i can accomplish that using:
if request.host.split('.').last == "com"
or
if request.host.split('.').last == "es"
But in this case, i don't know how i can do it.
Any suggestion?
Thanks.
You could add the :host param to your confirmation_url(#resource, :confirmation_token => #token), and look up the correct host in your translation table:
confirmation_url(#resource, :confirmation_token => #token, host: t('host'))
In your yaml file, you 'translate' the correct host for the user's language, like
en:
host: 'www.example.com'

Devise "Confirmation token is invalid" when user signs up

Using Rails 4 and Devise 3.1.0 on my web app. I wrote a Cucumber test to test user sign up; it fails when the "confirm my account" link is clicked from the e-mail.
Scenario: User signs up with valid data # features/users/sign_up.feature:9
When I sign up with valid user data # features/step_definitions/user_steps.rb:87
Then I should receive an email # features/step_definitions/email_steps.rb:51
When I open the email # features/step_definitions/email_steps.rb:76
Then I should see the email delivered from "no-reply#mysite.com" # features/step_definitions/email_steps.rb:116
And I should see "You can confirm your account email through the link below:" in the email body # features/step_definitions/email_steps.rb:108
When I follow "Confirm my account" in the email # features/step_definitions/email_steps.rb:178
Then I should be signed in # features/step_definitions/user_steps.rb:142
expected to find text "Logout" in "...Confirmation token is invalid..." (RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/user_steps.rb:143:in `/^I should be signed in$
This error is reproducible when I sign up manually through the web server as well, so it doesn't appear to be a Cucumber issue.
I would like:
The user to be able to one-click confirm their account through this e-mail's link
Have the user stay signed in after confirming their account
I have setup:
The latest Devise code, from GitHub (3.1.0, ref 041fcf90807df5efded5fdcd53ced80544e7430f)
A User class that implements confirmable
Using the 'default' confirmation controller (I have not defined my own custom one.)
I have read these posts:
Devise confirmation_token is invalid
Devise 3.1: Now with more secure defaults
GitHub Issue - Devise confirmation_token invalid
And have tried:
Setting config.allow_insecure_tokens_lookup = true in my Devise initializer, which throws an 'unknown method' error on startup. Plus it sounds like this is only supposed to be a temporary fix, so I'd like to avoid using it.
Purged my DB and started from scratch (so no old tokens are present)
Update:
Checking the confirmation token stored on the User after registering. The emails token matches the DBs token. According to the posts above, the new Devise behavior says not supposed to, and that instead it is should generate a second token based on the e-mail's token. This is suspicious. Running User.confirm_by_token('[EMAIL_CONFIRMATION_TOKEN]') returns a User who has errors set "#messages={:confirmation_token=>["is invalid"]}", which appears to be the source of the issue.
Mismatching tokens seems to be the heart of the issue; running the following code in console to manually change the User's confirmation_token causes confirmation to succeed:
new_token = Devise.token_generator.digest(User, :confirmation_token, '[EMAIL_TOKEN]')
u = User.first
u.confirmation_token = new_token
u.save
User.confirm_by_token('[EMAIL_TOKEN]') # Succeeds
So why is it saving the wrong confirmation token to the DB in the first place? I am using a custom registration controller... maybe there's something in it that causes it to be set incorrectly?
routes.rb
devise_for :users,
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
},
:controllers => {
:registrations => "users/registrations",
:sessions => "users/sessions"
}
users/registrations_controller.rb:
class Users::RegistrationsController < Devise::RegistrationsController
def create
# Custom code to fix DateTime issue
Utils::convert_params_date_select params[:user][:profile_attributes], :birthday, nil, true
super
end
def sign_up_params
# TODO: Still need to fix this. Strong parameters with nested attributes not working.
# Permitting all is a security hazard.
params.require(:user).permit!
#params.require(:user).permit(:email, :password, :password_confirmation, :profile_attributes)
end
private :sign_up_params
end
So upgrading to Devise 3.1.0 left some 'cruft' in a view that I hadn't touched in a while.
According to this blog post, you need to change your Devise mailer to use #token instead of the old #resource.confirmation_token.
Find this in app/views/<user>/mailer/confirmation_instructions.html.erb and change it to something like:
<p>Welcome <%= #resource.email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(#resource, :confirmation_token => #token) %></p>
This should fix any token-based confirmation problems you're having. This is likely to fix any unlock or reset password token problems as well.
A friend of mine just found this question and emailed me asking if I had figured this out, which reminded me that I never submitted my own answer, so here goes :)
I ended up resetting the token & using send to get the raw token. It's ugly, but it works in a punch for devise (3.5.1).
26 it "should auto create org" do
27 email = FG.generate :email
28 visit new_user_registration_path
29 fill_in :user_name, with: 'Ryan Angilly'
30 fill_in :user_user_provided_email, with: email
31 fill_in :user_password, with: '1234567890'
32
33 expect do
34 click_button 'Continue'
35 end.to change { Organization.count }.by(1)
36
37 expect(page.current_path).to eq(confirmation_required_path)
38 u = User.where(email: email).first
39 u.send :generate_confirmation_token
40 email_token = u.instance_variable_get(:#raw_confirmation_token)
41 u.save!
42 os = u.organizations
43 expect(os.size).to eq(1)
44 visit user_confirmation_path(confirmation_token: email_token)
45 o = os.first
46
47 u.reload
48 expect(u.confirmed?)
49 expect(page.current_url).to eq(organization_getting_started_url(o))
50 end
As of devise 3.5.2, the confirmation token is no longer digested during the confirmation process. This means that the token in the email will match the token in the database.
I was still having trouble with confirmations after figuring this out, but in my case it turned out to be a bug I introduced when I overrode find_first_by_auth_conditions. By fixing the bug I introduced in that method, I fixed my errors with confirmation.

Problems With Resetting Password - Devise

I'm having problems when resetting a password using Devise.
When I click on 'Send me reset password instructions', I get:
ArgumentError at /users/password
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
It says that the problem is in /views/devise/mailer/reset_password_instructions.html.erb on line 5.
On line 5 in that file there is:
<p><%= link_to 'Change my password', edit_password_url(#resource, :reset_password_token => #resource.reset_password_token) %></p>
I have no idea how to setup a mailer in Rails although I have tried to. Can anybody help me with this?
Finally, you need to set up default url options for the mailer in each
environment. Here is the configuration for "config/environments/development.rb":
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
You need to specify the host so it can be shown in the confimation email.
You can create a default filter like this:
# application_controller.rb
before_filter :mailer_set_url_options
...
def mailer_set_url_options
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end

Resources