powerhome-activeldap 3.2.3

Sign up to get free protection for your applications and to get access to all the features.
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,205 @@
1
+ require 'active_ldap/association/belongs_to'
2
+ require 'active_ldap/association/belongs_to_many'
3
+ require 'active_ldap/association/has_many'
4
+ require 'active_ldap/association/has_many_wrap'
5
+
6
+ module ActiveLdap
7
+ # Associations
8
+ #
9
+ # Associations provides the class methods needed for
10
+ # the extension classes to create methods using
11
+ # belongs_to and has_many
12
+ module Associations
13
+ def self.append_features(base)
14
+ super
15
+ base.extend(ClassMethods)
16
+ base.class_attribute(:associations)
17
+ base.associations ||= []
18
+ end
19
+
20
+ module ClassMethods
21
+ def set_associated_class(name, klass)
22
+ @associated_classes ||= {}
23
+ @associated_classes[name.to_s] = klass
24
+ end
25
+
26
+ def associated_class(name)
27
+ @associated_classes[name.to_s]
28
+ end
29
+
30
+ # belongs_to
31
+ #
32
+ # This defines a method for an extension class map its DN key
33
+ # attribute value on to multiple items which reference it by
34
+ # |:foreign_key| in the other LDAP entry covered by class
35
+ # |:class_name|.
36
+ #
37
+ # Example:
38
+ # belongs_to :groups, :class_name => "Group",
39
+ # :many => "memberUid" # Group#memberUid
40
+ # # :primary_key => "uid" # User#uid
41
+ # ## deprecated since 1.1.0. Use :primary_key instead.
42
+ # ## :foreign_key => "uid" # User#uid
43
+ # # dn attribute value is used by default
44
+ # belongs_to :primary_group, :class_name => "Group",
45
+ # :foreign_key => "gidNumber", # User#gidNumber
46
+ # :primary_key => "gidNumber" # Group#gidNumber
47
+ #
48
+ def belongs_to(association_id, options={})
49
+ validate_belongs_to_options(options)
50
+ klass = options[:class]
51
+ klass ||= (options[:class_name] || association_id.to_s).classify
52
+ foreign_key = options[:foreign_key]
53
+ primary_key = options[:primary_key]
54
+ many = options[:many]
55
+ set_associated_class(association_id, klass)
56
+
57
+ opts = {
58
+ :association_id => association_id,
59
+ :foreign_key_name => foreign_key,
60
+ :primary_key_name => primary_key,
61
+ :many => many,
62
+ :extend => options[:extend],
63
+ }
64
+ if opts[:many]
65
+ association_class = Association::BelongsToMany
66
+ foreign_key_name = opts[:foreign_key_name]
67
+ if foreign_key_name
68
+ message = _(":foreign_key belongs_to(:many) option is " \
69
+ "deprecated since 1.1.0. Use :primary_key instead.")
70
+ ActiveSupport::Deprecation.warn(message)
71
+ opts[:primary_key_name] ||= foreign_key_name
72
+ end
73
+ opts[:primary_key_name] ||= dn_attribute
74
+ else
75
+ association_class = Association::BelongsTo
76
+ opts[:foreign_key_name] ||= "#{association_id}_id"
77
+
78
+ before_save(<<-EOC)
79
+ if defined?(@#{association_id})
80
+ association = @#{association_id}
81
+ if association and association.updated?
82
+ self[association.__send__(:primary_key)] =
83
+ association[#{opts[:foreign_key_name].dump}]
84
+ end
85
+ end
86
+ EOC
87
+ end
88
+
89
+ association_accessor(association_id) do |target|
90
+ association_class.new(target, opts)
91
+ end
92
+ end
93
+
94
+
95
+ # has_many
96
+ #
97
+ # This defines a method for an extension class expand an
98
+ # existing multi-element attribute into ActiveLdap objects.
99
+ # This discards any calls which result in entries that
100
+ # don't exist in LDAP!
101
+ #
102
+ # Example:
103
+ # has_many :primary_members, :class_name => "User",
104
+ # :primary_key => "gidNumber", # Group#gidNumber
105
+ # :foreign_key => "gidNumber" # User#gidNumber
106
+ # ## deprecated since 1.1.0. Those options
107
+ # ## are inverted.
108
+ # # :primary_key => "gidNumber", # User#gidNumber
109
+ # # :foreign_key => "gidNumber" # Group#gidNumber
110
+ # has_many :members, :class_name => "User",
111
+ # :wrap => "memberUid" # Group#memberUid
112
+ def has_many(association_id, options = {})
113
+ validate_has_many_options(options)
114
+ klass = options[:class]
115
+ klass ||= (options[:class_name] || association_id.to_s).classify
116
+ foreign_key = options[:foreign_key]
117
+ primary_key = options[:primary_key]
118
+ set_associated_class(association_id, klass)
119
+
120
+ opts = {
121
+ :association_id => association_id,
122
+ :foreign_key_name => foreign_key,
123
+ :primary_key_name => primary_key,
124
+ :wrap => options[:wrap],
125
+ :extend => options[:extend],
126
+ }
127
+ if opts[:wrap]
128
+ association_class = Association::HasManyWrap
129
+ else
130
+ association_class = Association::HasMany
131
+ primary_key_name = opts[:primary_key_name]
132
+ foreign_key_name = opts[:foreign_key_name]
133
+ if primary_key_name != foreign_key_name and
134
+ primary_key_name != "dn" and
135
+ !new.have_attribute?(primary_key_name)
136
+ message = _(":primary_key and :foreign_key has_many options are " \
137
+ "inverted their mean since 1.1.0. Please invert them.")
138
+ ActiveSupport::Deprecation.warn(message)
139
+ opts[:foreign_key_name] = primary_key_name
140
+ opts[:primary_key_name] = foreign_key_name
141
+ end
142
+ end
143
+
144
+ association_accessor(association_id) do |target|
145
+ association_class.new(target, opts)
146
+ end
147
+ end
148
+
149
+ private
150
+ def association_accessor(name, &make_association)
151
+ define_method("__make_#{name}") do
152
+ make_association.call(self)
153
+ end
154
+ associations << name
155
+ association_reader(name, &make_association)
156
+ association_writer(name, &make_association)
157
+ end
158
+
159
+ def association_reader(name, &make_association)
160
+ class_eval(<<-EOM, __FILE__, __LINE__ + 1)
161
+ def #{name}
162
+ @#{name} ||= __make_#{name}
163
+ end
164
+ EOM
165
+ end
166
+
167
+ def association_writer(name, &make_association)
168
+ class_eval(<<-EOM, __FILE__, __LINE__ + 1)
169
+ def #{name}=(new_value)
170
+ association = defined?(@#{name}) ? @#{name} : nil
171
+ association ||= __make_#{name}
172
+ association.replace(new_value)
173
+ @#{name} = new_value.nil? ? nil : association
174
+ @#{name}
175
+ end
176
+ EOM
177
+ end
178
+
179
+ VALID_BELONGS_TO_OPTIONS = [:class, :class_name,
180
+ :foreign_key, :primary_key, :many,
181
+ :extend]
182
+ def validate_belongs_to_options(options)
183
+ options.assert_valid_keys(VALID_BELONGS_TO_OPTIONS)
184
+ end
185
+
186
+ VALID_HAS_MANY_OPTIONS = [:class, :class_name,
187
+ :foreign_key, :primary_key, :wrap,
188
+ :extend]
189
+ def validate_has_many_options(options)
190
+ options.assert_valid_keys(VALID_HAS_MANY_OPTIONS)
191
+ end
192
+ end
193
+
194
+ def clear_association_cache
195
+ return if new_record?
196
+ (self.class.associations || []).each do |association|
197
+ instance_variable_set("@#{association}", nil)
198
+ end
199
+ end
200
+ end
201
+
202
+ module Association
203
+ autoload :Children, 'active_ldap/association/children'
204
+ end
205
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveLdap
2
+ module AttributeMethods
3
+ extend ActiveSupport::Concern
4
+ include ActiveModel::AttributeMethods
5
+
6
+ def methods(singleton_methods = true)
7
+ target_names = entry_attribute.all_names
8
+ target_names -= ['objectClass', 'objectClass'.underscore]
9
+ super + target_names.uniq.collect do |attr|
10
+ self.class.attribute_method_matchers.collect do |matcher|
11
+ :"#{matcher.prefix}#{attr}#{matcher.suffix}"
12
+ end
13
+ end.flatten
14
+ end
15
+
16
+ protected
17
+
18
+ # overiding ActiveModel::AttributeMethods
19
+ def attribute_method?(method_name)
20
+ have_attribute?(method_name, ['objectClass'])
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module ActiveLdap
2
+ module AttributeMethods
3
+ module BeforeTypeCast
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ attribute_method_suffix '_before_type_cast'
8
+ end
9
+
10
+ protected
11
+ def attribute_before_type_cast(attr)
12
+ get_attribute_before_type_cast(attr)[1]
13
+ end
14
+
15
+ def get_attribute_before_type_cast(name, force_array=false)
16
+ name = to_real_attribute_name(name)
17
+
18
+ value = @data[name]
19
+ value = [] if value.nil?
20
+ [name, array_of(value, force_array)]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ #
2
+ module ActiveLdap
3
+ module AttributeMethods
4
+ module Dirty
5
+ extend ActiveSupport::Concern
6
+ include ActiveModel::Dirty
7
+
8
+ # Attempts to +save+ the record and clears changed attributes if successful.
9
+ def save(*) #:nodoc:
10
+ succeeded = super
11
+ if succeeded
12
+ @previously_changed = changes
13
+ @changed_attributes.clear
14
+ end
15
+ succeeded
16
+ end
17
+
18
+ # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
19
+ def save!(*) #:nodoc:
20
+ super.tap do
21
+ @previously_changed = changes
22
+ @changed_attributes.clear
23
+ end
24
+ end
25
+
26
+ # <tt>reload</tt> the record and clears changed attributes.
27
+ def reload(*) #:nodoc:
28
+ super.tap do
29
+ @previously_changed.clear
30
+ @changed_attributes.clear
31
+ end
32
+ end
33
+
34
+ protected
35
+ def set_attribute(name, value)
36
+ if name and name != "objectClass"
37
+ attribute_will_change!(name) unless value == get_attribute(name)
38
+ end
39
+ super
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ module ActiveLdap
3
+ module AttributeMethods
4
+ module Query
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attribute_method_suffix '?'
9
+ end
10
+
11
+ protected
12
+ def get_attribute_as_query(name, force_array=false)
13
+ name, value = get_attribute_before_type_cast(name, force_array)
14
+ if force_array
15
+ value.collect {|x| !false_value?(x)}
16
+ else
17
+ !false_value?(value)
18
+ end
19
+ end
20
+
21
+ def false_value?(value)
22
+ value.nil? or value == false or value == [] or
23
+ value == "false" or value == "FALSE" or value == ""
24
+ end
25
+
26
+ def attribute?(attr)
27
+ return get_attribute_as_query(attr)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,44 @@
1
+ module ActiveLdap
2
+ module AttributeMethods
3
+ module Read
4
+ extend ActiveSupport::Concern
5
+
6
+ protected
7
+ def attribute(attr, *args)
8
+ return get_attribute(attr, args.first)
9
+ end
10
+
11
+ # get_attribute
12
+ #
13
+ # Return the value of the attribute called by method_missing?
14
+ def get_attribute(name, force_array=false)
15
+ name, value = get_attribute_before_type_cast(name, force_array)
16
+ return value if name.nil?
17
+ attribute = schema.attribute(name)
18
+ type_cast(attribute, value)
19
+ end
20
+
21
+ def type_cast(attribute, value)
22
+ case value
23
+ when Hash
24
+ result = {}
25
+ value.each do |option, val|
26
+ result[option] = type_cast(attribute, val)
27
+ end
28
+ if result.size == 1 and result.has_key?("binary")
29
+ result["binary"]
30
+ else
31
+ result
32
+ end
33
+ when Array
34
+ value.collect do |val|
35
+ type_cast(attribute, val)
36
+ end
37
+ else
38
+ attribute.type_cast(value)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,38 @@
1
+ module ActiveLdap
2
+ module AttributeMethods
3
+ module Write
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ attribute_method_suffix '='
8
+ end
9
+
10
+ protected
11
+ def attribute=(attr, *args)
12
+ return set_attribute(attr, args.first)
13
+ end
14
+
15
+ # set_attribute
16
+ #
17
+ # Set the value of the attribute called by method_missing?
18
+ def set_attribute(name, value)
19
+ real_name = to_real_attribute_name(name)
20
+ _dn_attribute = nil
21
+ valid_dn_attribute = true
22
+ begin
23
+ _dn_attribute = dn_attribute
24
+ rescue DistinguishedNameInvalid
25
+ valid_dn_attribute = false
26
+ end
27
+ if valid_dn_attribute and real_name == _dn_attribute
28
+ real_name, value = register_new_dn_attribute(real_name, value)
29
+ end
30
+ raise UnknownAttribute.new(name) if real_name.nil?
31
+
32
+ @data[real_name] = value
33
+ @simplified_data = nil
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,176 @@
1
+ module ActiveLdap
2
+ module Attributes
3
+ def self.included(base)
4
+ base.class_eval do
5
+ extend(ClassMethods)
6
+ extend(Normalizable)
7
+ include(Normalizable)
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def blank_value?(value)
13
+ case value
14
+ when Hash
15
+ value.values.all? {|val| blank_value?(val)}
16
+ when Array
17
+ value.all? {|val| blank_value?(val)}
18
+ when String
19
+ /\A\s*\z/ =~ value
20
+ when nil
21
+ true
22
+ else
23
+ value.blank?
24
+ end
25
+ end
26
+
27
+ def remove_blank_value(value)
28
+ case value
29
+ when Hash
30
+ result = {}
31
+ value.each do |k, v|
32
+ v = remove_blank_value(v)
33
+ next if v.nil?
34
+ result[k] = v
35
+ end
36
+ result = nil if result.blank?
37
+ result
38
+ when Array
39
+ result = []
40
+ value.each do |v|
41
+ v = remove_blank_value(v)
42
+ next if v.nil?
43
+ result << v
44
+ end
45
+ result = nil if result.blank?
46
+ result
47
+ when String
48
+ if /\A\s*\z/ =~ value
49
+ nil
50
+ else
51
+ value
52
+ end
53
+ else
54
+ value
55
+ end
56
+ end
57
+ end
58
+
59
+ module Normalizable
60
+ def normalize_attribute_name(name)
61
+ name.to_s.downcase
62
+ end
63
+
64
+ # Enforce typing:
65
+ # Hashes are for subtypes
66
+ # Arrays are for multiple entries
67
+ def normalize_attribute(name, value)
68
+ if name.nil?
69
+ raise RuntimeError, _('The first argument, name, must not be nil. ' \
70
+ 'Please report this as a bug!')
71
+ end
72
+
73
+ name = normalize_attribute_name(name)
74
+ [name, schema.attribute(name).normalize_value(value)]
75
+ end
76
+
77
+ def unnormalize_attributes(attributes)
78
+ result = {}
79
+ attributes.each do |name, values|
80
+ unnormalize_attribute(name, values, result)
81
+ end
82
+ result
83
+ end
84
+
85
+ def unnormalize_attribute(name, values, result={})
86
+ if values.empty?
87
+ result[name] = []
88
+ else
89
+ values.each do |value|
90
+ if value.is_a?(Hash)
91
+ suffix, real_value = unnormalize_attribute_options(value)
92
+ new_name = name + suffix
93
+ unnormalize_attribute(new_name, real_value, result)
94
+ else
95
+ result[name] ||= []
96
+ if value.is_a?(DN)
97
+ result[name] << value.to_s
98
+ else
99
+ result[name] << value.dup
100
+ end
101
+ end
102
+ end
103
+ end
104
+ result
105
+ end
106
+
107
+ # normalize_attribute_options
108
+ #
109
+ # Makes the Hashized value from the full attribute name
110
+ # e.g. userCertificate;binary => "some_bin"
111
+ # becomes userCertificate => {"binary" => "some_bin"}
112
+ def normalize_attribute_options(attr, value)
113
+ return [attr, value] unless attr.match(/;/)
114
+
115
+ ret_attr, *options = attr.split(/;/)
116
+ [ret_attr,
117
+ [options.reverse.inject(value) {|result, option| {option => result}}]]
118
+ end
119
+
120
+ # unnormalize_attribute_options
121
+ #
122
+ # Unnormalizes all of the subtypes from a given set of nested hashes
123
+ # and returns the attribute suffix and the final true value
124
+ def unnormalize_attribute_options(value)
125
+ options = ''
126
+ ret_val = value
127
+ if value.class == Hash
128
+ options = ';' + value.keys[0]
129
+ ret_val = value[value.keys[0]]
130
+ if ret_val.class == Hash
131
+ sub_options, ret_val = unnormalize_attribute_options(ret_val)
132
+ options += sub_options
133
+ end
134
+ end
135
+ ret_val = [ret_val] unless ret_val.class == Array
136
+ [options, ret_val]
137
+ end
138
+ end
139
+
140
+ private
141
+ def sanitize_for_mass_assignment(attributes, role=nil)
142
+ role ||= :default
143
+ authorizer = mass_assignment_authorizer(role)
144
+ black_list_p =
145
+ authorizer.is_a?(ActiveModel::MassAssignmentSecurity::BlackList)
146
+
147
+ always_needless_attributes = {}
148
+ needless_attributes = {}
149
+
150
+ _dn_attribute = nil
151
+ begin
152
+ _dn_attribute = dn_attribute_with_fallback
153
+ rescue DistinguishedNameInvalid
154
+ end
155
+ [_dn_attribute, 'objectClass'].compact.each do |name|
156
+ always_needless_attributes[to_real_attribute_name(name)] = true
157
+ end
158
+ authorizer.each do |name|
159
+ needless_attributes[to_real_attribute_name(name)] = black_list_p
160
+ end
161
+
162
+ sanitized_attributes = attributes.collect do |key, value|
163
+ key = _dn_attribute if ["id", "dn"].include?(key.to_s)
164
+ [to_real_attribute_name(key) || key, value]
165
+ end
166
+ sanitized_attributes = sanitized_attributes.reject do |key, value|
167
+ always_needless_attributes[key] or needless_attributes[key]
168
+ end
169
+ sanitized_attributes
170
+ end
171
+
172
+ def normalize_attribute_name(name)
173
+ self.class.normalize_attribute_name(name)
174
+ end
175
+ end
176
+ end