devise reconfirmable - ruby-on-rails-3

I would like to use the devise option :reconfirmable in my user model, so whenever a user changes his email, he needs to confirm it with a link sent by email.
The big problem is, that the email gets never sent ...
My setup is with devise 2.1.2 is:
user model:
attr_accessible: unconfirmed_email, ...
devise :invitable, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable
in the initilizer devise.rb:
config.reconfirmable = true
in the routes:
devise_for :users
in the form the model field unconfirmed_email gets set properly. I checked this through the console.
The first confirmation email, when a user registers on the page gets send out without problem.
I tried debugging the problem with adding this code to the initializers directory to overwrite the devise methode that gets triggered as a after_update hook:
module Devise::Models::Confirmable
def send_confirmation_instructions
debugger
end
end
it seems like send_confirmation_instructions is never called, since I never get to the debugger.
Do I somehow need to call reconfirmable, or does it gets triggered automatically when setting the model attribute "unconfirmed_email" to a new email address?
Thankfull for any help,
j.

OK, this is embarrassing..
After diving into the Devise code, I figured out that you don't need to set the unconfirmed_email attribute of your user model, but just change the existing email attribute. The attribute unconfirmed_email is just used internally for Devise to store the email address until it's confirmed.
Later version of devise gem explains this in initial migration. Here is "Confirmable" section (note the comment on the last line) from XXX_devise_create_users.rb migration:
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
Sorry for bothering, but hopefully this can help somebody having the same problem...

Related

Fetching all posts made by a user with Devise gem

