Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1678 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
93201e7386
commit
eb1d969237
|
@ -44,7 +44,16 @@ class AccountController < ApplicationController
|
||||||
else
|
else
|
||||||
# Authenticate user
|
# Authenticate user
|
||||||
user = User.try_to_login(params[:username], params[:password])
|
user = User.try_to_login(params[:username], params[:password])
|
||||||
if user
|
if user.nil?
|
||||||
|
# Invalid credentials
|
||||||
|
flash.now[:error] = l(:notice_account_invalid_creditentials)
|
||||||
|
elsif user.new_record?
|
||||||
|
# Onthefly creation failed, display the registration form to fill/fix attributes
|
||||||
|
@user = user
|
||||||
|
session[:auth_source_registration] = {:login => user.login, :auth_source_id => user.auth_source_id }
|
||||||
|
render :action => 'register'
|
||||||
|
else
|
||||||
|
# Valid user
|
||||||
self.logged_user = user
|
self.logged_user = user
|
||||||
# generate a key and set cookie if autologin
|
# generate a key and set cookie if autologin
|
||||||
if params[:autologin] && Setting.autologin?
|
if params[:autologin] && Setting.autologin?
|
||||||
|
@ -52,12 +61,8 @@ class AccountController < ApplicationController
|
||||||
cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
|
cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
|
||||||
end
|
end
|
||||||
redirect_back_or_default :controller => 'my', :action => 'page'
|
redirect_back_or_default :controller => 'my', :action => 'page'
|
||||||
else
|
|
||||||
flash.now[:error] = l(:notice_account_invalid_creditentials)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue User::OnTheFlyCreationFailure
|
|
||||||
flash.now[:error] = 'Redmine could not retrieve the required information from the LDAP to create your account. Please, contact your Redmine administrator.'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Log out current user and redirect to welcome page
|
# Log out current user and redirect to welcome page
|
||||||
|
@ -107,14 +112,26 @@ class AccountController < ApplicationController
|
||||||
|
|
||||||
# User self-registration
|
# User self-registration
|
||||||
def register
|
def register
|
||||||
redirect_to(home_url) && return unless Setting.self_registration?
|
redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration]
|
||||||
if request.get?
|
if request.get?
|
||||||
|
session[:auth_source_registration] = nil
|
||||||
@user = User.new(:language => Setting.default_language)
|
@user = User.new(:language => Setting.default_language)
|
||||||
else
|
else
|
||||||
@user = User.new(params[:user])
|
@user = User.new(params[:user])
|
||||||
@user.admin = false
|
@user.admin = false
|
||||||
@user.login = params[:user][:login]
|
|
||||||
@user.status = User::STATUS_REGISTERED
|
@user.status = User::STATUS_REGISTERED
|
||||||
|
if session[:auth_source_registration]
|
||||||
|
@user.status = User::STATUS_ACTIVE
|
||||||
|
@user.login = session[:auth_source_registration][:login]
|
||||||
|
@user.auth_source_id = session[:auth_source_registration][:auth_source_id]
|
||||||
|
if @user.save
|
||||||
|
session[:auth_source_registration] = nil
|
||||||
|
self.logged_user = @user
|
||||||
|
flash[:notice] = l(:notice_account_activated)
|
||||||
|
redirect_to :controller => 'my', :action => 'account'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@user.login = params[:user][:login]
|
||||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
|
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
|
||||||
case Setting.self_registration
|
case Setting.self_registration
|
||||||
when '1'
|
when '1'
|
||||||
|
@ -144,6 +161,7 @@ class AccountController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Token based account activation
|
# Token based account activation
|
||||||
def activate
|
def activate
|
||||||
|
|
|
@ -20,10 +20,7 @@ class AuthSource < ActiveRecord::Base
|
||||||
|
|
||||||
validates_presence_of :name
|
validates_presence_of :name
|
||||||
validates_uniqueness_of :name
|
validates_uniqueness_of :name
|
||||||
validates_length_of :name, :host, :maximum => 60
|
validates_length_of :name, :maximum => 60
|
||||||
validates_length_of :account_password, :maximum => 60, :allow_nil => true
|
|
||||||
validates_length_of :account, :base_dn, :maximum => 255
|
|
||||||
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30
|
|
||||||
|
|
||||||
def authenticate(login, password)
|
def authenticate(login, password)
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,10 @@ require 'iconv'
|
||||||
|
|
||||||
class AuthSourceLdap < AuthSource
|
class AuthSourceLdap < AuthSource
|
||||||
validates_presence_of :host, :port, :attr_login
|
validates_presence_of :host, :port, :attr_login
|
||||||
validates_presence_of :attr_firstname, :attr_lastname, :attr_mail, :if => Proc.new { |a| a.onthefly_register? }
|
validates_length_of :name, :host, :account_password, :maximum => 60, :allow_nil => true
|
||||||
|
validates_length_of :account, :base_dn, :maximum => 255, :allow_nil => true
|
||||||
|
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
|
||||||
|
validates_numericality_of :port, :only_integer => true
|
||||||
|
|
||||||
def after_initialize
|
def after_initialize
|
||||||
self.port = 389 if self.port == 0
|
self.port = 389 if self.port == 0
|
||||||
|
|
|
@ -103,19 +103,16 @@ class User < ActiveRecord::Base
|
||||||
# user is not yet registered, try to authenticate with available sources
|
# user is not yet registered, try to authenticate with available sources
|
||||||
attrs = AuthSource.authenticate(login, password)
|
attrs = AuthSource.authenticate(login, password)
|
||||||
if attrs
|
if attrs
|
||||||
onthefly = new(*attrs)
|
user = new(*attrs)
|
||||||
onthefly.login = login
|
user.login = login
|
||||||
onthefly.language = Setting.default_language
|
user.language = Setting.default_language
|
||||||
if onthefly.save
|
if user.save
|
||||||
user = find(:first, :conditions => ["login=?", login])
|
user.reload
|
||||||
logger.info("User '#{user.login}' created from the LDAP") if logger
|
logger.info("User '#{user.login}' created from the LDAP") if logger
|
||||||
else
|
|
||||||
logger.error("User '#{onthefly.login}' found in LDAP but could not be created (#{onthefly.errors.full_messages.join(', ')})") if logger
|
|
||||||
raise OnTheFlyCreationFailure.new
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
user.update_attribute(:last_login_on, Time.now) if user
|
user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
|
||||||
user
|
user
|
||||||
rescue => text
|
rescue => text
|
||||||
raise text
|
raise text
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!--[form:user]-->
|
<!--[form:user]-->
|
||||||
|
<% if @user.auth_source_id.nil? %>
|
||||||
<p><label for="user_login"><%=l(:field_login)%> <span class="required">*</span></label>
|
<p><label for="user_login"><%=l(:field_login)%> <span class="required">*</span></label>
|
||||||
<%= text_field 'user', 'login', :size => 25 %></p>
|
<%= text_field 'user', 'login', :size => 25 %></p>
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
|
|
||||||
<p><label for="password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
|
<p><label for="password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
|
||||||
<%= password_field_tag 'password_confirmation', nil, :size => 25 %></p>
|
<%= password_field_tag 'password_confirmation', nil, :size => 25 %></p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label>
|
<p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label>
|
||||||
<%= text_field 'user', 'firstname' %></p>
|
<%= text_field 'user', 'firstname' %></p>
|
||||||
|
|
|
@ -22,14 +22,12 @@
|
||||||
|
|
||||||
<p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label>
|
<p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label>
|
||||||
<%= text_field 'auth_source', 'base_dn', :size => 60 %></p>
|
<%= text_field 'auth_source', 'base_dn', :size => 60 %></p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="box">
|
|
||||||
<p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
|
<p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
|
||||||
<%= check_box 'auth_source', 'onthefly_register' %></p>
|
<%= check_box 'auth_source', 'onthefly_register' %></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p>
|
<fieldset class="box"><legend><%=l(:label_attribute_plural)%></legend>
|
||||||
<fieldset><legend><%=l(:label_attribute_plural)%></legend>
|
|
||||||
<p><label for="auth_source_attr_login"><%=l(:field_login)%> <span class="required">*</span></label>
|
<p><label for="auth_source_attr_login"><%=l(:field_login)%> <span class="required">*</span></label>
|
||||||
<%= text_field 'auth_source', 'attr_login', :size => 20 %></p>
|
<%= text_field 'auth_source', 'attr_login', :size => 20 %></p>
|
||||||
|
|
||||||
|
@ -42,7 +40,5 @@
|
||||||
<p><label for="auth_source_attr_mail"><%=l(:field_mail)%></label>
|
<p><label for="auth_source_attr_mail"><%=l(:field_mail)%></label>
|
||||||
<%= text_field 'auth_source', 'attr_mail', :size => 20 %></p>
|
<%= text_field 'auth_source', 'attr_mail', :size => 20 %></p>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<!--[eoform:auth_source]-->
|
<!--[eoform:auth_source]-->
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
|
|
||||||
require "#{File.dirname(__FILE__)}/../test_helper"
|
require "#{File.dirname(__FILE__)}/../test_helper"
|
||||||
|
|
||||||
|
begin
|
||||||
|
require 'mocha'
|
||||||
|
rescue
|
||||||
|
# Won't run some tests
|
||||||
|
end
|
||||||
|
|
||||||
class AccountTest < ActionController::IntegrationTest
|
class AccountTest < ActionController::IntegrationTest
|
||||||
fixtures :users
|
fixtures :users
|
||||||
|
|
||||||
|
@ -102,4 +108,46 @@ class AccountTest < ActionController::IntegrationTest
|
||||||
assert_redirected_to 'account/login'
|
assert_redirected_to 'account/login'
|
||||||
log_user('newuser', 'newpass')
|
log_user('newuser', 'newpass')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Object.const_defined?(:Mocha)
|
||||||
|
|
||||||
|
def test_onthefly_registration
|
||||||
|
# disable registration
|
||||||
|
Setting.self_registration = '0'
|
||||||
|
AuthSource.expects(:authenticate).returns([:login => 'foo', :firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com', :auth_source_id => 66])
|
||||||
|
|
||||||
|
post 'account/login', :username => 'foo', :password => 'bar'
|
||||||
|
assert_redirected_to 'my/page'
|
||||||
|
|
||||||
|
user = User.find_by_login('foo')
|
||||||
|
assert user.is_a?(User)
|
||||||
|
assert_equal 66, user.auth_source_id
|
||||||
|
assert user.hashed_password.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_onthefly_registration_with_invalid_attributes
|
||||||
|
# disable registration
|
||||||
|
Setting.self_registration = '0'
|
||||||
|
AuthSource.expects(:authenticate).returns([:login => 'foo', :lastname => 'Smith', :auth_source_id => 66])
|
||||||
|
|
||||||
|
post 'account/login', :username => 'foo', :password => 'bar'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'account/register'
|
||||||
|
assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
|
||||||
|
assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
|
||||||
|
assert_no_tag :input, :attributes => { :name => 'user[login]' }
|
||||||
|
assert_no_tag :input, :attributes => { :name => 'user[password]' }
|
||||||
|
|
||||||
|
post 'account/register', :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
|
||||||
|
assert_redirected_to 'my/account'
|
||||||
|
|
||||||
|
user = User.find_by_login('foo')
|
||||||
|
assert user.is_a?(User)
|
||||||
|
assert_equal 66, user.auth_source_id
|
||||||
|
assert user.hashed_password.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
puts 'Mocha is missing. Skipping tests.'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue