i need to select when devise send the confirmation mail. I overwrite the send_confirmation_instructions and add a date field named invited on my user model. If the invited field is null send the mail, otherwise not sent.
Here's my code:
def send_confirmation_instructions
unless invited.nil?
self.confirmation_token = nil if reconfirmation_required?
#reconfirmation_required = false
generate_confirmation_token! if self.confirmation_token.blank?
else
self.confirmation_token = nil if reconfirmation_required?
#reconfirmation_required = false
generate_confirmation_token! if self.confirmation_token.blank?
self.devise_mailer.confirmation_instructions(self).deliver
end
end
The output of my console its:
Loading development environment (Rails 3.0.10)
1.9.3-p0 :001 > User.create!(:email => "hello#test.com") NoMethodError: undefined method `reconfirmation_required?' for
I have rewrite many other devise method without problems. Any idea ?
Thanks in advance.
The best solution was to connect manually to the database and add the fields to the users table.
# read configuration from database.yml
config = Rails.application.config.database_configuration[Rails.env]
host = config["host"]
database = config["database"]
username = config["username"]
password = config["password"]
# stablish db connection
mysql = Mysql2::Client.new(:host => host, :username => username, :database => database, :password => password)
# generate devise confirmation token
token = (Digest::MD5.hexdigest "#{ActiveSupport::SecureRandom.hex(10)}-#{DateTime.now.to_s}")
# made the sql
sql = "INSERT INTO users (email, confirmation_token, confirmation_sent_at) VALUES ('email#test.com', '#{token}', '#{Time.now.to_s}')"
# execute query
mysql.query(sql)
# close mysql connection
mysql.close
I hope this will be useful.
Related
The "authenticate" method can only be found here: https://apidock.com/rails/ActiveModel/SecurePassword/InstanceMethodsOnActivation/authenticate
, with version 6.0.0 being grayed out. So this seems to be outdated.
I have searched the Rails 6 documentation for the authenticate method, and found no record of it under https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html.
Yet in the code snippet on the same page
# Schema: User(name:string, password_digest:string, recovery_password_digest:string)
class User < ActiveRecord::Base
has_secure_password
has_secure_password :recovery_password, validations: false
end
user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
user.save # => false, password required
user.password = 'mUc3m00RsqyRe'
user.save # => false, confirmation doesn't match
user.password_confirmation = 'mUc3m00RsqyRe'
user.save # => true
user.recovery_password = "42password"
user.recovery_password_digest # => "$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC"
user.save # => true
user.authenticate('notright') # => false
user.authenticate('mUc3m00RsqyRe') # => user
user.authenticate_recovery_password('42password') # => user
User.find_by(name: 'david')&.authenticate('notright') # => false
User.find_by(name: 'david')&.authenticate('mUc3m00RsqyRe') # => user
The authenticate method is still used (user.authenticate). Where does this method come from if I can't find it in the latest documentation?
Edit:
A related question regarding differences in documentation: I am able to find ActionDispatch::Request::Session on rubydocs but not on api.rubyonrails.
https://www.rubydoc.info/docs/rails/ActionDispatch/Request/Session
https://api.rubyonrails.org/classes/ActionDispatch/Request.html
Now I am not certain where I should be looking when searching for methods. Is api.rubyonrails not the "definitive" place to look for documentation?
It looks like they forgot to mention it in the documentation for has_secure_password. If you look into source code of ActiveModel::SecurePassword. You will find
# Returns +self+ if the password is correct, otherwise +false+.
#
# class User < ActiveRecord::Base
# has_secure_password validations: false
# end
#
# user = User.new(name: 'david', password: 'mUc3m00RsqyRe')
# user.save
# user.authenticate_password('notright') # => false
# user.authenticate_password('mUc3m00RsqyRe') # => user
define_method("authenticate_#{attribute}") do |unencrypted_password|
attribute_digest = public_send("#{attribute}_digest")
BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self
end
alias_method :authenticate, :authenticate_password if attribute == :password
You can se it is now defined as dynamic method based on the parametr name provided to has_secure_password method. So they implemented it in more general way. And to be more friendly with backwards compatibility the implemented the alias authenticate for authenticate_password which was the original implementation.
Unfortunately these dynamic methods are not very well documented in the rails API docs.
In devise's user table i'm trying to save email and password through a different controller , but in server log i'm getting this error ,
WARNING: Can't mass-assign protected attributes for User: encrypted_password
------------------------------------------------------------------------------
(0.1ms) BEGIN
User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'mail#mail.com' LIMIT 1
(0.2ms) ROLLBACK
Added encrypted_password attribute to the model.
So i'm not able to insert it to users table.
And ,How to encrypt password? as devise gem has built in.
Controller :
#user = User.new(:email => params[:supplier][:username],:username => params[:supplier][:username],:encrypted_password => '$2a$10$/Hh7UegsWm2ndRXbDEfjvOKBUiI1fa/z1GIbE5OYFpyqW6P97llsG')
#user.save
puts #user.errors
Model :
attr_accessible :encrypted_password
I would simply use
user = User.new(email: "...", password: "password", password_confirmation: "password")
user.skip_confirmation!
user.save!
This way, devise will do the work for you, and you don't have to bother about confirmation emails. If you want confirmation emails still to be send out, remove the second line
I want to create one user (admin) and I want to use console (without user registration model). I use solution from RailsCasts (http://railscasts.com/episodes/270-authentication-in-rails-3-1).
But I have one problem: when I do User.create(..., :password => "pass") in console my password stored in database without encription (like "pass"). And I can't login with my data.
How can I create user from console? :)
Straight from the Rails API
# Schema: User(name:string, password_digest:string)
class User < ActiveRecord::Base
has_secure_password
end
user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch")
user.save # => false, password required
user.password = "mUc3m00RsqyRe"
user.save # => false, confirmation doesn't match
user.password_confirmation = "mUc3m00RsqyRe"
user.save # => true
user.authenticate("notright") # => false
user.authenticate("mUc3m00RsqyRe") # => user
You need to include :password_confirmation => "pass in your hash!
Right, so taking a look at has_secure_password you want to perform BCrypt::Password.create(unencrypted_password) to obtain it. You'll need the bcrypt-ruby gem to do the above.
I've been fighting with this for a couple of days and there doesn't seem to be much help online. I've looked at the Typus wiki, sample app, and tests and I appear to be doing things correctly but I stil get HTTP Status Code 302 (Redirect) where I expect 200 (Success) in my tests.
Below are what should be the appropriate files (with irrelevant stuff removed)
config/initializers/typus.rb (rails g typus:migration has been run as I have an admin_users table):
Typus.setup do |config|
# Application name.
config.admin_title = "Something"
# config.admin_sub_title = ""
# When mailer_sender is set, password recover is enabled. This email
# address will be used in Admin::Mailer.
config.mailer_sender = "noreply#somewhere.com"
# Define paperclip attachment styles.
# config.file_preview = :medium
# config.file_thumbnail = :thumb
# Authentication: +:none+, +:http_basic+
# Run `rails g typus:migration` if you need an advanced authentication system.
config.authentication = :session
# Define user_class_name.
config.user_class_name = "AdminUser"
# Define user_fk.
config.user_fk = "admin_user_id"
# Define master_role.
config.master_role = "admin"
end
config/typus/admin_user.yml
AdminUser:
fields:
default: first_name, last_name, role, email, locale
list: email, role, status
form: first_name, last_name, role, email, password, password_confirmation, locale
options:
selectors: role, locale
booleans:
status: Active, Inactive
filters: status, role
search: first_name, last_name, email
application: Admin
description: Users Administration
test/factories/admin_users.rb:
Factory.define :admin_user do |u|
u.first_name 'Admin'
u.last_name 'User'
u.email 'admin#somewhere.com'
u.role 'admin'
u.password 'password!'
u.token '1A2B3C4D5E6F'
u.status true
u.locale 'en'
end
test/functional/admin/credits_controller_test.rb:
require 'test_helper'
class Admin::CreditsControllerTest < ActionController::TestCase
setup do
#admin_user = Factory(:admin_user)
#request.session[:admin_user_id] = #admin_user.id
#request.env['HTTP_REFERER'] = '/admin/credits/new'
end
context "new" do
should "be successful" do
get :new
assert_response :success
end
end
end
#response.body:
<html>
<body>You are being redirected.
</body>
</html>
As you can see, I've set up the typus to use admin_user and admin_user_id for the session key. But for some reason that test fails getting 302 rather than 200. I'm sure this is because I'm doing something wrong that I just don't see. I've also created all these a gist, just in case someone prefers that.
Edited 2011-05-19 09:58am Central Time: Added Response body text per request.
I figured this out. It was a problem with the config/typus/admin_roles.yml file.
Before:
admin:
Category: create, read, update
Credit: read
...
After:
admin:
Category: create, read, update
Credit: read, create
...
The problem was that admin users didn't have access to the CREATE action on the admin/credits_controller which resulted in the user being sent back to the admin login address.
Giving admin users access to the action and changing the
#session[:admin_user_id]
to
#session[:typus_user_id] #Just like in the Typus docs
solved the problem. I had changed it to :admin_user_id because of the
config.user_fk = "admin_user_id"
in the typus config files, while trying to troubleshoot this issue.
Rails 2.3.11
I'm trying to send an activation-style email whenever a user registers. The email gets sent successfully, but has the wrong "from" email address. The subject, content, and recipient's email are all fine. Instead of being sent from activation#[domain].net, they come from [login-name]#box570.bluehost.com.
/app/models/franklin.rb:
class Franklin < ActionMailer::Base
def activation(user)
recipients user.email
from "activation#[sub].[domain].net"
subject "[Product] Registration"
body :user => user
end
end
Applicable part of the controller that calls it:
#user = User.create(
:first_name => params[:first_name],
:last_name => params[:last_name],
:email => params[:email],
:password => params[:password],
:password_confirmation => params[:password_confirmation],
:user_class => "User"
)
Franklin.deliver_activation(#user)
/config/environments/development.rb:
# Settings specified here will take precedence over those in config/environment.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching = false
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :sendmail
Thank you!
This looks like a Bluehost-specific problem. You may need to make sure the activation#[sub].[domain].net e-mail address is actually set up as a full email account with Bluehost (this seems to be a common solution).