ruby-activeldap 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/test/test_adapter.rb +17 -0
  2. data/test/test_associations.rb +19 -0
  3. data/test/test_attributes.rb +2 -1
  4. data/test/test_base.rb +28 -1
  5. data/test/test_base_per_instance.rb +2 -1
  6. data/test/test_callback.rb +2 -2
  7. data/test/test_connection.rb +2 -1
  8. data/test/test_connection_per_dn.rb +81 -0
  9. data/test/test_dn.rb +3 -2
  10. data/test/test_find.rb +35 -1
  11. data/test/test_object_class.rb +12 -1
  12. data/test/test_reflection.rb +16 -10
  13. data/test/test_schema.rb +141 -2
  14. data/test/test_user.rb +14 -4
  15. metadata +7 -104
  16. data/CHANGES +0 -397
  17. data/COPYING +0 -340
  18. data/LICENSE +0 -58
  19. data/Manifest.txt +0 -99
  20. data/README +0 -85
  21. data/Rakefile +0 -70
  22. data/TODO +0 -23
  23. data/benchmark/bench-al.rb +0 -152
  24. data/examples/config.yaml.example +0 -5
  25. data/examples/example.der +0 -0
  26. data/examples/example.jpg +0 -0
  27. data/examples/groupadd +0 -41
  28. data/examples/groupdel +0 -35
  29. data/examples/groupls +0 -49
  30. data/examples/groupmod +0 -42
  31. data/examples/lpasswd +0 -55
  32. data/examples/objects/group.rb +0 -13
  33. data/examples/objects/ou.rb +0 -4
  34. data/examples/objects/user.rb +0 -20
  35. data/examples/ouadd +0 -38
  36. data/examples/useradd +0 -45
  37. data/examples/useradd-binary +0 -50
  38. data/examples/userdel +0 -34
  39. data/examples/userls +0 -50
  40. data/examples/usermod +0 -42
  41. data/examples/usermod-binary-add +0 -47
  42. data/examples/usermod-binary-add-time +0 -51
  43. data/examples/usermod-binary-del +0 -48
  44. data/examples/usermod-lang-add +0 -43
  45. data/lib/active_ldap.rb +0 -964
  46. data/lib/active_ldap/adapter/base.rb +0 -461
  47. data/lib/active_ldap/adapter/ldap.rb +0 -232
  48. data/lib/active_ldap/adapter/ldap_ext.rb +0 -69
  49. data/lib/active_ldap/adapter/net_ldap.rb +0 -288
  50. data/lib/active_ldap/adapter/net_ldap_ext.rb +0 -29
  51. data/lib/active_ldap/association/belongs_to.rb +0 -40
  52. data/lib/active_ldap/association/belongs_to_many.rb +0 -39
  53. data/lib/active_ldap/association/collection.rb +0 -80
  54. data/lib/active_ldap/association/has_many.rb +0 -40
  55. data/lib/active_ldap/association/has_many_wrap.rb +0 -55
  56. data/lib/active_ldap/association/proxy.rb +0 -89
  57. data/lib/active_ldap/associations.rb +0 -162
  58. data/lib/active_ldap/attributes.rb +0 -203
  59. data/lib/active_ldap/base.rb +0 -1510
  60. data/lib/active_ldap/callbacks.rb +0 -19
  61. data/lib/active_ldap/command.rb +0 -46
  62. data/lib/active_ldap/configuration.rb +0 -106
  63. data/lib/active_ldap/connection.rb +0 -142
  64. data/lib/active_ldap/distinguished_name.rb +0 -246
  65. data/lib/active_ldap/ldap_error.rb +0 -74
  66. data/lib/active_ldap/object_class.rb +0 -74
  67. data/lib/active_ldap/schema.rb +0 -299
  68. data/lib/active_ldap/timeout.rb +0 -75
  69. data/lib/active_ldap/timeout_stub.rb +0 -17
  70. data/lib/active_ldap/user_password.rb +0 -92
  71. data/lib/active_ldap/validations.rb +0 -76
  72. data/rails/plugin/active_ldap/README +0 -54
  73. data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +0 -7
  74. data/rails/plugin/active_ldap/generators/scaffold_al/templates/ldap.yml +0 -21
  75. data/rails/plugin/active_ldap/init.rb +0 -12
  76. data/test/TODO +0 -2
  77. data/test/al-test-utils.rb +0 -381
  78. data/test/command.rb +0 -62
  79. data/test/config.yaml.sample +0 -6
  80. data/test/run-test.rb +0 -29
  81. data/test/test-unit-ext.rb +0 -2
  82. data/test/test-unit-ext/always-show-result.rb +0 -28
  83. data/test/test-unit-ext/priority.rb +0 -163
