powerhome-activeldap 3.2.3

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 (145) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +6 -0
  3. data/COPYING +340 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE +59 -0
  6. data/README.textile +140 -0
  7. data/TODO +32 -0
  8. data/benchmark/README.md +64 -0
  9. data/benchmark/bench-backend.rb +247 -0
  10. data/benchmark/bench-instantiate.rb +98 -0
  11. data/benchmark/config.yaml.sample +5 -0
  12. data/doc/text/development.textile +54 -0
  13. data/doc/text/news.textile +811 -0
  14. data/doc/text/rails.textile +144 -0
  15. data/doc/text/tutorial.textile +1010 -0
  16. data/examples/config.yaml.example +5 -0
  17. data/examples/example.der +0 -0
  18. data/examples/example.jpg +0 -0
  19. data/examples/groupadd +41 -0
  20. data/examples/groupdel +35 -0
  21. data/examples/groupls +49 -0
  22. data/examples/groupmod +42 -0
  23. data/examples/lpasswd +55 -0
  24. data/examples/objects/group.rb +13 -0
  25. data/examples/objects/ou.rb +4 -0
  26. data/examples/objects/user.rb +20 -0
  27. data/examples/ouadd +38 -0
  28. data/examples/useradd +45 -0
  29. data/examples/useradd-binary +53 -0
  30. data/examples/userdel +34 -0
  31. data/examples/userls +50 -0
  32. data/examples/usermod +42 -0
  33. data/examples/usermod-binary-add +50 -0
  34. data/examples/usermod-binary-add-time +54 -0
  35. data/examples/usermod-binary-del +48 -0
  36. data/examples/usermod-lang-add +43 -0
  37. data/lib/active_ldap.rb +85 -0
  38. data/lib/active_ldap/action_controller/ldap_benchmarking.rb +55 -0
  39. data/lib/active_ldap/acts/tree.rb +78 -0
  40. data/lib/active_ldap/adapter/base.rb +707 -0
  41. data/lib/active_ldap/adapter/jndi.rb +184 -0
  42. data/lib/active_ldap/adapter/jndi_connection.rb +185 -0
  43. data/lib/active_ldap/adapter/ldap.rb +290 -0
  44. data/lib/active_ldap/adapter/ldap_ext.rb +105 -0
  45. data/lib/active_ldap/adapter/net_ldap.rb +309 -0
  46. data/lib/active_ldap/adapter/net_ldap_ext.rb +23 -0
  47. data/lib/active_ldap/association/belongs_to.rb +47 -0
  48. data/lib/active_ldap/association/belongs_to_many.rb +58 -0
  49. data/lib/active_ldap/association/children.rb +21 -0
  50. data/lib/active_ldap/association/collection.rb +105 -0
  51. data/lib/active_ldap/association/has_many.rb +31 -0
  52. data/lib/active_ldap/association/has_many_utils.rb +44 -0
  53. data/lib/active_ldap/association/has_many_wrap.rb +75 -0
  54. data/lib/active_ldap/association/proxy.rb +107 -0
  55. data/lib/active_ldap/associations.rb +205 -0
  56. data/lib/active_ldap/attribute_methods.rb +23 -0
  57. data/lib/active_ldap/attribute_methods/before_type_cast.rb +24 -0
  58. data/lib/active_ldap/attribute_methods/dirty.rb +43 -0
  59. data/lib/active_ldap/attribute_methods/query.rb +31 -0
  60. data/lib/active_ldap/attribute_methods/read.rb +44 -0
  61. data/lib/active_ldap/attribute_methods/write.rb +38 -0
  62. data/lib/active_ldap/attributes.rb +176 -0
  63. data/lib/active_ldap/base.rb +1410 -0
  64. data/lib/active_ldap/callbacks.rb +71 -0
  65. data/lib/active_ldap/command.rb +49 -0
  66. data/lib/active_ldap/compatible.rb +44 -0
  67. data/lib/active_ldap/configuration.rb +147 -0
  68. data/lib/active_ldap/connection.rb +299 -0
  69. data/lib/active_ldap/distinguished_name.rb +291 -0
  70. data/lib/active_ldap/entry_attribute.rb +78 -0
  71. data/lib/active_ldap/escape.rb +12 -0
  72. data/lib/active_ldap/get_text.rb +20 -0
  73. data/lib/active_ldap/get_text/parser.rb +161 -0
  74. data/lib/active_ldap/helper.rb +92 -0
  75. data/lib/active_ldap/human_readable.rb +133 -0
  76. data/lib/active_ldap/ldap_error.rb +74 -0
  77. data/lib/active_ldap/ldif.rb +930 -0
  78. data/lib/active_ldap/log_subscriber.rb +50 -0
  79. data/lib/active_ldap/object_class.rb +95 -0
  80. data/lib/active_ldap/operations.rb +624 -0
  81. data/lib/active_ldap/persistence.rb +100 -0
  82. data/lib/active_ldap/populate.rb +53 -0
  83. data/lib/active_ldap/railtie.rb +43 -0
  84. data/lib/active_ldap/railties/controller_runtime.rb +48 -0
  85. data/lib/active_ldap/schema.rb +701 -0
  86. data/lib/active_ldap/schema/syntaxes.rb +422 -0
  87. data/lib/active_ldap/timeout.rb +75 -0
  88. data/lib/active_ldap/timeout_stub.rb +17 -0
  89. data/lib/active_ldap/user_password.rb +99 -0
  90. data/lib/active_ldap/validations.rb +200 -0
  91. data/lib/active_ldap/version.rb +3 -0
  92. data/lib/active_ldap/xml.rb +139 -0
  93. data/lib/rails/generators/active_ldap/model/USAGE +18 -0
  94. data/lib/rails/generators/active_ldap/model/model_generator.rb +47 -0
  95. data/lib/rails/generators/active_ldap/model/templates/model_active_ldap.rb +3 -0
  96. data/lib/rails/generators/active_ldap/scaffold/scaffold_generator.rb +14 -0
  97. data/lib/rails/generators/active_ldap/scaffold/templates/ldap.yml +19 -0
  98. data/po/en/active-ldap.po +4029 -0
  99. data/po/ja/active-ldap.po +4060 -0
  100. data/test/add-phonetic-attribute-options-to-slapd.ldif +10 -0
  101. data/test/al-test-utils.rb +428 -0
  102. data/test/command.rb +111 -0
  103. data/test/config.yaml.sample +6 -0
  104. data/test/fixtures/lower_case_object_class_schema.rb +802 -0
  105. data/test/run-test.rb +34 -0
  106. data/test/test_acts_as_tree.rb +60 -0
  107. data/test/test_adapter.rb +121 -0
  108. data/test/test_associations.rb +701 -0
  109. data/test/test_attributes.rb +117 -0
  110. data/test/test_base.rb +1214 -0
  111. data/test/test_base_per_instance.rb +61 -0
  112. data/test/test_bind.rb +62 -0
  113. data/test/test_callback.rb +31 -0
  114. data/test/test_configuration.rb +40 -0
  115. data/test/test_connection.rb +82 -0
  116. data/test/test_connection_per_class.rb +112 -0
  117. data/test/test_connection_per_dn.rb +112 -0
  118. data/test/test_dirty.rb +98 -0
  119. data/test/test_dn.rb +172 -0
  120. data/test/test_find.rb +176 -0
  121. data/test/test_groupadd.rb +50 -0
  122. data/test/test_groupdel.rb +46 -0
  123. data/test/test_groupls.rb +107 -0
  124. data/test/test_groupmod.rb +51 -0
  125. data/test/test_ldif.rb +1890 -0
  126. data/test/test_load.rb +133 -0
  127. data/test/test_lpasswd.rb +75 -0
  128. data/test/test_object_class.rb +74 -0
  129. data/test/test_persistence.rb +131 -0
  130. data/test/test_reflection.rb +175 -0
  131. data/test/test_schema.rb +559 -0
  132. data/test/test_syntax.rb +444 -0
  133. data/test/test_user.rb +217 -0
  134. data/test/test_user_password.rb +108 -0
  135. data/test/test_useradd-binary.rb +62 -0
  136. data/test/test_useradd.rb +57 -0
  137. data/test/test_userdel.rb +48 -0
  138. data/test/test_userls.rb +91 -0
  139. data/test/test_usermod-binary-add-time.rb +65 -0
  140. data/test/test_usermod-binary-add.rb +64 -0
  141. data/test/test_usermod-binary-del.rb +66 -0
  142. data/test/test_usermod-lang-add.rb +59 -0
  143. data/test/test_usermod.rb +58 -0
  144. data/test/test_validation.rb +274 -0
  145. metadata +379 -0
