activeldap 1.2.4 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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