activeldap 1.2.4 → 3.1.0

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.
Files changed (45) hide show
  1. data/Gemfile +18 -0
  2. data/LICENSE +2 -1
  3. data/README.textile +137 -0
  4. data/doc/text/development.textile +50 -0
  5. data/{CHANGES → doc/text/news.textile} +256 -237
  6. data/doc/text/rails.textile +144 -0
  7. data/doc/text/tutorial.textile +1005 -0
  8. data/lib/active_ldap/adapter/base.rb +5 -3
  9. data/lib/active_ldap/adapter/net_ldap_ext.rb +1 -1
  10. data/lib/active_ldap/associations.rb +6 -2
  11. data/lib/active_ldap/base.rb +16 -71
  12. data/lib/active_ldap/callbacks.rb +52 -33
  13. data/lib/active_ldap/configuration.rb +2 -2
  14. data/lib/active_ldap/get_text/parser.rb +2 -2
  15. data/lib/active_ldap/human_readable.rb +5 -4
  16. data/lib/active_ldap/log_subscriber.rb +50 -0
  17. data/lib/active_ldap/persistence.rb +65 -0
  18. data/lib/active_ldap/railtie.rb +40 -0
  19. data/lib/active_ldap/railties/controller_runtime.rb +48 -0
  20. data/lib/active_ldap/user_password.rb +1 -0
  21. data/lib/active_ldap/validations.rb +34 -72
  22. data/lib/active_ldap.rb +13 -912
  23. data/{rails_generators/model_active_ldap → lib/rails/generators/active_ldap/model}/USAGE +2 -1
  24. data/lib/rails/generators/active_ldap/model/model_generator.rb +47 -0
  25. data/{rails_generators/model_active_ldap → lib/rails/generators/active_ldap/model}/templates/model_active_ldap.rb +0 -0
  26. data/lib/rails/generators/active_ldap/scaffold/scaffold_generator.rb +14 -0
  27. data/{rails_generators/scaffold_active_ldap → lib/rails/generators/active_ldap/scaffold}/templates/ldap.yml +1 -0
  28. data/test/test_base.rb +9 -0
  29. data/test/test_callback.rb +2 -6
  30. data/test/test_connection.rb +2 -2
  31. data/test/test_user.rb +2 -2
  32. data/test/test_validation.rb +11 -11
  33. metadata +165 -106
  34. data/README +0 -155
  35. data/Rakefile +0 -133
  36. data/rails/README +0 -54
  37. data/rails/init.rb +0 -33
  38. data/rails_generators/model_active_ldap/model_active_ldap_generator.rb +0 -69
  39. data/rails_generators/model_active_ldap/templates/unit_test.rb +0 -8
  40. data/rails_generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +0 -7
  41. data/test/al-test-utils.rb +0 -439
  42. data/test/command.rb +0 -112
  43. data/test/config.yaml.sample +0 -6
  44. data/test/fixtures/lower_case_object_class_schema.rb +0 -802
  45. data/test/run-test.rb +0 -44
