ruby-activeldap 0.8.1 → 0.8.2

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 (65) hide show
  1. data/CHANGES +5 -0
  2. data/Manifest.txt +91 -25
  3. data/README +22 -0
  4. data/Rakefile +41 -8
  5. data/TODO +1 -6
  6. data/examples/config.yaml.example +5 -0
  7. data/examples/example.der +0 -0
  8. data/examples/example.jpg +0 -0
  9. data/examples/groupadd +41 -0
  10. data/examples/groupdel +35 -0
  11. data/examples/groupls +49 -0
  12. data/examples/groupmod +42 -0
  13. data/examples/lpasswd +55 -0
  14. data/examples/objects/group.rb +13 -0
  15. data/examples/objects/ou.rb +4 -0
  16. data/examples/objects/user.rb +20 -0
  17. data/examples/ouadd +38 -0
  18. data/examples/useradd +45 -0
  19. data/examples/useradd-binary +50 -0
  20. data/examples/userdel +34 -0
  21. data/examples/userls +50 -0
  22. data/examples/usermod +42 -0
  23. data/examples/usermod-binary-add +47 -0
  24. data/examples/usermod-binary-add-time +51 -0
  25. data/examples/usermod-binary-del +48 -0
  26. data/examples/usermod-lang-add +43 -0
  27. data/lib/active_ldap.rb +213 -214
  28. data/lib/active_ldap/adapter/base.rb +461 -0
  29. data/lib/active_ldap/adapter/ldap.rb +232 -0
  30. data/lib/active_ldap/adapter/ldap_ext.rb +69 -0
  31. data/lib/active_ldap/adapter/net_ldap.rb +288 -0
  32. data/lib/active_ldap/adapter/net_ldap_ext.rb +29 -0
  33. data/lib/active_ldap/association/belongs_to.rb +3 -1
  34. data/lib/active_ldap/association/belongs_to_many.rb +5 -6
  35. data/lib/active_ldap/association/has_many.rb +9 -17
  36. data/lib/active_ldap/association/has_many_wrap.rb +4 -5
  37. data/lib/active_ldap/attributes.rb +4 -0
  38. data/lib/active_ldap/base.rb +201 -56
  39. data/lib/active_ldap/configuration.rb +11 -1
  40. data/lib/active_ldap/connection.rb +15 -9
  41. data/lib/active_ldap/distinguished_name.rb +246 -0
  42. data/lib/active_ldap/ldap_error.rb +74 -0
  43. data/lib/active_ldap/object_class.rb +9 -5
  44. data/lib/active_ldap/schema.rb +50 -9
  45. data/lib/active_ldap/validations.rb +11 -13
  46. data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +7 -0
  47. data/rails/plugin/active_ldap/generators/scaffold_al/templates/ldap.yml +21 -0
  48. data/rails/plugin/active_ldap/init.rb +10 -4
  49. data/test/al-test-utils.rb +46 -3
  50. data/test/run-test.rb +16 -4
  51. data/test/test-unit-ext/always-show-result.rb +28 -0
  52. data/test/test-unit-ext/priority.rb +163 -0
  53. data/test/test_adapter.rb +81 -0
  54. data/test/test_attributes.rb +8 -1
  55. data/test/test_base.rb +132 -3
  56. data/test/test_base_per_instance.rb +14 -3
  57. data/test/test_connection.rb +19 -0
  58. data/test/test_dn.rb +161 -0
  59. data/test/test_find.rb +24 -0
  60. data/test/test_object_class.rb +15 -2
  61. data/test/test_schema.rb +108 -1
  62. metadata +111 -41
  63. data/lib/active_ldap/adaptor/base.rb +0 -29
  64. data/lib/active_ldap/adaptor/ldap.rb +0 -466
  65. data/lib/active_ldap/ldap.rb +0 -113
@@ -12,23 +12,20 @@ module ActiveLdap
12
12
  validate :validate_required_values
13
13
 
14
14
  class << self
15
- alias_method :evaluate_condition_for_active_record,
16
- :evaluate_condition
17
- def evaluate_condition(condition, entry)
18
- evaluate_condition_for_active_record(condition, entry)
15
+ def evaluate_condition_with_active_ldap_support(condition, entry)
16
+ evaluate_condition_without_active_ldap_support(condition, entry)
19
17
  rescue ActiveRecord::ActiveRecordError
