Rails: Customize Devise Confirmable module? - ruby-on-rails

I have my Rails app setup with Devise, but it's still in the development stages. I also have a Thor task that creates the default Admin user.
Problem is Devise won't let that admin user login to the site until the account is confirmed. Is there any way I can disable the confirmable module for the creation of specific users, such as Admin?
My Thor task:
class Setup < Thor
desc "create_admin [EMAIL] [PASSWORD]", "Creates the administrative user."
def create_admin(email = "admin#bogus.com", password = "testpassword123")
require File.expand_path('config/environment.rb') # load Rails environment
admin = User.create(:email => email, :password => password, :password_confirmation => password)
admin.assign_role :admin
puts "Admin user (#{ email }) created."
end
end

Once your user is created you can call the devise provided confirm! method on it rather than updating the database directly. Eg.:
admin = User.create(:email => email, :password => password, :password_confirmation => password)
admin.assign_role :admin
admin.confirm!

This should work
admin = User.create(:email => email, :password => password, :password_confirmation => password)
So your confirmed_at is set, which is the field devise refers to when checking user confirmation.
EDIT
Forgive me if this seems like a hack but this seems to work for me. After executing the above line,
admin.update_attributes(:confirmed_at => Time.now)

just coment :confirmable in User or Admin model
devise :database_authenticatable, :recoverable, :rememberable, :trackable, #:confirmable...
In config/inicializers/devise.rb
you can set here how many time user have to confirm his account

Related

Rails 5, Devise, Omniauth, Twitter

I know this has been asked many times, but the answers are never fully acceptable to me.
So I am following Ryan Bates' Railscast about this topic, and mixing that with the official Devise Omniauth guide (that is based on FB), but I am just not getting it to work like I expect, so I would love some help.
I have a Users::OmniauthCallbacksController that looks like this:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect root_path, :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
else
session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages
redirect_to new_user_registration_url
end
end
alias_method :twitter, :all
def failure
redirect_to root_path
end
end
Then I also have two methods on my User.rb
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.update(
email: auth.info.email,
password: Devise.friendly_token[0,20],
username: auth.info.nickname,
remote_avatar_url: auth.info.image,
token: auth.credentials.token,
secret: auth.credentials.secret
)
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.twitter_data"]
# user.attributes = params
user.update(
email: params[:email],
password: Devise.friendly_token[0,20],
username: data["info"]["nickname"],
remote_avatar_url: data["info"]["image"],
token: data["credentials"]["token"],
secret: data["credentials"]["secret"]
)
end
end
end
I run into a variety of problems. The most immediate is because I am setting the password, the user doesn't know the password when they try to login (and I don't auto sign them in upon confirmation).
But if I don't set the password, it doesn't ask them to set the password...so that's kinda weird too.
These are my devise settings on my User model:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable, :omniauth_providers => [:twitter]
validates :username,
presence: true,
uniqueness: {
case_sensitive: false
}
validate :validate_username
def validate_username
if User.where(email: username).exists?
errors.add(:username, :invalid)
end
end
So my question is this, when someone signs up via Twitter, do they need to enter a password? I automatically send them to the registration/new.html.erb anyway because Twitter doesn't return an email value. But I am trying to just get the process working first, before optimizing it.
How do I deal with the password issue?
Edit 1
For more clarity, I will have to deal with this password_required issue regardless of the OAuth provider.
So how do I override that requirement for all OAuth providers?
You should add the following method to the User class:
def password_required?
(provider.blank? || uid.blank?) && super
end
Since Twitter doesn't return the user's email, you may also want to tweak that email validation, but redirecting the user to registration/new.html.erb like you are already doing seems like the correct approach to me.

Devise + Twitter OmniAuth Get user Email