@@ -1,439 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'erb'
4
- require 'yaml'
5
- require 'socket'
6
- require 'rbconfig'
7
- require 'tempfile'
8
-
9
- require 'active_ldap'
10
-
11
- require File.join(File.expand_path(File.dirname(__FILE__)), "command")
12
-
13
- LDAP_ENV = "test" unless defined?(LDAP_ENV)
14
-
15
- module AlTestUtils
16
- def self.included(base)
17
- base.class_eval do
18
- include ActiveLdap::GetTextSupport
19
- include Utilities
20
- include Assertions
21
- include Config
22
- include Connection
23
- include Populate
24
- include TemporaryEntry
25
- include CommandSupport
26
- include MockLogger
27
- end
28
- end
29
-
30
- module Utilities
31
- def dn(string)
32
- ActiveLdap::DN.parse(string)
33
- end
34
- end
35
-
36
- module Assertions
37
- def assert_true(actual, *args)
38
- assert_equal(true, actual, *args)
39
- end
40
-
41
- def assert_false(actual, *args)
42
- assert_equal(false, actual, *args)
43
- end
44
- end
45
-
46
- module Config
47
- def setup
48
- super
49
- @base_dir = File.expand_path(File.dirname(__FILE__))
50
- @top_dir = File.expand_path(File.join(@base_dir, ".."))
51
- @example_dir = File.join(@top_dir, "examples")
52
- @fixtures_dir = File.join(@base_dir, "fixtures")
53
- @config_file = File.join(@base_dir, "config.yaml")
54
- ActiveLdap::Base.configurations = read_config
55
- end
56
-
57
- def teardown
58
- super
59
- end
60
-
61
- def current_configuration
62
- ActiveLdap::Base.configurations[LDAP_ENV]
63
- end
64
-
65
- def read_config
66
- unless File.exist?(@config_file)
67
- raise "config file for testing doesn't exist: #{@config_file}"
68
- end
69
- erb = ERB.new(File.read(@config_file))
70
- erb.filename = @config_file
71
- config = YAML.load(erb.result)
72
- _adapter = adapter
73
- config.each do |key, value|
74
- value[:adapter] = _adapter if _adapter
75
- end
76
- config
77
- end
78
-
79
- def adapter
80
- ENV["ACTIVE_LDAP_TEST_ADAPTER"]
81
- end
82
-
83
- def fixture(*components)
84
- File.join(@fixtures_dir, *components)
85
- end
86
- end
87
-
88
- module ExampleFile
89
- def certificate_path
90
- File.join(@example_dir, 'example.der')
91
- end
92
-
93
- @@certificate = nil
94
- def certificate
95
- return @@certificate if @@certificate
96
- if File.exists?(certificate_path)
97
- @@certificate = read_binary_file(certificate_path)
98
- return @@certificate
99
- end
100
-
101
- require 'openssl'
102
- rsa = OpenSSL::PKey::RSA.new(512)
103
- comment = "Generated by Ruby/OpenSSL"
104
-
105
- cert = OpenSSL::X509::Certificate.new
106
- cert.version = 3
107
- cert.serial = 0
108
- subject = [["OU", "test"],
109
- ["CN", Socket.gethostname]]
110
- name = OpenSSL::X509::Name.new(subject)
111
- cert.subject = name
112
- cert.issuer = name
113
- cert.not_before = Time.now
114
- cert.not_after = Time.now + (365*24*60*60)
115
- cert.public_key = rsa.public_key
116
-
117
- ef = OpenSSL::X509::ExtensionFactory.new(nil, cert)
118
- ef.issuer_certificate = cert
119
- cert.extensions = [
120
- ef.create_extension("basicConstraints","CA:FALSE"),
121
- ef.create_extension("keyUsage", "keyEncipherment"),
122
- ef.create_extension("subjectKeyIdentifier", "hash"),
123
- ef.create_extension("extendedKeyUsage", "serverAuth"),
124
- ef.create_extension("nsComment", comment),
125
- ]
126
- aki = ef.create_extension("authorityKeyIdentifier",
127
- "keyid:always,issuer:always")
128
- cert.add_extension(aki)
129
- cert.sign(rsa, OpenSSL::Digest::SHA1.new)
130
-
131
- @@certificate = cert.to_der
132
- @@certificate
133
- end
134
-
135
- def jpeg_photo_path
136
- File.join(@example_dir, 'example.jpg')
137
- end
138
-
139
- def jpeg_photo
140
- read_binary_file(jpeg_photo_path)
141
- end
142
-
143
- def read_binary_file(path)
144
- File.open(path, "rb") do |input|
145
- input.set_encoding("ascii-8bit") if input.respond_to?(:set_encoding)
146
- input.read
147
- end
148
- end
149
- end
150
-
151
- module Connection
152
- def setup
153
- super
154
- ActiveLdap::Base.setup_connection
155
- end
156
-
157
- def teardown
158
- ActiveLdap::Base.remove_active_connections!
159
- super
160
- end
161
- end
162
-
163
- module Populate
164
- def setup
165
- @dumped_data = nil
166
- super
167
- begin
168
- @dumped_data = ActiveLdap::Base.dump(:scope => :sub)
169
- rescue ActiveLdap::ConnectionError
170
- end
171
- ActiveLdap::Base.delete_all(nil, :scope => :sub)
172
- populate
173
- end
174
-
175
- def teardown
176
- if @dumped_data
177
- ActiveLdap::Base.setup_connection
178
- ActiveLdap::Base.delete_all(nil, :scope => :sub)
179
- ActiveLdap::Base.load(@dumped_data)
180
- end
181
- super
182
- end
183
-
184
- def populate
185
- populate_base
186
- populate_ou
187
- populate_user_class
188
- populate_group_class
189
- populate_associations
190
- populate_get_text_fix
191
- end
192
-
193
- def populate_base
194
- ActiveLdap::Populate.ensure_base
195
- end
196
-
197
- def ou_class(prefix="")
198
- ou_class = Class.new(ActiveLdap::Base)
199
- ou_class.ldap_mapping(:dn_attribute => "ou",
200
- :prefix => prefix,
201
- :classes => ["top", "organizationalUnit"])
202
- ou_class
203
- end
204
-
205
- def dc_class(prefix="")
206
- dc_class = Class.new(ActiveLdap::Base)
207
- dc_class.ldap_mapping(:dn_attribute => "dc",
208
- :prefix => prefix,
209
- :classes => ["top", "dcObject", "organization"])
210
- dc_class
211
- end
212
-
213
- def entry_class(prefix="")
214
- entry_class = Class.new(ActiveLdap::Base)
215
- entry_class.ldap_mapping(:prefix => prefix,
216
- :scope => :sub,
217
- :classes => ["top"])
218
- entry_class.dn_attribute = nil
219
- entry_class
220
- end
221
-
222
- def populate_ou
223
- %w(Users Groups).each do |name|
224
- make_ou(name)
225
- end
226
- end
227
-
228
- def make_ou(name)
229
- ActiveLdap::Populate.ensure_ou(name)
230
- end
231
-
232
- def make_dc(name)
233
- ActiveLdap::Populate.ensure_dc(name)
234
- end
235
-
236
- def populate_user_class
237
- @user_class = Class.new(ActiveLdap::Base)
238
- @user_class_classes = ["posixAccount", "person"]
239
- @user_class.ldap_mapping :dn_attribute => "uid",
240
- :prefix => "ou=Users",
241
- :scope => :sub,
242
- :classes => @user_class_classes
243
- end
244
-
245
- def populate_group_class
246
- @group_class = Class.new(ActiveLdap::Base)
247
- @group_class.ldap_mapping :prefix => "ou=Groups",
248
- :scope => :sub,
249
- :classes => ["posixGroup"]
250
- end
251
-
252
- def populate_associations
253
- @user_class.belongs_to :groups, :many => "memberUid"
254
- @user_class.belongs_to :primary_group,
255
- :foreign_key => "gidNumber",
256
- :primary_key => "gidNumber"
257
- @group_class.has_many :members, :wrap => "memberUid"
258
- @group_class.has_many :primary_members,
259
- :foreign_key => "gidNumber",
260
- :primary_key => "gidNumber"
261
- @user_class.set_associated_class(:groups, @group_class)
262
- @user_class.set_associated_class(:primary_group, @group_class)
263
- @group_class.set_associated_class(:members, @user_class)
264
- @group_class.set_associated_class(:primary_members, @user_class)
265
- end
266
-
267
- def populate_get_text_fix
268
- return if ActiveLdap.get_text_supported?
269
-
270
- def @user_class.name
271
- "User"
272
- end
273
-
274
- def @group_class.name
275
- "Group"
276
- end
277
- end
278
- end
279
-
280
- module TemporaryEntry
281
- include ExampleFile
282
-
283
- def setup
284
- super
285
- @user_index = 0
286
- @group_index = 0
287
- end
288
-
289
- def make_temporary_user(config={})
290
- @user_index += 1
291
- uid = config[:uid] || "temp-user#{@user_index}"
292
- ensure_delete_user(uid) do
293
- password = config[:password] || "password#{@user_index}"
294
- uid_number = config[:uid_number] || default_uid
295
- gid_number = config[:gid_number] || default_gid
296
- home_directory = config[:home_directory] || "/nonexistent"
297
- see_also = config[:see_also]
298
- _wrap_assertion do
299
- assert(!@user_class.exists?(uid))
300
- assert_raise(ActiveLdap::EntryNotFound) do
301
- @user_class.find(uid).dn
302
- end
303
- user = @user_class.new(uid)
304
- assert(user.new_entry?)
305
- user.cn = user.uid
306
- user.sn = user.uid
307
- user.uid_number = uid_number
308
- user.gid_number = gid_number
309
- user.home_directory = home_directory
310
- user.user_password = ActiveLdap::UserPassword.ssha(password)
311
- user.see_also = see_also
312
- unless config[:simple]
313
- user.add_class('shadowAccount', 'inetOrgPerson',
314
- 'organizationalPerson')
315
- user.user_certificate = certificate
316
- user.jpeg_photo = jpeg_photo
317
- end
318
- user.save
319
- assert(!user.new_entry?)
320
- yield(@user_class.find(user.uid), password)
321
- end
322
- end
323
- end
324
-
325
- def make_temporary_group(config={})
326
- @group_index += 1
327
- cn = config[:cn] || "temp-group#{@group_index}"
328
- ensure_delete_group(cn) do
329
- gid_number = config[:gid_number] || default_gid
330
- _wrap_assertion do
331
- assert(!@group_class.exists?(cn))
332
- assert_raise(ActiveLdap::EntryNotFound) do
333
- @group_class.find(cn)
334
- end
335
- group = @group_class.new(cn)
336
- assert(group.new_entry?)
337
- group.gid_number = gid_number
338
- assert(group.save)
339
- assert(!group.new_entry?)
340
- yield(@group_class.find(group.cn))
341
- end
342
- end
343
- end
344
-
345
- def ensure_delete_user(uid)
346
- yield(uid)
347
- ensure
348
- if @user_class.exists?(uid)
349
- @user_class.search(:value => uid) do |dn, attribute|
350
- @user_class.remove_connection(dn)
351
- @user_class.delete(dn)
352
- end
353
- end
354
- end
355
-
356
- def ensure_delete_group(cn)
357
- yield(cn)
358
- ensure
359
- @group_class.delete(cn) if @group_class.exists?(cn)
360
- end
361
-
362
- def default_uid
363
- "10000#{@user_index}"
364
- end
365
-
366
- def default_gid
367
- "10000#{@group_index}"
368
- end
369
- end
370
-
371
- module CommandSupport
372
- def setup
373
- super
374
- @fakeroot = "fakeroot"
375
- @ruby = File.join(::Config::CONFIG["bindir"],
376
- ::Config::CONFIG["RUBY_INSTALL_NAME"])
377
- @top_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
378
- @examples_dir = File.join(@top_dir, "examples")
379
- @lib_dir = File.join(@top_dir, "lib")
380
- @ruby_args = [
381
- "-I", @examples_dir,
382
- "-I", @lib_dir,
383
- ]
384
- end
385
-
386
- def run_command(*args, &block)
387
- file = Tempfile.new("al-command-support")
388
- file.open
389
- file.puts(ActiveLdap::Base.configurations["test"].to_yaml)
390
- file.close
391
- run_ruby(*[@command, "--config", file.path, *args], &block)
392
- end
393
-
394
- def run_ruby(*ruby_args, &block)
395
- args = [@ruby, *@ruby_args]
396
- args.concat(ruby_args)
397
- Command.run(*args, &block)
398
- end
399
-
400
- def run_ruby_with_fakeroot(*ruby_args, &block)
401
- args = [@fakeroot, @ruby, *@ruby_args]
402
- args.concat(ruby_args)
403
- Command.run(*args, &block)
404
- end
405
- end
406
-
407
- module MockLogger
408
- def make_mock_logger
409
- logger = Object.new
410
- class << logger
411
- def messages(type)
412
- @messages ||= {}
413
- @messages[type] ||= []
414
- @messages[type]
415
- end
416
-
417
- def info(content=nil)
418
- messages(:info) << (block_given? ? yield : content)
419
- end
420
- def warn(content=nil)
421
- messages(:warn) << (block_given? ? yield : content)
422
- end
423
- def error(content=nil)
424
- messages(:error) << (block_given? ? yield : content)
425
- end
426
- end
427
- logger
428
- end
429
-
430
- def with_mock_logger
431
- original_logger = ActiveLdap::Base.logger
432
- mock_logger = make_mock_logger
433
- ActiveLdap::Base.logger = mock_logger
434
- yield(mock_logger)
435
- ensure
436
- ActiveLdap::Base.logger = original_logger
437
- end
438
- end
439
- end
data/test/command.rb DELETED
@@ -1,112 +0,0 @@
1
- require "thread"
2
- require "socket"
3
- require "shellwords"
4
-
5
- module Command
6
- class Error < StandardError
7
- attr_reader :command, :result
8
- def initialize(command, result)
9
- @command = command
10
- @result = result
11
- super("#{command}: #{result}")
12
- end
13
- end
14
-
15
- module_function
16
- def detach_io
17
- require 'fcntl'
18
- [TCPSocket, ::File].each do |c|
19
- ObjectSpace.each_object(c) do |io|
20
- begin
21
- unless io.closed?
22
- io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
23
- end
24
- rescue SystemCallError,IOError => e
25
- end
26
- end
27
- end
28
- end
29
-
30
- def run(cmd, *args, &block)
31
- raise ArgumentError, "command isn't specified" if cmd.nil?
32
- if args.any? {|x| x.nil?}
33
- raise ArgumentError, "args has nil: #{args.inspect}"
34
- end
35
- return java_run(cmd, *args, &block) if Object.respond_to?(:java)
36
- in_r, in_w = IO.pipe
37
- out_r, out_w = IO.pipe
38
- pid = exit_status = nil
39
- Thread.exclusive do
40
- verbose = $VERBOSE
41
- # ruby(>=1.8)'s fork terminates other threads with warning messages
42
- $VERBOSE = nil
43
- pid = fork do
44
- $VERBOSE = verbose
45
- detach_io
46
- out = STDERR.dup
47
- STDIN.reopen(in_r)
48
- in_r.close
49
- STDOUT.reopen(out_w)
50
- STDERR.reopen(out_w)
51
- out_w.close
52
- exec(cmd, *args.collect {|arg| arg.to_s})
53
- exit!(-1)
54
- end
55
- $VERBOSE = verbose
56
- end
57
- yield(out_r, in_w) if block_given?
58
- in_r.close unless in_r.closed?
59
- out_w.close unless out_w.closed?
60
- pid, status = Process.waitpid2(pid)
61
- [status.exited? && status.exitstatus.zero?, out_r.read]
62
- end
63
-
64
- def java_run(cmd, *args, &block)
65
- runtime = java.lang.Runtime.get_runtime
66
- process = runtime.exec([cmd, *args].to_java(:string))
67
- input = JavaReaderWrapper.new(process.get_input_stream)
68
- output = JavaWriterWrapper.new(process.get_output_stream)
69
- error = JavaReaderWrapper.new(process.get_error_stream)
70
- yield(input, output) if block_given?
71
- output.close
72
- success = process.wait_for.zero?
73
-
74
- [success, input.read + error.read]
75
- end
76
-
77
- class JavaReaderWrapper
78
- def initialize(input)
79
- @input = input
80
- end
81
-
82
- def read
83
- result = ""
84
- while (c = @input.read) != -1
85
- result << c.chr
86
- end
87
- result
88
- end
89
- end
90
-
91
- class JavaWriterWrapper
92
- def initialize(output)
93
- output = java.io.OutputStreamWriter.new(output)
94
- @output = java.io.BufferedWriter.new(output)
95
- end
96
-
97
- def puts(*messages)
98
- messages.each do |message|
99
- message += "\n" if /\n/ !~ message
100
- @output.write(message)
101
- end
102
- end
103
-
104
- def flush
105
- @output.flush
106
- end
107
-
108
- def close
109
- @output.close
110
- end
111
- end
112
- end
@@ -1,6 +0,0 @@
1
- test:
2
- host: 127.0.0.1
3
- base: dc=test,dc=localdomain
4
- method: :tls
5
- bind_dn: cn=user-name,dc=localdomain
6
- password: secret