20
18
  raise Error, $!.message
21
19
  end
20
+ alias_method_chain :evaluate_condition, :active_ldap_support
22
21
  end
23
22
 
24
- alias_method :save_with_validation_for_active_record!,
25
- :save_with_validation!
26
- def save_with_validation!
27
- save_with_validation_for_active_record!
23
+ def save_with_active_ldap_support!
24
+ save_without_active_ldap_support!
28
25
  rescue ActiveRecord::RecordInvalid
29
26
  raise EntryInvalid, $!.message
30
27
  end
31
- alias_method :save!, :save_with_validation!
28
+ alias_method_chain :save!, :active_ldap_support
32
29
 
33
30
  def valid?
34
31
  ensure_apply_object_class
@@ -46,7 +43,8 @@ module ActiveLdap
46
43
  @musts.each do |object_class, attributes|
47
44
  attributes.each do |required_attribute|
48
45
  # Normalize to ensure we catch schema problems
49
- real_name = to_real_attribute_name(required_attribute)
46
+ real_name = to_real_attribute_name(required_attribute, true)
47
+ raise UnknownAttribute.new(required_attribute) if real_name.nil?
50
48
  # # Set default if it wasn't yet set.
51
49
  # @data[real_name] ||= [] # need?
52
50
  value = @data[real_name] || []
@@ -66,12 +64,12 @@ module ActiveLdap
66
64
  end
67
65
 
68
66
  private
69
- alias_method :run_validations_for_active_record, :run_validations
70
- def run_validations(validation_method)
71
- run_validations_for_active_record(validation_method)
67
+ def run_validations_with_active_ldap_support(validation_method)
68
+ run_validations_without_active_ldap_support(validation_method)
72
69
  rescue ActiveRecord::ActiveRecordError
73
70
  raise Error, $!.message
74
71
  end
72
+ alias_method_chain :run_validations, :active_ldap_support
75
73
  end
76
74
  end
77
75
  end
@@ -0,0 +1,7 @@
1
+ class ScaffoldAlGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.template("ldap.yml", File.join("config", "ldap.yml"))
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ development:
2
+ host: 127.0.0.1
3
+ port: 389
4
+ base: dc=devel,dc=local,dc=net
5
+ bind_dn: cn=admin,dc=local,dc=net
6
+ password: secret
7
+
8
+ test:
9
+ host: 127.0.0.1
10
+ port: 389
11
+ base: dc=test,dc=local,dc=net
12
+ bind_dn: cn=admin,dc=local,dc=net
13
+ password: secret
14
+
15
+ production:
16
+ host: 127.0.0.1
17
+ port: 389
18
+ method: :tls
19
+ base: dc=production,dc=local,dc=net
20
+ bind_dn: cn=admin,dc=local,dc=net
21
+ password: secret
@@ -1,6 +1,12 @@
1
- require_dependency 'active_ldap'
1
+ require_library_or_gem 'active_ldap'
2
2
  ActiveLdap::Base.logger ||= RAILS_DEFAULT_LOGGER
3
3
  ldap_configuration_file = File.join(RAILS_ROOT, 'config', 'ldap.yml')
4
- configurations = YAML::load(ERB.new(IO.read(ldap_configuration_file)).result)
5
- ActiveLdap::Base.configurations = configurations
6
- ActiveLdap::Base.establish_connection
4
+ if File.exist?(ldap_configuration_file)
5
+ configurations = YAML::load(ERB.new(IO.read(ldap_configuration_file)).result)
6
+ ActiveLdap::Base.configurations = configurations
7
+ ActiveLdap::Base.establish_connection
8
+ else
9
+ message = "You should run 'script/generator scaffold_al' " +
10
+ "to make #{ldap_configuration_file}"
11
+ ActiveLdap::Base.logger.error(message)
12
+ end
@@ -22,6 +22,7 @@ module AlTestUtils
22
22
  include Populate
23
23
  include TemporaryEntry
24
24
  include CommandSupport
25
+ include MockLogger
25
26
  end
26
27
  end
27
28
 
@@ -47,7 +48,12 @@ module AlTestUtils
47
48
  unless File.exist?(@config_file)
48
49
  raise "config file for testing doesn't exist: #{@config_file}"