I'm using Devise to manage user model.
Here's the User model, user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
acts_as_voter
has_many :topics
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Here's the Topics model, topic.rb
class Topic < ActiveRecord::Base
acts_as_voteable
belongs_to :user
end
When I create a post, the user ID is stored in the "user_id" column of Topics. I want to a User profile page, which should display all the posts he has made. In my User profile page view, I have,
<%= Topic.find_by_user_id(#user.id) %>
I have two posts made by the same user,
But when I try fetch all the posts made by the user, the SQL command automatically queries with a LIMIT of 1. Like this,
And because of this, the view is fetching only 1 post made by the user. How do I fetch all the posts?
find_by_attribute will always return only one result. You need to change your code to:
Topic.where(user_id: #user.id)
or even better:
#user.topics

Ruby validates_uniqueness_of email leading to wrong SQL uniqueness check

I am seeing the following SQL being used to check that an email address (e.g. joebloggs#joebloggs.com) is unique when a user signs up on my Ruby website:
SELECT `users`.id FROM `users` WHERE (`users`.`email` = BINARY '--- !ruby/object:Mail::Multibyte::Chars \nwrapped_string: joebloggs#joebloggs.com\n') LIMIT 1
This is always resulting in zero rows being returned, so Ruby attempts to create the user in the database. On the attempted record creation in MySQL, it fails because users.email has a unique index on it.
Can anyone tell me why Ruby is generating the SQL statement above? It does this on my live site running in production or development mode. On my development site (running in production or development mode), the following (correct) SQL is generated:
SELECT `users`.id FROM `users` WHERE (`users`.`email` = BINARY 'joebloggs#joebloggs.com') LIMIT 1
For user management, I am using devise with the following setting:
validates_uniqueness_of :email
Thanks in advance for your help.
In your user model you can add email validation to uniqueness as false.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,:registerable,
:recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:email]
validate :email, presence: true, uniqueness: false
end

How do I get devise 2.2.3 to accept auto-geneated password for rails 3.2.13 app

I am attempting to create a rails 3.2.13 app where when the user is created a password is auto generated for that user. Right now I am using a before_validate to generate and assign the password to the password and password_confirmation fields on the user object before it is creates but devise still complains that the password is still blank.
What is the best approach to get devise to accept the password that I have generated for my user object? It would be nice to be able to do this without having to overwriting the internal validation if possible.
I don't known what you are doing wrong... Tried quickly here and everything turned out ok.
Here is my model
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
before_validation :set_user_password
def set_user_password
#password = Devise.friendly_token
end
end
I didn't even had to set password_confirmation just password and it saved without errors at the rails console.
The previous solution is awesome. But you can not reset your password. set_user_password should only execute when creating account.
before_validation :set_user_password, :on => :create
def set_user_password
#password = Devise.friendly_token
end

"Email can't be blank" Devise using username or email

I was following this how-to on How To: Allow users to sign in using their username or email address and did all the steps detailed there but when I try to register via the registrations/new.html.erb form I get this error:
Email can't be blank
In my model I have:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :username, :email, :password, :password_confirmation, :remember_me
attr_accessor :login
attr_accessible :login
and
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
any advice with this problem?
======= UPDATE
I found something here ■[rails]How to use Devise and Rails , without EMail here it is something like:
# Email is not required
def email_required?
false
end
With that added in my model I can create a record with username and leaving the email field blank, but when I try to create a second record without email the database rises an error:
Mysql2::Error: Duplicate entry '' for key 'index_parents_on_email':...
Should I use this, remove the index from my table in the database, and just validate the username in the model? because I don't really need the email field on that model.
Update
Asiniy's answer below actually works like a charm (:
Original (who knew?)
Your problem is the index on the mysql table, you might remove it from your migrations, but I'm not sure that will solve your problem. Not using the email in Devise is tricky, I would suggest a workaround like a fake email out of the username, something like this
"#{user.username}#fake.me"
It's not very clean but I see devise doing something similar for passwords when you use omniauth.
Rails 4 and Strong Parameters
I got into this problem for username in rails 4, and I had to configure the permitted parameters as below for sign_up:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit :username, :email, :password, :password_confirmation
end
end
end
This is described in Devise Doc
Normal solution
class User < AR::Base
devise_for tralala
def email_required?
false
end
end
Please refer to the https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L29

I need to authenticate a user directly in the console under Devise. How can I do it?

I need to do something like this from Rails console to do some testing and experiments:
User.authenticate(username, password)
I'm using Devise, but I have no idea how to do this.
I saw this other answer here
How to sign in a user using Devise from a Rails console?
But I need something cleaner and more direct. If necessary, I just need the algorithm to hash an attempted password with the salt and compare it to the encryped_password.
Is it this?
User.find(1).valid_password?('password123')
General info:
Check out the Devise README found here.
As an example, here is a helper method that you can use to do this test:
class User
def self.authenticate(username, password)
user = User.find_for_authentication(:username => username)
user.valid_password?(password) ? user : nil
end
end
Testing it, I get:
1.9.3p194 :001 > user = User.find(1)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User id: 1, {...USER DETAILS SHOWN HERE...}
1.9.3p194 :002 > user.valid_password?('is this it?')=> false
Also working: User.find(1).valid_password?('1') in Rails console:
1.9.3p194 :011 > User.find(1).valid_password?('1')
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> false
For reference, here's my Devise setup for the User model:
class User < ActiveRecord::Base`
devise :database_authenticatable, :registerable, :timeoutable, :recoverable, :rememberable, :trackable, :validatable
{...}
end
Like you said in the comments, there is no sessions_controller since Devise. Look into the Devise config file in /config/initializers/devise.rb. Depending on your application configuration, you may also want to look at the token.rb and session_store.rb initializer configs.
EDIT: Can you check your user model to see if devise is properly configured for it? Compare it against my devise line. The :validatable property could be missing.
EDIT 2: Added the helper method to do this test if you want to do it outside of the console. Check up top.
Side-note: The rails_admin gem is pretty useful and may be worth checking out!
Hope that helps.
I think implement can be much simpler without using any kind of gem.
At least we know the email id.
email : 'currentuser#email.com'
Current password: 'rubyuser'
user = User.find_by_email('currentuser#email.com')
user.valid_password?('wrong_password') #returns false
user.valid_password?('rubyuser') #returns true