@@ -0,0 +1,444 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'al-test-utils'
4
+
5
+ class TestSyntax < Test::Unit::TestCase
6
+ include AlTestUtils
7
+ include ActiveLdap::Helper
8
+
9
+ SYNTAXES = \
10
+ [
11
+ "( 1.3.6.1.1.16.1 DESC 'UUID' )",
12
+ "( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
13
+ "( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
14
+ "( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
15
+ "( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
16
+ "( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' " +
17
+ "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
18
+ "( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
19
+ "( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
20
+ "( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
21
+ "( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
22
+ "( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
23
+ "( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
24
+ "( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
25
+ "( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
26
+ "( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' X-NOT-HUMAN-READABLE 'TRUE' )",
27
+ "( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
28
+ "( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
29
+ "( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
30
+ "( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
31
+ "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
32
+ "( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
33
+ "( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
34
+ "( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
35
+ "( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
36
+ "( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " +
37
+ "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
38
+ "( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " +
39
+ "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
40
+ "( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " +
41
+ "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
42
+ "( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
43
+ "( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
44
+ "( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' X-NOT-HUMAN-READABLE 'TRUE' )",
45
+ "( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' X-NOT-HUMAN-READABLE 'TRUE' )"
46
+ ]
47
+
48
+ def setup
49
+ @schema = ActiveLdap::Schema.new("ldapSyntaxes" => SYNTAXES.dup)
50
+ @syntaxes = {}
51
+ @schema.ldap_syntaxes.each do |syntax|
52
+ @syntaxes[syntax.description] = syntax
53
+ end
54
+ end
55
+
56
+ def teardown
57
+ end
58
+
59
+ priority :must
60
+ def test_id_with_length
61
+ id = "1.3.6.1.4.1.1466.115.121.1.26"
62
+
63
+ syntax = ActiveLdap::Schema::Syntax.new(id, @schema)
64
+ assert_equal([id, nil], [syntax.id, syntax.length])
65
+
66
+ syntax = ActiveLdap::Schema::Syntax.new("#{id}{128}", @schema)
67
+ assert_equal([id, 128], [syntax.id, syntax.length])
68
+ end
69
+
70
+ priority :normal
71
+ def test_bit_string_type_cast
72
+ assert_type_cast_without_validation(nil, nil, 'Bit String')
73
+ assert_type_cast("0101111101", "'0101111101'B", 'Bit String')
74
+ end
75
+
76
+ def test_boolean_type_cast
77
+ assert_type_cast_without_validation(nil, nil, 'Boolean')
78
+ assert_type_cast(true, "TRUE", "Boolean")
79
+ assert_type_cast(false, "FALSE", "Boolean")
80
+ end
81
+
82
+ def test_boolean_normalize_value
83
+ assert_normalize_value("TRUE", true, 'Boolean')
84
+ assert_normalize_value("TRUE", "1", 'Boolean')
85
+ assert_normalize_value("FALSE", false, 'Boolean')
86
+ assert_normalize_value("FALSE", "0", 'Boolean')
87
+ end
88
+
89
+ def test_dn_type_cast
90
+ assert_type_cast_without_validation(nil, nil, 'Distinguished Name')
91
+ assert_dn_type_cast("cn=test", 'Distinguished Name')
92
+ end
93
+
94
+ class TestGeneralizedTime < self
95
+ private
96
+ def syntax_name
97
+ "Generalized Time"
98
+ end
99
+
100
+ class TestTypeCast < self
101
+ def test_nil
102
+ assert_type_cast_without_validation(nil, nil, syntax_name)
103
+ end
104
+
105
+ def test_timezone_none
106
+ assert_type_cast(Time.parse("1994/12/16 10:32:12"),
107
+ "19941216103212")
108
+ end
109
+
110
+ def test_timezone_Z
111
+ assert_type_cast(Time.parse("1994/12/16 10:32:12Z"),
112
+ "19941216103212Z")
113
+ end
114
+
115
+ def test_timezone_difference
116
+ assert_type_cast(Time.parse("1994/12/16 10:32:12.345 +09:00"),
117
+ "19941216103212.345+0900")
118
+ end
119
+
120
+ def test_year_month_day_hour_minute
121
+ assert_type_cast(Time.parse("2008/01/07 03:46:00"),
122
+ "200801070346")
123
+ end
124
+
125
+ def test_before_posix_time
126
+ time_can_handle_before_posix_time = false
127
+ begin
128
+ Time.utc(1601)
129
+ time_can_handle_before_posix_time = true
130
+ rescue ArgumentError
131
+ end
132
+
133
+ if time_can_handle_before_posix_time
134
+ assert_type_cast(Time.utc(1601, 1, 1, 0, 4, 17),
135
+ "16010101000417.0Z")
136
+ else
137
+ assert_type_cast(Time.at(0),
138
+ "16010101000417.0Z")
139
+ end
140
+ end
141
+
142
+ private
143
+ def assert_type_cast(type_casted_value, original_value)
144
+ super(type_casted_value, original_value, syntax_name)
145
+ end
146
+ end
147
+
148
+ class TestValidate < self
149
+ class TestValid < self
150
+ def test_no_timezone
151
+ assert_valid("19941216103201")
152
+ end
153
+
154
+ def test_timezone_Z
155
+ assert_valid("19941216103212Z")
156
+ end
157
+
158
+ def test_timezone_difference
159
+ assert_valid("19941216103230+0900")
160
+ end
161
+
162
+ def test_fraction_separator_period
163
+ assert_valid("20080107034615.0Z")
164
+ end
165
+
166
+ def test_fraction_separator_comma
167
+ assert_valid("20080107034615,123-0900")
168
+ end
169
+
170
+ def test_year_month_day_hour_minute
171
+ assert_valid("199412161032")
172
+ end
173
+
174
+ private
175
+ def assert_valid(value)
176
+ super(value, syntax_name)
177
+ end
178
+ end
179
+
180
+ class TestInvalid < self
181
+ def test_year_only
182
+ value = "1994"
183
+ params = [value.inspect, %w(month day hour minute).join(", ")]
184
+ assert_invalid(_("%s has missing components: %s") % params,
185
+ value)
186
+ end
187
+
188
+ def test_year_month_day_hour_only
189
+ value = "1994121610"
190
+ params = [value.inspect, %w(minute).join(", ")]
191
+ assert_invalid(_("%s has missing components: %s") % params,
192
+ value)
193
+ end
194
+
195
+ private
196
+ def assert_invalid(reason, value)
197
+ super(reason, value, syntax_name)
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ def test_integer_type_cast
204
+ assert_type_cast_without_validation(nil, nil, "Integer")
205
+ assert_type_cast(1321, "1321", "Integer")
206
+ end
207
+
208
+ def test_bit_string_validate
209
+ assert_valid("'0101111101'B", 'Bit String')
210
+ assert_valid("''B", 'Bit String')
211
+
212
+ value = "0101111101'B"
213
+ assert_invalid(_("%s doesn't have the first \"'\"") % value.inspect,
214
+ value, 'Bit String')
215
+
216
+ value = "'0101111101'"
217
+ assert_invalid(_("%s doesn't have the last \"'B\"") % value.inspect,
218
+ value, 'Bit String')
219
+
220
+ value = "'0101111101B"
221
+ assert_invalid(_("%s doesn't have the last \"'B\"") % value.inspect,
222
+ value, 'Bit String')
223
+
224
+ value = "'0A'B"
225
+ assert_invalid(_("%s has invalid character '%s'") % [value.inspect, "A"],
226
+ value, 'Bit String')
227
+ end
228
+
229
+ def test_boolean_validate
230
+ assert_valid("TRUE", "Boolean")
231
+ assert_valid("FALSE", "Boolean")
232
+
233
+ value = "true"
234
+ assert_invalid(_("%s should be TRUE or FALSE") % value.inspect,
235
+ value, "Boolean")
236
+ end
237
+
238
+ def test_country_string_validate
239
+ assert_valid("ja", "Country String")
240
+ assert_valid("JA", "Country String")
241
+
242
+ value = "japan"
243
+ assert_invalid(_("%s should be just 2 printable characters") % value.inspect,
244
+ value, "Country String")
245
+ end
246
+
247
+ def test_dn_validate
248
+ assert_valid("cn=test", 'Distinguished Name')
249
+ assert_valid("CN=Steve Kille,O=Isode Limited,C=GB", 'Distinguished Name')
250
+ assert_valid("OU=Sales+CN=J. Smith,O=Widget Inc.,C=US", 'Distinguished Name')
251
+ assert_valid("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB",
252
+ 'Distinguished Name')
253
+ assert_valid("CN=Before\\0DAfter,O=Test,C=GB", 'Distinguished Name')
254
+ assert_valid("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB",
255
+ 'Distinguished Name')
256
+ assert_valid("SN=Lu\\C4\\8Di\\C4\\87", 'Distinguished Name')
257
+
258
+ value = "test"
259
+ params = [value, _("attribute value is missing")]
260
+ assert_invalid(_('%s is invalid distinguished name (DN): %s') % params,
261
+ value, 'Distinguished Name')
262
+ end
263
+
264
+ def test_directory_string_validate
265
+ assert_valid("This is a string of DirectoryString containing \#!%\#@",
266
+ "Directory String")
267
+ assert_valid("これはDirectoryString文字列です。",
268
+ "Directory String")
269
+
270
+ value = "これはDirectoryString文字列です。"
271
+ if value.respond_to?(:encode)
272
+ value = value.encode("euc-jp")
273
+ else
274
+ value = NKF.nkf("-We", value)
275
+ end
276
+ assert_invalid(_("%s has invalid UTF-8 character") % value.inspect,
277
+ value, "Directory String")
278
+ end
279
+
280
+ def test_integer_validate
281
+ assert_valid("1321", "Integer")
282
+
283
+ assert_invalid_integer("13.5")
284
+ assert_invalid_integer("string")
285
+ end
286
+
287
+ def test_jpeg_validate
288
+ assert_valid([0xffd8].pack("n"), "JPEG")
289
+
290
+ assert_invalid(_("invalid JPEG format"), "", "JPEG")
291
+ assert_invalid(_("invalid JPEG format"), "jpeg", "JPEG")
292
+ end
293
+
294
+ def test_name_and_optional_uid_validate
295
+ assert_valid("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B",
296
+ "Name And Optional UID")
297
+ assert_valid("cn=test", "Name And Optional UID")
298
+
299
+ value = "test"
300
+ params = [value, _("attribute value is missing")]
301
+ assert_invalid(_('%s is invalid distinguished name (DN): %s') % params,
302
+ value, "Name And Optional UID")
303
+
304
+ bit_string = "'00x'B"
305
+ params = [bit_string.inspect, "x"]
306
+ assert_invalid(_("%s has invalid character '%s'") % params,
307
+ "cn=test\##{bit_string}", "Name And Optional UID")
308
+ end
309
+
310
+ def test_numeric_string_validate
311
+ assert_valid("1997", "Numeric String")
312
+
313
+ assert_invalid_numeric_string("-3")
314
+ assert_invalid_numeric_string("-3.5")
315
+ assert_invalid_numeric_string("string")
316
+ end
317
+
318
+ def test_oid_validate
319
+ assert_valid("1.2.3.4", "OID")
320
+ assert_valid("cn", "OID")
321
+
322
+ assert_invalid_oid("\#@!", "attribute type is missing")
323
+ end
324
+
325
+ def test_other_mailbox_validate
326
+ assert_valid("smtp$bob@example.com", "Other Mailbox")
327
+
328
+
329
+ value = "smtp"
330
+ assert_invalid(_("%s has no mailbox") % value.inspect,
331
+ value, "Other Mailbox")
332
+
333
+ value = "smtp$"
334
+ assert_invalid(_("%s has no mailbox") % value.inspect,
335
+ value, "Other Mailbox")
336
+
337
+ value = "$bob@example.com"
338
+ assert_invalid(_("%s has no mailbox type") % value.inspect,
339
+ value, "Other Mailbox")
340
+
341
+ value = "!$bob@example.com"
342
+ params = [value.inspect, "!"]
343
+ reason = _("%s has unprintable character in mailbox type: '%s'") % params
344
+ assert_invalid(reason, value, "Other Mailbox")
345
+ end
346
+
347
+ def test_postal_address_validate
348
+ assert_valid("1234 Main St.$Anytown, CA 12345$USA", "Postal Address")
349
+ assert_valid("\\241,000,000 Sweepstakes$PO Box 1000000$Anytown, " +
350
+ "CA 12345$USA", "Postal Address")
351
+ assert_valid("$", "Postal Address")
352
+ assert_valid("1234 Main St.$", "Postal Address")
353
+
354
+
355
+ assert_invalid(_("empty string"), "", "Postal Address")
356
+
357
+ value = "東京"
358
+ if value.respond_to?(:encode)
359
+ value = value.encode("euc-jp")
360
+ else
361
+ value = NKF.nkf("-We", value)
362
+ end
363
+ assert_invalid(_("%s has invalid UTF-8 character") % value.inspect,
364
+ value, "Postal Address")
365
+ end
366
+
367
+ def test_printable_string_validate
368
+ assert_valid("This is a PrintableString", "Printable String")
369
+
370
+ assert_invalid(_("empty string"), "", "Printable String")
371
+
372
+
373
+ value = "abc!def"
374
+ params = [value.inspect, "!"]
375
+ reason = _("%s has unprintable character: '%s'") % params
376
+ assert_invalid(reason, value, "Printable String")
377
+
378
+ value = "abcあdef"
379
+ params = [value.inspect, "あ"]
380
+ reason = _("%s has unprintable character: '%s'") % params
381
+ assert_invalid(reason, value, "Printable String")
382
+ end
383
+
384
+ def test_telephone_number_validate
385
+ assert_valid("+1 512 305 0280", "Telephone Number")
386
+ assert_valid("", "Telephone Number")
387
+
388
+ value = "+1 5!2 305 0280"
389
+ params = [value.inspect, "!"]
390
+ reason = _("%s has unprintable character: '%s'") % params
391
+ assert_invalid(reason, value, "Telephone Number")
392
+ end
393
+
394
+ private
395
+ def assert_valid(value, syntax_name)
396
+ assert_nil(@syntaxes[syntax_name].validate(value))
397
+ end
398
+
399
+ def assert_invalid(reason, value, syntax_name)
400
+ assert_equal(reason, @syntaxes[syntax_name].validate(value))
401
+ end
402
+
403
+ def assert_invalid_integer(value)
404
+ assert_invalid(_("%s is invalid integer format") % value.inspect,
405
+ value, "Integer")
406
+ end
407
+
408
+ def assert_invalid_numeric_string(value)
409
+ assert_invalid(_("%s is invalid numeric format") % value.inspect,
410
+ value, "Numeric String")
411
+ end
412
+
413
+ def assert_invalid_oid(value, reason=nil)
414
+ if reason
415
+ message = _("%s is invalid OID format: %s") % [value.inspect, _(reason)]
416
+ else
417
+ message = _("%s is invalid OID format") % value.inspect
418
+ end
419
+ assert_invalid(message, value, "OID")
420
+ end
421
+
422
+ def assert_type_cast_without_validation(type_casted_value, original_value,
423
+ syntax_name)
424
+ syntax = @syntaxes[syntax_name]
425
+ assert_equal(type_casted_value, syntax.type_cast(original_value))
426
+ assert_equal(type_casted_value, syntax.type_cast(type_casted_value))
427
+ end
428
+
429
+ def assert_type_cast(type_casted_value, original_value, syntax_name)
430
+ assert_type_cast_without_validation(type_casted_value, original_value,
431
+ syntax_name)
432
+ assert_valid(type_casted_value, syntax_name)
433
+ end
434
+
435
+ def assert_dn_type_cast(original_value, syntax_name)
436
+ assert_type_cast(ActiveLdap::DN.parse(original_value), original_value,
437
+ syntax_name)
438
+ end
439
+
440
+ def assert_normalize_value(normalized_value, original_value, syntax_name)
441
+ syntax = @syntaxes[syntax_name]
442
+ assert_equal(normalized_value, syntax.normalize_value(original_value))
443
+ end
444
+ end
@@ -0,0 +1,217 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestUser < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ # This adds all required attributes and writes
7
+ def test_add
8
+ ensure_delete_user("test-user") do |uid|
9
+ user = @user_class.new(uid)
10
+
11
+ assert(user.new_entry?, "#{uid} must not exist in LDAP prior to testing")
12
+
13
+ assert_equal(['posixAccount', 'person'].sort, user.classes.sort,
14
+ "Class User's ldap_mapping should specify " +
15
+ "['posixAccount', 'person']. This was not returned.")
16
+
17
+ user.add_class('posixAccount', 'shadowAccount',
18
+ 'person', 'inetOrgPerson', 'organizationalPerson')
19
+
20
+ cn = 'Test User (Default Language)'
21
+ user.cn = cn
22
+ assert_equal(cn, user.cn, 'user.cn should have returned "#{cn}"')
23
+
24
+ # test force_array
25
+ assert_equal([cn], user.cn(true),
26
+ 'user.cn(true) should have returned "[#{cn}]"')
27
+
28
+ cn = {'lang-en-us' => 'Test User (EN-US Language)'}
29
+ user.cn = cn
30
+ # Test subtypes
31
+ assert_equal(cn, user.cn, 'user.cn should match')
32
+
33
+ cn = ['Test User (Default Language)',
34
+ {'lang-en-us' => ['Test User (EN-US Language)', 'Foo']}]
35
+ user.cn = cn
36
+ # Test multiple entries with subtypes
37
+ assert_equal(cn, user.cn,
38
+ 'This should have returned an array of a ' +
39
+ 'normal cn and a lang-en-us cn.')
40
+
41
+ uid_number = "9000"
42
+ user.uid_number = uid_number
43
+ assert_equal(uid_number.to_i, user.uid_number)
44
+ assert_equal(uid_number, user.uid_number_before_type_cast)
45
+
46
+ gid_number = 9000
47
+ user.gid_number = gid_number
48
+ assert_equal(gid_number, user.gid_number)
49
+ assert_equal(gid_number, user.gid_number_before_type_cast)
50
+
51
+ home_directory = '/home/foo'
52
+ user.home_directory = home_directory
53
+ # just for sanity's sake
54
+ assert_equal(home_directory, user.home_directory,
55
+ 'This should be #{home_directory.dump}.')
56
+ assert_equal([home_directory], user.home_directory(true),
57
+ 'This should be [#{home_directory.dump}].')
58
+
59
+ see_also = "cn=XXX,dc=local,dc=net"
60
+ user.see_also = see_also
61
+ assert_equal(ActiveLdap::DN.parse(see_also), user.see_also)
62
+
63
+ see_also = ActiveLdap::DN.parse(see_also)
64
+ user.see_also = see_also
65
+ assert_equal(see_also, user.see_also)
66
+
67
+ assert(!user.valid?)
68
+ assert(user.errors[:sn].any?)
69
+ errors = %w(person organizationalPerson
70
+ inetOrgPerson).collect do |object_class|
71
+ if ActiveLdap.get_text_supported?
72
+ format = _("is required attribute by objectClass '%s': " \
73
+ "aliases: %s")
74
+ format = user._(format)
75
+ format % [user.class.human_object_class_name(object_class),
76
+ user.class.human_attribute_name("surname")]
77
+ else
78
+ format = "is required attribute by objectClass '%s': aliases: %s"
79
+ user._(format) % [object_class, "surname"]
80
+ end
81
+ end
82
+ assert_equal(errors.sort, user.errors[:sn].sort)
83
+ user.sn = ['User']
84
+ assert(user.valid?)
85
+ assert_equal(0, user.errors.size)
86
+
87
+ assert_nothing_raised {user.save!}
88
+
89
+ user.user_certificate = certificate
90
+ user.jpeg_photo = jpeg_photo
91
+
92
+ assert(ActiveLdap::Base.schema.attribute('jpegPhoto').binary?,
93
+ 'jpegPhoto is binary?')
94
+
95
+ assert(ActiveLdap::Base.schema.attribute('userCertificate').binary?,
96
+ 'userCertificate is binary?')
97
+ assert_nothing_raised {user.save!}
98
+ end
99
+ end
100
+
101
+
102
+ # This tests the reload of a binary_required type
103
+ def test_binary_required
104
+ require 'openssl'
105
+ make_temporary_user do |user, password|
106
+ # validate add
107
+ user.user_certificate = nil
108
+ assert_nil(user.user_certificate)
109
+ assert_nothing_raised() { user.save! }
110
+ assert_nil(user.user_certificate)
111
+
112
+ user.user_certificate = {"binary" => [certificate]}
113
+ assert_equal(certificate, user.user_certificate)
114
+ assert_nothing_raised() { user.save! }
115
+ assert_equal(certificate, user.user_certificate)
116
+
117
+ # now test modify
118
+ user.user_certificate = nil
119
+ assert_nil(user.user_certificate)
120
+ assert_nothing_raised() { user.save! }
121
+ assert_nil(user.user_certificate)
122
+
123
+ user.user_certificate = certificate
124
+ assert_equal(certificate, user.user_certificate)
125
+ assert_nothing_raised() { user.save! }
126
+
127
+ # validate modify
128
+ user = @user_class.find(user.uid)
129
+ assert_equal(certificate, user.user_certificate)
130
+
131
+ expected_cert = OpenSSL::X509::Certificate.new(certificate)
132
+ actual_cert = user.user_certificate
133
+ actual_cert = OpenSSL::X509::Certificate.new(actual_cert)
134
+ assert_equal(expected_cert.subject.to_s,
135
+ actual_cert.subject.to_s,
136
+ 'Cert must parse correctly still')
137
+ end
138
+ end
139
+
140
+ def test_binary_required_nested
141
+ make_temporary_user do |user, password|
142
+ user.user_certificate = {"lang-en" => [certificate]}
143
+ assert_equal({'lang-en' => certificate},
144
+ user.user_certificate)
145
+ assert_nothing_raised() { user.save! }
146
+ assert_equal({'lang-en' => certificate},
147
+ user.user_certificate)
148
+ end
149
+ end
150
+
151
+ # This tests the reload of a binary type (not forced!)
152
+ def test_binary
153
+ make_temporary_user do |user, password|
154
+ # reload and see what happens
155
+ assert_equal(jpeg_photo, user.jpeg_photo,
156
+ "This should have been equal to #{jpeg_photo_path.dump}")
157
+
158
+ # now test modify
159
+ user.jpeg_photo = nil
160
+ assert_nil(user.jpeg_photo)
161
+ assert_nothing_raised() { user.save! }
162
+ assert_nil(user.jpeg_photo)
163
+
164
+ user.jpeg_photo = jpeg_photo
165
+ assert_equal(jpeg_photo, user.jpeg_photo)
166
+ assert_nothing_raised() { user.save! }
167
+
168
+ # now validate modify
169
+ user = @user_class.find(user.uid)
170
+ assert_equal(jpeg_photo, user.jpeg_photo)
171
+ end
172
+ end
173
+
174
+ # This tests the removal of a objectclass
175
+ def test_remove_object_class
176
+ make_temporary_user do |user, password|
177
+ assert_nil(user.shadow_max,
178
+ 'Should get the default nil value for shadowMax')
179
+
180
+ # Remove shadowAccount
181
+ user.remove_class('shadowAccount')
182
+ assert(user.valid?)
183
+ assert_nothing_raised() { user.save! }
184
+
185
+ assert_raise(NoMethodError,
186
+ 'shadowMax should not be defined anymore' ) do
187
+ user.shadow_max
188
+ end
189
+ end
190
+ end
191
+
192
+
193
+ # Just modify a few random attributes
194
+ def test_modify_with_subtypes
195
+ make_temporary_user do |user, password|
196
+ cn = ['Test User', {'lang-en-us' => ['Test User', 'wad']}]
197
+ user.cn = cn
198
+ assert_nothing_raised() { user.save! }
199
+
200
+ user = @user_class.find(user.uid)
201
+ assert_equal(cn, user.cn,
202
+ 'Making sure a modify with mixed subtypes works')
203
+ end
204
+ end
205
+
206
+ # This tests some invalid input handling
207
+ def test_invalid_input
208
+ end
209
+
210
+ # This tests deletion
211
+ def test_destroy
212
+ make_temporary_user do |user, password|
213
+ user.destroy
214
+ assert(user.new_entry?, 'user should no longer exist')
215
+ end
216
+ end
217
+ end