]> source.dussan.org Git - redmine.git/commitdiff
Improved on-the-fly account creation. If some attributes are missing (eg. not present...
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 19 Jul 2008 10:47:19 +0000 (10:47 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 19 Jul 2008 10:47:19 +0000 (10:47 +0000)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1678 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/account_controller.rb
app/models/auth_source.rb
app/models/auth_source_ldap.rb
app/models/user.rb
app/views/account/register.rhtml
app/views/auth_sources/_form.rhtml
test/integration/account_test.rb

index a9b8a1b82107ddd925a92af66f9fcea15868c830..1fe9900072780c120cdf1e34b15ca5c833375f5c 100644 (file)
@@ -44,7 +44,16 @@ class AccountController < ApplicationController
     else
       # Authenticate user
       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
         # generate a key and set cookie if autologin
         if params[:autologin] && Setting.autologin?
@@ -52,12 +61,8 @@ class AccountController < ApplicationController
           cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
         end
         redirect_back_or_default :controller => 'my', :action => 'page'
-      else
-        flash.now[:error] = l(:notice_account_invalid_creditentials)
       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
 
   # Log out current user and redirect to welcome page
@@ -107,39 +112,52 @@ class AccountController < ApplicationController
   
   # User self-registration
   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?
+      session[:auth_source_registration] = nil
       @user = User.new(:language => Setting.default_language)
     else
       @user = User.new(params[:user])
       @user.admin = false
-      @user.login = params[:user][:login]
       @user.status = User::STATUS_REGISTERED
-      @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
-      case Setting.self_registration
-      when '1'
-        # Email activation
-        token = Token.new(:user => @user, :action => "register")
-        if @user.save and token.save
-          Mailer.deliver_register(token)
-          flash[:notice] = l(:notice_account_register_done)
-          redirect_to :action => 'login'
-        end
-      when '3'
-        # Automatic activation
+      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
-        # Manual activation by the administrator
-        if @user.save
-          # Sends an email to the administrators
-          Mailer.deliver_account_activation_request(@user)
-          flash[:notice] = l(:notice_account_pending)
-          redirect_to :action => 'login'
+        @user.login = params[:user][:login]
+        @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
+        case Setting.self_registration
+        when '1'
+          # Email activation
+          token = Token.new(:user => @user, :action => "register")
+          if @user.save and token.save
+            Mailer.deliver_register(token)
+            flash[:notice] = l(:notice_account_register_done)
+            redirect_to :action => 'login'
+          end
+        when '3'
+          # Automatic activation
+          @user.status = User::STATUS_ACTIVE
+          if @user.save
+            self.logged_user = @user
+            flash[:notice] = l(:notice_account_activated)
+            redirect_to :controller => 'my', :action => 'account'
+          end
+        else
+          # Manual activation by the administrator
+          if @user.save
+            # Sends an email to the administrators
+            Mailer.deliver_account_activation_request(@user)
+            flash[:notice] = l(:notice_account_pending)
+            redirect_to :action => 'login'
+          end
         end
       end
     end
index 47c121a1356a8b35b4f4603105c5389e72642313..a0a2cdc5f398aea4fdbac7aa26f5728f373a6bf4 100644 (file)
@@ -20,10 +20,7 @@ class AuthSource < ActiveRecord::Base
   
   validates_presence_of :name
   validates_uniqueness_of :name
-  validates_length_of :name, :host, :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
+  validates_length_of :name, :maximum => 60
 
   def authenticate(login, password)
   end
index a438bd3c7ba9165be384de6421d752b2d89df117..655ffd6d544d1217afb8c2c404c272c0edfc2dd0 100644 (file)
@@ -20,7 +20,10 @@ require 'iconv'
 
 class AuthSourceLdap < AuthSource 
   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
     self.port = 389 if self.port == 0
index 55fe3ac0d446046de4af2ddbc34c4254a447bd99..5a839721cecf93843397aeb450c85f54e30a68e5 100644 (file)
@@ -103,19 +103,16 @@ class User < ActiveRecord::Base
       # user is not yet registered, try to authenticate with available sources
       attrs = AuthSource.authenticate(login, password)
       if attrs
-        onthefly = new(*attrs)
-        onthefly.login = login
-        onthefly.language = Setting.default_language
-        if onthefly.save
-          user = find(:first, :conditions => ["login=?", login])
+        user = new(*attrs)
+        user.login = login
+        user.language = Setting.default_language
+        if user.save
+          user.reload
           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    
-    user.update_attribute(:last_login_on, Time.now) if user
+    user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
     user
   rescue => text
     raise text
index 4e2b5adf2ace87c5ed0077886b1258188c9c9381..755a7ad4b12f08d9373a202863314bced47540f4 100644 (file)
@@ -5,8 +5,9 @@
 
 <div class="box">
 <!--[form:user]-->
+<% if @user.auth_source_id.nil? %>
 <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>
 
 <p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
 <%= password_field_tag 'password', nil, :size => 25  %><br />
@@ -14,6 +15,7 @@
 
 <p><label for="password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
 <%= password_field_tag 'password_confirmation', nil, :size => 25  %></p>
+<% end %>
 
 <p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label>
 <%= text_field 'user', 'firstname'  %></p>
index 3d148c11f744f5020ebb14adadaa54e142466bed..9ffffafc711df25871b3b03f81d128931584334b 100644 (file)
 
 <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>
-</div>
 
-<div class="box">
 <p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
 <%= check_box 'auth_source', 'onthefly_register' %></p>
+</div>
 
-<p>
-<fieldset><legend><%=l(:label_attribute_plural)%></legend>
+<fieldset class="box"><legend><%=l(:label_attribute_plural)%></legend>
 <p><label for="auth_source_attr_login"><%=l(:field_login)%> <span class="required">*</span></label>
 <%= text_field 'auth_source', 'attr_login', :size => 20  %></p>
 
@@ -42,7 +40,5 @@
 <p><label for="auth_source_attr_mail"><%=l(:field_mail)%></label>
 <%= text_field 'auth_source', 'attr_mail', :size => 20  %></p>
 </fieldset>
-</p>
-</div>
 <!--[eoform:auth_source]-->
 
index a01a3ba09a668c19b8bb22e043b3125ce2c081a3..c349200d3f7fa3e5856f964dff2d7a2ab91a33e3 100644 (file)
 
 require "#{File.dirname(__FILE__)}/../test_helper"
 
+begin
+  require 'mocha'
+rescue
+  # Won't run some tests
+end
+
 class AccountTest < ActionController::IntegrationTest
   fixtures :users
 
@@ -102,4 +108,46 @@ class AccountTest < ActionController::IntegrationTest
     assert_redirected_to 'account/login'
     log_user('newuser', 'newpass')
   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