### Eclipse Workspace Patch 1.0
#P redmine
Index: app/views/auth_sources/_form.rhtml
===================================================================
--- app/views/auth_sources/_form.rhtml (revision 1725)
+++ app/views/auth_sources/_form.rhtml (working copy)
@@ -23,6 +23,9 @@
<%= text_field 'auth_source', 'base_dn', :size => 60 %>
+
+<%= text_field 'auth_source', 'user_filter', :size => 60 %>
+
<%= check_box 'auth_source', 'onthefly_register' %>
Index: app/views/auth_sources/list.rhtml
===================================================================
--- app/views/auth_sources/list.rhtml (revision 1725)
+++ app/views/auth_sources/list.rhtml (working copy)
@@ -19,6 +19,7 @@
<%= source.auth_method_name %> |
<%= source.host %> |
<%= link_to l(:button_test), :action => 'test_connection', :id => source %> |
+ <%= link_to l(:button_import_ldap), :action => 'import', :id => source %> |
<%= button_to l(:button_delete), { :action => 'destroy', :id => source }, :confirm => l(:text_are_you_sure), :class => "button-small" %> |
<% end %>
Index: app/controllers/auth_sources_controller.rb
===================================================================
--- app/controllers/auth_sources_controller.rb (revision 1725)
+++ app/controllers/auth_sources_controller.rb (working copy)
@@ -61,10 +61,22 @@
end
end
+ def import
+ @auth_source = AuthSource.find(params[:id])
+ begin
+ result = @auth_source.import
+ msg = "Found #{result[:found]} users, imported #{result[:imported]}, skipped: #{result[:skipped].join ', '}"
+ flash[:notice] = l(msg)
+ rescue => err
+ flash[:error] = "Unable to import (#{err})"
+ end
+ redirect_to :action => 'list'
+ end
+
def test_connection
- @auth_method = AuthSource.find(params[:id])
+ @auth_source = AuthSource.find(params[:id])
begin
- @auth_method.test_connection
+ @auth_source.test_connection
flash[:notice] = l(:notice_successful_connection)
rescue => text
flash[:error] = "Unable to connect (#{text})"
Index: lang/en.yml
===================================================================
--- lang/en.yml (revision 1725)
+++ lang/en.yml (working copy)
@@ -560,6 +562,7 @@
button_annotate: Annotate
button_update: Update
button_configure: Configure
+button_import_ldap: Bulk import
status_active: active
status_registered: registered
Index: db/migrate/096_add_auth_sources_user_filter.rb
===================================================================
--- db/migrate/096_add_auth_sources_user_filter.rb (revision 0)
+++ db/migrate/096_add_auth_sources_user_filter.rb (revision 0)
@@ -0,0 +1,9 @@
+class AddAuthSourcesUserFilter < ActiveRecord::Migration
+ def self.up
+ add_column :auth_sources, :user_filter, :string, :default => '(objectClass=*)', :null => true
+ end
+
+ def self.down
+ remove_column :auth_sources, :user_filter
+ end
+end
Index: app/models/auth_source.rb
===================================================================
--- app/models/auth_source.rb (revision 1725)
+++ app/models/auth_source.rb (working copy)
@@ -32,6 +32,12 @@
"Abstract"
end
+ def import
+ # bulk create AR User classes from auth_source so
+ # users from external auth sources don't need to login
+ # just to be visible in the UI
+ end
+
# Try to authenticate a user not yet registered against available sources
def self.authenticate(login, password)
AuthSource.find(:all, :conditions => ["onthefly_register=?", true]).each do |source|
Index: app/models/auth_source_ldap.rb
===================================================================
--- app/models/auth_source_ldap.rb (revision 1725)
+++ app/models/auth_source_ldap.rb (working copy)
@@ -21,7 +21,7 @@
class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login
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 :account, :base_dn, :user_filter, :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
@@ -59,6 +59,69 @@
raise "LdapError: " + text
end
+ def import
+ ldap_con = initialize_ldap_con(self.account, self.account_password)
+ if self.user_filter
+ search_filter = self.user_filter
+ else
+ search_filter = Net::LDAP::Filter.eq("objectClass", "*")
+ end
+ found = created = 0
+ skipped = []
+ ldap_con.search(
+ :base => self.base_dn,
+ :filter => search_filter,
+ :attributes => ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail, self.attr_login]
+ ) do | entry |
+ logger.debug("Found entry with DN: #{entry.dn}") if logger
+ found += 1
+ skip = false
+ attrs = [:firstname => (AuthSourceLdap.get_attr(entry, self.attr_firstname) != nil ? \
+ AuthSourceLdap.get_attr(entry, self.attr_firstname) : "Unknown"),
+ :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
+ :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
+ :auth_source_id => self.id ]
+ #sanity checking (all the above attributes are required)
+ login = AuthSourceLdap.get_attr(entry, self.attr_login)
+ catch :SKIP do
+ skip = false
+ attrs.each { |e|
+ e.each { |k, v|
+ if v == nil
+ # give the admin a clue why importing failed...
+ logger.debug("User #{login} misses value for attribute '#{k}'.")
+ skipped.push(login+"(missing attribute '#{k}')")
+ skip = true
+ throw :SKIP
+ end
+ }
+ }
+ end
+ next if skip
+ if User.find(:first, :conditions => ["login=?", login])
+ logger.debug("User #{login} already there, skipping...") if logger
+ skipped.push(login+'(exists)')
+ next
+ end
+
+ #create user
+ begin
+ logger.debug("Trying to create user with attrs: %s" % attrs.to_s) if logger
+ u = User.create(*attrs)
+ u.login = login
+ u.language = Setting.default_language
+ if u.save
+ created += 1
+ else
+ skipped.push(login+'(add failed)')
+ end
+ end
+ end
+ logger.info("Found #{found} users, imported #{created}.")
+ logger.info("Skipped users: #{skipped.join(" ")}")
+ return {:found => found, :imported => created, :skipped => skipped}
+ end
+
# test the connection to the LDAP
def test_connection
ldap_con = initialize_ldap_con(self.account, self.account_password)