ruby rails send an email after sign up with devise without confirmable - ruby

i create a sign in /up with devise for my app rails , and i would like just send a email of welcoming but without confirmable or redirecting,
"devise :confirmable, ...
has_many :emails
delegate :confirmation_sent_at, :confirmed_at, :confirmation_token, to: :primary_email
def primary_email
emails.primary || (emails.first if new_record?)
end"
i read the documentation of devise but i didn't find ( or understand) my answer.
thx for your help i am new in the community and don't speak english well.

You can set up an after_action in the model to send an email.
model
after_action :send_welcome_email, only: [:sign_up]
You will need to create the send_welcome_email yourself. Look up actionMailer which will give you an idea of what you need to do.

Related

Welcome emails in Ruby

I'm using Ruby and Devise:Confirmable. A day or so after a new user has registered and confirmed a new trial account we'd like to automatically send him or her a 'follow up email'. Is this something we should also do through devise, or is there a separate gem or process we should implement?
Since you are using Devise already, you can just overwrite the confirmation controller, try something like this.
class ConfirmationsController < Devise::ConfirmationsController
# GET /resource/confirmation?confirmation_token=abcdef
def show
super do |resource|
YourMailerClass.follow_up(resource).deliver_later(wait_until: 1.day.from_now) if resource.errors.empty?
end
end
end
You also need to update the routes.rb file, add the option controllers: { confirmations: :confirmations } at the end of the line where you define devise_for (restart your server after this).
I'm assuming you already have a background jobs proccesor, like sidekiq
Hope it helps

Migrating from devise to omniauth (identity)

I'm thinking of moving over to Omniauth 1.0 (using the "identity" strategy or gem) from Devise 1.4.7, my question is after doing all the code conversion, views etc, will the old passwords, those user accounts created with Devise, still work with the same passwords under OmniAuth?
I've done some research and both are using bcrypt, so I'm guessing "yes" they will work as before and users won't have to create new passwords. Or am I missing something crucial?
Devise passwords are not directly compatible with omniauth-identity
It is true that they both use bcrypt to hash the password, however Devise adds a "pepper" to the password. You would have to add code to omniauth-identity to support a "pepper".
OmniAuth-Identity - lib/omniauth/identity/secure_password.rb
Devise - lib/devise/models/database_authenticatable.rb
Pepper your passwords
Devise adds a pepper to your passwords (since it is already salted by bcrypt), so in order for you to migrate devise users to omniauth-identity, you have to teach the identity strategy how to pepper passwords. This snippit works for us, however we didn't change the :stretches configuration option in devise.
# snatch the pepper setting from the devise initializer
pepper = "biglonguglystringfromyourdeviseinitializer"
# password created by devise in your db (i.e. "my_password_123")
encrypted_password = "$2a$10$iU.Br8ZClxuqldJt8Evl5OaBbHPJeBWbGV/1RoUsaNIZMBo8wHYTq"
# pepper the password then compare it using BCrypt like identity does
BCrypt::Password.new(encrypted_password) == "my_password_123#{pepper}"
=> true
How we made it work
This is a very quick and dirty monkey patch we used to make it work. We are investigating how to add this functionality in a more appropriate manner.
# file: ~/railsapp/config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :identity
end
module OmniAuth
module Identity
module SecurePassword
module InstanceMethodsOnActivation
# Returns self if the password is correct, otherwise false.
def authenticate(unencrypted_password)
pepper = "the big pepper string from the devise initializer"
if BCrypt::Password.new(password_digest) == "#{unencrypted_password}#{pepper}"
self
else
false
end
end
# Encrypts the password into the password_digest attribute.
def password=(unencrypted_password)
pepper = "the big pepper string from the devise initializer"
#password = unencrypted_password
unless unencrypted_password.empty?
self.password_digest = BCrypt::Password.create("#{unencrypted_password}#{pepper}")
end
end
end
end
end
end
I dont think you are missing anything crucial at all. Both are using bcrypt. Awesome.
But does that matter ? I think it really does.
Devise completes your authentication process w.r.t to a Model i.e. say users in this case.
Now your old users are already registered and confirmed, so that really wouldn't be an issue. The encrypted_password and hashed_password are still in the users table for the users to access.
What do you have to worry about ?
=> You probably have to worry about the authenticate_user! filter. I am guessing since they both use bcrypt the authentication wouldn't really be an issue. Perhaps if OmniAuth isn't, they the way it authenticates users would be completely different and your code will break apart.
Thats the only thing you will have to look after is what i feel.

Devise: Is it possible to NOT send a confirmation email in specific cases ? (even when confirmable is active)

