activeldap 4.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,31 @@
1
1
  h1. News
2
2
 
3
+ h2(#4-0-1). 4.0.1: 2013-08-29
4
+
5
+ h3. Improvements
6
+
7
+ * Added ActiveLdap::EntryAttribute#exist?.
8
+ * [GitHub:#66] Improved Active Directory support.
9
+ Binary data can be validated correctly. [Reported by Nowhere Man]
10
+ * [GitHub:#6][GitHub:#69] Improved setup description in tutorial.
11
+ [Reported by Radosław Antoniuk] [Patch by Francisco Miguel Biete]
12
+ * [GitHub:#56] Supported moving sub-tree. It requires Ruby/LDAP 0.9.13 or later,
13
+ JRuby or net-ldap 0.5.0 or later. (net-ldap 0.5.0 isn't released yet.)
14
+ [Reported by Jean-François Rioux]
15
+
16
+ h3. Fixes
17
+
18
+ * [GitHub:#65] Removed removed attributes values by removing
19
+ objectClasses. [Reported by mbab]
20
+
21
+ h3. Thanks
22
+
23
+ * mbab
24
+ * Nowhere Man
25
+ * Radosław Antoniuk
26
+ * Francisco Miguel Biete
27
+ * Jean-François Rioux
28
+
3
29
  h2(#4-0-0). 4.0.0: 2013-07-13
4
30
 
5
31
  h3. Improvements
@@ -7,7 +7,7 @@ h2. Install
7
7
  To install, simply add the following code to your Gemfile:
8
8
 
9
9
  <pre>
10
- gem 'activeldap'
10
+ gem 'activeldap', :require => 'active_ldap/railtie'
11
11
  </pre>
12
12
 
13
13
  You should also depend on an LDAP adapter such as Net::LDAP
@@ -20,13 +20,6 @@ gem 'ruby-ldap'
20
20
  Bundler will install the gems automatically when you run
21
21
  'bundle install'.
22
22
 
23
- You also need to include the ActiveLdap railtie in
24
- config/application.rb, after the other railties:
25
-
26
- <pre>
27
- require "active_ldap/railtie"
28
- </pre>
29
-
30
23
  h2. Configuration
31
24
 
32
25
  You can use a LDAP configuration per environment. They are in
@@ -56,9 +56,9 @@ module ActiveLdap
56
56
 
57
57
  def parent=(entry)
58
58
  if entry.is_a?(String) or entry.is_a?(DN)
59
- base = entry
59
+ base = entry.to_s
60
60
  elsif entry.respond_to?(:dn)
61
- base = entry.dn
61
+ base = entry.dn.to_s
62
62
  if entry.respond_to?(:clear_association_cache)
63
63
  entry.clear_association_cache
64
64
  end
@@ -66,12 +66,20 @@ module ActiveLdap
66
66
  message = _("parent must be an entry or parent DN: %s") % entry.inspect
67
67
  raise ArgumentError, message
68
68
  end
69
+
69
70
  unless new_entry?
70
- self.class.delete_entry(dn, :connection => connection)
71
- @new_entry = true
71
+ begin
72
+ self.class.modify_rdn_entry(dn, "#{dn_attribute}=#{id}",
73
+ true, base,
74
+ :connection => connection)
75
+ rescue NotImplemented
76
+ self.class.delete_entry(dn, :connection => connection)
77
+ @new_entry = true
78
+ end
72
79
  end
80
+
73
81
  self.dn = "#{dn_attribute}=#{id},#{base}"
74
- save
82
+ save if new_entry?
75
83
  end
76
84
  end
77
85
  end
@@ -638,8 +638,8 @@ module ActiveLdap
638
638
  try_reconnect = options[:try_reconnect]
639
639
  else
640
640
  try_reconnect = true
641
- end
642
-
641
+ end
642
+
643
643
  search(:base => "",
644
644
  :scope => :base,
645
645
  :attributes => attrs,
@@ -152,7 +152,8 @@ module ActiveLdap
152
152
 
153
153
  def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
154
154
  super do |_dn, _new_rdn, _delete_old_rdn, _new_superior|
155
- if _new_superior
155
+ rename_available_p = @connection.respond_to?(:rename)
156
+ if _new_superior and not rename_available_p
156
157
  raise NotImplemented.new(_("modify RDN with new superior"))
157
158
  end
158
159
  info = {
@@ -162,7 +163,12 @@ module ActiveLdap
162
163
  :new_superior => _new_superior,
163
164
  :delete_old_rdn => _delete_old_rdn
164
165
  }
165
- execute(:modrdn, info, _dn, _new_rdn, _delete_old_rdn)
166
+ if rename_available_p
167
+ execute(:rename, info,
168
+ _dn, _new_rdn, _new_superior, _delete_old_rdn, [], [])
169
+ else
170
+ execute(:modrdn, info, _dn, _new_rdn, _delete_old_rdn)
171
+ end
166
172
  end
167
173
  end
168
174
 
@@ -119,9 +119,6 @@ module ActiveLdap
119
119
 
120
120
  def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
121
121
  super do |_dn, _new_rdn, _delete_old_rdn, _new_superior|
122
- if _new_superior
123
- raise NotImplemented.new(_("modify RDN with new superior"))
124
- end
125
122
  info = {
126
123
  :name => "modify: RDN",
127
124
  :dn => _dn,
@@ -132,7 +129,8 @@ module ActiveLdap
132
129
  execute(:rename, info,
133
130
  :olddn => _dn,
134
131
  :newrdn => _new_rdn,
135
- :delete_attributes => _delete_old_rdn)
132
+ :delete_attributes => _delete_old_rdn,
133
+ :new_superior => _new_superior)
136
134
  end
137
135
  end
138
136
 
@@ -147,9 +145,13 @@ module ActiveLdap
147
145
  end
148
146
  end
149
147
  message = nil
150
- if result.is_a?(Hash)
148
+ case result
149
+ when Hash
151
150
  message = result[:errorMessage]
152
151
  result = result[:resultCode]
152
+ when Net::LDAP::PDU
153
+ message = result.error_message
154
+ result = result.result_code
153
155
  end
154
156
  unless result.zero?
155
157
  klass = LdapError::ERRORS[result]
@@ -94,7 +94,7 @@ module ActiveLdap
94
94
 
95
95
  # has_many
96
96
  #
97
- # This defines a method for an extension class expand an
97
+ # This defines a method for an extension class expand an
98
98
  # existing multi-element attribute into ActiveLdap objects.
99
99
  # This discards any calls which result in entries that
100
100
  # don't exist in LDAP!
@@ -931,6 +931,17 @@ module ActiveLdap
931
931
  end
932
932
  end
933
933
 
934
+ def clear_removed_attributes_data(removed_attributes)
935
+ return if removed_attributes.empty?
936
+ removed_entry_attribute = EntryAttribute.new(nil, [])
937
+ removed_attributes.each do |attribute|
938
+ removed_entry_attribute.register(attribute)
939
+ end
940
+ @data.reject! do |key, _|
941
+ removed_entry_attribute.exist?(key)
942
+ end
943
+ end
944
+
934
945
  def schema
935
946
  @schema ||= super
936
947
  end
@@ -13,7 +13,7 @@ module ActiveLdap
13
13
  @must = []
14
14
  @may = []
15
15
  @object_classes = []
16
- register(schema.attribute('objectClass'))
16
+ register(schema.attribute('objectClass')) if schema
17
17
  object_classes.each do |objc|
18
18
  # get all attributes for the class
19
19
  object_class = schema.object_class(objc)
@@ -56,6 +56,10 @@ module ActiveLdap
56
56
  end
57
57
  end
58
58
 
59
+ def exist?(name)
60
+ not normalize(name).nil?
61
+ end
62
+
59
63
  def all_names
60
64
  @names.keys + @aliases.keys
61
65
  end
@@ -28,8 +28,12 @@ module ActiveLdap
28
28
  new_classes = target_classes.flatten.compact.uniq
29
29
  assert_object_classes(new_classes)
30
30
  if new_classes.sort != classes.sort
31
+ original_attributes = must + may
31
32
  set_attribute('objectClass', new_classes)
32
33
  clear_object_class_based_cache
34
+ new_attributes = must + may
35
+ removed_attributes = original_attributes - new_attributes
36
+ clear_removed_attributes_data(removed_attributes)
33
37
  end
34
38
  end
35
39
  alias_method(:classes=, :replace_class)
@@ -325,7 +325,12 @@ module ActiveLdap
325
325
  super(id, schema, "ldapSyntaxes")
326
326
  @id = id
327
327
  @name = nil if @name == @id
328
- @validator = Syntaxes[@id]
328
+ @built_in_syntax = Syntaxes[@id]
329
+ end
330
+
331
+ def binary?
332
+ return true if @built_in_syntax and @built_in_syntax.binary?
333
+ binary_transfer_required? or !human_readable?
329
334
  end
330
335
 
331
336
  def binary_transfer_required?
@@ -341,24 +346,24 @@ module ActiveLdap
341
346
  end
342
347
 
343
348
  def validate(value)
344
- if @validator
345
- @validator.validate(value)
349
+ if @built_in_syntax
350
+ @built_in_syntax.validate(value)
346
351
  else
347
352
  nil
348
353
  end
349
354
  end
350
355
 
351
356
  def type_cast(value)
352
- if @validator
353
- @validator.type_cast(value)
357
+ if @built_in_syntax
358
+ @built_in_syntax.type_cast(value)
354
359
  else
355
360
  value
356
361
  end
357
362
  end
358
363
 
359
364
  def normalize_value(value)
360
- if @validator
361
- @validator.normalize_value(value)
365
+ if @built_in_syntax
366
+ @built_in_syntax.normalize_value(value)
362
367
  else
363
368
  value
364
369
  end
@@ -413,8 +418,8 @@ module ActiveLdap
413
418
 
414
419
  # binary?
415
420
  #
416
- # Returns true if the given attribute's syntax
417
- # is X-NOT-HUMAN-READABLE or X-BINARY-TRANSFER-REQUIRED
421
+ # Returns true if the given attribute's syntax is binary syntax,
422
+ # X-NOT-HUMAN-READABLE or X-BINARY-TRANSFER-REQUIRED
418
423
  def binary?
419
424
  @binary
420
425
  end
@@ -503,7 +508,7 @@ module ActiveLdap
503
508
  @syntax = @schema.ldap_syntax(@syntax) if @syntax
504
509
  if @syntax
505
510
  @binary_required = @syntax.binary_transfer_required?
506
- @binary = (@binary_required or !@syntax.human_readable?)
511
+ @binary = @syntax.binary?
507
512
  @derived_syntax = @syntax
508
513
  else
509
514
  @binary_required = false
@@ -20,6 +20,10 @@ module ActiveLdap
20
20
  PRINTABLE_CHARACTER = /[#{printable_character_source}]/ #
21
21
  UNPRINTABLE_CHARACTER = /[^#{printable_character_source}]/ #
22
22
 
23
+ def binary?
24
+ false
25
+ end
26
+
23
27
  def type_cast(value)
24
28
  value
25
29
  end
@@ -366,6 +370,19 @@ module ActiveLdap
366
370
  end
367
371
  end
368
372
 
373
+ class OctetString < Base
374
+ SYNTAXES["1.3.6.1.4.1.1466.115.121.1.40"] = self
375
+
376
+ def binary?
377
+ true
378
+ end
379
+
380
+ private
381
+ def validate_normalized_value(value, original_value)
382
+ nil
383
+ end
384
+ end
385
+
369
386
  class PostalAddress < Base
370
387
  SYNTAXES["1.3.6.1.4.1.1466.115.121.1.41"] = self
371
388
 
@@ -1,3 +1,3 @@
1
1
  module ActiveLdap
2
- VERSION = "4.0.0"
2
+ VERSION = "4.0.1"
3
3
  end
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "al-test-utils"
4
+
5
+ class TestEntryAttribute < Test::Unit::TestCase
6
+ include AlTestUtils
7
+
8
+ class TestExist < self
9
+ priority :must
10
+ def test_existence
11
+ schema = ActiveLdap::Base.connection.schema
12
+ object_classes = ["posixAccount"]
13
+ entry_attribute = ActiveLdap::EntryAttribute.new(schema, object_classes)
14
+ assert_true(entry_attribute.exist?("cn"))
15
+ end
16
+
17
+ def test_non_existence
18
+ schema = nil
19
+ object_classes = []
20
+ entry_attribute = ActiveLdap::EntryAttribute.new(schema, object_classes)
21
+ assert_false(entry_attribute.exist?("nonExistence"))
22
+ end
23
+ end
24
+ end
@@ -71,4 +71,23 @@ class TestObjectClass < Test::Unit::TestCase
71
71
  assert_raises(TypeError) {group.add_class(:posixAccount)}
72
72
  end
73
73
  end
74
+
75
+ class TestRemoveClass < self
76
+ def test_clear_existing_attributes
77
+ make_temporary_user(:simple => true) do |user, password|
78
+ user.add_class("inetOrgPerson")
79
+ user.given_name = "new given name"
80
+
81
+ original_attributes = user.attributes
82
+ user.remove_class("inetOrgPerson")
83
+ new_attributes = user.attributes
84
+ original_attributes.delete("objectClass")
85
+ removed_attributes = original_attributes.reject do |key, value|
86
+ value == new_attributes[key]
87
+ end
88
+ assert_equal({"givenName" => "new given name"},
89
+ removed_attributes)
90
+ end
91
+ end
92
+ end
74
93
  end
@@ -6,6 +6,16 @@ class TestValidation < Test::Unit::TestCase
6
6
  include ActiveLdap::Helper
7
7
 
8
8
  priority :must
9
+ def test_octet_string
10
+ make_temporary_user(:simple => true) do |user,|
11
+ utf8_encoded_binary_value = "\xff".force_encoding("UTF-8")
12
+ user.user_password = utf8_encoded_binary_value
13
+ assert_true(user.save)
14
+ assert_equal([], user.errors.full_messages)
15
+ end
16
+ end
17
+
18
+ priority :normal
9
19
  def test_rename_duplicated
10
20
  make_temporary_user(:simple => true) do |user1,|
11
21
  make_temporary_user(:simple => true) do |user2,|
@@ -20,7 +30,6 @@ class TestValidation < Test::Unit::TestCase
20
30
  end
21
31
  end
22
32
 
23
- priority :normal
24
33
  def test_not_show_binary_value
25
34
  make_temporary_user do |user,|
26
35
  user.user_certificate = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeldap
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-07-13 00:00:00.000000000 Z
13
+ date: 2013-08-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activemodel
@@ -172,6 +172,22 @@ dependencies:
172
172
  - - ! '>='
173
173
  - !ruby/object:Gem::Version
174
174
  version: '0'
175
+ - !ruby/object:Gem::Dependency
176
+ name: packnga
177
+ requirement: !ruby/object:Gem::Requirement
178
+ none: false
179
+ requirements:
180
+ - - ! '>='
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ! '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
175
191
  description: ! " 'ActiveLdap' is a ruby library which provides a clean\n objected
176
192
  oriented interface to the Ruby/LDAP library. It was inspired\n by ActiveRecord.
177
193
  This is not nearly as clean or as flexible as\n ActiveRecord, but it is still
@@ -303,6 +319,7 @@ files:
303
319
  - test/test_dirty.rb
304
320
  - test/test_dn.rb
305
321
  - test/test_entry.rb
322
+ - test/test_entry_attribute.rb
306
323
  - test/test_find.rb
307
324
  - test/test_groupadd.rb
308
325
  - test/test_groupdel.rb
@@ -343,7 +360,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
343
360
  version: '0'
344
361
  segments:
345
362
  - 0
346
- hash: -4416735177306675209
363
+ hash: -4556557570349939659
347
364
  required_rubygems_version: !ruby/object:Gem::Requirement
348
365
  none: false
349
366
  requirements:
@@ -352,7 +369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
352
369
  version: '0'
353
370
  segments:
354
371
  - 0
355
- hash: -4416735177306675209
372
+ hash: -4556557570349939659
356
373
  requirements: []
357
374
  rubyforge_project: ruby-activeldap
358
375
  rubygems_version: 1.8.23
@@ -381,6 +398,7 @@ test_files:
381
398
  - test/test_dirty.rb
382
399
  - test/test_dn.rb
383
400
  - test/test_entry.rb
401
+ - test/test_entry_attribute.rb
384
402
  - test/test_find.rb
385
403
  - test/test_groupadd.rb
386
404
  - test/test_groupdel.rb