49
50
  end
50
- YAML.load(ERB.new(File.read(@config_file)).result)
51
+ config = YAML.load(ERB.new(File.read(@config_file)).result)
52
+ config.each do |key, value|
53
+ adapter = ENV["ACTIVE_LDAP_TEST_ADAPTER"]
54
+ value[:adapter] = adapter if adapter
55
+ end
56
+ config
51
57
  end
52
58
  end
53
59
 
@@ -112,7 +118,10 @@ module AlTestUtils
112
118
  next if dc_class.exists?(value, :prefix => "dc=#{value}")
113
119
  dc = dc_class.new(value)
114
120
  dc.o = dc.dc
115
- dc.save
121
+ begin
122
+ dc.save
123
+ rescue ActiveLdap::OperationNotPermitted
124
+ end
116
125
  end
117
126
  end
118
127
 
@@ -136,10 +145,11 @@ module AlTestUtils
136
145
 
137
146
  def populate_user_class
138
147
  @user_class = Class.new(ActiveLdap::Base)
148
+ @user_class_classes = ["posixAccount", "person"]
139
149
  @user_class.ldap_mapping :dn_attribute => "uid",
140
150
  :prefix => "ou=Users",
141
151
  :scope => :sub,
142
- :classes => ["posixAccount", "person"]
152
+ :classes => @user_class_classes
143
153
  end
144
154
 
145
155
  def populate_group_class
@@ -335,4 +345,37 @@ module AlTestUtils
335
345
  Command.run(*args, &block)
336
346
  end
337
347
  end
348
+
349
+ module MockLogger
350
+ def make_mock_logger
351
+ logger = Object.new
352
+ class << logger
353
+ def messages(type)
354
+ @messages ||= {}
355
+ @messages[type] ||= []
356
+ @messages[type]
357
+ end
358
+
359
+ def info(content=nil)
360
+ messages(:info) << (block_given? ? yield : content)
361
+ end
362
+ def warn(content=nil)
363
+ messages(:warn) << (block_given? ? yield : content)
364
+ end
365
+ def error(content=nil)
366
+ messages(:error) << (block_given? ? yield : content)
367
+ end
368
+ end
369
+ logger
370
+ end
371
+
372
+ def with_mock_logger
373
+ original_logger = ActiveLdap::Base.logger
374
+ mock_logger = make_mock_logger
375
+ ActiveLdap::Base.logger = mock_logger
376
+ yield(mock_logger)
377
+ ensure
378
+ ActiveLdap::Base.logger = original_logger
379
+ end
380
+ end
338
381
  end
data/test/run-test.rb CHANGED
@@ -10,8 +10,20 @@ $LOAD_PATH.unshift(File.join(top_dir, "test"))
10
10
 
11
11
  require 'test-unit-ext'
12
12
 
13
- if Test::Unit::AutoRunner.respond_to?(:standalone?)
14
- exit Test::Unit::AutoRunner.run($0, File.dirname($0))
15
- else
16
- exit Test::Unit::AutoRunner.run(false, File.dirname($0))
13
+ test_file = "test/test_*.rb"
14
+ Dir.glob(test_file) do |file|
15
+ require file
16
+ end
17
+
18
+ [nil, "ldap", "net-ldap"].each do |adapter|
19
+ ENV["ACTIVE_LDAP_TEST_ADAPTER"] = adapter
20
+ puts "using adapter: #{adapter ? adapter : 'default'}"
21
+ args = [File.dirname($0), ARGV.dup]
22
+ if Test::Unit::AutoRunner.respond_to?(:standalone?)
23
+ args.unshift(false)
24
+ else
25
+ args.unshift($0)
26
+ end
27
+ Test::Unit::AutoRunner.run(*args)
28
+ puts
17
29
  end
