Restful_authentication: Where is 'crypted_password'?

Hi,

I’m using the latest version of RoR installed on Fedora Core 6 Linux
with Apache 2.2. I just installed the plugin
“restful_authentication” (http://agilewebdevelopment.com/plugins/
restful_authentication), but whenever I try and create a new user, via
this code:

    def userconfirm
            @user = User.new(params[:user])    # line 59
            if @user.save
                    flash[:notice] = 'User was successfully

created.’
redirect_to :action => ‘list’
else
render :action => ‘userinfo’
end
end

but I get this error. Where do I find this “crypted_password” method?

  • Dave

NameError in RegisterController#userconfirm

undefined local variable or method `crypted_password’ for #<User:
0xb766e3a8>

RAILS_ROOT: ./script/…/config/…
Application Trace | Framework Trace | Full Trace

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/base.rb:1863:in method_missing' /usr/local/apache2/htdocs/easyrx/app/models/user.rb:93:in password_required?’
/usr/local/apache2/htdocs/easyrx/app/controllers/
register_controller.rb:59:in `userconfirm’

that should be a column on the table users

On Jan 21, 2008 12:22 PM, [email protected]
[email protected] wrote:

            @user = User.new(params[:user])    # line 59
  • Dave
    active_record/base.rb:1863:in method_missing' /usr/local/apache2/htdocs/easyrx/app/models/user.rb:93:in password_required?’
    /usr/local/apache2/htdocs/easyrx/app/controllers/
    register_controller.rb:59:in `userconfirm’

If you ran the command

script/generate authenticated user session

after installing the plugin, then it should have generated a migration
which creates the users table with the necessary attributes.

If you didn’t and your Users table already exists, you can generate
the rest of the stuff by using the --skip-migration option on the
generate.

You can see the fields which are needed in this case by looking in
vendor/plugins/restful_authentication/generators/authenticated/templates/migration.rb


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Ok, I added the column “crypted_password” to my users table. I assume
this means I should have deleted the column “password”. Anyway, now I
get another warning when I try and create a user. Upon completing the
fields and entering a password and a confirmed password, I get

There were problems with the following fields:
* Password confirmation can’t be blank

even though I’m entering a value for password confirmation. I don’t
have a field “password_confirmation” in my database … didn’t think I
needed one. This is what the code looks like:

Username
<%= text_field 'user', 'login' %>

Password
<%= password_field 'user', 'password' %>

Confirm Password
<%= password_field 'password_confirmation', '' %>

Any ideas? - Dave

On Jan 21, 11:39 am, Jimmy P. [email protected]

On Jan 21, 2008, at 2:50 PM, [email protected] wrote:

have a field “password_confirmation” in my database … didn’t think I

Any ideas? - Dave

On Jan 21, 11:39 am, Jimmy P. [email protected]
wrote:

that should be a column on the table users

You should have bits in your user model that look like these (nearly
all of it is pure generated code from acts_as_authenticated):

Virtual attribute for the unencrypted password

attr_accessor :password

validates_presence_of :login, :email
validates_presence_of :password, :if
=> :password_required?
validates_presence_of :password_confirmation, :if
=> :password_required?
validates_length_of :password, :within => 4…40, :if
=> :password_required?
validates_confirmation_of :password, :if
=> :password_required?
validates_length_of :login, :within => 3…40
validates_length_of :email, :within => 3…100
validates_uniqueness_of :login, :email, :case_sensitive =>
false, :message => “has already been taken. Please choose another.”

before_save :encrypt_password

Authenticates a user by their email and unencrypted password.

Returns the user or nil.

NOTE: This implicitly relies on the case-insensitive string

equality of

MySql when finding a matching email address. If this were to

ever change,

the email should probably be made lowercase before being saved

(and before

doing the find, of course).

def self.authenticate(email, password)
u = find_by_email(email) # need to get the salt
u && u.authenticated?(password) ? u : nil
end

def record_login_time
update_attribute(:last_loggedin_at, Time.now.utc)
end

Encrypts some data with the salt.

def self.encrypt(password, salt)
Digest::SHA1.hexdigest(“–#{salt}–#{password}–”)
end

Encrypts the password with the user salt

def encrypt(password)
self.class.encrypt(password, salt)
end

def authenticated?(password)
crypted_password == encrypt(password)
end

def remember_token?
remember_token_expires_at && Time.now.utc <
remember_token_expires_at
end

These create and unset the fields required for remembering users

between browser closes
def remember_me
self.remember_token_expires_at = 2.weeks.from_now.utc
self.remember_token = encrypt(“#{email}–
#{remember_token_expires_at}”)
save(false)
end

def forget_me
self.remember_token_expires_at = nil
self.remember_token = nil
save(false)
end

protected

before save filter

def encrypt_password
return if password.blank?
self.salt = Digest::SHA1.hexdigest(“–#{Time.now.to_s}–
#{email}–”) if new_record?
self.crypted_password = encrypt(password)
end

conditional validation

def password_required?
crypted_password.blank? || !password.blank?
end

Pay particular attention to the conditional nature of the
validations. You only have to worry about the validation if you do
not yet have a crypted_password (i.e., already in the database) or you
have a non-blank password which typically means that the user is in
the midst of changing (or establishing) it.

NOTE: This is code that was extracted from a working model in a real
Rails project. It does not necessarily work as is in YOUR project and
any difference between it and the code that the acts_as_authenticated
plugin produced is present for a reason (even if that reason is just
that I liked the indentation a bit better my way ;-). YMMV

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

<%= password_field ‘password_confirmation’, ‘’ %>

should be

<%= password_field ‘user’, ‘password_confirmation’ %>

Thanks. This cured the problem. On to the next one. When I create
the user, I now see an error:

NoMethodError in RegisterController#userconfirm
undefined method `salt=’ for #User:0xb76961c8
RAILS_ROOT: ./script/…/config/…
Application Trace | Framework Trace | Full Trace

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/base.rb:1860:in method_missing' /usr/local/apache2/htdocs/easyrx/app/models/user.rb:88:inencrypt_password’
/usr/local/apache2/htdocs/easyrx/app/controllers/
register_controller.rb:59:in `userconfirm’

How do I get salt defined? Here is the code in my user.rb file:

protected
# before filter
def encrypt_password
return if password.blank?
self.salt = Digest::SHA1.hexdigest("–#{Time.now.to_s}–
#{login}–") if new_record? # line 88
self.crypted_password = encrypt(password)
end

and here is code from my register_controller.rb file:

    def userconfirm
            @user = User.new(params[:user])
            if @user.save         # line 59
                    flash[:notice] = 'User was successfully

created.’
redirect_to :action => ‘list’
else
render :action => ‘userinfo’
end
end

Thanks for your continued help, - Dave

Did you run script/generate authenticated account user? I’m beginning to
think not.

salt is a required string field of your users table

On Jan 21, 2008, at 6:59 PM, [email protected] wrote:

/usr/local/apache2/htdocs/easyrx/app/models/user.rb:88:in
encrypt_password' /usr/local/apache2/htdocs/easyrx/app/controllers/ register_controller.rb:59:in userconfirm’

How do I get salt defined? Here is the code in my user.rb file:

That should be a column in your database (and thus an attribute of
your user model).

-Rob
Rob B. http://agileconsultingllc.com
[email protected]

Hi,

This was the problem. I also had forgotten to add a column named
“activation_code”.

Did I download this plugin from the wrong web site (http://
agilewebdevelopment.com/plugins/)? I didn’t find any of this info on
there.

Thanks for all your help, - Dave

On Jan 21, 6:16 pm, Rob B. [email protected]

On Jan 21, 2008, at 5:33 PM, Ryan B. wrote:

<%= password_field ‘password_confirmation’, ‘’ %>

should be

<%= password_field ‘user’, ‘password_confirmation’ %>

I think Ryan probably took better aim on this one. I’m used to use
form_for and not form_tag so my brain saw:
<%= f.password_field ‘password_confirmation’ %>
and filled in the rest!

But perhaps what I said helps someone else :wink:

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

On 1/22/08, [email protected] [email protected] wrote:

Hi,

This was the problem. I also had forgotten to add a column named
“activation_code”.

Did I download this plugin from the wrong web site (http://
agilewebdevelopment.com/plugins/)? I didn’t find any of this info on
there.
Did you read the instructions there:

http://agilewebdevelopment.com/plugins/restful_authentication

The plugin is used as a generator which creates the models,
controllers, and the migration.

Used correctly, there’s no need to add any fields, the generated
migration does it for you.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Thanks for this. One problem I’m having right now is setting up a
form that logs the user in. I couldn’t find any documentation on your
page. Here’s my form right now:

<%= form_tag(’/login’, :method => :post) %>

Login: <%= text_field_tag("login", '') %>
Password: <%= password_field_tag("password", '') %>
<%= submit_tag("Login") %>
<%= end_form_tag %>

and added this to my config/routes.rb file

map.signup ‘/signup’, :controller => ‘users’, :action => ‘new’
map.login ‘/login’, :controller => ‘session’, :action => ‘new’
map.logout ‘/logout’, :controller => ‘session’, :action => ‘destroy’

but whenever I submit the above form, with correct or incorrect
credentials, I get this error:

Unknown action
No action responded to show

Any ideas? - Dave

Rick DeNatale said the following on 23/01/08 08:16 PM:

http://agilewebdevelopment.com/plugins/restful_authentication

The plugin is used as a generator which creates the models,
controllers, and the migration.

Used correctly, there’s no need to add any fields, the generated
migration does it for you.

Ah,not quite.
The migration will create a table, yes, but it has the line

create_table "users", :force => true do |t|

Doesn’t this zap any previous table?
In the ActiveRecord code I see the lines

if options[:force]
drop_table(table_name, options) rescue nil
end

Which means that any previous information that may have been in the
table such as ‘address’ is now lost. Id rather that didn’t happen.

I’ve written here before about this problem with plugins and the
migrations they generate but no-one picked up on it.

This is particularly pernicious in the case of restful_authentication
when security is being added to an already partially developed
application. It really does need to be addressed.


Wherever you see a successful business, someone once made a courageous
decision.
–Peter F. Drucker