Project

General

Profile

Feature #1838 » bulk_import_ldap2.patch

bulk import patch - paul k, 2008-09-01 11:35

View differences:

app/views/auth_sources/_form.rhtml (working copy)
23 23
<p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label>
24 24
<%= text_field 'auth_source', 'base_dn', :size => 60 %></p>
25 25

  
26
<p><label for="auth_source_user_filter"><%=l(:field_user_filter)%></label>
27
<%= text_field 'auth_source', 'user_filter', :size => 60 %></p>
28

  
26 29
<p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
27 30
<%= check_box 'auth_source', 'onthefly_register' %></p>
28 31
</div>
app/views/auth_sources/list.rhtml (working copy)
19 19
    <td align="center"><%= source.auth_method_name %></td>
20 20
    <td align="center"><%= source.host %></td>    
21 21
    <td align="center"><%= link_to l(:button_test), :action => 'test_connection', :id => source %></td>
22
	 <td align="center"><%= link_to l(:button_import_ldap), :action => 'import', :id => source %></td>
22 23
    <td align="center"><%= button_to l(:button_delete), { :action => 'destroy', :id => source }, :confirm => l(:text_are_you_sure), :class => "button-small" %></td>
23 24
  </tr>
24 25
<% end %>
app/controllers/auth_sources_controller.rb (working copy)
61 61
    end
62 62
  end
63 63
  
64
  def import
65
    @auth_source = AuthSource.find(params[:id])
66
    begin
67
      result = @auth_source.import
68
      msg = "Found #{result[:found]} users, imported #{result[:imported]}, skipped: #{result[:skipped].join ', '}"
69
      flash[:notice] = l(msg)
70
    rescue => err
71
      flash[:error] = "Unable to import (#{err})"
72
    end
73
    redirect_to :action => 'list'
74
  end
75
  
64 76
  def test_connection
65
    @auth_method = AuthSource.find(params[:id])
77
    @auth_source = AuthSource.find(params[:id])
66 78
    begin
67
      @auth_method.test_connection
79
      @auth_source.test_connection
68 80
      flash[:notice] = l(:notice_successful_connection)
69 81
    rescue => text
70 82
      flash[:error] = "Unable to connect (#{text})"
lang/en.yml (working copy)
560 562
button_annotate: Annotate
561 563
button_update: Update
562 564
button_configure: Configure
565
button_import_ldap: Bulk import
563 566

  
564 567
status_active: active
565 568
status_registered: registered
db/migrate/096_add_auth_sources_user_filter.rb (revision 0)
1
class AddAuthSourcesUserFilter < ActiveRecord::Migration
2
  def self.up
3
    add_column :auth_sources, :user_filter, :string, :default => '(objectClass=*)', :null => true
4
  end
5

  
6
  def self.down
7
    remove_column :auth_sources, :user_filter
8
  end
9
end
app/models/auth_source.rb (working copy)
32 32
    "Abstract"
33 33
  end
34 34

  
35
  def import
36
    # bulk create AR User classes from auth_source so
37
    # users from external auth sources don't need to login
38
    # just to be visible in the UI
39
  end
40
  
35 41
  # Try to authenticate a user not yet registered against available sources
36 42
  def self.authenticate(login, password)
37 43
    AuthSource.find(:all, :conditions => ["onthefly_register=?", true]).each do |source|
app/models/auth_source_ldap.rb (working copy)
21 21
class AuthSourceLdap < AuthSource 
22 22
  validates_presence_of :host, :port, :attr_login
23 23
  validates_length_of :name, :host, :account_password, :maximum => 60, :allow_nil => true
24
  validates_length_of :account, :base_dn, :maximum => 255, :allow_nil => true
24
  validates_length_of :account, :base_dn, :user_filter, :maximum => 255, :allow_nil => true
25 25
  validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
26 26
  validates_numericality_of :port, :only_integer => true
27 27
  
......
59 59
    raise "LdapError: " + text
60 60
  end
61 61

  
62
  def import
63
    ldap_con = initialize_ldap_con(self.account, self.account_password)
64
    if self.user_filter
65
      search_filter = self.user_filter 
66
    else
67
      search_filter = Net::LDAP::Filter.eq("objectClass", "*")
68
    end
69
    found = created = 0
70
    skipped = []
71
    ldap_con.search(
72
        :base => self.base_dn,
73
        :filter => search_filter,
74
        :attributes => ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail, self.attr_login]
75
        ) do | entry |
76
            logger.debug("Found entry with DN: #{entry.dn}") if logger
77
            found += 1
78
            skip = false
79
            attrs = [:firstname => (AuthSourceLdap.get_attr(entry, self.attr_firstname) != nil ? \
80
                                    AuthSourceLdap.get_attr(entry, self.attr_firstname) : "Unknown"),
81
                     :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
82
                     :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
83
                     :auth_source_id => self.id ]
84
            #sanity checking (all the above attributes are required)
85
            login = AuthSourceLdap.get_attr(entry, self.attr_login)
86
            catch :SKIP do
87
              skip = false
88
              attrs.each { |e| 
89
                e.each { |k, v|
90
                  if v == nil
91
                    # give the admin a clue why importing failed...
92
                    logger.debug("User #{login} misses value for attribute '#{k}'.")
93
                    skipped.push(login+"(missing attribute '#{k}')")
94
                    skip = true
95
                    throw :SKIP
96
                  end
97
                }
98
              }
99
            end
100
            next if skip
101
            if User.find(:first, :conditions => ["login=?", login])
102
              logger.debug("User #{login} already there, skipping...") if logger
103
              skipped.push(login+'(exists)')
104
              next
105
            end
106
         
107
            #create user
108
            begin
109
              logger.debug("Trying to create user with attrs: %s" % attrs.to_s) if logger
110
              u = User.create(*attrs)
111
              u.login = login
112
              u.language = Setting.default_language
113
              if u.save
114
                created += 1
115
              else
116
                skipped.push(login+'(add failed)')
117
              end
118
            end
119
        end
120
        logger.info("Found #{found} users, imported #{created}.")
121
        logger.info("Skipped users: #{skipped.join(" ")}")
122
        return {:found => found, :imported => created, :skipped => skipped}
123
  end
124
  
62 125
  # test the connection to the LDAP
63 126
  def test_connection
64 127
    ldap_con = initialize_ldap_con(self.account, self.account_password)
(2-2/6)