@@ -0,0 +1,28 @@
1
+ require "test/unit/ui/testrunnermediator"
2
+
3
+ module Test
4
+ module Unit
5
+ module UI
6
+ class TestRunnerMediator
7
+ alias_method :original_run_suite, :run_suite
8
+ def run_suite
9
+ @notified_finished = false
10
+ begin_time = Time.now
11
+ original_run_suite
12
+ rescue Interrupt
13
+ unless @notified_finished
14
+ end_time = Time.now
15
+ elapsed_time = end_time - begin_time
16
+ notify_listeners(FINISHED, elapsed_time)
17
+ end
18
+ raise
19
+ end
20
+
21
+ def notify_listeners(channel_name, *arguments)
22
+ @notified_finished = true if channel_name == FINISHED
23
+ super
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,163 @@
1
+ require "test/unit"
2
+
3
+ require "fileutils"
4
+
5
+ module Test
6
+ module Unit
7
+ class TestCase
8
+ class << self
9
+ def inherited(sub)
10
+ super
11
+ sub.instance_variable_set("@priority_initialized", true)
12
+ sub.instance_variable_set("@priority_table", {})
13
+ sub.priority :normal
14
+ end
15
+
16
+ def include(*args)
17
+ args.reverse_each do |mod|
18
+ super(mod)
19
+ next unless defined?(@priority_initialized)
20
+ mod.instance_methods(false).each do |name|
21
+ set_priority(name)
22
+ end
23
+ end
24
+ end
25
+
26
+ def method_added(name)
27
+ set_priority(name) if defined?(@priority_initialized)
28
+ end
29
+
30
+ def priority(name, *tests)
31
+ unless private_methods.include?(priority_check_method_name(name))
32
+ raise ArgumentError, "unknown priority: #{name}"
33
+ end
34
+ if tests.empty?
35
+ @current_priority = name
36
+ else
37
+ tests.each do |test|
38
+ set_priority(test, name)
39
+ end
40
+ end
41
+ end
42
+
43
+ def need_to_run?(test_name)
44
+ normalized_test_name = normalize_test_name(test_name)
45
+ priority = @priority_table[normalized_test_name]
46
+ return true unless priority
47
+ __send__(priority_check_method_name(priority), test_name)
48
+ end
49
+
50
+ private
51
+ def priority_check_method_name(priority_name)
52
+ "run_priority_#{priority_name}?"
53
+ end
54
+
55
+ def normalize_test_name(test_name)
56
+ "test_#{test_name.to_s.sub(/^test_/, '')}"
57
+ end
58
+
59
+ def set_priority(name, priority=@current_priority)
60
+ @priority_table[normalize_test_name(name)] = priority
61
+ end
62
+
63
+ def run_priority_must?(test_name)
64
+ true
65
+ end
66
+
67
+ def run_priority_important?(test_name)
68
+ rand > 0.1
69
+ end
70
+
71
+ def run_priority_high?(test_name)
72
+ rand > 0.3
73
+ end
74
+
75
+ def run_priority_normal?(test_name)
76
+ rand > 0.5
77
+ end
78
+
79
+ def run_priority_low?(test_name)
80
+ rand > 0.75
81
+ end
82
+
83
+ def run_priority_never?(test_name)
84
+ false
85
+ end
86
+ end
87
+
88
+ def need_to_run?
89
+ !previous_test_success? or self.class.need_to_run?(@method_name)
90
+ end
91
+
92
+ alias_method :original_run, :run
93
+ def run(result, &block)
94
+ original_run(result, &block)
95
+ ensure
96
+ if passed?
97
+ FileUtils.rm_f(not_passed_file)
98
+ else
99
+ FileUtils.touch(not_passed_file)
100
+ end
101
+ end
102
+
103
+ private
104
+ def previous_test_success?
105
+ not File.exist?(not_passed_file)
106
+ end
107
+
108
+ def result_dir
109
+ dir = File.join(File.dirname($0), ".test-result",
110
+ self.class.name, @method_name.to_s)
111
+ dir = File.expand_path(dir)
112
+ FileUtils.mkdir_p(dir)
113
+ dir
114
+ end
115
+
116
+ def not_passed_file
117
+ File.join(result_dir, "not-passed")
118
+ end
119
+ end
120
+
121
+ class TestSuite
122
+ @@priority_mode = false
123
+
124
+ class << self
125
+ def priority_mode=(bool)
126
+ @@priority_mode = bool
127
+ end
128
+ end
129
+
130
+ alias_method :original_run, :run
131
+ def run(*args, &block)
132
+ priority_mode = @@priority_mode
133
+ if priority_mode
134
+ @original_tests = @tests
135
+ apply_priority
136
+ end
137
+ original_run(*args, &block)
138
+ ensure
139
+ @tests = @original_tests if priority_mode
140
+ end
141
+
142
+ def apply_priority
143
+ @tests = @tests.reject {|test| !test.need_to_run?}
144
+ end
145
+
146
+ def need_to_run?
147
+ apply_priority
148
+ !@tests.empty?
149
+ end
150
+ end
151
+
152
+ class AutoRunner
153
+ alias_method :original_options, :options
154
+ def options
155
+ opts = original_options
156
+ opts.on("--[no-]priority", "use priority mode") do |bool|
157
+ TestSuite.priority_mode = bool
158
+ end
159
+ opts
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,81 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestAdapter < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ def setup
7
+ end
8
+
9
+ def teardown
10
+ end
11
+
12
+ priority :must
13
+
14
+ priority :normal
15
+ def test_empty_filter
16
+ assert_parse_filter(nil, nil)
17
+ assert_parse_filter(nil, "")
18
+ assert_parse_filter(nil, " ")
19
+ end
20
+
21
+ def test_simple_filter
22
+ assert_parse_filter("(objectClass=*)", "objectClass=*")
23
+ assert_parse_filter("(objectClass=*)", "(objectClass=*)")
24
+ assert_parse_filter("(&(uid=bob)(objectClass=*))",
25
+ "(&(uid=bob)(objectClass=*))")
26
+
27
+ assert_parse_filter("(objectClass=*)", {:objectClass => "*"})
28
+ assert_parse_filter("(&(objectClass=*)(uid=bob))",
29
+ {:uid => "bob", :objectClass => "*"})
30
+
31
+ assert_parse_filter("(&(uid=bob)(objectClass=*))",
32
+ [:and, "uid=bob", "objectClass=*"])
33
+ assert_parse_filter("(&(uid=bob)(objectClass=*))",
34
+ [:&, "uid=bob", "objectClass=*"])
35
+ assert_parse_filter("(|(uid=bob)(objectClass=*))",
36
+ [:or, "uid=bob", "objectClass=*"])
37
+ assert_parse_filter("(|(uid=bob)(objectClass=*))",
38
+ [:|, "uid=bob", "objectClass=*"])
39
+ end
40
+
41
+ def test_multi_value_filter
42
+ assert_parse_filter("(&(objectClass=top)(objectClass=posixAccount))",
43
+ {:objectClass => ["top", "posixAccount"]})
44
+
45
+ assert_parse_filter("(&(objectClass=top)(objectClass=posixAccount))",
46
+ [[:objectClass, "top"],
47
+ [:objectClass, "posixAccount"]])
48
+ assert_parse_filter("(&(objectClass=top)(objectClass=posixAccount))",
49
+ [[:objectClass, ["top", "posixAccount"]]])
50
+ end
51
+
52
+ def test_nested_filter
53
+ assert_parse_filter("(&(objectClass=*)(uid=bob))",
54
+ [:and, {:uid => "bob", :objectClass => "*"}])
55
+ assert_parse_filter("(&(objectClass=*)(|(uid=bob)(uid=alice)))",
56
+ [:and, {:objectClass => "*"},
57
+ [:or, [:uid, "bob"], [:uid, "alice"]]])
58
+ assert_parse_filter("(&(objectClass=*)(|(uid=bob)(uid=alice)))",
59
+ [:and,
60
+ {:objectClass => "*",
61
+ :uid => [:or, "bob", "alice"]}])
62
+ assert_parse_filter("(&(gidNumber=100001)" +
63
+ "(|(uid=temp-user1)(uid=temp-user2)))",
64
+ [:and,
65
+ [:and, {"gidNumber"=>["100001"]}],
66
+ [:or, {"uid"=>["temp-user1", "temp-user2"]}]])
67
+ end
68
+
69
+ def test_invalid_operator
70
+ assert_raises(ArgumentError) do
71
+ assert_parse_filter("(&(objectClass=*)(uid=bob))",
72
+ [:xxx, {:uid => "bob", :objectClass => "*"}])
73
+ end
74
+ end
75
+
76
+ private
77
+ def assert_parse_filter(expected, filter)
78
+ adapter = ActiveLdap::Adapter::Base.new
79
+ assert_equal(expected, adapter.send(:parse_filter, filter))
80
+ end
81
+ end