Here is my situation, I use devise to allow users to create account on
my site and manage their authentication.
During the registration process I allow customers to change some
options, leading to an actually different account being created but
still based on the same core user resource.
I would like to choose not to send a confirmation email for some of
those account types. I don't care if the account do not get confirmed
and user cannot log in, that's ok, no pb with that.
How would I go about doing that ?
Thanks,
Alex
Actually it's quite easy once I dig a little deeper.
Just override one method in your User model (or whatever you are using):
# Callback to overwrite if confirmation is required or not.
def confirmation_required?
!confirmed?
end
Put your conditions and job's done !
Alex
If you just want to skip sending the email but not doing confirmation, use:
# Skips sending the confirmation/reconfirmation notification email after_create/after_update. Unlike
# #skip_confirmation!, record still requires confirmation.
#user.skip_confirmation_notification!
If you don't want to call this in your model with a callback overwrite this method:
def send_confirmation_notification?
false
end
You can also simply add the following line of code in your controller before creating the new user:
#user.skip_confirmation!
I don't know if Devise added this after the other answers were submitted, but the code for this is right there in confirmable.rb:
# If you don't want confirmation to be sent on create, neither a code
# to be generated, call skip_confirmation!
def skip_confirmation!
self.confirmed_at = Time.now
end
I was able to do something similar with the functions:
registrations_controller.rb
def build_resource(*args)
super
if session[:omniauth] # TODO -- what about the case where they have a session, but are not logged in?
#user.apply_omniauth(session[:omniauth])
#user.mark_as_confirmed # we don't need to confirm the account if they are using external authentication
# #user.valid?
end
end
And then in my user model:
user.rb
def mark_as_confirmed
self.confirmation_token = nil
self.confirmed_at = Time.now
end

Can I execute custom actions after successful sign in with Devise?

I have an app that has basic Devise authentication. After sign in, I would like to look up the user account (user belongs_to account, account has_many users), and store that in the session so that it is available like the #current_user.
What is the rails way of storing session in formation like this?
Is there a hook I can use with Devise to execute code after successful sign-in?
Actually, the accepted answer does not work properly in case of combined Omniauth and Database login modules in Devise.
The native hook that is executed after every successfull sign in action in Devise (disregarding the user authentication channel) is warden.set_user (called by devise sign_in helper: http://www.rubydoc.info/github/plataformatec/devise/Devise/Controllers/SignInOut#sign_in-instance_method).
In order to execute custom action after successfull user sign in (according to Warden Docs: https://github.com/hassox/warden/wiki/Callbacks), put this into initializer (eg. after_sign_in.rb in config/initializers)
Warden::Manager.after_set_user except: :fetch do |user, auth, opts|
#your custom code
end
Update 2015-04-30: Thanks to #seanlinsley suggestion (see comments below), I have corrected the answer to include except: :fetch in order to trigger the callback only when user is authenticated and not every time it is set.
Update 2018-12-27 Thanks to #thesecretmaster for pointing out that Warden now has built-in callbacks for executing your own code on after_authentication https://github.com/wardencommunity/warden/wiki/Callbacks#after_authentication
Edit: Please consider that this was once a good solution, but there are probably better ways of handling this. I am only leaving it here to give people another option and to preserve history, please do not downvote.
Yes, you can do this. The first resource I'd look at is http://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in. Also, check out How to redirect to a specific page on successful sign up using rails devise gem? for some ideas.
You can do something like:
def after_sign_in_path_for(resource_or_scope)
session[:my_account] = current_user.account
profile_url
end
You can implement this method in your ApplicationController or in a custom RegistrationsController.
i'm using rails 5 and devise 4.2.1, my solution is overide devise function on user model:
def after_database_authentication
# here's the custom code
end
and the user model will look like this:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:timeoutable, :lockable
def after_database_authentication
# here's the custom code
end
end
it was called just after the authentication,
i read it from this devise documentation, hope this could help
I resolved this problem by overriding the create method of the session controller like following
class Admin::SessionsController < Devise::SessionsController
def create
super
# here goes my code
# my settings, etc
# do something with current_admin.fullname, for example
end
end
In other words, if authentication is successful (by calling super) then I perform my settings.
In application controller, you can simply add an after action.
app/controllers/users/application_controller.rb
class ApplicationController < ActionController::Base
after_action :do_something
def do_something
# do something
end
end

Acts_as_Inviteable Plugin not sending out invites in Ruby on Rails

I have been trying to create beta invites that each existing user can send out and was hoping to be able to use a plugin called acts_as_inviteable http://github.com/brianjlandau/acts_as_inviteable
I was wondering if anyone had direct experience with it. When I checked the console, it appears to be creating the right queries, but no email or email related errors come up.
I am tempted to just use Ryan Bates' excellent tutorial on beta invites and write it up myself, but I'd love to have something working. We just can't seem to figure it out.
There's a number of problems you need to fix:
Add this line to one of your config blocks (either in environment.rb or each of the files in config/environment):
config.action_mailer.default_url_options = {:host => 'somewhere.com'}
In app/models/invitation.rb on line 3 you have call attr_accessible :recipient_email this will prevent you from mass assigning the sender. You should change it to this:
attr_accessible :recipient_email, :sender, :sender_id
Also invitations_controller.rb should look like this:
class InvitationsController < ApplicationController
before_filter :require_analyst
def new
#invitation = Invitation.new
end
def create
#invitation = Invitation.new(params[:invitation])
#invitation.sender = current_analyst
if #invitation.save
flash[:notice] = "Thank you, invitation sent."
redirect_to root_url
else
render :action => 'new'
end
end
end
You really can't send an invitation unless you're logged in (because you need a sender, which in this case is an current_analyst not #current_user), so the lines having different logic depending on being logged in or not has been removed.
Also, the email will be automatically sent by the Invitation model so calling Mailer.deliver_invitation(#invitation, signup_url(#invitation.token)) is unnecessary (and actually it would have to be AnalystInvitationMailer.deliver_invitation(#invitation))
You can see a full working patch here: http://gist.github.com/290911

Resources