Ruby on Rails
SaltedHashLoginUse (Version #39)

This page relates to the use of the SaltedHashLoginGenerator.

The fine manuals

There are two README files associated with the two gems required for SHLG. You are advised to read them :)

Generation


ruby script/generate salted_login User Localization

Once generated, consult the readme for instructions on how to use the produced code in your application. Modifications to the README have been made that explain some of the requirements of the new code. You may also wish to refer to the SaltedLoginGeneratorQuickstart, which walks you through the steps required.

In the above example, two README files would have been installed in your app’s root directory as README_USER_LOGIN and README_LOCALIZATION.

Restart the server after editing environment files

If after installing the SHLG and visiting /user/login you get a uninitialized constant CONFIG error, try re-starting the web server. This is probably obvious to most people, but it had me flummoxed for days. I hope this saves other people from some serious frustration.

Iconv Related Issues

Use the salted hash login generator without iconv

To use the salted hash login generator without iconv I just defined LOCALIZED_STRINGS in /lib/localization.rb to the contents of /lang/en.yaml i.e.


#require 'iconv'

module Localization

  LOCALIZED_STRINGS = {'en' => {
    :account_login_succeeded => 'Login successful',
    :account_login_head => 'Please login'
    # etc...
  }}

You should also follow the instructions in the README_LOCALIZATION file to include the various files, but without the “Localization::load_localized_strings” call. —Steve

Missing iconv

If you are using the One-Click Ruby Installer under windows, you may find that you are getting an iconv related error. Specifically, you are missing ruby/lib/ruby/1.8/i386-mswin32/iconv.so

See iconv for more information and how to fix the problem. Copying the iconv.so from one of these distributions into the appropriate folder solved the problem for me—Jay

Other issues

SHLG 1.1.1 on rails 0.13.1 setup using the README instructions is spamming my logs with ./script/../config/../app/helpers/user_helper.rb:7: warning: already initialized constant DEFAULT_HEAD_OPTIONS

any ideas how to fix this?


In app/helpers/user_helper.rb, changing


module UserHelper

  DEFAULT_HEAD_OPTIONS = {
    :notice => true,
    :message => true,
    :error => false
  }.freeze

to


module UserHelper

  DEFAULT_HEAD_OPTIONS = {
    :notice => true,
    :message => true,
    :error => false
  }.freeze unless const_defined? "DEFAULT_HEAD_OPTIONS" 

seems to work.

-Brett

On the security of emailing passwords

I think it somewhat defeats the purpose of hashed+salted password data when clear text passwords are emailed on registration and password change. I suggest removing the password from all emails. —mrj


I think the main reason is to keep the clear text password out of a DB which can be hacked or read by someone with legitimate access to it. However, it’s pretty easy to remove this – just edit the mailer templates.


Emails are even less secure that the DB because they can be monitored along the delivery path, not just at the host. Of course the security token emails can be intercepted as well, but at least the user is given an indication through an unexpected password change that something is up. —mrj

I can easily change the templates. I’m just suggesting you change them in the gem itself. —mrj


Comments

