ruby-activeldap 0.8.1 → 0.8.2

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