ruby-activeldap 0.7.4 → 0.8.0

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 (74) hide show
  1. data/CHANGES +375 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +58 -0
  4. data/Manifest.txt +33 -0
  5. data/README +63 -0
  6. data/Rakefile +37 -0
  7. data/TODO +31 -0
  8. data/benchmark/bench-al.rb +152 -0
  9. data/lib/{activeldap.rb → active_ldap.rb} +280 -263
  10. data/lib/active_ldap/adaptor/base.rb +29 -0
  11. data/lib/active_ldap/adaptor/ldap.rb +466 -0
  12. data/lib/active_ldap/association/belongs_to.rb +38 -0
  13. data/lib/active_ldap/association/belongs_to_many.rb +40 -0
  14. data/lib/active_ldap/association/collection.rb +80 -0
  15. data/lib/active_ldap/association/has_many.rb +48 -0
  16. data/lib/active_ldap/association/has_many_wrap.rb +56 -0
  17. data/lib/active_ldap/association/proxy.rb +89 -0
  18. data/lib/active_ldap/associations.rb +162 -0
  19. data/lib/active_ldap/attributes.rb +199 -0
  20. data/lib/active_ldap/base.rb +1343 -0
  21. data/lib/active_ldap/callbacks.rb +19 -0
  22. data/lib/active_ldap/command.rb +46 -0
  23. data/lib/active_ldap/configuration.rb +96 -0
  24. data/lib/active_ldap/connection.rb +137 -0
  25. data/lib/{activeldap → active_ldap}/ldap.rb +1 -1
  26. data/lib/active_ldap/object_class.rb +70 -0
  27. data/lib/active_ldap/schema.rb +258 -0
  28. data/lib/{activeldap → active_ldap}/timeout.rb +0 -0
  29. data/lib/{activeldap → active_ldap}/timeout_stub.rb +0 -0
  30. data/lib/active_ldap/user_password.rb +92 -0
  31. data/lib/active_ldap/validations.rb +78 -0
  32. data/rails/plugin/active_ldap/README +54 -0
  33. data/rails/plugin/active_ldap/init.rb +6 -0
  34. data/test/TODO +2 -0
  35. data/test/al-test-utils.rb +337 -0
  36. data/test/command.rb +62 -0
  37. data/test/config.yaml +8 -0
  38. data/test/config.yaml.sample +6 -0
  39. data/test/run-test.rb +17 -0
  40. data/test/test-unit-ext.rb +2 -0
  41. data/test/test_associations.rb +334 -0
  42. data/test/test_attributes.rb +71 -0
  43. data/test/test_base.rb +345 -0
  44. data/test/test_base_per_instance.rb +32 -0
  45. data/test/test_bind.rb +53 -0
  46. data/test/test_callback.rb +35 -0
  47. data/test/test_connection.rb +38 -0
  48. data/test/test_connection_per_class.rb +50 -0
  49. data/test/test_find.rb +36 -0
  50. data/test/test_groupadd.rb +50 -0
  51. data/test/test_groupdel.rb +46 -0
  52. data/test/test_groupls.rb +107 -0
  53. data/test/test_groupmod.rb +51 -0
  54. data/test/test_lpasswd.rb +75 -0
  55. data/test/test_object_class.rb +32 -0
  56. data/test/test_reflection.rb +173 -0
  57. data/test/test_schema.rb +166 -0
  58. data/test/test_user.rb +209 -0
  59. data/test/test_user_password.rb +93 -0
  60. data/test/test_useradd-binary.rb +59 -0
  61. data/test/test_useradd.rb +55 -0
  62. data/test/test_userdel.rb +48 -0
  63. data/test/test_userls.rb +86 -0
  64. data/test/test_usermod-binary-add-time.rb +62 -0
  65. data/test/test_usermod-binary-add.rb +61 -0
  66. data/test/test_usermod-binary-del.rb +64 -0
  67. data/test/test_usermod-lang-add.rb +57 -0
  68. data/test/test_usermod.rb +56 -0
  69. data/test/test_validation.rb +38 -0
  70. metadata +94 -21
  71. data/lib/activeldap/associations.rb +0 -170
  72. data/lib/activeldap/base.rb +0 -1456
  73. data/lib/activeldap/configuration.rb +0 -59
  74. data/lib/activeldap/schema2.rb +0 -217