@@ -1,74 +0,0 @@
1
- module ActiveLdap
2
- class LdapError < Error
3
- class << self
4
- def define(code, name, target)
5
- klass_name = name.downcase.camelize
6
- target.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
7
- class #{klass_name} < #{self}
8
- CODE = #{code}
9
- def code
10
- CODE
11
- end
12
- end
13
- EOC
14
- target.const_get(klass_name)
15
- end
16
- end
17
-
18
- ERRORS = {}
19
- {
20
- 0x00 => "SUCCESS",
21
- 0x01 => "OPERATIONS_ERROR",
22
- 0x02 => "PROTOCOL_ERROR",
23
- 0x03 => "TIMELIMIT_EXCEEDED",
24
- 0x04 => "SIZELIMIT_EXCEEDED",
25
- 0x05 => "COMPARE_FALSE",
26
- 0x06 => "COMPARE_TRUE",
27
- 0x07 => "AUTH_METHOD_NOT_SUPPORTED",
28
- 0x08 => "STRONG_AUTH_REQUIRED",
29
- 0x09 => "PARTIAL_RESULTS", # LDAPv2+ (not LDAPv3)
30
-
31
- 0x0a => "REFERRAL",
32
- 0x0b => "ADMINLIMIT_EXCEEDED",
33
- 0x0c => "UNAVAILABLE_CRITICAL_EXTENSION",
34
- 0x0d => "CONFIDENTIALITY_REQUIRED",
35
- 0x0e => "LDAP_SASL_BIND_IN_PROGRESS",
36
-
37
- 0x10 => "NO_SUCH_ATTRIBUTE",
38
- 0x11 => "UNDEFINED_TYPE",
39
- 0x12 => "INAPPROPRIATE_MATCHING",
40
- 0x13 => "CONSTRAINT_VIOLATION",
41
- 0x14 => "TYPE_OR_VALUE_EXISTS",
42
- 0x15 => "INVALID_SYNTAX",
43
-
44
- 0x20 => "NO_SUCH_OBJECT",
45
- 0x21 => "ALIAS_PROBLEM",
46
- 0x22 => "INVALID_DN_SYNTAX",
47
- 0x23 => "IS_LEAF",
48
- 0x24 => "ALIAS_DEREF_PROBLEM",
49
-
50
- 0x2F => "PROXY_AUTHZ_FAILURE",
51
- 0x30 => "INAPPROPRIATE_AUTH",
52
- 0x31 => "INVALID_CREDENTIALS",
53
- 0x32 => "INSUFFICIENT_ACCESS",
54
-
55
- 0x33 => "BUSY",
56
- 0x34 => "UNAVAILABLE",
57
- 0x35 => "UNWILLING_TO_PERFORM",
58
- 0x36 => "LOOP_DETECT",
59
-
60
- 0x40 => "NAMING_VIOLATION",
61
- 0x41 => "OBJECT_CLASS_VIOLATION",
62
- 0x42 => "NOT_ALLOWED_ON_NONLEAF",
63
- 0x43 => "NOT_ALLOWED_ON_RDN",
64
- 0x44 => "ALREADY_EXISTS",
65
- 0x45 => "NO_OBJECT_CLASS_MODS",
66
- 0x46 => "RESULTS_TOO_LARGE",
67
- 0x47 => "AFFECTS_MULTIPLE_DSAS",
68
-
69
- 0x50 => "OTHER",
70
- }.each do |code, name|
71
- ERRORS[code] = LdapError.define(code, name, self)
72
- end
73
- end
74
- end
@@ -1,74 +0,0 @@
1
- module ActiveLdap
2
- module ObjectClass
3
- def self.included(base)
4
- base.extend(ClassMethods)
5
- end
6
-
7
- module ClassMethods
8
- end
9
-
10
- def add_class(*target_classes)
11
- replace_class((classes + target_classes.flatten).uniq)
12
- end
13
-
14
- def ensure_recommended_classes
15
- add_class(self.class.recommended_classes)
16
- end
17
-
18
- def remove_class(*target_classes)
19
- replace_class((classes - target_classes.flatten).uniq)
20
- end
21
-
22
- def replace_class(*target_classes)
23
- new_classes = target_classes.flatten.uniq
24
- assert_object_classes(new_classes)
25
- if new_classes.sort != classes.sort
26
- set_attribute('objectClass', new_classes)
27
- end
28
- end
29
-
30
- def classes
31
- (get_attribute('objectClass', true) || []).dup
32
- end
33
-
34
- private
35
- def assert_object_classes(new_classes)
36
- assert_valid_object_class_value_type(new_classes)
37
- assert_valid_object_class_value(new_classes)
38
- assert_have_all_required_classes(new_classes)
39
- end
40
-
41
- def assert_valid_object_class_value_type(new_classes)
42
- invalid_classes = new_classes.reject do |new_class|
43
- new_class.is_a?(String)
44
- end
45
- unless invalid_classes.empty?
46
- message = "Value in objectClass array is not a String"
47
- invalid_classes_info = invalid_classes.collect do |invalid_class|
48
- "#{invalid_class.class}:#{invalid_class.inspect}"
49
- end.join(", ")
50
- raise TypeError, "#{message}: #{invalid_classes_info}"
51
- end
52
- end
53
-
54
- def assert_valid_object_class_value(new_classes)
55
- invalid_classes = new_classes.reject do |new_class|
56
- schema.exist_name?("objectClasses", new_class)
57
- end
58
- unless invalid_classes.empty?
59
- message = "unknown objectClass in LDAP server"
60
- message = "#{message}: #{invalid_classes.join(', ')}"
61
- raise ObjectClassError, message
62
- end
63
- end
64
-
65
- def assert_have_all_required_classes(new_classes)
66
- required_classes = self.class.required_classes - new_classes
67
- unless required_classes.empty?
68
- raise RequiredObjectClassMissed,
69
- "Can't remove required objectClass: " +
70
- required_classes.join(", ")
71
- end
72
- end
73
- end
74
- end
@@ -1,299 +0,0 @@
1
- module ActiveLdap
2
- class Schema
3
- def initialize(entries)
4
- @entries = default_entries.merge(entries || {})
5
- @schema_info = {}
6
- @class_attributes_info = {}
7
- @cache = {}
8
- end
9
-
10
- def names(group)
11
- alias_map(group).keys
12
- end
13
-
14
- def exist_name?(group, name)
15
- alias_map(group).has_key?(normalize_schema_name(name))
16
- end
17
-
18
- # attribute
19
- #
20
- # This is just like LDAP::Schema#attribute except that it allows
21
- # look up in any of the given keys.
22
- # e.g.
23
- # attribute('attributeTypes', 'cn', 'DESC')
24
- # attribute('ldapSyntaxes', '1.3.6.1.4.1.1466.115.121.1.5', 'DESC')
25
- def attribute(group, id_or_name, attribute_name)
26
- return [] if attribute_name.empty?
27
- attribute_name = normalize_attribute_name(attribute_name)
28
- value = attributes(group, id_or_name)[attribute_name]
29
- value ? value.dup : []
30
- end
31
- alias_method :[], :attribute
32
- alias_method :attr, :attribute
33
-
34
- NUMERIC_OID_RE = "\\d[\\d\\.]+"
35
- DESCRIPTION_RE = "[a-zA-Z][a-zA-Z\\d\\-]*"
36
- OID_RE = "(?:#{NUMERIC_OID_RE}|#{DESCRIPTION_RE}-oid)"
37
- def attributes(group, id_or_name)
38
- return {} if group.empty? or id_or_name.empty?
39
-
40
- unless @entries.has_key?(group)
41
- raise ArgumentError, "Unknown schema group: #{group}"
42
- end
43
-
44
- # Initialize anything that is required
45
- info, ids, aliases = ensure_schema_info(group)
46
- id, name = determine_id_or_name(id_or_name, aliases)
47
-
48
- # Check already parsed options first
49
- return ids[id] if ids.has_key?(id)
50
-
51
- schemata = @entries[group] || []
52
- while schema = schemata.shift
53
- next unless /\A\s*\(\s*(#{OID_RE})\s*(.*)\s*\)\s*\z/ =~ schema
54
- schema_id = $1
55
- rest = $2
56
- next if ids.has_key?(schema_id)
57
-
58
- attributes = {}
59
- ids[schema_id] = attributes
60
-
61
- parse_attributes(rest, attributes)
62
- (attributes["NAME"] || []).each do |v|
63
- normalized_name = normalize_schema_name(v)
64
- aliases[normalized_name] = schema_id
65
- id = schema_id if id.nil? and name == normalized_name
66
- end
67
-
68
- break if id == schema_id
69
- end
70
-
71
- ids[id || aliases[name]] || {}
72
- end
73
-
74
- # attribute_aliases
75
- #
76
- # Returns all names from the LDAP schema for the
77
- # attribute given.
78
- def attribute_aliases(name)
79
- cache([:attribute_aliases, name]) do
80
- attribute_type(name, 'NAME')
81
- end
82
- end
83
-
84
- # read_only?
85
- #
86
- # Returns true if an attribute is read-only
87
- # NO-USER-MODIFICATION
88
- def read_only?(name)
89
- cache([:read_only?, name]) do
90
- attribute_type(name, 'NO-USER-MODIFICATION')[0] == 'TRUE'
91
- end
92
- end
93
-
94
- # single_value?
95
- #
96
- # Returns true if an attribute can only have one
97
- # value defined
98
- # SINGLE-VALUE
99
- def single_value?(name)
100
- cache([:single_value?, name]) do
101
- attribute_type(name, 'SINGLE-VALUE')[0] == 'TRUE'
102
- end
103
- end
104
-
105
- # binary?
106
- #
107
- # Returns true if the given attribute's syntax
108
- # is X-NOT-HUMAN-READABLE or X-BINARY-TRANSFER-REQUIRED
109
- def binary?(name)
110
- cache([:binary?, name]) do
111
- # Get syntax OID
112
- syntax = attribute_type(name, 'SYNTAX')[0]
113
- !syntax.nil? and
114
- (ldap_syntax(syntax, 'X-NOT-HUMAN-READABLE') == ["TRUE"] or
115
- ldap_syntax(syntax, 'X-BINARY-TRANSFER-REQUIRED') == ["TRUE"])
116
- end
117
- end
118
-
119
- # binary_required?
120
- #
121
- # Returns true if the value MUST be transferred in binary
122
- def binary_required?(name)
123
- cache([:binary_required?, name]) do
124
- # Get syntax OID
125
- syntax = attribute_type(name, 'SYNTAX')[0]
126
- !syntax.nil? and
127
- ldap_syntax(syntax, 'X-BINARY-TRANSFER-REQUIRED') == ["TRUE"]
128
- end
129
- end
130
-
131
- # class_attributes
132
- #
133
- # Returns an Array of all the valid attributes (but not with full aliases)
134
- # for the given objectClass
135
- def class_attributes(objc)
136
- cache([:class_attributes, objc]) do
137
- # First get all the current level attributes
138
- must = object_class(objc, 'MUST')
139
- may = object_class(objc, 'MAY')
140
-
141
- # Now add all attributes from the parent object (SUPerclasses)
142
- # Hopefully an iterative approach will be pretty speedy
143
- # 1. build complete list of SUPs
144
- # 2. Add attributes from each
145
- sups = object_class(objc, 'SUP')
146
- loop do
147
- start_size = sups.size
148
- new_sups = []
149
- sups.each do |sup|
150
- new_sups.concat(object_class(sup, 'SUP'))
151
- end
152
-
153
- sups.concat(new_sups)
154
- sups.uniq!
155
- break if sups.size == start_size
156
- end
157
- sups.each do |sup|
158
- must.concat(object_class(sup, 'MUST'))
159
- may.concat(object_class(sup, 'MAY'))
160
- end
161
-
162
- # Clean out the dupes.
163
- must.uniq!
164
- may.uniq!
165
- if objc == "inetOrgPerson"
166
- may.collect! do |name|
167
- if name == "x500uniqueIdentifier"
168
- "x500UniqueIdentifier"
169
- else
170
- name
171
- end
172
- end
173
- end
174
-
175
- {:must => must, :may => may}
176
- end
177
- end
178
-
179
- private
180
- def cache(key)
181
- (@cache[key] ||= [yield])[0]
182
- end
183
-
184
- def ensure_schema_info(group)
185
- @schema_info[group] ||= {:ids => {}, :aliases => {}}
186
- info = @schema_info[group]
187
- [info, info[:ids], info[:aliases]]
188
- end
189
-
190
- def determine_id_or_name(id_or_name, aliases)
191
- if /\A[\d\.]+\z/ =~ id_or_name
192
- id = id_or_name
193
- name = nil
194
- else
195
- name = normalize_schema_name(id_or_name)
196
- id = aliases[name]
197
- end
198
- [id, name]
199
- end
200
-
201
- # from RFC 2252
202
- attribute_type_description_reserved_names =
203
- ["NAME", "DESC", "OBSOLETE", "SUP", "EQUALITY", "ORDERING", "SUBSTR",
204
- "SYNTAX", "SINGLE-VALUE", "COLLECTIVE", "NO-USER-MODIFICATION", "USAGE"]
205
- syntax_description_reserved_names = ["DESC"]
206
- object_class_description_reserved_names =
207
- ["NAME", "DESC", "OBSOLETE", "SUP", "ABSTRACT", "STRUCTURAL",
208
- "AUXILIARY", "MUST", "MAY"]
209
- matching_rule_description_reserved_names =
210
- ["NAME", "DESC", "OBSOLETE", "SYNTAX"]
211
- matching_rule_use_description_reserved_names =
212
- ["NAME", "DESC", "OBSOLETE", "APPLIES"]
213
- private_experiment_reserved_names = ["X-[A-Z\\-_]+"]
214
- reserved_names =
215
- (attribute_type_description_reserved_names +
216
- syntax_description_reserved_names +
217
- object_class_description_reserved_names +
218
- matching_rule_description_reserved_names +
219
- matching_rule_use_description_reserved_names +
220
- private_experiment_reserved_names).uniq
221
- RESERVED_NAMES_RE = /(?:#{reserved_names.join('|')})/
222
-
223
- def parse_attributes(str, attributes)
224
- str.scan(/([A-Z\-_]+)\s+
225
- (?:\(\s*([\w\-]+(?:\s+\$\s+[\w\-]+)+)\s*\)|
226
- \(\s*([^\)]*)\s*\)|
227
- '([^\']*)'|
228
- ((?!#{RESERVED_NAMES_RE})[a-zA-Z][a-zA-Z\d\-;]*)|
229
- (\d[\d\.\{\}]+)|
230
- ()
231
- )/x
232
- ) do |name, multi_amp, multi, string, literal, syntax, no_value|
233
- case
234
- when multi_amp
235
- values = multi_amp.rstrip.split(/\s*\$\s*/)
236
- when multi
237
- values = multi.scan(/\s*'([^\']*)'\s*/).collect {|value| value[0]}
238
- when string
239
- values = [string]
240
- when literal
241
- values = [literal]
242
- when syntax
243
- values = [syntax]
244
- when no_value
245
- values = ["TRUE"]
246
- end
247
- attributes[normalize_attribute_name(name)] = values
248
- end
249
- end
250
-
251
- def attribute_type(name, attribute_name)
252
- cache([:attribute_type, name, attribute_name]) do
253
- attribute("attributeTypes", name, attribute_name)
254
- end
255
- end
256
-
257
- def ldap_syntax(name, attribute_name)
258
- return [] unless @entries.has_key?("ldapSyntaxes")
259
- cache([:ldap_syntax, name, attribute_name]) do
260
- attribute("ldapSyntaxes", name, attribute_name)
261
- end
262
- end
263
-
264
- def object_class(name, attribute_name)
265
- cache([:object_class, name, attribute_name]) do
266
- attribute("objectClasses", name, attribute_name)
267
- end
268
- end
269
-
270
- def alias_map(group)
271
- ensure_parse(group)
272
- return {} if @schema_info[group].nil?
273
- @schema_info[group][:aliases] || {}
274
- end
275
-
276
- def ensure_parse(group)
277
- return if @entries[group].nil?
278
- unless @entries[group].empty?
279
- attribute(group, 'nonexistent', 'nonexistent')
280
- end
281
- end
282
-
283
- def normalize_schema_name(name)
284
- name.downcase.sub(/;.*$/, '')
285
- end
286
-
287
- def normalize_attribute_name(name)
288
- name.upcase.gsub(/_/, "-")
289
- end
290
-
291
- def default_entries
292
- {
293
- "objectClasses" => [],
294
- "attributeTypes" => [],
295
- "ldapSyntaxes" => [],
296
- }
297
- end
298
- end # Schema
299
- end
@@ -1,75 +0,0 @@
1
- require 'timeout'
2
-
3
- module Timeout
4
-
5
- # A forking timeout implementation that relies on
6
- # signals to interrupt blocking I/O instead of passing
7
- # that code to run in a separate process.
8
- #
9
- # A process is fork()ed, sleeps for _sec_,
10
- # then sends a ALRM signal to the Process.ppid
11
- # process. ALRM is used to avoid conflicts with sleep()
12
- #
13
- # This overwrites any signal
14
- def Timeout.alarm(sec, exception=Timeout::Error, &block)
15
- return block.call if sec == nil or sec.zero?
16
-
17
-
18
- # Trap an alarm in case it comes before we're ready
19
- orig_alrm = trap(:ALRM, 'IGNORE')
20
-
21
- # Setup a fallback in case of a race condition of an
22
- # alarm before we set the other trap
23
- trap(:ALRM) do
24
- # Don't leave zombies
25
- Process.wait2()
26
- # Restore the original handler
27
- trap('ALRM', orig_alrm)
28
- # Now raise an exception!
29
- raise exception, 'execution expired'
30
- end
31
-
32
- # Spawn the sleeper
33
- pid = Process.fork {
34
- begin
35
- # Sleep x seconds then send SIGALRM
36
- sleep(sec)
37
- # Send alarm!
38
- Process.kill(:ALRM, Process.ppid)
39
- end
40
- exit! 0
41
- }
42
-
43
- # Setup the real handler
44
- trap(:ALRM) do
45
- # Make sure we clean up any zombies
46
- Process.waitpid(pid)
47
- # Restore the original handler
48
- trap(:ALRM, orig_alrm)
49
- # Now raise an exception!
50
- raise exception, 'execution expired'
51
- end
52
-
53
- begin
54
- # Run the code!
55
- return block.call
56
- ensure
57
- # Restore old alarm handler since we're done
58
- trap(:ALRM, orig_alrm)
59
- # Make sure the process is dead
60
- # This may be run twice (trap occurs during execution) so ignore ESRCH
61
- Process.kill(:TERM, pid) rescue Errno::ESRCH
62
- # Don't leave zombies
63
- Process.waitpid(pid) rescue Errno::ECHILD
64
- end
65
- end
66
- end # Timeout
67
-
68
- if __FILE__ == $0
69
- require 'time'
70
- Timeout.alarm(2) do
71
- loop do
72
- p Time.now
73
- end
74
- end
75
- end