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.
- checksums.yaml +7 -0
- data/.yardopts +6 -0
- data/COPYING +340 -0
- data/Gemfile +12 -0
- data/LICENSE +59 -0
- data/README.textile +140 -0
- data/TODO +32 -0
- data/benchmark/README.md +64 -0
- data/benchmark/bench-backend.rb +247 -0
- data/benchmark/bench-instantiate.rb +98 -0
- data/benchmark/config.yaml.sample +5 -0
- data/doc/text/development.textile +54 -0
- data/doc/text/news.textile +811 -0
- data/doc/text/rails.textile +144 -0
- data/doc/text/tutorial.textile +1010 -0
- data/examples/config.yaml.example +5 -0
- data/examples/example.der +0 -0
- data/examples/example.jpg +0 -0
- data/examples/groupadd +41 -0
- data/examples/groupdel +35 -0
- data/examples/groupls +49 -0
- data/examples/groupmod +42 -0
- data/examples/lpasswd +55 -0
- data/examples/objects/group.rb +13 -0
- data/examples/objects/ou.rb +4 -0
- data/examples/objects/user.rb +20 -0
- data/examples/ouadd +38 -0
- data/examples/useradd +45 -0
- data/examples/useradd-binary +53 -0
- data/examples/userdel +34 -0
- data/examples/userls +50 -0
- data/examples/usermod +42 -0
- data/examples/usermod-binary-add +50 -0
- data/examples/usermod-binary-add-time +54 -0
- data/examples/usermod-binary-del +48 -0
- data/examples/usermod-lang-add +43 -0
- data/lib/active_ldap.rb +85 -0
- data/lib/active_ldap/action_controller/ldap_benchmarking.rb +55 -0
- data/lib/active_ldap/acts/tree.rb +78 -0
- data/lib/active_ldap/adapter/base.rb +707 -0
- data/lib/active_ldap/adapter/jndi.rb +184 -0
- data/lib/active_ldap/adapter/jndi_connection.rb +185 -0
- data/lib/active_ldap/adapter/ldap.rb +290 -0
- data/lib/active_ldap/adapter/ldap_ext.rb +105 -0
- data/lib/active_ldap/adapter/net_ldap.rb +309 -0
- data/lib/active_ldap/adapter/net_ldap_ext.rb +23 -0
- data/lib/active_ldap/association/belongs_to.rb +47 -0
- data/lib/active_ldap/association/belongs_to_many.rb +58 -0
- data/lib/active_ldap/association/children.rb +21 -0
- data/lib/active_ldap/association/collection.rb +105 -0
- data/lib/active_ldap/association/has_many.rb +31 -0
- data/lib/active_ldap/association/has_many_utils.rb +44 -0
- data/lib/active_ldap/association/has_many_wrap.rb +75 -0
- data/lib/active_ldap/association/proxy.rb +107 -0
- data/lib/active_ldap/associations.rb +205 -0
- data/lib/active_ldap/attribute_methods.rb +23 -0
- data/lib/active_ldap/attribute_methods/before_type_cast.rb +24 -0
- data/lib/active_ldap/attribute_methods/dirty.rb +43 -0
- data/lib/active_ldap/attribute_methods/query.rb +31 -0
- data/lib/active_ldap/attribute_methods/read.rb +44 -0
- data/lib/active_ldap/attribute_methods/write.rb +38 -0
- data/lib/active_ldap/attributes.rb +176 -0
- data/lib/active_ldap/base.rb +1410 -0
- data/lib/active_ldap/callbacks.rb +71 -0
- data/lib/active_ldap/command.rb +49 -0
- data/lib/active_ldap/compatible.rb +44 -0
- data/lib/active_ldap/configuration.rb +147 -0
- data/lib/active_ldap/connection.rb +299 -0
- data/lib/active_ldap/distinguished_name.rb +291 -0
- data/lib/active_ldap/entry_attribute.rb +78 -0
- data/lib/active_ldap/escape.rb +12 -0
- data/lib/active_ldap/get_text.rb +20 -0
- data/lib/active_ldap/get_text/parser.rb +161 -0
- data/lib/active_ldap/helper.rb +92 -0
- data/lib/active_ldap/human_readable.rb +133 -0
- data/lib/active_ldap/ldap_error.rb +74 -0
- data/lib/active_ldap/ldif.rb +930 -0
- data/lib/active_ldap/log_subscriber.rb +50 -0
- data/lib/active_ldap/object_class.rb +95 -0
- data/lib/active_ldap/operations.rb +624 -0
- data/lib/active_ldap/persistence.rb +100 -0
- data/lib/active_ldap/populate.rb +53 -0
- data/lib/active_ldap/railtie.rb +43 -0
- data/lib/active_ldap/railties/controller_runtime.rb +48 -0
- data/lib/active_ldap/schema.rb +701 -0
- data/lib/active_ldap/schema/syntaxes.rb +422 -0
- data/lib/active_ldap/timeout.rb +75 -0
- data/lib/active_ldap/timeout_stub.rb +17 -0
- data/lib/active_ldap/user_password.rb +99 -0
- data/lib/active_ldap/validations.rb +200 -0
- data/lib/active_ldap/version.rb +3 -0
- data/lib/active_ldap/xml.rb +139 -0
- data/lib/rails/generators/active_ldap/model/USAGE +18 -0
- data/lib/rails/generators/active_ldap/model/model_generator.rb +47 -0
- data/lib/rails/generators/active_ldap/model/templates/model_active_ldap.rb +3 -0
- data/lib/rails/generators/active_ldap/scaffold/scaffold_generator.rb +14 -0
- data/lib/rails/generators/active_ldap/scaffold/templates/ldap.yml +19 -0
- data/po/en/active-ldap.po +4029 -0
- data/po/ja/active-ldap.po +4060 -0
- data/test/add-phonetic-attribute-options-to-slapd.ldif +10 -0
- data/test/al-test-utils.rb +428 -0
- data/test/command.rb +111 -0
- data/test/config.yaml.sample +6 -0
- data/test/fixtures/lower_case_object_class_schema.rb +802 -0
- data/test/run-test.rb +34 -0
- data/test/test_acts_as_tree.rb +60 -0
- data/test/test_adapter.rb +121 -0
- data/test/test_associations.rb +701 -0
- data/test/test_attributes.rb +117 -0
- data/test/test_base.rb +1214 -0
- data/test/test_base_per_instance.rb +61 -0
- data/test/test_bind.rb +62 -0
- data/test/test_callback.rb +31 -0
- data/test/test_configuration.rb +40 -0
- data/test/test_connection.rb +82 -0
- data/test/test_connection_per_class.rb +112 -0
- data/test/test_connection_per_dn.rb +112 -0
- data/test/test_dirty.rb +98 -0
- data/test/test_dn.rb +172 -0
- data/test/test_find.rb +176 -0
- data/test/test_groupadd.rb +50 -0
- data/test/test_groupdel.rb +46 -0
- data/test/test_groupls.rb +107 -0
- data/test/test_groupmod.rb +51 -0
- data/test/test_ldif.rb +1890 -0
- data/test/test_load.rb +133 -0
- data/test/test_lpasswd.rb +75 -0
- data/test/test_object_class.rb +74 -0
- data/test/test_persistence.rb +131 -0
- data/test/test_reflection.rb +175 -0
- data/test/test_schema.rb +559 -0
- data/test/test_syntax.rb +444 -0
- data/test/test_user.rb +217 -0
- data/test/test_user_password.rb +108 -0
- data/test/test_useradd-binary.rb +62 -0
- data/test/test_useradd.rb +57 -0
- data/test/test_userdel.rb +48 -0
- data/test/test_userls.rb +91 -0
- data/test/test_usermod-binary-add-time.rb +65 -0
- data/test/test_usermod-binary-add.rb +64 -0
- data/test/test_usermod-binary-del.rb +66 -0
- data/test/test_usermod-lang-add.rb +59 -0
- data/test/test_usermod.rb +58 -0
- data/test/test_validation.rb +274 -0
- metadata +379 -0
data/test/test_syntax.rb
ADDED
|
@@ -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
|
data/test/test_user.rb
ADDED
|
@@ -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
|