@@ -0,0 +1,32 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestObjectClass < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ priority :must
7
+
8
+ priority :normal
9
+ def test_unknown_object_class
10
+ make_temporary_group do |group|
11
+ assert_raises(ActiveLdap::ObjectClassError) do
12
+ group.add_class("unknownObjectClass")
13
+ end
14
+ end
15
+ end
16
+
17
+ def test_remove_required_class
18
+ make_temporary_group do |group|
19
+ assert_raises(ActiveLdap::RequiredObjectClassMissed) do
20
+ group.remove_class("posixGroup")
21
+ end
22
+ end
23
+ end
24
+
25
+ def test_invalid_object_class_value
26
+ make_temporary_group do |group|
27
+ assert_raises(TypeError) {group.add_class(:posixAccount)}
28
+ end
29
+ end
30
+
31
+ priority :normal
32
+ end
@@ -0,0 +1,173 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestReflection < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ priority :must
7
+
8
+ priority :normal
9
+ def test_base_class
10
+ assert_equal(ActiveLdap::Base, ActiveLdap::Base.base_class)
11
+ assert_equal(@user_class, @user_class.base_class)
12
+ sub_user_class = Class.new(@user_class)
13
+ assert_equal(@user_class, sub_user_class.base_class)
14
+ end
15
+
16
+ def test_respond_to?
17
+ make_temporary_user do |user, password|
18
+ attributes = user.must + user.may
19
+ _wrap_assertion do
20
+ attributes.each do |name|
21
+ assert(user.respond_to?(name), name)
22
+ assert(user.respond_to?("#{name}="), "#{name}=")
23
+ assert(user.respond_to?("#{name}?"), "#{name}?")
24
+ assert(user.respond_to?("#{name}_before_type_cast"),
25
+ "#{name}_before_type_cast")
26
+ end
27
+ end
28
+
29
+ user.replace_class(user.class.required_classes)
30
+ new_attributes = collect_attributes(user.class.required_classes)
31
+
32
+ _wrap_assertion do
33
+ assert_not_equal([], new_attributes)
34
+ new_attributes.each do |name|
35
+ assert(user.respond_to?(name), name)
36
+ assert(user.respond_to?("#{name}="), "#{name}=")
37
+ assert(user.respond_to?("#{name}?"), "#{name}?")
38
+ assert(user.respond_to?("#{name}_before_type_cast"),
39
+ "#{name}_before_type_cast")
40
+ end
41
+
42
+ remained_attributes = (attributes - new_attributes)
43
+ assert_not_equal([], remained_attributes)
44
+ remained_attributes.each do |name|
45
+ assert(!user.respond_to?(name), name)
46
+ assert(!user.respond_to?("#{name}="), "#{name}=")
47
+ assert(!user.respond_to?("#{name}?"), "#{name}?")
48
+ assert(!user.respond_to?("#{name}_before_type_cast"),
49
+ "#{name}_before_type_cast")
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def test_methods
56
+ make_temporary_user do |user, password|
57
+ assert_equal(user.methods.uniq.size, user.methods.size)
58
+ assert_equal(user.methods(false).uniq.size, user.methods(false).size)
59
+ end
60
+
61
+ make_temporary_user do |user, password|
62
+ attributes = user.must + user.may - ["objectClass"]
63
+ assert_equal([], attributes - user.methods)
64
+ assert_equal([], attributes - user.methods(false))
65
+
66
+ assert_methods_with_only_required_classes(user, attributes)
67
+ end
68
+
69
+ make_temporary_user do |user, password|
70
+ user.remove_class("inetOrgPerson")
71
+ attributes = user.must + user.may - ["objectClass"]
72
+ assert_equal([], attributes - user.methods)
73
+ assert_equal([], attributes - user.methods(false))
74
+
75
+ assert_methods_with_only_required_classes(user, attributes)
76
+ end
77
+
78
+ make_temporary_user do |user, password|
79
+ attributes = user.must + user.may - ["objectClass"]
80
+ attributes = attributes.collect {|x| x.downcase}
81
+ assert_not_equal([], attributes - user.methods)
82
+ assert_not_equal([], attributes - user.methods(false))
83
+
84
+ normalize_attributes_list = Proc.new do |*attributes_list|
85
+ attributes_list.collect do |attrs|
86
+ attrs.collect {|x| x.downcase}
87
+ end
88
+ end
89
+ assert_methods_with_only_required_classes(user, attributes,
90
+ &normalize_attributes_list)
91
+ end
92
+
93
+ make_temporary_user do |user, password|
94
+ attributes = user.must + user.may - ["objectClass"]
95
+ attributes = attributes.collect do |x|
96
+ Inflector.underscore(x)
97
+ end
98
+ assert_equal([], attributes - user.methods)
99
+ assert_equal([], attributes - user.methods(false))
100
+
101
+ normalize_attributes_list = Proc.new do |*attributes_list|
102
+ attributes_list.collect do |attrs|
103
+ attrs.collect {|x| Inflector.underscore(x)}
104
+ end
105
+ end
106
+ assert_methods_with_only_required_classes(user, attributes,
107
+ &normalize_attributes_list)
108
+ end
109
+
110
+ make_temporary_user do |user, password|
111
+ user.remove_class("inetOrgPerson")
112
+ attributes = user.must + user.may - ["objectClass"]
113
+ attributes = attributes.collect do |x|
114
+ Inflector.underscore(x)
115
+ end
116
+ assert_equal([], attributes - user.methods)
117
+ assert_equal([], attributes - user.methods(false))
118
+
119
+ normalize_attributes_list = Proc.new do |*attributes_list|
120
+ attributes_list.collect do |attrs|
121
+ attrs.collect {|x| Inflector.underscore(x)}
122
+ end
123
+ end
124
+ assert_methods_with_only_required_classes(user, attributes,
125
+ &normalize_attributes_list)
126
+ end
127
+ end
128
+
129
+ def test_attribute_names
130
+ make_temporary_user do |user, password|
131
+ attributes = collect_attributes(user.classes)
132
+ assert_equal([], attributes.uniq - user.attribute_names)
133
+ assert_equal([], user.attribute_names - attributes.uniq)
134
+ end
135
+ end
136
+
137
+ def assert_methods_with_only_required_classes(object, attributes)
138
+ old_classes = (object.classes - object.class.required_classes).uniq
139
+ old_attributes = collect_attributes(old_classes, false).uniq.sort
140
+ required_attributes = collect_attributes(object.class.required_classes,
141
+ false).uniq.sort
142
+ if block_given?
143
+ old_attributes, required_attributes =
144
+ yield(old_attributes, required_attributes)
145
+ end
146
+
147
+ object.replace_class(object.class.required_classes)
148
+
149
+ assert_equal([],
150
+ old_attributes -
151
+ (attributes - object.methods - required_attributes) -
152
+ required_attributes)
153
+ assert_equal([],
154
+ old_attributes -
155
+ (attributes - object.methods(false) - required_attributes) -
156
+ required_attributes)
157
+ end
158
+
159
+ def collect_attributes(object_classes, with_aliases=true)
160
+ attributes = []
161
+ object_classes.each do |object_class|
162
+ attrs = ActiveLdap::Base.schema.class_attributes(object_class)
163
+ if with_aliases
164
+ (attrs[:must] + attrs[:may]).each do |name|
165
+ attributes.concat(ActiveLdap::Base.schema.attribute_aliases(name))
166
+ end
167
+ else
168
+ attributes.concat(attrs[:must] + attrs[:may])
169
+ end
170
+ end
171
+ attributes
172
+ end
173
+ end
@@ -0,0 +1,166 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestSchema < Test::Unit::TestCase
4
+ def test_name_as_key
5
+ top_schema = "( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' " +
6
+ "ABSTRACT MUST objectClass )"
7
+ expect = {
8
+ :name => ["top"],
9
+ :desc => ['top of the superclass chain'],
10
+ :abstract => ["TRUE"],
11
+ :must => ["objectClass"]
12
+ }
13
+ assert_schema(expect, "2.5.6.0", top_schema)
14
+ assert_schema(expect, "top", top_schema)
15
+ end
16
+
17
+ def test_name_as_key_for_multiple_name
18
+ uid_schema = "( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' ) " +
19
+ "DESC 'RFC1274: user identifier' EQUALITY caseIgnoreMatch " +
20
+ "SUBSTR caseIgnoreSubstringsMatch " +
21
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )"
22
+
23
+ expect = {
24
+ :name => ["uid", "userid"],
25
+ :desc => ['RFC1274: user identifier'],
26
+ :equality => ["caseIgnoreMatch"],
27
+ :substr => ["caseIgnoreSubstringsMatch"],
28
+ :syntax => ["1.3.6.1.4.1.1466.115.121.1.15{256}"],
29
+ }
30
+ assert_schema(expect, "0.9.2342.19200300.100.1.1", uid_schema)
31
+ assert_schema(expect, "uid", uid_schema)
32
+ assert_schema(expect, "userid", uid_schema)
33
+ end
34
+
35
+ def test_dollar
36
+ dn_match_schema = "( 2.5.13.1 NAME 'distinguishedNameMatch' APPLIES " +
37
+ "( creatorsName $ modifiersName $ subschemaSubentry " +
38
+ "$ namingContexts $ aliasedObjectName $ " +
39
+ "distinguishedName $ seeAlso $ olcDefaultSearchBase $ " +
40
+ "olcRootDN $ olcSchemaDN $ olcSuffix $ olcUpdateDN $ " +
41
+ "member $ owner $ roleOccupant $ manager $ " +
42
+ "documentAuthor $ secretary $ associatedName $ " +
43
+ "dITRedirect ) )"
44
+
45
+ expect = {
46
+ :name => ["distinguishedNameMatch"],
47
+ :applies => %w(creatorsName modifiersName subschemaSubentry
48
+ namingContexts aliasedObjectName
49
+ distinguishedName seeAlso olcDefaultSearchBase
50
+ olcRootDN olcSchemaDN olcSuffix olcUpdateDN
51
+ member owner roleOccupant manager
52
+ documentAuthor secretary associatedName
53
+ dITRedirect),
54
+ }
55
+ assert_schema(expect, "2.5.13.1", dn_match_schema)
56
+ assert_schema(expect, "distinguishedNameMatch", dn_match_schema)
57
+ end
58
+
59
+ def test_dc_object
60
+ dc_object_schema = "( 1.3.6.1.4.1.1466.344 NAME 'dcObject' DESC " +
61
+ "'RFC2247: domain component object' SUP top " +
62
+ "AUXILIARY MUST dc )"
63
+
64
+ expect = {
65
+ :name => ["dcObject"],
66
+ :desc => ['RFC2247: domain component object'],
67
+ :auxiliary => ["TRUE"],
68
+ :must => ["dc"],
69
+ }
70
+ assert_schema(expect, "1.3.6.1.4.1.1466.344", dc_object_schema)
71
+ assert_schema(expect, "dcObject", dc_object_schema)
72
+ end
73
+
74
+ def test_organization
75
+ organization_schema = "( 2.5.6.4 NAME 'organization' DESC " +
76
+ "'RFC2256: an organization' SUP top STRUCTURAL " +
77
+ "MUST o MAY ( userPassword $ searchGuide $ " +
78
+ "seeAlso $ businessCategory $ x121Address $ " +
79
+ "registeredAddress $ destinationIndicator $ " +
80
+ "preferredDeliveryMethod $ telexNumber $ " +
81
+ "teletexTerminalIdentifier $ telephoneNumber $ " +
82
+ "internationaliSDNNumber $ " +
83
+ "facsimileTelephoneNumber $ street $ " +
84
+ "postOfficeBox $ postalCode $ postalAddress $ " +
85
+ "physicalDeliveryOfficeName $ st $ l $ " +
86
+ "description ) )"
87
+
88
+ expect = {
89
+ :name => ["organization"],
90
+ :desc => ['RFC2256: an organization'],
91
+ :sup => ["top"],
92
+ :structural => ["TRUE"],
93
+ :must => ["o"],
94
+ :may => %w(userPassword searchGuide seeAlso businessCategory
95
+ x121Address registeredAddress destinationIndicator
96
+ preferredDeliveryMethod telexNumber
97
+ teletexTerminalIdentifier telephoneNumber
98
+ internationaliSDNNumber
99
+ facsimileTelephoneNumber street
100
+ postOfficeBox postalCode postalAddress
101
+ physicalDeliveryOfficeName st l description),
102
+ }
103
+ assert_schema(expect, "2.5.6.4", organization_schema)
104
+ assert_schema(expect, "organization", organization_schema)
105
+ end
106
+
107
+ def test_posix_account
108
+ posix_account_schema = "( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC " +
109
+ "'Abstraction of an account with POSIX " +
110
+ "attributes' SUP top AUXILIARY MUST ( cn $ " +
111
+ "uid $ uidNumber $ gidNumber $ homeDirectory " +
112
+ ") MAY ( userPassword $ loginShell $ gecos $ " +
113
+ "description ) )"
114
+ expect = {
115
+ :name => ["posixAccount"],
116
+ :desc => ['Abstraction of an account with POSIX attributes'],
117
+ :sup => ["top"],
118
+ :auxiliary => ["TRUE"],
119
+ :must => %w(cn uid uidNumber gidNumber homeDirectory),
120
+ :may => %w(userPassword loginShell gecos description),
121
+ }
122
+ assert_schema(expect, "1.3.6.1.1.1.2.0", posix_account_schema)
123
+ assert_schema(expect, "posixAccount", posix_account_schema)
124
+ end
125
+
126
+ def test_jpeg_photo
127
+ jpeg_photo_schema = "( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' " +
128
+ "DESC 'RFC2798: a JPEG image' SYNTAX " +
129
+ "1.3.6.1.4.1.1466.115.121.1.28 )"
130
+ expect = {
131
+ :name => ["jpegPhoto"],
132
+ :desc => ['RFC2798: a JPEG image'],
133
+ :syntax => ["1.3.6.1.4.1.1466.115.121.1.28"],
134
+ }
135
+ assert_schema(expect, "0.9.2342.19200300.100.1.60", jpeg_photo_schema)
136
+ assert_schema(expect, "jpegPhoto", jpeg_photo_schema)
137
+
138
+ jpeg_schema = "( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " +
139
+ "X-NOT-HUMAN-READABLE 'TRUE' )"
140
+
141
+ expect = {
142
+ :desc => ['JPEG'],
143
+ :x_not_human_readable => ["TRUE"],
144
+ }
145
+ assert_schema(expect, "1.3.6.1.4.1.1466.115.121.1.28", jpeg_schema)
146
+
147
+ schema = ActiveLdap::Schema.new({"attributeTypes" => [jpeg_photo_schema],
148
+ "ldapSyntaxes" => [jpeg_schema]})
149
+ assert(schema.binary?("jpegPhoto"))
150
+ end
151
+
152
+ private
153
+ def assert_schema(expect, name, schema)
154
+ sub = "objectClass"
155
+ entry = {sub => [schema]}
156
+ schema = ActiveLdap::Schema.new(entry)
157
+ actual = {}
158
+ normalized_expect = {}
159
+ expect.each do |key, value|
160
+ normalized_key = key.to_s.gsub(/_/, "-")
161
+ normalized_expect[normalized_key] = value
162
+ actual[normalized_key] = schema.attr(sub, name, normalized_key)
163
+ end
164
+ assert_equal(normalized_expect, actual)
165
+ end
166
+ end
data/test/test_user.rb ADDED
@@ -0,0 +1,209 @@
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
+ # Test to_s on Fixnums
44
+ assert_equal(uid_number.to_s, user.uid_number)
45
+
46
+ gid_number = 9000
47
+ user.gid_number = gid_number
48
+ # Test to_s on Fixnums
49
+ assert_equal(gid_number.to_s, user.gid_number)
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
+
60
+ assert(!user.valid?)
61
+ assert(user.errors.invalid?(:sn))
62
+ errors = %w(person organizationalPerson
63
+ inetOrgPerson).collect do |object_class|
64
+ "is required attribute (aliases: surname) by " +
65
+ "objectClass '#{object_class}'"
66
+ end
67
+ assert_equal(errors.sort, user.errors.on(:sn).sort)
68
+ user.sn = ['User']
69
+ assert(user.valid?)
70
+ assert_equal(0, user.errors.size)
71
+
72
+ assert_nothing_raised {user.save!}
73
+
74
+ user.user_certificate = certificate
75
+ user.jpeg_photo = jpeg_photo
76
+
77
+ assert(ActiveLdap::Base.schema.binary?('jpegPhoto'),
78
+ 'jpegPhoto is binary?')
79
+
80
+ assert(ActiveLdap::Base.schema.binary?('userCertificate'),
81
+ 'userCertificate is binary?')
82
+ assert_nothing_raised {user.save!}
83
+ end
84
+ end
85
+
86
+
87
+ # This tests the reload of a binary_required type
88
+ def test_binary_required
89
+ make_temporary_user do |user, password|
90
+ # validate add
91
+ user.user_certificate = nil
92
+ assert_equal({'binary' => nil}, user.user_certificate)
93
+ assert_nothing_raised() { user.save! }
94
+ assert_equal({'binary' => nil}, user.user_certificate)
95
+
96
+ user.user_certificate = {"binary" => [certificate]}
97
+ assert_equal({'binary' => certificate},
98
+ user.user_certificate,
99
+ 'This should have been forced to be a binary subtype.')
100
+ assert_nothing_raised() { user.save! }
101
+ assert_equal({'binary' => certificate},
102
+ user.user_certificate,
103
+ 'This should have been forced to be a binary subtype.')
104
+
105
+ # now test modify
106
+ user.user_certificate = nil
107
+ assert_equal({"binary" => nil}, user.user_certificate)
108
+ assert_nothing_raised() { user.save! }
109
+ assert_equal({"binary" => nil}, user.user_certificate)
110
+
111
+ user.user_certificate = certificate
112
+ assert_equal({'binary' => certificate},
113
+ user.user_certificate,
114
+ 'This should have been forced to be a binary subtype.')
115
+ assert_nothing_raised() { user.save! }
116
+
117
+ # validate modify
118
+ user = @user_class.find(user.uid)
119
+ assert_equal({'binary' => certificate},
120
+ user.user_certificate,
121
+ 'This should have been forced to be a binary subtype.')
122
+
123
+ expected_cert = OpenSSL::X509::Certificate.new(certificate)
124
+ actual_cert = user.user_certificate['binary']
125
+ actual_cert = OpenSSL::X509::Certificate.new(actual_cert)
126
+ assert_equal(expected_cert.subject.to_s,
127
+ actual_cert.subject.to_s,
128
+ 'Cert must parse correctly still')
129
+ end
130
+ end
131
+
132
+ def test_binary_required_nested
133
+ make_temporary_user do |user, password|
134
+ user.user_certificate = {"lang-en" => [certificate]}
135
+ assert_equal({'lang-en' => {'binary' => certificate}},
136
+ user.user_certificate)
137
+ assert_nothing_raised() { user.save! }
138
+ assert_equal({'lang-en' => {'binary' => certificate}},
139
+ user.user_certificate)
140
+ end
141
+ end
142
+
143
+ # This tests the reload of a binary type (not forced!)
144
+ def test_binary
145
+ make_temporary_user do |user, password|
146
+ # reload and see what happens
147
+ assert_equal(jpeg_photo, user.jpeg_photo,
148
+ "This should have been equal to #{jpeg_photo_path.dump}")
149
+
150
+ # now test modify
151
+ user.jpeg_photo = nil
152
+ assert_nil(user.jpeg_photo)
153
+ assert_nothing_raised() { user.save! }
154
+ assert_nil(user.jpeg_photo)
155
+
156
+ user.jpeg_photo = jpeg_photo
157
+ assert_equal(jpeg_photo, user.jpeg_photo)
158
+ assert_nothing_raised() { user.save! }
159
+
160
+ # now validate modify
161
+ user = @user_class.find(user.uid)
162
+ assert_equal(jpeg_photo, user.jpeg_photo)
163
+ end
164
+ end
165
+
166
+ # This tests the removal of a objectclass
167
+ def test_remove_object_class
168
+ make_temporary_user do |user, password|
169
+ assert_nil(user.shadow_max,
170
+ 'Should get the default nil value for shadowMax')
171
+
172
+ # Remove shadowAccount
173
+ user.remove_class('shadowAccount')
174
+ assert(user.valid?)
175
+ assert_nothing_raised() { user.save! }
176
+
177
+ assert_raise(NoMethodError,
178
+ 'shadowMax should not be defined anymore' ) do
179
+ user.shadow_max
180
+ end
181
+ end
182
+ end
183
+
184
+
185
+ # Just modify a few random attributes
186
+ def test_modify_with_subtypes
187
+ make_temporary_user do |user, password|
188
+ cn = ['Test User', {'lang-en-us' => ['Test User', 'wad']}]
189
+ user.cn = cn
190
+ assert_nothing_raised() { user.save! }
191
+
192
+ user = @user_class.find(user.uid)
193
+ assert_equal(cn, user.cn,
194
+ 'Making sure a modify with mixed subtypes works')
195
+ end
196
+ end
197
+
198
+ # This tests some invalid input handling
199
+ def test_invalid_input
200
+ end
201
+
202
+ # This tests deletion
203
+ def test_destroy
204
+ make_temporary_user do |user, password|
205
+ user.destroy
206
+ assert(user.new_entry?, 'user should no longer exist')
207
+ end
208
+ end
209
+ end