ucb_ldap 2.0.0.pre1 → 2.0.0.pre3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/CHANGELOG +137 -135
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/{README → README.md} +82 -80
- data/Rakefile +38 -20
- data/lib/ucb_ldap.rb +238 -204
- data/lib/{ucb_ldap_address.rb → ucb_ldap/address.rb} +106 -106
- data/lib/{ucb_ldap_affiliation.rb → ucb_ldap/affiliation.rb} +16 -16
- data/lib/{ucb_ldap_entry.rb → ucb_ldap/entry.rb} +455 -448
- data/lib/{ucb_ldap_person_job_appointment.rb → ucb_ldap/job_appointment.rb} +77 -79
- data/lib/{ucb_ldap_namespace.rb → ucb_ldap/namespace.rb} +40 -50
- data/lib/{ucb_ldap_org.rb → ucb_ldap/org.rb} +427 -429
- data/lib/{ucb_ldap_person.rb → ucb_ldap/person.rb} +157 -148
- data/lib/{person → ucb_ldap/person}/affiliation_methods.rb +23 -22
- data/lib/ucb_ldap/person/common_attributes.rb +63 -0
- data/lib/{ucb_ldap_schema.rb → ucb_ldap/schema.rb} +28 -28
- data/lib/{ucb_ldap_schema_attribute.rb → ucb_ldap/schema_attribute.rb} +152 -153
- data/lib/{ucb_ldap_service.rb → ucb_ldap/service.rb} +17 -19
- data/lib/{ucb_ldap_student_term.rb → ucb_ldap/student_term.rb} +29 -31
- data/lib/ucb_ldap/version.rb +3 -0
- data/spec/rails_binds.yml +9 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/ucb_ldap/address_spec.rb +54 -0
- data/spec/ucb_ldap/affiliation_spec.rb +85 -0
- data/spec/ucb_ldap/entry_spec.rb +241 -0
- data/spec/ucb_ldap/job_appointment_spec.rb +65 -0
- data/spec/ucb_ldap/namespace_spec.rb +72 -0
- data/spec/ucb_ldap/org_spec.rb +217 -0
- data/spec/ucb_ldap/person_spec.rb +225 -0
- data/spec/ucb_ldap/schema_attribute_spec.rb +122 -0
- data/spec/ucb_ldap/schema_spec.rb +104 -0
- data/spec/ucb_ldap/service_spec.rb +127 -0
- data/spec/ucb_ldap/student_term_spec.rb +121 -0
- data/spec/ucb_ldap_spec.rb +182 -0
- data/ucb_ldap.gemspec +20 -27
- metadata +113 -64
- data/Manifest +0 -23
- data/TODO +0 -2
- data/lib/person/adv_con_person.rb +0 -0
- data/lib/person/generic_attributes.rb +0 -68
- data/lib/ucb_ldap_exceptions.rb +0 -27
- data/version.yml +0 -1
data/Rakefile
CHANGED
@@ -1,20 +1,38 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
require 'bundler/setup'
|
6
|
+
rescue LoadError => e
|
7
|
+
require('rubygems') && retry
|
8
|
+
puts "Please `gem install bundler' and run `bundle install' to ensure you have all dependencies"
|
9
|
+
raise e
|
10
|
+
end
|
11
|
+
|
12
|
+
Bundler::GemHelper.install_tasks
|
13
|
+
|
14
|
+
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
17
|
+
t.rspec_opts = ['--color', "--format documentation"]
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Update schema file"
|
21
|
+
task :update_schema_file do
|
22
|
+
print 'rebuilding schema file ... '
|
23
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
24
|
+
require 'ucb_ldap'
|
25
|
+
include UCB::LDAP
|
26
|
+
File.open(Schema.schema_file, "w") do |file|
|
27
|
+
file.print Schema.yaml_from_url
|
28
|
+
end
|
29
|
+
puts 'done'
|
30
|
+
end
|
31
|
+
task :package => :update_schema_file
|
32
|
+
task :repackage => :update_schema_file
|
33
|
+
|
34
|
+
|
35
|
+
#desc "Performance tests"
|
36
|
+
#task :perf do
|
37
|
+
# require 'test/performance/_run_all'
|
38
|
+
#end
|
data/lib/ucb_ldap.rb
CHANGED
@@ -1,204 +1,238 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'net/ldap'
|
3
|
-
require 'time'
|
4
|
-
|
5
|
-
require
|
6
|
-
require '
|
7
|
-
require '
|
8
|
-
|
9
|
-
require 'person
|
10
|
-
require '
|
11
|
-
require '
|
12
|
-
|
13
|
-
require '
|
14
|
-
require '
|
15
|
-
require '
|
16
|
-
require '
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
#
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
def
|
97
|
-
@
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
#
|
106
|
-
|
107
|
-
#
|
108
|
-
#
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
#
|
145
|
-
#
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
#
|
154
|
-
#
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'net/ldap'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
require "ucb_ldap/version"
|
6
|
+
require 'ucb_ldap/schema'
|
7
|
+
require 'ucb_ldap/schema_attribute'
|
8
|
+
require 'ucb_ldap/entry'
|
9
|
+
require 'ucb_ldap/person'
|
10
|
+
require 'ucb_ldap/job_appointment'
|
11
|
+
require 'ucb_ldap/org'
|
12
|
+
require 'ucb_ldap/namespace'
|
13
|
+
require 'ucb_ldap/address'
|
14
|
+
require 'ucb_ldap/student_term'
|
15
|
+
require 'ucb_ldap/affiliation'
|
16
|
+
require 'ucb_ldap/service'
|
17
|
+
|
18
|
+
|
19
|
+
module UCB
|
20
|
+
#:nodoc:
|
21
|
+
#
|
22
|
+
# =UCB::LDAP
|
23
|
+
#
|
24
|
+
# <b>If you are doing searches that don't require a privileged bind
|
25
|
+
# and are accessing the default (production) server
|
26
|
+
# you probably don't need to call any of the methods in this module.</b>
|
27
|
+
#
|
28
|
+
# Methods in this module are about making <em>connections</em>
|
29
|
+
# to the LDAP directory.
|
30
|
+
#
|
31
|
+
# Interaction with the directory (searches and updates) is usually through the search()
|
32
|
+
# and other methods of UCB::LDAP::Entry and its sub-classes.
|
33
|
+
#
|
34
|
+
module LDAP
|
35
|
+
|
36
|
+
BadAttributeNameException = Class.new(Exception) #:nodoc:
|
37
|
+
|
38
|
+
class BindFailedException < Exception #:nodoc:
|
39
|
+
def initialize
|
40
|
+
super("Failed to bind username '#{UCB::LDAP.username}' to '#{UCB::LDAP.host}'")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ConnectionFailedException < Exception #:nodoc:
|
45
|
+
def initialize
|
46
|
+
super("Failed to connect to ldap host '#{UCB::LDAP.host}''")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class DirectoryNotUpdatedException < Exception #:nodoc:
|
51
|
+
def initialize
|
52
|
+
result = UCB::LDAP.net_ldap.get_operation_result
|
53
|
+
super("(Code=#{result.code}) #{result.message}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
HOST_PRODUCTION = 'nds.berkeley.edu'
|
59
|
+
HOST_TEST = 'nds-test.berkeley.edu'
|
60
|
+
|
61
|
+
class << self
|
62
|
+
# Execute UCB::LDAP commands with a different username and password.
|
63
|
+
# Original credentials are restored.
|
64
|
+
def with_credentials(username_to_use, password_to_use)
|
65
|
+
original_username = username
|
66
|
+
original_password = password
|
67
|
+
|
68
|
+
UCB::LDAP.authenticate(username_to_use, password_to_use)
|
69
|
+
|
70
|
+
yield
|
71
|
+
ensure
|
72
|
+
UCB::LDAP.authenticate(original_username, original_password)
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Give (new) bind credentials to LDAP. An attempt will be made
|
77
|
+
# to bind and will raise BindFailedException if bind fails.
|
78
|
+
#
|
79
|
+
# Call clear_authentication() to remove privileged bind.
|
80
|
+
#
|
81
|
+
def authenticate(username, password)
|
82
|
+
@username, @password = username, password
|
83
|
+
new_net_ldap() # to force bind()
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Removes current bind (username, password).
|
88
|
+
#
|
89
|
+
def clear_authentication
|
90
|
+
authenticate(nil, nil)
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Returns LDAP host used for lookups. Default is HOST_PRODUCTION.
|
95
|
+
#
|
96
|
+
def host
|
97
|
+
@host || HOST_PRODUCTION
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Setter for #host.
|
102
|
+
#
|
103
|
+
# Note: validation of host is deferred until a search is performed
|
104
|
+
# or #authenticate() is called at which time a bad host will
|
105
|
+
# raise ConnectionFailedException.
|
106
|
+
#---
|
107
|
+
# Don't want to reconnect unless host really changed.
|
108
|
+
#
|
109
|
+
def host=(host)
|
110
|
+
if host != @host
|
111
|
+
@host = host
|
112
|
+
@net_ldap = nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Returns Net::LDAP instance that is used by UCB::LDAP::Entry
|
118
|
+
# and subclasses for directory searches.
|
119
|
+
#
|
120
|
+
# You might need this to perform searches not supported by
|
121
|
+
# sub-classes of Entry.
|
122
|
+
#
|
123
|
+
# Note: callers should not cache the results of this call unless they
|
124
|
+
# are prepared to handle timed-out connections (which this method does).
|
125
|
+
#
|
126
|
+
def net_ldap
|
127
|
+
@net_ldap ||= new_net_ldap
|
128
|
+
end
|
129
|
+
|
130
|
+
def password #:nodoc:
|
131
|
+
@password
|
132
|
+
end
|
133
|
+
|
134
|
+
def username #:nodoc:
|
135
|
+
@username
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# If you are using UCB::LDAP in a Rails application you can specify binds on a
|
140
|
+
# per-environment basis, just as you can with database credentials.
|
141
|
+
#
|
142
|
+
# # in ../config/ldap.yml
|
143
|
+
#
|
144
|
+
# development:
|
145
|
+
# username: user_dev
|
146
|
+
# password: pass_dev
|
147
|
+
#
|
148
|
+
# # etc.
|
149
|
+
#
|
150
|
+
#
|
151
|
+
# # in ../config/environment.rb
|
152
|
+
#
|
153
|
+
# require 'ucb_ldap'
|
154
|
+
# UCB::LDAP.bind_for_rails()
|
155
|
+
#
|
156
|
+
# Runtime error will be raised if bind_file not found or if environment key not
|
157
|
+
# found in bind_file.
|
158
|
+
#
|
159
|
+
def bind_for_rails(bind_file = "#{Rails.root}/config/ldap.yml", environment = Rails.env)
|
160
|
+
bind(bind_file, environment)
|
161
|
+
end
|
162
|
+
|
163
|
+
def bind(bind_file, environment)
|
164
|
+
raise "Can't find bind file: #{bind_file}" unless FileTest.exists?(bind_file)
|
165
|
+
binds = YAML.load(IO.read(bind_file))
|
166
|
+
bind = binds[environment] || raise("Can't find environment=#{environment} in bind file")
|
167
|
+
authenticate(bind['username'], bind['password'])
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# Returns +arg+ as a Ruby +Date+ in local time zone. Returns +nil+ if +arg+ is +nil+.
|
172
|
+
#
|
173
|
+
def local_date_parse(arg)
|
174
|
+
arg.nil? ? nil : Date.parse(Time.parse(arg.to_s).localtime.to_s)
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# Returns +arg+ as a Ruby +DateTime+ in local time zone. Returns +nil+ if +arg+ is +nil+.
|
179
|
+
#
|
180
|
+
def local_datetime_parse(arg)
|
181
|
+
arg.nil? ? nil : DateTime.parse(Time.parse(arg.to_s).localtime.to_s)
|
182
|
+
end
|
183
|
+
|
184
|
+
## TODO: restore private
|
185
|
+
# private unless $TESTING
|
186
|
+
|
187
|
+
##
|
188
|
+
# The value of the :auth parameter for Net::LDAP.new.
|
189
|
+
#
|
190
|
+
def authentication_information
|
191
|
+
password.nil? ?
|
192
|
+
{ :method => :anonymous } :
|
193
|
+
{ :method => :simple, :username => username, :password => password }
|
194
|
+
end
|
195
|
+
|
196
|
+
##
|
197
|
+
# Returns +true+ if connection simple search works.
|
198
|
+
#
|
199
|
+
def ldap_ping
|
200
|
+
search_attrs = {
|
201
|
+
:base => "",
|
202
|
+
:scope => Net::LDAP::SearchScope_BaseObject,
|
203
|
+
:attributes => [1.1]
|
204
|
+
}
|
205
|
+
result = false
|
206
|
+
@net_ldap.search(search_attrs) { result = true }
|
207
|
+
result
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# Returns new Net::LDAP instance.
|
212
|
+
#
|
213
|
+
def new_net_ldap
|
214
|
+
params = {
|
215
|
+
:host => host,
|
216
|
+
:auth => authentication_information,
|
217
|
+
:port => 636,
|
218
|
+
:encryption => { :method => :simple_tls }
|
219
|
+
}
|
220
|
+
@net_ldap = Net::LDAP.new(params)
|
221
|
+
@net_ldap.bind || raise(BindFailedException)
|
222
|
+
@net_ldap
|
223
|
+
rescue Net::LDAP::LdapError => e
|
224
|
+
raise(BindFailedException)
|
225
|
+
end
|
226
|
+
|
227
|
+
##
|
228
|
+
# Used for testing
|
229
|
+
#
|
230
|
+
def clear_instance_variables
|
231
|
+
@host = nil
|
232
|
+
@net_ldap = nil
|
233
|
+
@username = nil
|
234
|
+
@password = nil
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|