This page relates to the use of the SaltedHashLoginGenerator.
There are two README files associated with the two gems required for SHLG. You are advised to read them :)
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.
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.
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
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
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
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
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.
$ script/generate salted_login Account Localizationclass Account < ActiveRecord::Base
set_table_name "users"class User < AccountFrom 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
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
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
}
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)
I used the db schema in the README, then cut n’ pasted the Welcome! code:
<%= @session['user'].name %><%= @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
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
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
and the fix for me was to add:
ActionMailer::Base.template_root ||= "#{RAILS_ROOT}/app/views/"
to “environment.rb”. —Max
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...
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 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:
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?
self.use_transactional_fixtures = false
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
—GuidoSohneC:\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 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.
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
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
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
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?
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
Thanks
-erAny suggestions?
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 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.
There are two README files associated with the two gems required for SHLG. You are advised to read them :)
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.
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.
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
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
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
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
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.
$ script/generate salted_login Account Localizationclass Account < ActiveRecord::Base
set_table_name "users"class User < AccountFrom 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
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
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
}
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)
I used the db schema in the README, then cut n’ pasted the Welcome! code:
<%= @session['user'].name %><%= @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
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
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
and the fix for me was to add:
ActionMailer::Base.template_root ||= "#{RAILS_ROOT}/app/views/"
to “environment.rb”. —Max
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...
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 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:
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?
self.use_transactional_fixtures = false
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
—GuidoSohneC:\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 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.
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
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
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
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?
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
Thanks
-erAny suggestions?
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 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?