I've been using Devise + OmniAuth Twitter to authenticate the user to my portal. I am currently facing two issues.
When the user is accessing /users/sign_up, the form is publicly visible. Instead, I want to redirect him to the Twitter authentication page.
When the user is accessing /users/sign_up, the email form is visible. I'm using this form to get the email address of the users after he signs up successfully from Twitter.
Can someone please help me solve this issue from people accessing the forms directly?
Adding Code Snippets:
#config/routes.rb
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
devise_scope :user do
get "skcript1625" => "devise/sessions#new", as: :login
get "logout", to: "devise/sessions#destroy", as: :logout
end
# app/models/user.rb
devise :database_authenticatable, :registerable, :rememberable, :trackable, :validatable
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
user.profileimg = auth.info.profileimg # assuming the user model has an image
end
end
You have to redirect the user with the following link
<%= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter) %>
Make sure you told your model (usually 'user') that it is 'omniauthable'
devise :omniauthable, :omniauth_providers => [:twitter]
When the user authorized twitter to share your info with the app, all the user's information is available in a hash request.env["omniauth.auth"].
See the documentation for more detail about this hash.
Edit: Everything is well explained here

Devise - Skipping user confirmation in Development

How do you skip user confirmation in development in devise.
I have set up the production environment to send emails with SendGrid, but now I have done that it won't let me log in.
Thanks for your time!
create User in console:
user = User.create(
:first_name => 'admin',
:last_name => 'admin',
:email => 'foo...#email.com',
:password => 'password1',
:password_confirmation => 'password1'
).skip_confirmation!
# Devise :doc:
# If you don't want confirmation to be sent on create, neither a code
# to be generated, call skip_confirmation!
or in model:
after_create :skip_conf!
def skip_conf!
self.confirm! if Rails.env.development?
end
Another way:
User.new(email: 'xx#xx.xx', password: '12345678').confirm!
BTW, you can skip :password_confirmation at all, because #confirm! skips validation if record does not persisted yet.

Rails, devise gem: can't login after add a user via rake task

When i add default users in my rails app via rake task all goes fine, but when i try to login i can't access. Instead, if i sign up via the form, then I can access to the backend of my rails app.
I need to add Users via rake command but I don't understand why I can't login after the users are added to the db.
rails v 3.2.8
devise v 3.2.0
desc "Create a default admin user"
task :default_user => :environment do
User.create(name: "myname", email: "my#email.com", login: "mylogin", password: "mypassword", password_confirmation: "mypassword")
end
I use the following modules:
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :encryptable, :encryptor => :restful_authentication_sha1
Since I switched from restful_authentication to devise, I've included
:encryptable, :encryptor => :restful_authentication_sha1
If they are omitted, I suppose that the old users, already present in my users table, can't login, but if a new user is created via rake task, then I can login with it.

Why my recoverable module from Devise gem isn't working?

I have UserMailer class with next code:
User.rb:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
-----------------
class UserMailer < ActionMailer::Base
default :from => "denys.medynskyi#gmail.com"
def password_reset(user, password)
#user = user
#password = password
mail(:to => user.email,
:subject => 'Password Reset Notification')
end
def congrats_email(user)
mail(to: user.email, subject: "Welcome Message")
end
end
setup_mail.rb:
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:user_name => "denys.medynskyi",
:password => "********",
:authentication => "plain",
:enable_starttls_auto => true
}
and from devise.rb:
Devise.setup do |config|
# ==> Mailer Configuration
config.mailer_sender = "UserMailer"
end
and after forgot password submit I go to some page, but it deosn't show me any notice adn doesn't send email.
What I'm doing wrong ?
I'm not 100% sure this is the cause of any or all of your problems, but if you're trying to work with Devise, overriding some of the default mailer behavior but not all of it, you should inherit from Devise::Mailer rather than ActionMailer::Base.
So
class UserMailer < Devise::Mailer
Edit: The method that Devise calls in Devise::Mailer to render the password reset mail template is reset_password_instructions. So your method isn't even overwriting that. Also, the way Devise works, it's the resource that eventually calls the method that sends the instructions e-mail. The job of the reset_password_instructions method is just to generate the e-mail from the view template. So it looks to me like the code you've got above isn't really working with the normal Devise flow. What calls password_reset in your app?

Resources