September 5 2005
I had to do a few things to get this running.
1. Move the render_body alias in lib/localization.rb below the method.
2. in views/account_notify/*_en I had to remove the _en suffix because it was not recognizing the locale. The signup failed with an arbitrary message and then once I removed the rescue I received the No rhtml, rxml,... for method signup. This is NOT the account signup view, it is the account_notify signup view it’s looking for. Removing the suffix is the short-term fix.
3. Make sure you specify an action mailer setting in your env of choice. I got away with the bare basics:

ActionMailer::Base.server_settings = { :address => "domain.com", :domain => "domain.com" } -Caged

If someone can help me out with this one, I’d appreciate it. I’m running with Mac OS X 10.4.2 and Mandrake, and don’t see this problem generating the docs.



Important: Don’t forget to include the localization environment in config/environment.rb. These lines need to be included:
require ‘environments/user_environment’
require ‘environments/localization_environment’
This is not mentioned in README_USER_LOGIN and the error message “method ‘l’ missing” is pretty unclear.

I wanted to seperate the authentication functionality from my actual User model… I’m hoping that it shields me from upgrades down the road (I have a lot of my own custom methods in my model). I did the following:
  1. $ script/generate salted_login Account Localization
  2. Followed all of the directions in the README’s
  3. Changed the head of models/account.rb:
    class Account < ActiveRecord::Base
      set_table_name "users"
  4. Changed the head of models/user.rb:
    class User < Account
  5. Do all of my login related actions through the \AccountController.

From an email to the mailing list:

A number of people have seen problems with verification not working, and lots of test failures. I believe a lot of these problems are caused by trying to include the ‘before_filter :login_required’ directly in the UserController (assuming the model class is ‘User’). This should work (I haven’t tested this yet) – but if you do it, I’m guessing you must also include the same code that the README says to include assuming it is placed in the ApplicationController class. For example, you would need the following lines (showing only the pertinent lines to this problem):


require 'user_system'

UserController < ApplicationController
    include UserSystem
    helper :user
    model :user # probably don't need this if you are including it directly in this controller
    before_filter :login_required
    ...
end

Bear in mind, though, that the protect? method is provided so that you can check permissions in a specific controller, so there’s really no problem including there, unless you have lots of controllers with unprotected actions and you want to avoid the filter invocation.


Is the db_structure a \RubyForge project as well? I assume it is as it is available from gems.rubyforge.com, but I can’t find it. Editing it to add the options I need is a good stop-gap, but being able to contribe back changes (like adding options for sqlite3) would be best.
—Brian G.


Yes, it is. You can find it at http://rubyforge.org/projects/localization/. I’m looking at making both public so that others can contribute changes. First I’d like to find someone to manage them, since my time has been limited lately.


If you’ve been having trouble with verification issues and you’re using lighttpd then be sure that you have these rewrites set up:


url.rewrite = ( 
            "^/$" =>  "/dispatch.fcgi?controller=home&action=index",
            "^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9%]+)\??([\-_a-zA-Z0-9=&%]*)$"  => 
                "/dispatch.fcgi?controller=$1&action=$2&id=$3&$4",
            "^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$"  => 
                "/dispatch.fcgi?controller=$1&action=$2&$3",
            "^/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$"  =>  
                "/dispatch.fcgi?controller=$1&action=index&$2" 
)

The first rewrite rule can be changed to whichever controller and action you prefer.

There may be some other issues which cause email verification failure, and those are listed in the README which comes with the code, but setting up these rewrites solved the verification issue I was experiencing on an Ubuntu box.

You may find more information at Lighttpd and [[FastCGI?]].



execution expired

app/controllers/user_controller.rb:28:in `signup'
app/controllers/user_controller.rb:22:in `transaction'
app/controllers/user_controller.rb:22:in `signup'
script/server:48

this means your mail/actionmailer isn’t properly set up
comment out this line to test
"UserNotify.deliver_signup(@user, @params['user']['password'], url)" of course the system won’t work if you don’t get a verification email


Alternate fix for Localized mailing: Requires PATCH for ActionMailer

I’ve found another solution to the problem with ActionMailer when using the Localization generator. Unfortunately it requires a patch to ActionMailer::Base. Once the patch is in place, you can simply remove the ActionMailer::Base.module_eval <<-EOL block in lib/Localization.rb described above and replace it with:

    # in lib/Localization.rb within the module definition:
    class Mailer < ActionMailer::Base

      def initialize(method_name, *parameters)
        @template = method_name + "_#{CONFIG[:default_language]}" 
        super
      end
    end

then for the application mailers, simply replace inheritance from ActionMailer::Base with inheritance from Localization::Mailer, eg (in app/models/user_notify.rb):

  class UserNotify < Localization::Mailer

One concern with this approach is the handling of multi-part attachments. I’m thinking it may require copies or aliases of any image files with the correct extension (eg \_en). Another is the use of \@template. At this time, it is only used for tracking down filenames. If its use is extended to other functionallity, this could easily break.

-Brett


I was getting “NoMethodError” (You have a nil object when you probably didn’t expect it!) errors on Rails 0.13.1 for a bunch of methods (login, signup etc).

Changed to:


    if @request.get?
      generate_blank
    else 
      ...

Or am I missing something?


No, you’re not. I’ve tried the upgrade to 1.1.0, and it still has a lot of problems with :get versus :post. There were a bunch of corrections listed on this site before the cleaning of the wiki. It seems that the easiest way to correct for them is to use case @request.method statements around the part requiring post information:


  def signup
    generate_blank

    case @request.method
    when :get
      @user = User.new(@params['user'])
    else
      @params['user'].delete('form')
      @user = User.new(@params['user'])

      begin
    User.transaction(@user) do
      @user.new_password = true
      @user.lottds << Lottd.new({:name => 'General'})
          if @user.save
            key = @user.generate_security_token
            url = url_for(:action => 'welcome')

        url += "?user[id]=#{@user.id}&key=#{key}" 
        UserNotify.deliver_signup(@user, @params['user']['password'], url)
        flash['notice'] = l(:user_signup_succeeded)

            redirect_to :action => 'login'
          end
        end
      rescue
    flash.now['message'] = l(:user_confirmation_email_error)
      end
    end
  end 

I am happy, though, that the corrections made to the localization library seem to fix the problems with ActionMailer, without the above mentioned patch.

I was not the one to come up with this particular solution, by the way. Unfortunately, I can’t remember who it was.

-Brett


That was a goof on my part when submitting the gem. I released 1.1.1, which fixes the missing return on a GET when calling generate_(star).


Any ideas what my problem is here? Running signup will fail with ‘Error creating account: confirmation email not sent”. Having run
“rake test_functional” I get this error


ruby -Ilib;test "c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_lo
ader.rb" "test/functional/account_controller_test.rb" "test/functional/area_cont
roller_test.rb" "test/functional/project_controller_test.rb" "test/functional/us
er_controller_test.rb" 
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/base.rb:799
:in `method_missing': undefined method `salt=' for User:Class (NoMethodError)
        from ./test/functional/account_controller_test.rb:5
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5:in `load'
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5:in `each'
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5
rake aborted!
Command failed with status (1): [ruby -Ilib;test "c:/ruby/lib/ruby/gems/1.8...]

My database looks setup ok. Any ideas?

- Rusty


Rusty—
You need to specify a domain in your
development.rb file i.e.


ActionMailer::Base.server_settings = {
  :address=>'smtp.something',    # default: localhost
  :port=>'25',                        # default: 25
  :user_name=>'username',
  :password=>'password',
  :domain=>'something.wut',
  :authentication=>:plain             # :plain, :login or :cram_md5
}

that should fix your problem
—fluxin


When running tests, I kept getting cattr_accessor errors in the time.rb test, and also uninitialized constant Gem::Specification::Date errors in the user_test.rb

To solve this, near the top of the test_helper.rb file and before the require File.expand_path() line, I added require ‘rubygems’.

Here’s an example:


test_helper.rb:

require 'rubygems' # added this to fix several problems

# Expand the path to environment so that Ruby does not load it multiple times
# File.expand_path can be removed if Ruby 1.9 is in use.
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'application'

This still did not fix another problem in the functional tests.

I received this error report:


Started
....E....E
Finished in 0.826739 seconds.

  1) Error:
test_delete(UserControllerTest):
NoMethodError: undefined method `advance_by_days=' for Time:Class
    ./test/functional/user_controller_test.rb:132:in `test_delete'

  2) Error:
test_signup(UserControllerTest):
NoMethodError: undefined method `advance_by_days=' for Time:Class
    ./test/functional/user_controller_test.rb:51:in `do_test_signup'
    ./test/functional/user_controller_test.rb:145:in `test_signup'

and fixed this one by adding near the top of the file user_controller_test.rb


user_controller_test.rb:

require File.dirname(__FILE__) + '/../test_helper'
require 'user_controller'

# ADD to fix advance_by_days= problem
require File.dirname(__FILE__) + '/../mocks/test/time'

TomMornini?—Thanks! I concur with these results and fixes (identical behavior) on Macintosh OS X Tiger 10.4.2 with the fix_ruby stuff in place, PostgreSQL 8.0.3

Additionally, I also get this:


ruby -Ilib:test "/usr/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader.rb" "test/functional/user_controller_test.rb" 
Loaded suite /usr/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
Started
.....WARNING:  there is already a transaction in progress
....

Bug in 1.1.1 prevents login by token from forgot_password emails, as security tokens are not being updated in the database. This is because the db transaction in the user_controller forgot_password method is never ended. My fix was to move the transaction end to just below the email delivery statement. —mrj

Could you show your change? I am not seeing this problem with 1.1.1. The only way the DB transaction shouldn’t commit is if an exception is thrown, and I’m not sure where that would be happening if the email is actually being sent.

Hm, I’m surprised you’re not seeing this.

In user_controller.rb, line 79, change:


        User.transaction(user) do
          key = user.generate_security_token
          url = url_for(:action => 'change_password')
          url += "?user[id]=#{user.id}&key=#{key}" 
          UserNotify.deliver_forgot_password(user, url)
          flash['notice'] = l(:user_forgotten_password_emailed, "#{@params['user']['email']}")
          unless user?
            redirect_to :action => 'login'
            return
          end
          redirect_back_or_default :action => 'welcome'
        end

to


        User.transaction(user) do
          key = user.generate_security_token
          url = url_for(:action => 'change_password')
          url += "?user[id]=#{user.id}&key=#{key}" 
          UserNotify.deliver_forgot_password(user, url)
          flash['notice'] = l(:user_forgotten_password_emailed, "#{@params['user']['email']}")
        end
        unless user?
          redirect_to :action => 'login'
          return
        end
        redirect_back_or_default :action => 'welcome'

This prevents the non-returning redirect to ‘login’ preventing the ending of the transaction that updates the security token. —mrj

This error shows up very clearly when running the test scripts with SQLite, then you’ll get this error:


d:/ruby/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0-mswin32/lib/sqlite3/errors.rb:94:in `check': cannot start a transaction within a transaction (SQLite3::SQLException)

After appying the above fix the test scripts run beautifully. —gs


I used the db schema in the README, then cut n’ pasted the Welcome! code:

<%= @session['user'].name %>

There’s no name() function, so I updated this to
<%= @session['user'].firstname %>

Perhaps the README could reflect this, eventually.

-- wesgarrison


I updated :security_token_life_hours in user_environment to 96 to account for weekends. This caused the test: do_test_signup(bad_password, bad_email)
in user_controller_test to fail. Specifically:

      # First past the expiration.
      Time.advance_by_days = 1
      get :welcome, "user"=> { "id" => "#{user.id}" }, "key" => "#{key}" 
      Time.advance_by_days = 0
      user = User.find_by_email("<a href="mailto:newbob@test.com">newbob@test.com</a>")
      assert_equal 0, user.verified

Perhaps the advance_by_days should be be adjusted to use the environment value.
-- wesgarrison

No rhtml, rxml, or delegate template found for signup

I toyed around a bit with the salted login generator. This is the signup method (some adjustments)


def signup
    if request.post?
      @user = User.new(params[:user])
      begin
        @user.new_password = true
        @user.save!
        key = @user.generate_security_token
        url = url_for(:action => 'welcome')
        url += "?user[id]=#{@user.id}&key=#{key}" 
        UserNotify.deliver_signup(@user, @params[:user][:password], url)
        flash[:notice] = "Signup successful! Please check your registered email account
to verify your account registration and continue with the login." 
        redirect_to :action => 'login'
      rescue => exception
        flash.now[:notice] = "Sorry, but there was an error during registration.
Please inform the administrator.  #{exception}" 
      end
    end
  end

Works fine on GET, but once i POST the form I receive this error: “No rhtml, rxml, or delegate template found for signup”

Now under normal circumstances it should redirect to login but I guess it never gets there.. any help is appreciated as it’s driving me nuts

Solution

After a whole day of searching, I’ve found the solution to the above problem. You need to rename the file “signup_en.rhtml” in the “views/user_notify” directory to “signup.rhtml”. That solves it for me. Hope this helps, seems like a common problem with the current generator. —Steve

Alternate Solution


The above didn’t work for me. I am using:
  • salted_login_generator (1.1.1)
  • Rails 1.0.0
  • Ruby 1.8.2

and the fix for me was to add:


ActionMailer::Base.template_root ||= "#{RAILS_ROOT}/app/views/" 

to “environment.rb”. —Max



New user verification link does not work


For some reason that I have been unable to determine, the email link that I get in an email after registering does not verify the new user. The verified flag never gets set to 1, so the user can not log in. Does anyone have any idea why that might be? Thanks.


Sign-up not functioning/Test Units fails


When I try to sign-up a new user it fails during @user.save. The log file says:



“Column ‘logged_in_at’ cannot be null”
and rolls back the transaction.


The rake test_units also fails with:

"test/unit/user_test.rb" 
/var/www/rails/w3/config/../test/mocks/test/time.rb:5: undefined method `cattr_accessor' for Time:Class (NoMethodError)
...bunch of further trace...


Followup: New user verification link does not work


It would appear to be a result of the mysql version that was running on the server. v4.0.18. I was able to get it going by pointing it at a server running v4.1.14 (tests still fail maybe dependent on v5.x?).

I tried this on my Mac and…


I thought that I could easily get this thing to work
so I started on a demo but then got stumped.
Here's what I have...

RAILS

zmac11:/pt/TThier/Languages/ruby oracle$ rails saltl
      create  
      create  public/javascripts/slider.js
      create  doc/README_FOR_APP
SNIP
      create  log/production.log
      create  log/development.log
      create  log/test.log
zmac11:/pt/TThier/Languages/ruby oracle$ cd saltl

GENERATE

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ script/generate salted_login User Localization
  dependency  localization
      create    lang
      create    lib/localization.rb
      create    config/environments/localization_environment.rb
      create    test/unit/localization_test.rb
      create    lang/localizations.yaml
      create    README_LOCALIZATION
      create    LICENSE_LOCALIZATION
      create  lib/user_system.rb
      create  app/controllers/user_controller.rb
      create  test/functional/user_controller_test.rb
      create  app/helpers/user_helper.rb
      create  app/models/user.rb
      create  app/models/user_notify.rb
      create  test/mocks/test/user_notify.rb
      create  test/mocks/test/time.rb
      create  test/unit/user_test.rb
      create  test/fixtures/users.yml
      create  db/user_model.erbsql
      create  config/environments/user_environment.rb
      create  script/create_db
      create  lang/en.yaml
      create  app/views/layouts/scaffold.rhtml
      create  public/stylesheets/scaffold.css
      create  app/views/user
      create  app/views/user/welcome.rhtml
      create  app/views/user/login.rhtml
      create  app/views/user/logout.rhtml
      create  app/views/user/edit.rhtml
      create  app/views/user/signup.rhtml
      create  app/views/user/forgot_password.rhtml
      create  app/views/user/change_password.rhtml
      exists  app/views/user
      create  app/views/user/_edit.rhtml
      create  app/views/user/_password.rhtml
      create  app/views/user_notify
      create  app/views/user_notify/signup_en.rhtml
      create  app/views/user_notify/forgot_password_en.rhtml
      create  app/views/user_notify/change_password_en.rhtml
      create  app/views/user_notify/delete_en.rhtml
      create  app/views/user_notify/pending_delete_en.rhtml
      create  README_USER_LOGIN
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 

EDIT  application.rb

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ cd app/controllers
zmac11:/pt/TThier/Languages/ruby/saltl/app/controllers oracle$ ls
./            ../            application.rb        user_controller.rb
zmac11:/pt/TThier/Languages/ruby/saltl/app/controllers oracle$ cat application.rb
# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

require 'user_system'

class ApplicationController < ActionController::Base
  include UserSystem
  helper :user
  model :user
  before_filter :login_required
end
zmac11:/pt/TThier/Languages/ruby/saltl/app/controllers oracle$ 

CREATE the users table

zmac11:/pt/TThier/Languages/ruby/saltl/db oracle$ sqlite3 saltl.db
SQLite version 3.2.7
Enter ".help" for instructions
sqlite> .read user.sql
sqlite> .schema
CREATE TABLE 'users' (
    id INTEGER PRIMARY KEY,
    login VARCHAR(80) NOT NULL,
    salted_password VARCHAR(40) NOT NULL,
    email VARCHAR(60) NOT NULL,
    firstname VARCHAR(40),
    lastname VARCHAR(40),
    salt CHAR(40) NOT NULL,
    verified INT default 0,
    role VARCHAR(40) default NULL,
    security_token CHAR(40) default NULL,
    token_expiry DATETIME default NULL,
    deleted INT default 0,
    delete_after DATETIME default NULL
  );
sqlite> 

EDIT config/database.yml

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ cat config/database.yml
development:
  adapter: sqlite3
  dbfile: db/saltl.db
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 

EDIT config/environment.rb file:

zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ tail environment.rb
# Inflector.inflections do |inflect|
#   inflect.plural /^(ox)$/i, '\1en'
#   inflect.singular /^(ox)en/i, '\1'
#   inflect.irregular 'person', 'people'
#   inflect.uncountable %w( fish sheep )
# end

# Include your application configuration below

require 'environments/user_environment'

zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 

EDIT config/environments/development.rb

zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ cat environments/development.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

# Enable the breakpoint server that script/breakpointer connects to
config.breakpoint_server = true

# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching             = false

# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false

ActionMailer::Base.server_settings = {
  :address => "smtp.mac.com",
  :port => 25,
  :domain => "smtp.mac.com",
  :user_name => "steve",
  :password => "jobs",
  :authentication => :login
}
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 

WHAT Next?

I tried this:

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ script/server
[2005-10-23 19:24:34] INFO  WEBrick 1.3.1
[2005-10-23 19:24:34] INFO  ruby 1.8.2 (2004-12-25) [powerpc-darwin7.9.0]
[2005-10-23 19:24:34] INFO  WEBrick::HTTPServer#start: pid=4384 port=3000

THIS worked okay:

http://localhost:3000/

THIS did not:

http://localhost:3000/user/login

It gives..

 NoMethodError in User#login

Showing app/views/user/login.rhtml where line #2 raised:

undefined method `l' for #<#<Class:0x29327d0>:0x29323c0>

Extracted source (around line #2):

1: <div title="<%= title_helper %>" class="form">
2:   <%= head_helper %>
3: 
4:   <div class="form-padding">
5:     <%= start_form_tag_helper  %>

Application Trace | Framework Trace | Full Trace

./app/helpers/user_helper.rb:67:in `head_helper'
./app/views/user/login.rhtml:2
./app/controllers/user_controller.rb:172:in `generate_blank'
./app/controllers/user_controller.rb:6:in `login'

Anyone have any clues on how to get this working??

-Dan

ok,

I found a good recipe:
http://wiki.rubyonrails.com/rails/pages/SaltedLoginGeneratorQuickstart/versions/26

It gives me a login page.

I needed to add two steps to the above page:

EDIT environment.rb, add this to end:

# Include your application configuration below
require 'environments/localization_environment'
require 'localization'
Localization::load_localized_strings
require 'environments/user_environment'

EDIT app/helpers/application_helper.rb

# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
include Localization
end

-Dan

I cam across the following errors when I ran rake under 0.14.1.

  1) Failure:
test_change_password(UserControllerTest)
    [/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.10.1/lib/action_controller/deprecated_assertions.rb:23:in `assert_session_has'
     ./test/functional/user_controller_test.rb:189:in `do_change_password'
     ./test/functional/user_controller_test.rb:197:in `test_change_password']:
<"user"> is not in the session <#<ActionController::TestSession:0x274ae40
 @attributes={"user"=>nil, "flash"=>{}}>>

  2) Failure:
test_signup(UserControllerTest)
    [/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.10.1/lib/action_controller/deprecated_assertions.rb:13:in `assert_redirect'
     /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.10.1/lib/action_controller/deprecated_assertions.rb:98:in `assert_redirect_url'
     ./test/functional/user_controller_test.rb:40:in `do_test_signup'
     ./test/functional/user_controller_test.rb:148:in `test_signup']:
Expected response to be a <:redirect>, but was <200>

The problem I discovered after much trial and error was that I had created my users table in mysql without specifying that it should be a INNOdb table. Once I specified that the errors went away. —SteveRushe

My 2 cents:

The approach taken here of making this a generator is interesting, but I wonder how updates to the SaltedHash codebase can be distributed to apps that have already employed it?

It seems to me that the SaltedHashLogin would be a good candidate for a freestanding component as described in the Ruby on Rails book published by Pragmatic Programmers. In this scheme, the entire login codebase could be maintained in a single dedicated directory, which developers would deploy into the components directory of their applications. This would allow the code to be kept under revision control in its deployed form, either through gems or subversion or whathaveyou.

One problem with this idea is that developers who use the saltedhashlogin generator will most often want to extend the user model. This of course will lead to conflicts when merging changes. But conflicts can be resolved if using a version control system like subversion,darcs or cvs.

And you don’t necessarily need to implement your permissions logic in the user model. Instead of using a “role” field as in the login readme, one can have a separate administrators table that references users with a foreign key. This method is clumsy for most systems which just have customers and admins, but if you have a larger number of roles it might not be more complicated then mashing everything into one model. (Disclaimer: i am too new at this sort of thing to really have an informed opinion about that claim)

—jacob robbins

I am getting the same errors as SteveRushe, however I am on MS SQL Server, so no INNOdb. Any ideas how to fix it so those two failures go away?

—Chanan Braunstein

I’m getting the same problem, but I do have my tables set to inndodb. Has anyone else run across this problem and come up with a fix?

—Matt Giacomini

I am getting the same problem, and my tables are all InnoDB:


test_signup(UserControllerTest)
    [./test/functional/user_controller_test.rb:43:in `do_test_signup'
     ./test/functional/user_controller_test.rb:151:in `test_signup']:
Expected response to be a <:redirect>, but was <200>

I managed to fix the other failures through making minor adjustments.
This appears to be a problem with the signup routine itself. Every
forum post I could find, including this wiki, said InnoDB should fix
the issue but it hasn’t. It doesn’t appear to be creating the user record
on signup. Although, doing a regular signup (not in tests) works fine and sends mail. Any ideas?

—gfburke at google’s mail service


My users table was InnoDB but I was still getting the same 2 functional test errors discussed above (test_change_password and test_signup were failing in UserControllerTest) . Reading through “Agile Web Development with Rails” I noticed a reference to using Transactional Fixtures in order to speed up tests. Each test gets run inside a transaction and after the test is finished the transaction is rolled back. Very clever, except that these two failing tests are counting on a rollback in the middle of the test. So I tried putting:

self.use_transactional_fixtures = false

in the UserControllerTest and the tests all passed. You could also alter the same line in test_helper.rb if you wanted to globally disable transactional fixtures. I suspect that the 1.0 release of Rails automatically enables transactional tests for speed reasons. —jscruggs at thoughtworks dot com

In order to fix the second failure I splitted up the test_change_password UT into 3 separate unit tests:

# app/test/functional/user_controller_test.rb

 def test_change_password
    do_change_password(false, false)
#    do_change_password(true, false)
#    do_change_password(false, true)
  end

  def test_change_password2
    do_change_password(true, false)
  end

  def test_change_password3
    do_change_password(false, true)
  end

A UT that is causing the first failure looks strange from my noob point of view, therefore it got deleted.

—DmitryVerkhovsky

I tried Dmitry’s suggestion to split up the change password tests and I got a test failure in test_change_password3. I modified do_change_password as below to get the test working again.

def do_change_password(bad_password, bad_email)

    ...

    get :logout
    assert_session_has_no "user" 

    if not bad_password and not bad_email
      post :login, "user" => { "login" => "bob", "password" => "changed_password" }
      assert_session_has "user" 
      post :change_password, "user" => { "password" => "atest", "password_confirmation" => "atest" }
      get :logout
    elsif not bad_password and bad_email
      post :login, "user" => { "login" => "bob", "password" => "changed_password" }
      assert_session_has "user" 
      post :change_password, "user" => { "password" => "atest", "password_confirmation" => "atest" }
      get :logout
    end

    post :login, "user" => { "login" => "bob", "password" => "atest" }
    assert_session_has "user" 

    get :logout

end

I guess you could always just remove the ‘and not bad_email’ portion so that the test becomes simpler, but I’m feeling lazy today :-0

—GuidoSohne


I have an error on the tests, after running through SaltedLoginGeneratorQuickstart, which I haven’t been able to solve.

C:\Documents and Settings\Rick\workspace\JC-rails>rake test_units
(in C:/Documents and Settings/Rick/workspace/JC-rails)
c:/ruby/bin/ruby -Ilib;test “c:/ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/
rake_test_loader.rb” “test/unit/localization_test.rb” “test/unit/user_test.rb”
Loaded suite c:/ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader

Started
........F….E
Finished in 0.453 seconds.

1) Failure:
test_auth(UserTest) [./test/unit/user_test.rb:9]:
expected but was
<#<User:0x3620fc8 @attributes= {"salt"=>"7f8b036f9b647d46d22abdbfc8113f44a88f9889", "delete_after"=>nil, "updated_at"=>nil, "security_token"=>nil, "role"=>nil, "lastname"=>nil, "firstname"=>nil, "id"=>"1000001", "deleted"=>"0", "token_expiry"=>nil, "verified"=>"1", "logged_in_at"=>nil, "salted_password"=>"ef94c16f6c124a4e84cc215c164767bfa25f6e92", "login"=>"bob", "created_at"=>nil, "email"=>"bob@test.com"}>>.
2) Error:
test_passwordchange(UserTest):
NoMethodError: You have a nil object when you didn't expect it!
The error occured while evaluating nil.change_password ./test/unit/user_test.rb:17:in `test_passwordchange'

14 tests, 27 assertions, 1 failures, 1 errors
rake aborted!
Command failed with status (1): [c:/ruby/bin/ruby -Ilib;test “c:/ruby/lib/r…]

Can’t find any specific reference to it anywhere online :-/

—Microchip [rick at gitk dot com]


I’ve set the table type to InnoDB, and I can register at my site and receive a verification email. However, the welcome method in user_controller.rb is empty! How can the registration verification link work with an empty welcome method??? I cannot find any code that would set verified to 1 in the database. And if I set it manually and then try to login, I never get a response back after clicking the Login button.

I’ve got to say that, at least for me, this generator is a detriment and impediment to adoption of Rails. I’ve tried to get it working several times and always walk away from it, and therefore Rails and Ruby, in disgust. Why doesn’t somebody do something about it? Either fix it or remove it.

I want the functionality that this thing offers, but I’m sick of failed attempts at getting it working. (And the Plugin Engine version doesn’t work either.)

Is it just me, or does this thing cause everyone grief? Nevermind the failed unit tests, I’d just like to get the basic functionality working.



I had the same problem as microchip. 2 tests failing. Setting test/test_helper.rb:

self.use_instantiated_fixtures = true

fixed the problem but I have functional tests failing too.

Okay, got my functional tests fixed: I split up the test_signup test that was doing 3 calls by changing the code in test/functional/user_controller_test.rb to

  def test_signup_tf
    do_test_signup(true, false)
  end

  def test_signup_ft
    do_test_signup(false, true)
  end

  def test_signup_ff
    do_test_signup(false, false)
  end


user.verified does not seem to be used

Using SLG 1.1.1 and Rails 1.0.

After signing up, you are sent an email with a verification link like http:\\localhost:3000/user/welcome?user[id]=1&key=3e5bc147c6b117907dbd82735075ab9970ce1e3c

The weclome action in the UserController is empty. It does nothing with the key given to it as far as I can see. I don’t see anywhere in the code (via grepping) where the verification column in the database is ever being set to 1 except for in User#update_expiry, which strangely also references a User attribute called ‘authenticated_by_token’ which I don’t see in the DB schema.

Loading the verification link produces a web page that says all is well, but the verified column in the users table is never being updated so the user is not logged in.

So it seems impossible for the system to work, which makes no sense, since I would think something like that would be fixed immediately. What am I missing here?

—Dav

There appears to be a bug in SLG that bites you mostly when you’re testing. If you sign up a new user (person1) and verify and login, then try to sign up another new user (person2) while logged in as person1, the first attempt at verification will fail and you’ll continue to be logged in as person1. If you logout from person1’s account, the verification will work. The fix is to put a ”@session[‘user’] = nil” right after UserController.signup’s “return if generate_blank”. This removes the authentication from the current session any time someone creates a new user.

—John

I had the same problem, logging out didn’t fix it for me, either. I added some code to the welcome controller which seems to work for me.


 def welcome
    @user = User.new(@params['user'])
    if @session['user'] == User.authenticate_by_token(@params['user']['id'], @params['key'])
      flash['notice'] = l(:user_login_succeeded)
      redirect_back_or_default :action => 'locations'
    end
  end

—droy


All rake tests hang

I am running Rails 1.0.0 with MySQL 4.1.5-standard

After doing a clean install of SaltedHashLoginGenerator on a new rails project I was getting the error “Client does not support authentication protocol requested by server; consider upgrading MySQL client” I used the fix found on this page I was confused about this, since I am not running MySQL 5.0 but the fix worked. However, now whenever I run the rake tests as described in step 11 of the quickstart they just hang. If I start the webrick server it also hangs. Any suggestions? I’m lost here.


I am trying to retrofit this to an existing project, is that feasible? The gem install is fine then:

ruby script/generate salted_login User Localization

tells me:

dependency  localization
    create    lang
    create    lib/localization.rb
No such file or directory - ./script/../config/../lib/localization.rb

thx

- Matt


It appear that edge rails (rev. 3518) isn’t happy with the Time.rb mock in the test environment. Loading that mock prevents proper dependency loading—gems fail to load raising a MissingSourceFile exception.

- LeeO


To add to Dan’s tip above, if you still get a “rails undefined method `l’” error for a User model, go to app/helpers/user_helper.rb and add “include Localization” at the very top, above the “module UserHelper” declaration.

-ChrisHolland



Verification e-mail link not working still.

I am trying to get the e-mail verification link to actually work. Right now it does nothing. I looked at what the other people said, but I don’t have anyone logged in at all, so it can’t be that problem. The welcome action is completely blank. What should welcome action have in it?

- Exar

Answer:

I decided not to wait for help and wrote a quick thing that works. The welcome action can look like this:

def welcome
  @key = @params['key']
  @user = User.find(@params[:userid]) 
  if @user.security_token == @key
      @user.verified = 1
      @user.save
  end               
end

I had to edit the login action to change the verification link from user[id] to userid. For some reason the browser wouldn’t get the brackets from the e-mail, only the ascii for it. So there you go, a working welcome method.
- Exar www.TheGregg.com

(Note that this still doesn’t 100% work, because expired users are still verified—Mike S.)

The verification actually takes place in User#authenticate_by_token, which is called from UserSystem#user? , which is in turn called in UserSystem#login_required . It seems like UserController was designed to rely on having login_required as a before_filter, so either put it in UserController or ApplicationController. That should make the verification link in the email work.


user/signup raises an exception at this line:

@user.lottds << Lottd.new({:name => ‘General’})

What is Lottd? I couldn’t find any references to what it is. Thanks.

-vs



Verification e-mail link also not working here

I’m seeing the same problem as TheGregg. The welcome method is completely empty.



Verification fix


Although I’m damn near a Ruby newbie, I’ve found that placing the following line in the user_controller welcome method fixes verification: User.authenticate_by_token(@params‘user’, @params[‘key’])


Still problems


I added the welcome to the User controller however, I m just getting the welcome.rhtml comming up and it doesn’t seem to be running the welcome method, How do i change this behavior and make sure the welcome method in the controller gets run?

Thanks

-er


Newbie needs help


In the functional tests I get 3 Errors, but they each have the same source:
ArgumentError: comparison of Time with Date failed c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.12.5/lib/action_view/base.rb:515
:in `min’ H:/work/saltydog/config/../app/models/user.rb:33:in `each’ H:/work/saltydog/config/../app/models/user.rb:33:in `min’ H:/work/saltydog/config/../app/models/user.rb:33:in `update_expiry’ H:/work/saltydog/config/../app/models/user.rb:24:in `authenticate_by_token’ H:/work/saltydog/config/../lib/user_system.rb:94:in `user?’ H:/work/saltydog/config/../lib/user_system.rb:47:in `login_required’

Any suggestions?



“If after installing the SHLG and visiting /user/login you get a uninitialized constant CONFIG error, try re-starting the web server. This is probably obvious to most people, but it had me flummoxed for days. I hope this saves other people from some serious frustration.”

I have restarted my web server, I got added everything in application.rb … , but it still showing this message : uninitialized constant CONFIG

Can someone help me ? I will jump through the window…


>>>>>>> I fix the problem, I just erase my application and use salted_login with User and Localization. I was using SecuredUser and Localization but it did not works…


Sending localized emails won’t work

I might be doing a very noobish mistake, but it seems that I can’t send any localized emails.

I created an action to let the user change the language with a simple link:

views/layouts/scaffold.rhtml:

<= link_helper 'change_language_de', :action => 'change_language', :lang => 'de'>
<= link_helper 'change_language_en', :action => 'change_language', :lang => 'en'>

controllers/user_controller.rb:

def change_language
  Localization::CONFIG[:default_language] = @params['lang']
  redirect_to :back
end

Then I created some german .rhtml files in /user_notify/ like “signup_de.rhtml”.
The variable “default_language” is changed correctly and rendering pages in german works fine. But the emails are always send in english only. And I don’t have a clue why.

Any suggestions?

This page relates to the use of the SaltedHashLoginGenerator.

The fine manuals

There are two README files associated with the two gems required for SHLG. You are advised to read them :)

Generation


ruby script/generate salted_login User Localization

Once generated, consult the readme for instructions on how to use the produced code in your application. Modifications to the README have been made that explain some of the requirements of the new code. You may also wish to refer to the SaltedLoginGeneratorQuickstart, which walks you through the steps required.

In the above example, two README files would have been installed in your app’s root directory as README_USER_LOGIN and README_LOCALIZATION.

Restart the server after editing environment files

If after installing the SHLG and visiting /user/login you get a uninitialized constant CONFIG error, try re-starting the web server. This is probably obvious to most people, but it had me flummoxed for days. I hope this saves other people from some serious frustration.

Iconv Related Issues

Use the salted hash login generator without iconv

To use the salted hash login generator without iconv I just defined LOCALIZED_STRINGS in /lib/localization.rb to the contents of /lang/en.yaml i.e.


#require 'iconv'

module Localization

  LOCALIZED_STRINGS = {'en' => {
    :account_login_succeeded => 'Login successful',
    :account_login_head => 'Please login'
    # etc...
  }}

You should also follow the instructions in the README_LOCALIZATION file to include the various files, but without the “Localization::load_localized_strings” call. —Steve

Missing iconv

If you are using the One-Click Ruby Installer under windows, you may find that you are getting an iconv related error. Specifically, you are missing ruby/lib/ruby/1.8/i386-mswin32/iconv.so

See iconv for more information and how to fix the problem. Copying the iconv.so from one of these distributions into the appropriate folder solved the problem for me—Jay

Other issues

SHLG 1.1.1 on rails 0.13.1 setup using the README instructions is spamming my logs with ./script/../config/../app/helpers/user_helper.rb:7: warning: already initialized constant DEFAULT_HEAD_OPTIONS

any ideas how to fix this?


In app/helpers/user_helper.rb, changing


module UserHelper

  DEFAULT_HEAD_OPTIONS = {
    :notice => true,
    :message => true,
    :error => false
  }.freeze

to


module UserHelper

  DEFAULT_HEAD_OPTIONS = {
    :notice => true,
    :message => true,
    :error => false
  }.freeze unless const_defined? "DEFAULT_HEAD_OPTIONS" 

seems to work.

-Brett

On the security of emailing passwords

I think it somewhat defeats the purpose of hashed+salted password data when clear text passwords are emailed on registration and password change. I suggest removing the password from all emails. —mrj


I think the main reason is to keep the clear text password out of a DB which can be hacked or read by someone with legitimate access to it. However, it’s pretty easy to remove this – just edit the mailer templates.


Emails are even less secure that the DB because they can be monitored along the delivery path, not just at the host. Of course the security token emails can be intercepted as well, but at least the user is given an indication through an unexpected password change that something is up. —mrj

I can easily change the templates. I’m just suggesting you change them in the gem itself. —mrj


Comments

September 5 2005
I had to do a few things to get this running.
1. Move the render_body alias in lib/localization.rb below the method.
2. in views/account_notify/*_en I had to remove the _en suffix because it was not recognizing the locale. The signup failed with an arbitrary message and then once I removed the rescue I received the No rhtml, rxml,... for method signup. This is NOT the account signup view, it is the account_notify signup view it’s looking for. Removing the suffix is the short-term fix.
3. Make sure you specify an action mailer setting in your env of choice. I got away with the bare basics:

ActionMailer::Base.server_settings = { :address => "domain.com", :domain => "domain.com" } -Caged

If someone can help me out with this one, I’d appreciate it. I’m running with Mac OS X 10.4.2 and Mandrake, and don’t see this problem generating the docs.



Important: Don’t forget to include the localization environment in config/environment.rb. These lines need to be included:
require ‘environments/user_environment’
require ‘environments/localization_environment’
This is not mentioned in README_USER_LOGIN and the error message “method ‘l’ missing” is pretty unclear.

I wanted to seperate the authentication functionality from my actual User model… I’m hoping that it shields me from upgrades down the road (I have a lot of my own custom methods in my model). I did the following:
  1. $ script/generate salted_login Account Localization
  2. Followed all of the directions in the README’s
  3. Changed the head of models/account.rb:
    class Account < ActiveRecord::Base
      set_table_name "users"
  4. Changed the head of models/user.rb:
    class User < Account
  5. Do all of my login related actions through the \AccountController.

From an email to the mailing list:

A number of people have seen problems with verification not working, and lots of test failures. I believe a lot of these problems are caused by trying to include the ‘before_filter :login_required’ directly in the UserController (assuming the model class is ‘User’). This should work (I haven’t tested this yet) – but if you do it, I’m guessing you must also include the same code that the README says to include assuming it is placed in the ApplicationController class. For example, you would need the following lines (showing only the pertinent lines to this problem):


require 'user_system'

UserController < ApplicationController
    include UserSystem
    helper :user
    model :user # probably don't need this if you are including it directly in this controller
    before_filter :login_required
    ...
end

Bear in mind, though, that the protect? method is provided so that you can check permissions in a specific controller, so there’s really no problem including there, unless you have lots of controllers with unprotected actions and you want to avoid the filter invocation.


Is the db_structure a \RubyForge project as well? I assume it is as it is available from gems.rubyforge.com, but I can’t find it. Editing it to add the options I need is a good stop-gap, but being able to contribe back changes (like adding options for sqlite3) would be best.
—Brian G.


Yes, it is. You can find it at http://rubyforge.org/projects/localization/. I’m looking at making both public so that others can contribute changes. First I’d like to find someone to manage them, since my time has been limited lately.


If you’ve been having trouble with verification issues and you’re using lighttpd then be sure that you have these rewrites set up:


url.rewrite = ( 
            "^/$" =>  "/dispatch.fcgi?controller=home&action=index",
            "^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9%]+)\??([\-_a-zA-Z0-9=&%]*)$"  => 
                "/dispatch.fcgi?controller=$1&action=$2&id=$3&$4",
            "^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$"  => 
                "/dispatch.fcgi?controller=$1&action=$2&$3",
            "^/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$"  =>  
                "/dispatch.fcgi?controller=$1&action=index&$2" 
)

The first rewrite rule can be changed to whichever controller and action you prefer.

There may be some other issues which cause email verification failure, and those are listed in the README which comes with the code, but setting up these rewrites solved the verification issue I was experiencing on an Ubuntu box.

You may find more information at Lighttpd and [[FastCGI?]].



execution expired

app/controllers/user_controller.rb:28:in `signup'
app/controllers/user_controller.rb:22:in `transaction'
app/controllers/user_controller.rb:22:in `signup'
script/server:48

this means your mail/actionmailer isn’t properly set up
comment out this line to test
"UserNotify.deliver_signup(@user, @params['user']['password'], url)" of course the system won’t work if you don’t get a verification email


Alternate fix for Localized mailing: Requires PATCH for ActionMailer

I’ve found another solution to the problem with ActionMailer when using the Localization generator. Unfortunately it requires a patch to ActionMailer::Base. Once the patch is in place, you can simply remove the ActionMailer::Base.module_eval <<-EOL block in lib/Localization.rb described above and replace it with:

    # in lib/Localization.rb within the module definition:
    class Mailer < ActionMailer::Base

      def initialize(method_name, *parameters)
        @template = method_name + "_#{CONFIG[:default_language]}" 
        super
      end
    end

then for the application mailers, simply replace inheritance from ActionMailer::Base with inheritance from Localization::Mailer, eg (in app/models/user_notify.rb):

  class UserNotify < Localization::Mailer

One concern with this approach is the handling of multi-part attachments. I’m thinking it may require copies or aliases of any image files with the correct extension (eg \_en). Another is the use of \@template. At this time, it is only used for tracking down filenames. If its use is extended to other functionallity, this could easily break.

-Brett


I was getting “NoMethodError” (You have a nil object when you probably didn’t expect it!) errors on Rails 0.13.1 for a bunch of methods (login, signup etc).

Changed to:


    if @request.get?
      generate_blank
    else 
      ...

Or am I missing something?


No, you’re not. I’ve tried the upgrade to 1.1.0, and it still has a lot of problems with :get versus :post. There were a bunch of corrections listed on this site before the cleaning of the wiki. It seems that the easiest way to correct for them is to use case @request.method statements around the part requiring post information:


  def signup
    generate_blank

    case @request.method
    when :get
      @user = User.new(@params['user'])
    else
      @params['user'].delete('form')
      @user = User.new(@params['user'])

      begin
    User.transaction(@user) do
      @user.new_password = true
      @user.lottds << Lottd.new({:name => 'General'})
          if @user.save
            key = @user.generate_security_token
            url = url_for(:action => 'welcome')

        url += "?user[id]=#{@user.id}&key=#{key}" 
        UserNotify.deliver_signup(@user, @params['user']['password'], url)
        flash['notice'] = l(:user_signup_succeeded)

            redirect_to :action => 'login'
          end
        end
      rescue
    flash.now['message'] = l(:user_confirmation_email_error)
      end
    end
  end 

I am happy, though, that the corrections made to the localization library seem to fix the problems with ActionMailer, without the above mentioned patch.

I was not the one to come up with this particular solution, by the way. Unfortunately, I can’t remember who it was.

-Brett


That was a goof on my part when submitting the gem. I released 1.1.1, which fixes the missing return on a GET when calling generate_(star).


Any ideas what my problem is here? Running signup will fail with ‘Error creating account: confirmation email not sent”. Having run
“rake test_functional” I get this error


ruby -Ilib;test "c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_lo
ader.rb" "test/functional/account_controller_test.rb" "test/functional/area_cont
roller_test.rb" "test/functional/project_controller_test.rb" "test/functional/us
er_controller_test.rb" 
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/base.rb:799
:in `method_missing': undefined method `salt=' for User:Class (NoMethodError)
        from ./test/functional/account_controller_test.rb:5
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5:in `load'
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5:in `each'
        from c:/ruby/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
.rb:5
rake aborted!
Command failed with status (1): [ruby -Ilib;test "c:/ruby/lib/ruby/gems/1.8...]

My database looks setup ok. Any ideas?

- Rusty


Rusty—
You need to specify a domain in your
development.rb file i.e.


ActionMailer::Base.server_settings = {
  :address=>'smtp.something',    # default: localhost
  :port=>'25',                        # default: 25
  :user_name=>'username',
  :password=>'password',
  :domain=>'something.wut',
  :authentication=>:plain             # :plain, :login or :cram_md5
}

that should fix your problem
—fluxin


When running tests, I kept getting cattr_accessor errors in the time.rb test, and also uninitialized constant Gem::Specification::Date errors in the user_test.rb

To solve this, near the top of the test_helper.rb file and before the require File.expand_path() line, I added require ‘rubygems’.

Here’s an example:


test_helper.rb:

require 'rubygems' # added this to fix several problems

# Expand the path to environment so that Ruby does not load it multiple times
# File.expand_path can be removed if Ruby 1.9 is in use.
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'application'

This still did not fix another problem in the functional tests.

I received this error report:


Started
....E....E
Finished in 0.826739 seconds.

  1) Error:
test_delete(UserControllerTest):
NoMethodError: undefined method `advance_by_days=' for Time:Class
    ./test/functional/user_controller_test.rb:132:in `test_delete'

  2) Error:
test_signup(UserControllerTest):
NoMethodError: undefined method `advance_by_days=' for Time:Class
    ./test/functional/user_controller_test.rb:51:in `do_test_signup'
    ./test/functional/user_controller_test.rb:145:in `test_signup'

and fixed this one by adding near the top of the file user_controller_test.rb


user_controller_test.rb:

require File.dirname(__FILE__) + '/../test_helper'
require 'user_controller'

# ADD to fix advance_by_days= problem
require File.dirname(__FILE__) + '/../mocks/test/time'

TomMornini?—Thanks! I concur with these results and fixes (identical behavior) on Macintosh OS X Tiger 10.4.2 with the fix_ruby stuff in place, PostgreSQL 8.0.3

Additionally, I also get this:


ruby -Ilib:test "/usr/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader.rb" "test/functional/user_controller_test.rb" 
Loaded suite /usr/lib/ruby/gems/1.8/gems/rake-0.5.4/lib/rake/rake_test_loader
Started
.....WARNING:  there is already a transaction in progress
....

Bug in 1.1.1 prevents login by token from forgot_password emails, as security tokens are not being updated in the database. This is because the db transaction in the user_controller forgot_password method is never ended. My fix was to move the transaction end to just below the email delivery statement. —mrj

Could you show your change? I am not seeing this problem with 1.1.1. The only way the DB transaction shouldn’t commit is if an exception is thrown, and I’m not sure where that would be happening if the email is actually being sent.

Hm, I’m surprised you’re not seeing this.

In user_controller.rb, line 79, change:


        User.transaction(user) do
          key = user.generate_security_token
          url = url_for(:action => 'change_password')
          url += "?user[id]=#{user.id}&key=#{key}" 
          UserNotify.deliver_forgot_password(user, url)
          flash['notice'] = l(:user_forgotten_password_emailed, "#{@params['user']['email']}")
          unless user?
            redirect_to :action => 'login'
            return
          end
          redirect_back_or_default :action => 'welcome'
        end

to


        User.transaction(user) do
          key = user.generate_security_token
          url = url_for(:action => 'change_password')
          url += "?user[id]=#{user.id}&key=#{key}" 
          UserNotify.deliver_forgot_password(user, url)
          flash['notice'] = l(:user_forgotten_password_emailed, "#{@params['user']['email']}")
        end
        unless user?
          redirect_to :action => 'login'
          return
        end
        redirect_back_or_default :action => 'welcome'

This prevents the non-returning redirect to ‘login’ preventing the ending of the transaction that updates the security token. —mrj

This error shows up very clearly when running the test scripts with SQLite, then you’ll get this error:


d:/ruby/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0-mswin32/lib/sqlite3/errors.rb:94:in `check': cannot start a transaction within a transaction (SQLite3::SQLException)

After appying the above fix the test scripts run beautifully. —gs


I used the db schema in the README, then cut n’ pasted the Welcome! code:

<%= @session['user'].name %>

There’s no name() function, so I updated this to
<%= @session['user'].firstname %>

Perhaps the README could reflect this, eventually.

-- wesgarrison


I updated :security_token_life_hours in user_environment to 96 to account for weekends. This caused the test: do_test_signup(bad_password, bad_email)
in user_controller_test to fail. Specifically:

      # First past the expiration.
      Time.advance_by_days = 1
      get :welcome, "user"=> { "id" => "#{user.id}" }, "key" => "#{key}" 
      Time.advance_by_days = 0
      user = User.find_by_email("<a href="mailto:newbob@test.com">newbob@test.com</a>")
      assert_equal 0, user.verified

Perhaps the advance_by_days should be be adjusted to use the environment value.
-- wesgarrison

No rhtml, rxml, or delegate template found for signup

I toyed around a bit with the salted login generator. This is the signup method (some adjustments)


def signup
    if request.post?
      @user = User.new(params[:user])
      begin
        @user.new_password = true
        @user.save!
        key = @user.generate_security_token
        url = url_for(:action => 'welcome')
        url += "?user[id]=#{@user.id}&key=#{key}" 
        UserNotify.deliver_signup(@user, @params[:user][:password], url)
        flash[:notice] = "Signup successful! Please check your registered email account
to verify your account registration and continue with the login." 
        redirect_to :action => 'login'
      rescue => exception
        flash.now[:notice] = "Sorry, but there was an error during registration.
Please inform the administrator.  #{exception}" 
      end
    end
  end

Works fine on GET, but once i POST the form I receive this error: “No rhtml, rxml, or delegate template found for signup”

Now under normal circumstances it should redirect to login but I guess it never gets there.. any help is appreciated as it’s driving me nuts

Solution

After a whole day of searching, I’ve found the solution to the above problem. You need to rename the file “signup_en.rhtml” in the “views/user_notify” directory to “signup.rhtml”. That solves it for me. Hope this helps, seems like a common problem with the current generator. —Steve

Alternate Solution


The above didn’t work for me. I am using:
  • salted_login_generator (1.1.1)
  • Rails 1.0.0
  • Ruby 1.8.2

and the fix for me was to add:


ActionMailer::Base.template_root ||= "#{RAILS_ROOT}/app/views/" 

to “environment.rb”. —Max



New user verification link does not work


For some reason that I have been unable to determine, the email link that I get in an email after registering does not verify the new user. The verified flag never gets set to 1, so the user can not log in. Does anyone have any idea why that might be? Thanks.


Sign-up not functioning/Test Units fails


When I try to sign-up a new user it fails during @user.save. The log file says:



“Column ‘logged_in_at’ cannot be null”
and rolls back the transaction.


The rake test_units also fails with:

"test/unit/user_test.rb" 
/var/www/rails/w3/config/../test/mocks/test/time.rb:5: undefined method `cattr_accessor' for Time:Class (NoMethodError)
...bunch of further trace...


Followup: New user verification link does not work


It would appear to be a result of the mysql version that was running on the server. v4.0.18. I was able to get it going by pointing it at a server running v4.1.14 (tests still fail maybe dependent on v5.x?).

I tried this on my Mac and…


I thought that I could easily get this thing to work
so I started on a demo but then got stumped.
Here's what I have...

RAILS

zmac11:/pt/TThier/Languages/ruby oracle$ rails saltl
      create  
      create  public/javascripts/slider.js
      create  doc/README_FOR_APP
SNIP
      create  log/production.log
      create  log/development.log
      create  log/test.log
zmac11:/pt/TThier/Languages/ruby oracle$ cd saltl

GENERATE

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ script/generate salted_login User Localization
  dependency  localization
      create    lang
      create    lib/localization.rb
      create    config/environments/localization_environment.rb
      create    test/unit/localization_test.rb
      create    lang/localizations.yaml
      create    README_LOCALIZATION
      create    LICENSE_LOCALIZATION
      create  lib/user_system.rb
      create  app/controllers/user_controller.rb
      create  test/functional/user_controller_test.rb
      create  app/helpers/user_helper.rb
      create  app/models/user.rb
      create  app/models/user_notify.rb
      create  test/mocks/test/user_notify.rb
      create  test/mocks/test/time.rb
      create  test/unit/user_test.rb
      create  test/fixtures/users.yml
      create  db/user_model.erbsql
      create  config/environments/user_environment.rb
      create  script/create_db
      create  lang/en.yaml
      create  app/views/layouts/scaffold.rhtml
      create  public/stylesheets/scaffold.css
      create  app/views/user
      create  app/views/user/welcome.rhtml
      create  app/views/user/login.rhtml
      create  app/views/user/logout.rhtml
      create  app/views/user/edit.rhtml
      create  app/views/user/signup.rhtml
      create  app/views/user/forgot_password.rhtml
      create  app/views/user/change_password.rhtml
      exists  app/views/user
      create  app/views/user/_edit.rhtml
      create  app/views/user/_password.rhtml
      create  app/views/user_notify
      create  app/views/user_notify/signup_en.rhtml
      create  app/views/user_notify/forgot_password_en.rhtml
      create  app/views/user_notify/change_password_en.rhtml
      create  app/views/user_notify/delete_en.rhtml
      create  app/views/user_notify/pending_delete_en.rhtml
      create  README_USER_LOGIN
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 

EDIT  application.rb

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ cd app/controllers
zmac11:/pt/TThier/Languages/ruby/saltl/app/controllers oracle$ ls
./            ../            application.rb        user_controller.rb
zmac11:/pt/TThier/Languages/ruby/saltl/app/controllers oracle$ cat application.rb
# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

require 'user_system'

class ApplicationController < ActionController::Base
  include UserSystem
  helper :user
  model :user
  before_filter :login_required
end
zmac11:/pt/TThier/Languages/ruby/saltl/app/controllers oracle$ 

CREATE the users table

zmac11:/pt/TThier/Languages/ruby/saltl/db oracle$ sqlite3 saltl.db
SQLite version 3.2.7
Enter ".help" for instructions
sqlite> .read user.sql
sqlite> .schema
CREATE TABLE 'users' (
    id INTEGER PRIMARY KEY,
    login VARCHAR(80) NOT NULL,
    salted_password VARCHAR(40) NOT NULL,
    email VARCHAR(60) NOT NULL,
    firstname VARCHAR(40),
    lastname VARCHAR(40),
    salt CHAR(40) NOT NULL,
    verified INT default 0,
    role VARCHAR(40) default NULL,
    security_token CHAR(40) default NULL,
    token_expiry DATETIME default NULL,
    deleted INT default 0,
    delete_after DATETIME default NULL
  );
sqlite> 

EDIT config/database.yml

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ cat config/database.yml
development:
  adapter: sqlite3
  dbfile: db/saltl.db
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 

EDIT config/environment.rb file:

zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ tail environment.rb
# Inflector.inflections do |inflect|
#   inflect.plural /^(ox)$/i, '\1en'
#   inflect.singular /^(ox)en/i, '\1'
#   inflect.irregular 'person', 'people'
#   inflect.uncountable %w( fish sheep )
# end

# Include your application configuration below

require 'environments/user_environment'

zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 

EDIT config/environments/development.rb

zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ cat environments/development.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

# Enable the breakpoint server that script/breakpointer connects to
config.breakpoint_server = true

# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching             = false

# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false

ActionMailer::Base.server_settings = {
  :address => "smtp.mac.com",
  :port => 25,
  :domain => "smtp.mac.com",
  :user_name => "steve",
  :password => "jobs",
  :authentication => :login
}
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl/config oracle$ 

WHAT Next?

I tried this:

zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ 
zmac11:/pt/TThier/Languages/ruby/saltl oracle$ script/server
[2005-10-23 19:24:34] INFO  WEBrick 1.3.1
[2005-10-23 19:24:34] INFO  ruby 1.8.2 (2004-12-25) [powerpc-darwin7.9.0]
[2005-10-23 19:24:34] INFO  WEBrick::HTTPServer#start: pid=4384 port=3000

THIS worked okay:

http://localhost:3000/

THIS did not:

http://localhost:3000/user/login

It gives..

 NoMethodError in User#login

Showing app/views/user/login.rhtml where line #2 raised:

undefined method `l' for #<#<Class:0x29327d0>:0x29323c0>

Extracted source (around line #2):

1: <div title="<%= title_helper %>" class="form">
2:   <%= head_helper %>
3: 
4:   <div class="form-padding">
5:     <%= start_form_tag_helper  %>

Application Trace | Framework Trace | Full Trace

./app/helpers/user_helper.rb:67:in `head_helper'
./app/views/user/login.rhtml:2
./app/controllers/user_controller.rb:172:in `generate_blank'
./app/controllers/user_controller.rb:6:in `login'

Anyone have any clues on how to get this working??

-Dan

ok,

I found a good recipe:
http://wiki.rubyonrails.com/rails/pages/SaltedLoginGeneratorQuickstart/versions/26

It gives me a login page.

I needed to add two steps to the above page:

EDIT environment.rb, add this to end:

# Include your application configuration below
require 'environments/localization_environment'
require 'localization'
Localization::load_localized_strings
require 'environments/user_environment'

EDIT app/helpers/application_helper.rb

# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
include Localization
end

-Dan

I cam across the following errors when I ran rake under 0.14.1.

  1) Failure:
test_change_password(UserControllerTest)
    [/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.10.1/lib/action_controller/deprecated_assertions.rb:23:in `assert_session_has'
     ./test/functional/user_controller_test.rb:189:in `do_change_password'
     ./test/functional/user_controller_test.rb:197:in `test_change_password']:
<"user"> is not in the session <#<ActionController::TestSession:0x274ae40
 @attributes={"user"=>nil, "flash"=>{}}>>

  2) Failure:
test_signup(UserControllerTest)
    [/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.10.1/lib/action_controller/deprecated_assertions.rb:13:in `assert_redirect'
     /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.10.1/lib/action_controller/deprecated_assertions.rb:98:in `assert_redirect_url'
     ./test/functional/user_controller_test.rb:40:in `do_test_signup'
     ./test/functional/user_controller_test.rb:148:in `test_signup']:
Expected response to be a <:redirect>, but was <200>

The problem I discovered after much trial and error was that I had created my users table in mysql without specifying that it should be a INNOdb table. Once I specified that the errors went away. —SteveRushe

My 2 cents:

The approach taken here of making this a generator is interesting, but I wonder how updates to the SaltedHash codebase can be distributed to apps that have already employed it?

It seems to me that the SaltedHashLogin would be a good candidate for a freestanding component as described in the Ruby on Rails book published by Pragmatic Programmers. In this scheme, the entire login codebase could be maintained in a single dedicated directory, which developers would deploy into the components directory of their applications. This would allow the code to be kept under revision control in its deployed form, either through gems or subversion or whathaveyou.

One problem with this idea is that developers who use the saltedhashlogin generator will most often want to extend the user model. This of course will lead to conflicts when merging changes. But conflicts can be resolved if using a version control system like subversion,darcs or cvs.

And you don’t necessarily need to implement your permissions logic in the user model. Instead of using a “role” field as in the login readme, one can have a separate administrators table that references users with a foreign key. This method is clumsy for most systems which just have customers and admins, but if you have a larger number of roles it might not be more complicated then mashing everything into one model. (Disclaimer: i am too new at this sort of thing to really have an informed opinion about that claim)

—jacob robbins

I am getting the same errors as SteveRushe, however I am on MS SQL Server, so no INNOdb. Any ideas how to fix it so those two failures go away?

—Chanan Braunstein

I’m getting the same problem, but I do have my tables set to inndodb. Has anyone else run across this problem and come up with a fix?

—Matt Giacomini

I am getting the same problem, and my tables are all InnoDB:


test_signup(UserControllerTest)
    [./test/functional/user_controller_test.rb:43:in `do_test_signup'
     ./test/functional/user_controller_test.rb:151:in `test_signup']:
Expected response to be a <:redirect>, but was <200>

I managed to fix the other failures through making minor adjustments.
This appears to be a problem with the signup routine itself. Every
forum post I could find, including this wiki, said InnoDB should fix
the issue but it hasn’t. It doesn’t appear to be creating the user record
on signup. Although, doing a regular signup (not in tests) works fine and sends mail. Any ideas?

—gfburke at google’s mail service


My users table was InnoDB but I was still getting the same 2 functional test errors discussed above (test_change_password and test_signup were failing in UserControllerTest) . Reading through “Agile Web Development with Rails” I noticed a reference to using Transactional Fixtures in order to speed up tests. Each test gets run inside a transaction and after the test is finished the transaction is rolled back. Very clever, except that these two failing tests are counting on a rollback in the middle of the test. So I tried putting:

self.use_transactional_fixtures = false

in the UserControllerTest and the tests all passed. You could also alter the same line in test_helper.rb if you wanted to globally disable transactional fixtures. I suspect that the 1.0 release of Rails automatically enables transactional tests for speed reasons. —jscruggs at thoughtworks dot com

In order to fix the second failure I splitted up the test_change_password UT into 3 separate unit tests:

# app/test/functional/user_controller_test.rb

 def test_change_password
    do_change_password(false, false)
#    do_change_password(true, false)
#    do_change_password(false, true)
  end

  def test_change_password2
    do_change_password(true, false)
  end

  def test_change_password3
    do_change_password(false, true)
  end

A UT that is causing the first failure looks strange from my noob point of view, therefore it got deleted.

—DmitryVerkhovsky

I tried Dmitry’s suggestion to split up the change password tests and I got a test failure in test_change_password3. I modified do_change_password as below to get the test working again.

def do_change_password(bad_password, bad_email)

    ...

    get :logout
    assert_session_has_no "user" 

    if not bad_password and not bad_email
      post :login, "user" => { "login" => "bob", "password" => "changed_password" }
      assert_session_has "user" 
      post :change_password, "user" => { "password" => "atest", "password_confirmation" => "atest" }
      get :logout
    elsif not bad_password and bad_email
      post :login, "user" => { "login" => "bob", "password" => "changed_password" }
      assert_session_has "user" 
      post :change_password, "user" => { "password" => "atest", "password_confirmation" => "atest" }
      get :logout
    end

    post :login, "user" => { "login" => "bob", "password" => "atest" }
    assert_session_has "user" 

    get :logout

end

I guess you could always just remove the ‘and not bad_email’ portion so that the test becomes simpler, but I’m feeling lazy today :-0

—GuidoSohne


I have an error on the tests, after running through SaltedLoginGeneratorQuickstart, which I haven’t been able to solve.

C:\Documents and Settings\Rick\workspace\JC-rails>rake test_units
(in C:/Documents and Settings/Rick/workspace/JC-rails)
c:/ruby/bin/ruby -Ilib;test “c:/ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/
rake_test_loader.rb” “test/unit/localization_test.rb” “test/unit/user_test.rb”
Loaded suite c:/ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader

Started
........F….E
Finished in 0.453 seconds.

1) Failure:
test_auth(UserTest) [./test/unit/user_test.rb:9]:
expected but was
<#<User:0x3620fc8 @attributes= {"salt"=>"7f8b036f9b647d46d22abdbfc8113f44a88f9889", "delete_after"=>nil, "updated_at"=>nil, "security_token"=>nil, "role"=>nil, "lastname"=>nil, "firstname"=>nil, "id"=>"1000001", "deleted"=>"0", "token_expiry"=>nil, "verified"=>"1", "logged_in_at"=>nil, "salted_password"=>"ef94c16f6c124a4e84cc215c164767bfa25f6e92", "login"=>"bob", "created_at"=>nil, "email"=>"bob@test.com"}>>.
2) Error:
test_passwordchange(UserTest):
NoMethodError: You have a nil object when you didn't expect it!
The error occured while evaluating nil.change_password ./test/unit/user_test.rb:17:in `test_passwordchange'

14 tests, 27 assertions, 1 failures, 1 errors
rake aborted!
Command failed with status (1): [c:/ruby/bin/ruby -Ilib;test “c:/ruby/lib/r…]

Can’t find any specific reference to it anywhere online :-/

—Microchip [rick at gitk dot com]


I’ve set the table type to InnoDB, and I can register at my site and receive a verification email. However, the welcome method in user_controller.rb is empty! How can the registration verification link work with an empty welcome method??? I cannot find any code that would set verified to 1 in the database. And if I set it manually and then try to login, I never get a response back after clicking the Login button.

I’ve got to say that, at least for me, this generator is a detriment and impediment to adoption of Rails. I’ve tried to get it working several times and always walk away from it, and therefore Rails and Ruby, in disgust. Why doesn’t somebody do something about it? Either fix it or remove it.

I want the functionality that this thing offers, but I’m sick of failed attempts at getting it working. (And the Plugin Engine version doesn’t work either.)

Is it just me, or does this thing cause everyone grief? Nevermind the failed unit tests, I’d just like to get the basic functionality working.



I had the same problem as microchip. 2 tests failing. Setting test/test_helper.rb:

self.use_instantiated_fixtures = true

fixed the problem but I have functional tests failing too.

Okay, got my functional tests fixed: I split up the test_signup test that was doing 3 calls by changing the code in test/functional/user_controller_test.rb to

  def test_signup_tf
    do_test_signup(true, false)
  end

  def test_signup_ft
    do_test_signup(false, true)
  end

  def test_signup_ff
    do_test_signup(false, false)
  end


user.verified does not seem to be used

Using SLG 1.1.1 and Rails 1.0.

After signing up, you are sent an email with a verification link like http:\\localhost:3000/user/welcome?user[id]=1&key=3e5bc147c6b117907dbd82735075ab9970ce1e3c

The weclome action in the UserController is empty. It does nothing with the key given to it as far as I can see. I don’t see anywhere in the code (via grepping) where the verification column in the database is ever being set to 1 except for in User#update_expiry, which strangely also references a User attribute called ‘authenticated_by_token’ which I don’t see in the DB schema.

Loading the verification link produces a web page that says all is well, but the verified column in the users table is never being updated so the user is not logged in.

So it seems impossible for the system to work, which makes no sense, since I would think something like that would be fixed immediately. What am I missing here?

—Dav

There appears to be a bug in SLG that bites you mostly when you’re testing. If you sign up a new user (person1) and verify and login, then try to sign up another new user (person2) while logged in as person1, the first attempt at verification will fail and you’ll continue to be logged in as person1. If you logout from person1’s account, the verification will work. The fix is to put a ”@session[‘user’] = nil” right after UserController.signup’s “return if generate_blank”. This removes the authentication from the current session any time someone creates a new user.

—John

I had the same problem, logging out didn’t fix it for me, either. I added some code to the welcome controller which seems to work for me.


 def welcome
    @user = User.new(@params['user'])
    if @session['user'] == User.authenticate_by_token(@params['user']['id'], @params['key'])
      flash['notice'] = l(:user_login_succeeded)
      redirect_back_or_default :action => 'locations'
    end
  end

—droy


All rake tests hang

I am running Rails 1.0.0 with MySQL 4.1.5-standard

After doing a clean install of SaltedHashLoginGenerator on a new rails project I was getting the error “Client does not support authentication protocol requested by server; consider upgrading MySQL client” I used the fix found on this page I was confused about this, since I am not running MySQL 5.0 but the fix worked. However, now whenever I run the rake tests as described in step 11 of the quickstart they just hang. If I start the webrick server it also hangs. Any suggestions? I’m lost here.


I am trying to retrofit this to an existing project, is that feasible? The gem install is fine then:

ruby script/generate salted_login User Localization

tells me:

dependency  localization
    create    lang
    create    lib/localization.rb
No such file or directory - ./script/../config/../lib/localization.rb

thx

- Matt


It appear that edge rails (rev. 3518) isn’t happy with the Time.rb mock in the test environment. Loading that mock prevents proper dependency loading—gems fail to load raising a MissingSourceFile exception.

- LeeO


To add to Dan’s tip above, if you still get a “rails undefined method `l’” error for a User model, go to app/helpers/user_helper.rb and add “include Localization” at the very top, above the “module UserHelper” declaration.

-ChrisHolland



Verification e-mail link not working still.

I am trying to get the e-mail verification link to actually work. Right now it does nothing. I looked at what the other people said, but I don’t have anyone logged in at all, so it can’t be that problem. The welcome action is completely blank. What should welcome action have in it?

- Exar

Answer:

I decided not to wait for help and wrote a quick thing that works. The welcome action can look like this:

def welcome
  @key = @params['key']
  @user = User.find(@params[:userid]) 
  if @user.security_token == @key
      @user.verified = 1
      @user.save
  end               
end

I had to edit the login action to change the verification link from user[id] to userid. For some reason the browser wouldn’t get the brackets from the e-mail, only the ascii for it. So there you go, a working welcome method.
- Exar www.TheGregg.com

(Note that this still doesn’t 100% work, because expired users are still verified—Mike S.)

The verification actually takes place in User#authenticate_by_token, which is called from UserSystem#user? , which is in turn called in UserSystem#login_required . It seems like UserController was designed to rely on having login_required as a before_filter, so either put it in UserController or ApplicationController. That should make the verification link in the email work.


user/signup raises an exception at this line:

@user.lottds << Lottd.new({:name => ‘General’})

What is Lottd? I couldn’t find any references to what it is. Thanks.

-vs



Verification e-mail link also not working here

I’m seeing the same problem as TheGregg. The welcome method is completely empty.



Verification fix


Although I’m damn near a Ruby newbie, I’ve found that placing the following line in the user_controller welcome method fixes verification: User.authenticate_by_token(@params‘user’, @params[‘key’])


Still problems


I added the welcome to the User controller however, I m just getting the welcome.rhtml comming up and it doesn’t seem to be running the welcome method, How do i change this behavior and make sure the welcome method in the controller gets run?

Thanks

-er


Newbie needs help


In the functional tests I get 3 Errors, but they each have the same source:
ArgumentError: comparison of Time with Date failed c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.12.5/lib/action_view/base.rb:515
:in `min’ H:/work/saltydog/config/../app/models/user.rb:33:in `each’ H:/work/saltydog/config/../app/models/user.rb:33:in `min’ H:/work/saltydog/config/../app/models/user.rb:33:in `update_expiry’ H:/work/saltydog/config/../app/models/user.rb:24:in `authenticate_by_token’ H:/work/saltydog/config/../lib/user_system.rb:94:in `user?’ H:/work/saltydog/config/../lib/user_system.rb:47:in `login_required’

Any suggestions?



“If after installing the SHLG and visiting /user/login you get a uninitialized constant CONFIG error, try re-starting the web server. This is probably obvious to most people, but it had me flummoxed for days. I hope this saves other people from some serious frustration.”

I have restarted my web server, I got added everything in application.rb … , but it still showing this message : uninitialized constant CONFIG

Can someone help me ? I will jump through the window…


>>>>>>> I fix the problem, I just erase my application and use salted_login with User and Localization. I was using SecuredUser and Localization but it did not works…


Sending localized emails won’t work

I might be doing a very noobish mistake, but it seems that I can’t send any localized emails.

I created an action to let the user change the language with a simple link:

views/layouts/scaffold.rhtml:

<= link_helper 'change_language_de', :action => 'change_language', :lang => 'de'>
<= link_helper 'change_language_en', :action => 'change_language', :lang => 'en'>

controllers/user_controller.rb:

def change_language
  Localization::CONFIG[:default_language] = @params['lang']
  redirect_to :back
end

Then I created some german .rhtml files in /user_notify/ like “signup_de.rhtml”.
The variable “default_language” is changed correctly and rendering pages in german works fine. But the emails are always send in english only. And I don’t have a clue why.

Any suggestions?