activeldap 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +15 -0
- data/README +4 -1
- data/Rakefile +1 -1
- data/TODO +1 -2
- data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
- data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
- data/examples/al-admin/app/models/user.rb +1 -1
- data/examples/al-admin/config/boot.rb +1 -1
- data/examples/al-admin/config/environment.rb +1 -15
- data/examples/al-admin/config/initializers/session_store.rb +23 -0
- data/examples/al-admin/config/session_secret.txt +1 -0
- data/examples/al-admin/db/schema.rb +23 -0
- data/examples/al-admin/locale/en/LC_MESSAGES/al-admin.mo +0 -0
- data/examples/al-admin/locale/ja/LC_MESSAGES/al-admin.mo +0 -0
- data/examples/al-admin/locale/nl/LC_MESSAGES/al-admin.mo +0 -0
- data/lib/active_ldap.rb +3 -3
- data/lib/active_ldap/acts/tree.rb +1 -1
- data/lib/active_ldap/adapter/base.rb +9 -1
- data/lib/active_ldap/adapter/ldap.rb +7 -1
- data/lib/active_ldap/association/belongs_to_many.rb +6 -2
- data/lib/active_ldap/association/children.rb +1 -1
- data/lib/active_ldap/association/has_many_utils.rb +2 -2
- data/lib/active_ldap/association/has_many_wrap.rb +6 -2
- data/lib/active_ldap/attributes.rb +5 -1
- data/lib/active_ldap/base.rb +133 -59
- data/lib/active_ldap/connection.rb +10 -3
- data/lib/active_ldap/distinguished_name.rb +33 -1
- data/lib/active_ldap/ldif.rb +1 -0
- data/lib/active_ldap/operations.rb +33 -14
- data/lib/active_ldap/populate.rb +21 -12
- data/lib/active_ldap/schema.rb +21 -0
- data/lib/active_ldap/validations.rb +49 -4
- data/po/active-ldap.pot +4030 -0
- data/po/en/active-ldap.po +57 -37
- data/po/ja/active-ldap.po +58 -38
- data/test-unit/History.txt +1 -1
- data/test-unit/Manifest.txt +2 -0
- data/test-unit/README.txt +1 -1
- data/test-unit/lib/test/unit/assertions.rb +1 -1
- data/test-unit/lib/test/unit/autorunner.rb +19 -4
- data/test-unit/lib/test/unit/collector/load.rb +3 -1
- data/test-unit/lib/test/unit/color-scheme.rb +5 -1
- data/test-unit/lib/test/unit/error.rb +7 -5
- data/test-unit/lib/test/unit/runner/tap.rb +8 -0
- data/test-unit/lib/test/unit/ui/console/testrunner.rb +63 -8
- data/test-unit/lib/test/unit/ui/tap/testrunner.rb +92 -0
- data/test-unit/test/collector/test-load.rb +1 -5
- data/test-unit/test/test-color-scheme.rb +4 -0
- data/test/al-test-utils.rb +30 -2
- data/test/test_acts_as_tree.rb +6 -3
- data/test/test_associations.rb +3 -2
- data/test/test_base.rb +104 -5
- data/test/test_dn.rb +10 -0
- data/test/test_groupls.rb +1 -1
- data/test/test_lpasswd.rb +1 -1
- data/test/test_reflection.rb +23 -16
- data/test/test_schema.rb +33 -1
- data/test/test_useradd-binary.rb +1 -1
- data/test/test_useradd.rb +1 -1
- data/test/test_userdel.rb +1 -1
- data/test/test_userls.rb +1 -1
- data/test/test_usermod-binary-add-time.rb +1 -1
- data/test/test_usermod-binary-add.rb +1 -1
- data/test/test_usermod-binary-del.rb +1 -1
- data/test/test_usermod-lang-add.rb +1 -1
- data/test/test_usermod.rb +1 -1
- data/test/test_validation.rb +48 -10
- metadata +44 -35
data/CHANGES
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
= CHANGES
|
2
2
|
|
3
|
+
== 1.2.0: 2009-09-22
|
4
|
+
|
5
|
+
* Supported ActiveRecord 2.3.4 and Rails 2.3.4.
|
6
|
+
* [IMCOMPATIBLE]
|
7
|
+
[#23932] Inconsistant DN handling in object attributes [Marc Dequènes]
|
8
|
+
(ActiveLdap::Base#dn and ActiveLdap::Base#base return
|
9
|
+
ActiveLdap::DN not String)
|
10
|
+
* [#26824] support operational attributes detection [Marc Dequènes]
|
11
|
+
(added ActiveLdap::Schema::Attribute#directory_operation?)
|
12
|
+
* [#27] Error saving an ActiveLDAP user [brad@lucky-dip.net]
|
13
|
+
* [#29] Raised on modify_rdn_entry when rdn already exists [Alexey.Chebotar]
|
14
|
+
* Added ActiveLdap::DN.parent.
|
15
|
+
* Supported renaming an entry. Renaming other DTI is only supported by
|
16
|
+
JNDI backend.
|
17
|
+
|
3
18
|
== 1.1.0: 2009-07-18
|
4
19
|
|
5
20
|
* Improved tutorial. [Kazuaki Takase]
|
data/README
CHANGED
@@ -133,4 +133,7 @@ list, please point out.
|
|
133
133
|
* Tim Hermans: A bug report.
|
134
134
|
* Joe Francis: A suggestion.
|
135
135
|
* Tiago Fernandes: Bug reports.
|
136
|
-
* achemze
|
136
|
+
* achemze: A suggestion.
|
137
|
+
* George Montana Harkin: A suggestion.
|
138
|
+
* Marc Dequènes: Bug reports.
|
139
|
+
* brad@lucky-dip.net: A bug report.
|
data/Rakefile
CHANGED
@@ -65,7 +65,7 @@ project = Hoe.spec('activeldap') do
|
|
65
65
|
self.changes = self.paragraphs_of('CHANGES', 1..2).join("\n\n")
|
66
66
|
self.extra_deps = [
|
67
67
|
# ['ruby-ldap', '= 0.9.9'],
|
68
|
-
['activerecord', '= 2.3.
|
68
|
+
['activerecord', '= 2.3.4'],
|
69
69
|
['locale', '= 2.0.4'],
|
70
70
|
['gettext', '= 2.0.4'],
|
71
71
|
['gettext_activerecord', '= 2.0.4'],
|
data/TODO
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
- [1.1.
|
1
|
+
- [1.1.x] add :readonly option to :has_many.
|
2
2
|
- Work as framework on Rails.
|
3
|
-
- [1.1.x] ActiveLdap::Base#dn returns ActiveLdap::DN. [#23932] [Marc Dequènes]
|
4
3
|
- How to support dSCorePropagationData? ignore it?
|
5
4
|
all systemOnly == "TRUE" attribute can be ignored?
|
6
5
|
- Add parsing position to DistinguishedNameInvalid error like
|
Binary file
|
Binary file
|
@@ -82,8 +82,8 @@ module Rails
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def load_rubygems
|
85
|
+
min_version = '1.3.2'
|
85
86
|
require 'rubygems'
|
86
|
-
min_version = '1.3.1'
|
87
87
|
unless rubygems_version >= min_version
|
88
88
|
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
89
89
|
exit 1
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# ENV['RAILS_ENV'] ||= 'production'
|
6
6
|
|
7
7
|
# Specifies gem version of Rails to use when vendor/rails is not present
|
8
|
-
RAILS_GEM_VERSION = '2.3.
|
8
|
+
RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
|
9
9
|
|
10
10
|
# Bootstrap the Rails environment, frameworks, and default configuration
|
11
11
|
require File.join(File.dirname(__FILE__), 'boot')
|
@@ -55,20 +55,6 @@ Rails::Initializer.run do |config|
|
|
55
55
|
# config.i18n.load_path << Dir[File.join(RAILS_ROOT, 'my', 'locales', '*.{rb,yml}')]
|
56
56
|
# config.i18n.default_locale = :de
|
57
57
|
|
58
|
-
# Your secret key for verifying cookie session data integrity.
|
59
|
-
# If you change this key, all old sessions will become invalid!
|
60
|
-
# Make sure the secret is at least 30 characters and all random,
|
61
|
-
# no regular words or you'll be exposed to dictionary attacks.
|
62
|
-
config.action_controller.session = {
|
63
|
-
:session_key => '_al_admin_session',
|
64
|
-
:secret => '581ed74d26a88caa7cb2ff6d0ea0f0aeea1a49f98641ee6d3e7ba1dfcf6154e26cd2b3f9636c9cc02ed8139a4f74c64fdb529a53dcfd1b7ff7aa763f91083aad'
|
65
|
-
}
|
66
|
-
|
67
|
-
# Use the database for sessions instead of the cookie-based default,
|
68
|
-
# which shouldn't be used to store highly confidential information
|
69
|
-
# (create the session table with "rake db:sessions:create")
|
70
|
-
# config.action_controller.session_store = :active_record_store
|
71
|
-
|
72
58
|
# Use SQL instead of Active Record's schema dumper when creating the test database.
|
73
59
|
# This is necessary if your schema can't be completely dumped by the schema dumper,
|
74
60
|
# like if you have constraints or database-specific column types
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key for verifying cookie session data integrity.
|
4
|
+
# If you change this key, all old sessions will become invalid!
|
5
|
+
# Make sure the secret is at least 30 characters and all random,
|
6
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
7
|
+
session_secret_file = File.join(RAILS_ROOT, "config", "session_secret.txt")
|
8
|
+
unless File.exist?(session_secret_file)
|
9
|
+
File.open(session_secret_file, "w") do |file|
|
10
|
+
file.puts(ActiveSupport::SecureRandom.hex(64))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
session_secret = File.read(session_secret_file).strip
|
14
|
+
|
15
|
+
ActionController::Base.session = {
|
16
|
+
:key => '_al_admin_session',
|
17
|
+
:secret => session_secret,
|
18
|
+
}
|
19
|
+
|
20
|
+
# Use the database for sessions instead of the cookie-based default,
|
21
|
+
# which shouldn't be used to store highly confidential information
|
22
|
+
# (create the session table with "rake db:sessions:create")
|
23
|
+
# ActionController::Base.session_store = :active_record_store
|
@@ -0,0 +1 @@
|
|
1
|
+
455ed531e0b1f453d98bdf1bffc9941d659ae54b8ed7506fa63edab05c04516f8888540d4ef6870fa660fe525668f59ebfcc2408446f17e57fa41243e6edb0c6
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead of editing this file,
|
2
|
+
# please use the migrations feature of Active Record to incrementally modify your database, and
|
3
|
+
# then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your database schema. If you need
|
6
|
+
# to create the application database on another system, you should be using db:schema:load, not running
|
7
|
+
# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
8
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
9
|
+
#
|
10
|
+
# It's strongly recommended to check this file into your version control system.
|
11
|
+
|
12
|
+
ActiveRecord::Schema.define(:version => 1) do
|
13
|
+
|
14
|
+
create_table "users", :force => true do |t|
|
15
|
+
t.string "login"
|
16
|
+
t.string "dn"
|
17
|
+
t.datetime "updated_at"
|
18
|
+
t.string "salt"
|
19
|
+
t.string "remember_token"
|
20
|
+
t.datetime "remember_token_expires_at"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
data/lib/active_ldap.rb
CHANGED
@@ -901,7 +901,7 @@ require_gem_if_need = Proc.new do |library_name, gem_name, *gem_args|
|
|
901
901
|
end
|
902
902
|
end
|
903
903
|
|
904
|
-
require_gem_if_need.call("active_support", "activesupport", "= 2.3.
|
904
|
+
require_gem_if_need.call("active_support", "activesupport", "= 2.3.4")
|
905
905
|
|
906
906
|
if ActiveSupport.const_defined?(:Dependencies)
|
907
907
|
dependencies = ActiveSupport::Dependencies
|
@@ -914,7 +914,7 @@ if dependencies.respond_to?(:load_paths)
|
|
914
914
|
end
|
915
915
|
|
916
916
|
module ActiveLdap
|
917
|
-
VERSION = "1.
|
917
|
+
VERSION = "1.2.0"
|
918
918
|
end
|
919
919
|
|
920
920
|
if RUBY_PLATFORM.match('linux')
|
@@ -923,7 +923,7 @@ else
|
|
923
923
|
require 'active_ldap/timeout_stub'
|
924
924
|
end
|
925
925
|
|
926
|
-
require_gem_if_need.call("active_record", "activerecord", "= 2.3.
|
926
|
+
require_gem_if_need.call("active_record", "activerecord", "= 2.3.4")
|
927
927
|
begin
|
928
928
|
require_gem_if_need.call("locale", nil, "= 2.0.4")
|
929
929
|
require_gem_if_need.call("gettext", nil, "= 2.0.4")
|
@@ -139,6 +139,10 @@ module ActiveLdap
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
|
+
def naming_contexts
|
143
|
+
root_dse_values('namingContexts')
|
144
|
+
end
|
145
|
+
|
142
146
|
def entry_attribute(object_classes)
|
143
147
|
@entry_attributes[object_classes.uniq.sort] ||=
|
144
148
|
EntryAttribute.new(schema, object_classes)
|
@@ -615,7 +619,11 @@ module ActiveLdap
|
|
615
619
|
def root_dse_values(key, options={})
|
616
620
|
dse = root_dse([key], options)[0]
|
617
621
|
return [] if dse.nil?
|
618
|
-
|
622
|
+
normalized_key = key.downcase
|
623
|
+
dse.each do |_key, _value|
|
624
|
+
return _value if _key.downcase == normalized_key
|
625
|
+
end
|
626
|
+
[]
|
619
627
|
end
|
620
628
|
|
621
629
|
def root_dse(attrs, options={})
|
@@ -158,9 +158,15 @@ module ActiveLdap
|
|
158
158
|
|
159
159
|
def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
|
160
160
|
super do |_dn, _new_rdn, _delete_old_rdn, _new_superior|
|
161
|
+
if _new_superior
|
162
|
+
raise NotImplemented.new(_("modify RDN with new superior"))
|
163
|
+
end
|
161
164
|
info = {
|
162
165
|
:name => "modify: RDN",
|
163
|
-
:dn => _dn,
|
166
|
+
:dn => _dn,
|
167
|
+
:new_rdn => _new_rdn,
|
168
|
+
:new_superior => _new_superior,
|
169
|
+
:delete_old_rdn => _delete_old_rdn
|
164
170
|
}
|
165
171
|
execute(:modrdn, info, _dn, _new_rdn, _delete_old_rdn)
|
166
172
|
end
|
@@ -10,7 +10,9 @@ module ActiveLdap
|
|
10
10
|
if primary_key_name == "dn"
|
11
11
|
old_value = dn_values_to_string_values(old_value)
|
12
12
|
end
|
13
|
-
|
13
|
+
current_value = @owner[primary_key_name, true]
|
14
|
+
current_value = dn_values_to_string_values(current_value)
|
15
|
+
new_value = old_value + current_value
|
14
16
|
new_value = new_value.uniq.sort
|
15
17
|
if old_value != new_value
|
16
18
|
entry[@options[:many]] = new_value
|
@@ -25,7 +27,9 @@ module ActiveLdap
|
|
25
27
|
if primary_key_name == "dn"
|
26
28
|
old_value = dn_values_to_string_values(old_value)
|
27
29
|
end
|
28
|
-
|
30
|
+
current_value = @owner[primary_key_name, true]
|
31
|
+
current_value = dn_values_to_string_values(current_value)
|
32
|
+
new_value = old_value - current_value
|
29
33
|
new_value = new_value.uniq.sort
|
30
34
|
if old_value != new_value
|
31
35
|
entry[@options[:many]] = new_value
|
@@ -13,7 +13,9 @@ module ActiveLdap
|
|
13
13
|
if _primary_key == "dn"
|
14
14
|
old_value = dn_values_to_string_values(old_value)
|
15
15
|
end
|
16
|
-
|
16
|
+
current_value = entry[_primary_key, true]
|
17
|
+
current_value = dn_values_to_string_values(current_value)
|
18
|
+
new_value = (old_value + current_value).uniq.sort
|
17
19
|
if old_value != new_value
|
18
20
|
@owner[@options[:wrap]] = new_value
|
19
21
|
@owner.save
|
@@ -26,7 +28,9 @@ module ActiveLdap
|
|
26
28
|
if _primary_key == "dn"
|
27
29
|
old_value = dn_values_to_string_values(old_value)
|
28
30
|
end
|
29
|
-
|
31
|
+
current_value = entries.collect {|entry| entry[_primary_key]}
|
32
|
+
current_value = dn_values_to_string_values(current_value)
|
33
|
+
new_value = old_value - current_value
|
30
34
|
new_value = new_value.uniq.sort
|
31
35
|
if old_value != new_value
|
32
36
|
@owner[@options[:wrap]] = new_value
|
@@ -105,7 +105,11 @@ module ActiveLdap
|
|
105
105
|
result[new_name].concat(real_value)
|
106
106
|
else
|
107
107
|
result[name] ||= []
|
108
|
-
|
108
|
+
if value.is_a?(DN)
|
109
|
+
result[name] << value.to_s
|
110
|
+
else
|
111
|
+
result[name] << value.dup
|
112
|
+
end
|
109
113
|
end
|
110
114
|
end
|
111
115
|
end
|
data/lib/active_ldap/base.rb
CHANGED
@@ -259,6 +259,14 @@ module ActiveLdap
|
|
259
259
|
end
|
260
260
|
end
|
261
261
|
|
262
|
+
class NotImplemented < Error
|
263
|
+
attr_reader :target
|
264
|
+
def initialize(target)
|
265
|
+
@target = target
|
266
|
+
super(_("not implemented: %s") % @target)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
262
270
|
# Base
|
263
271
|
#
|
264
272
|
# Base is the primary class which contains all of the core
|
@@ -313,7 +321,7 @@ module ActiveLdap
|
|
313
321
|
end
|
314
322
|
end
|
315
323
|
|
316
|
-
class_local_attr_accessor false, :
|
324
|
+
class_local_attr_accessor false, :inheritable_prefix, :inheritable_base
|
317
325
|
class_local_attr_accessor true, :dn_attribute, :scope, :sort_by, :order
|
318
326
|
class_local_attr_accessor true, :required_classes, :recommended_classes
|
319
327
|
class_local_attr_accessor true, :excluded_classes
|
@@ -412,7 +420,6 @@ module ActiveLdap
|
|
412
420
|
public_class_method :new
|
413
421
|
end
|
414
422
|
|
415
|
-
alias_method :base_inheritable, :base
|
416
423
|
# Base.base
|
417
424
|
#
|
418
425
|
# This method when included into Base provides
|
@@ -424,22 +431,23 @@ module ActiveLdap
|
|
424
431
|
# configuration.rb into this class.
|
425
432
|
# When subclassing, the specified prefix will be concatenated.
|
426
433
|
def base
|
427
|
-
|
428
|
-
_base = configuration[:base] if _base.nil? and configuration
|
429
|
-
_base ||= base_inheritable(true)
|
430
|
-
[prefix, _base].find_all do |component|
|
431
|
-
!component.blank?
|
432
|
-
end.join(",")
|
434
|
+
@base ||= compute_base
|
433
435
|
end
|
436
|
+
alias_method :parsed_base, :base # for backward compatibility
|
434
437
|
|
435
|
-
alias_method :base_without_parsed_cache_clear=, :base=
|
436
438
|
def base=(value)
|
437
|
-
self.
|
438
|
-
@
|
439
|
+
self.inheritable_base = value
|
440
|
+
@base = nil
|
439
441
|
end
|
440
442
|
|
441
|
-
def
|
442
|
-
@
|
443
|
+
def prefix
|
444
|
+
@prefix ||= inheritable_prefix and DN.parse(inheritable_prefix)
|
445
|
+
end
|
446
|
+
|
447
|
+
def prefix=(value)
|
448
|
+
self.inheritable_prefix = value
|
449
|
+
@prefix = nil
|
450
|
+
@base = nil
|
443
451
|
end
|
444
452
|
|
445
453
|
alias_method :scope_without_validation=, :scope=
|
@@ -473,17 +481,23 @@ module ActiveLdap
|
|
473
481
|
elsif abstract_class?
|
474
482
|
"#{super}(abstract)"
|
475
483
|
else
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
484
|
+
detail = nil
|
485
|
+
begin
|
486
|
+
must = []
|
487
|
+
may = []
|
488
|
+
class_names = classes.collect do |object_class|
|
489
|
+
must.concat(object_class.must)
|
490
|
+
may.concat(object_class.may)
|
491
|
+
object_class.name
|
492
|
+
end
|
493
|
+
detail = ["objectClass:<#{class_names.join(', ')}>",
|
494
|
+
"must:<#{inspect_attributes(must)}>",
|
495
|
+
"may:<#{inspect_attributes(may)}>"].join(", ")
|
496
|
+
rescue ActiveLdap::ConnectionNotSetup
|
497
|
+
detail = "not-connected"
|
498
|
+
rescue ActiveLdap::Error
|
499
|
+
detail = "connection-failure"
|
483
500
|
end
|
484
|
-
detail = ["objectClass:<#{class_names.join(', ')}>",
|
485
|
-
"must:<#{inspect_attributes(must)}>",
|
486
|
-
"may:<#{inspect_attributes(may)}>"].join(", ")
|
487
501
|
"#{super}(#{detail})"
|
488
502
|
end
|
489
503
|
end
|
@@ -615,6 +629,28 @@ module ActiveLdap
|
|
615
629
|
"ou=#{name.demodulize.pluralize}"
|
616
630
|
end
|
617
631
|
end
|
632
|
+
|
633
|
+
def compute_base
|
634
|
+
_base = inheritable_base
|
635
|
+
_base = configuration[:base] if _base.nil? and configuration
|
636
|
+
if _base.nil?
|
637
|
+
target = superclass
|
638
|
+
loop do
|
639
|
+
break unless target.respond_to?(:base)
|
640
|
+
_base = target.base
|
641
|
+
break if _base
|
642
|
+
target = target.superclass
|
643
|
+
end
|
644
|
+
end
|
645
|
+
_prefix = prefix
|
646
|
+
|
647
|
+
_base ||= connection.naming_contexts.first
|
648
|
+
return _prefix if _base.blank?
|
649
|
+
|
650
|
+
_base = DN.parse(_base)
|
651
|
+
_base = _prefix + _base if _prefix
|
652
|
+
_base
|
653
|
+
end
|
618
654
|
end
|
619
655
|
|
620
656
|
self.scope = :sub
|
@@ -763,12 +799,8 @@ module ActiveLdap
|
|
763
799
|
#
|
764
800
|
# Delete this entry from LDAP
|
765
801
|
def destroy
|
766
|
-
|
767
|
-
|
768
|
-
@new_entry = true
|
769
|
-
rescue Error
|
770
|
-
raise DeleteError.new(_("Failed to delete LDAP entry: %s") % dn)
|
771
|
-
end
|
802
|
+
self.class.delete(dn)
|
803
|
+
@new_entry = true
|
772
804
|
end
|
773
805
|
|
774
806
|
def delete(options={})
|
@@ -844,9 +876,9 @@ module ActiveLdap
|
|
844
876
|
return true if super
|
845
877
|
|
846
878
|
name = name.to_s
|
847
|
-
return true if have_attribute?(name)
|
879
|
+
return true if have_attribute?(name, ["objectClass"])
|
848
880
|
return false if /(?:=|\?|_before_type_cast)$/ !~ name
|
849
|
-
have_attribute?($PREMATCH)
|
881
|
+
have_attribute?($PREMATCH, ["objectClass"])
|
850
882
|
end
|
851
883
|
|
852
884
|
# Updates a given attribute and saves immediately
|
@@ -870,7 +902,7 @@ module ActiveLdap
|
|
870
902
|
# This returns the key value pairs in @data with all values
|
871
903
|
# cloned
|
872
904
|
def attributes
|
873
|
-
|
905
|
+
@data.clone
|
874
906
|
end
|
875
907
|
|
876
908
|
# This allows a bulk update to the attributes of a record
|
@@ -1006,18 +1038,15 @@ module ActiveLdap
|
|
1006
1038
|
@schema ||= super
|
1007
1039
|
end
|
1008
1040
|
|
1009
|
-
alias_method :base_of_class, :base
|
1010
1041
|
def base
|
1011
|
-
|
1012
|
-
[@base, base_of_class].find_all do |component|
|
1013
|
-
not component.blank?
|
1014
|
-
end.join(",")
|
1042
|
+
@base ||= compute_base
|
1015
1043
|
end
|
1016
1044
|
|
1017
1045
|
def base=(object_local_base)
|
1018
1046
|
ensure_update_dn
|
1019
1047
|
@dn = nil
|
1020
|
-
@base =
|
1048
|
+
@base = nil
|
1049
|
+
@base_value = object_local_base
|
1021
1050
|
end
|
1022
1051
|
|
1023
1052
|
alias_method :scope_of_class, :scope
|
@@ -1030,6 +1059,14 @@ module ActiveLdap
|
|
1030
1059
|
@scope = scope
|
1031
1060
|
end
|
1032
1061
|
|
1062
|
+
def delete_all(options={})
|
1063
|
+
super({:base => dn}.merge(options || {}))
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
def destroy_all(options={})
|
1067
|
+
super({:base => dn}.merge(options || {}))
|
1068
|
+
end
|
1069
|
+
|
1033
1070
|
def inspect
|
1034
1071
|
object_classes = entry_attribute.object_classes
|
1035
1072
|
inspected_object_classes = object_classes.collect do |object_class|
|
@@ -1106,7 +1143,10 @@ module ActiveLdap
|
|
1106
1143
|
init_base
|
1107
1144
|
dn = Compatible.convert_to_utf8_encoded_object(dn)
|
1108
1145
|
attributes = Compatible.convert_to_utf8_encoded_object(attributes)
|
1146
|
+
@original_dn = dn.clone
|
1109
1147
|
@dn = dn
|
1148
|
+
@base = nil
|
1149
|
+
@base_value = nil
|
1110
1150
|
@new_entry = false
|
1111
1151
|
@dn_is_base = false
|
1112
1152
|
@ldap_data = attributes
|
@@ -1259,6 +1299,7 @@ module ActiveLdap
|
|
1259
1299
|
if new_name.nil? and new_value.nil?
|
1260
1300
|
@dn_is_base = true
|
1261
1301
|
@base = nil
|
1302
|
+
@base_value = nil
|
1262
1303
|
attr, value = bases[0].to_a[0]
|
1263
1304
|
@dn_attribute = attr
|
1264
1305
|
else
|
@@ -1271,10 +1312,11 @@ module ActiveLdap
|
|
1271
1312
|
new_bases = bases.empty? ? nil : DN.new(*bases).to_s
|
1272
1313
|
dn_components = ["#{new_name}=#{new_value}",
|
1273
1314
|
new_bases,
|
1274
|
-
|
1315
|
+
self.class.base.to_s]
|
1275
1316
|
dn_components = dn_components.find_all {|component| !component.blank?}
|
1276
1317
|
DN.parse(dn_components.join(','))
|
1277
|
-
@base =
|
1318
|
+
@base = nil
|
1319
|
+
@base_value = new_bases
|
1278
1320
|
@dn_attribute = new_name
|
1279
1321
|
end
|
1280
1322
|
end
|
@@ -1294,7 +1336,9 @@ module ActiveLdap
|
|
1294
1336
|
|
1295
1337
|
val = bases = nil
|
1296
1338
|
begin
|
1297
|
-
relative_dn_value = dn_value
|
1339
|
+
relative_dn_value = dn_value
|
1340
|
+
base_of_class = self.class.base
|
1341
|
+
relative_dn_value -= base_of_class if base_of_class
|
1298
1342
|
if relative_dn_value.rdns.empty?
|
1299
1343
|
val = []
|
1300
1344
|
bases = dn_value.rdns
|
@@ -1328,7 +1372,7 @@ module ActiveLdap
|
|
1328
1372
|
end
|
1329
1373
|
end
|
1330
1374
|
|
1331
|
-
def compute_dn
|
1375
|
+
def compute_dn
|
1332
1376
|
return base if @dn_is_base
|
1333
1377
|
|
1334
1378
|
ensure_update_dn
|
@@ -1338,14 +1382,21 @@ module ActiveLdap
|
|
1338
1382
|
message = format % [self.inspect, dn_attribute]
|
1339
1383
|
raise DistinguishedNameNotSetError.new, message
|
1340
1384
|
end
|
1341
|
-
dn_value = DN.escape_value(dn_value.to_s)
|
1385
|
+
dn_value = DN.escape_value(dn_value.to_s)
|
1342
1386
|
_base = base
|
1343
1387
|
_base = nil if _base.blank?
|
1344
|
-
["#{dn_attribute}=#{dn_value}", _base].compact.join(",")
|
1388
|
+
DN.parse(["#{dn_attribute}=#{dn_value}", _base].compact.join(","))
|
1345
1389
|
end
|
1346
1390
|
|
1347
|
-
def
|
1348
|
-
|
1391
|
+
def compute_base
|
1392
|
+
base_of_class = self.class.base
|
1393
|
+
if @base_value.nil?
|
1394
|
+
base_of_class
|
1395
|
+
else
|
1396
|
+
base_of_object = DN.parse(@base_value)
|
1397
|
+
base_of_object += base_of_class if base_of_class
|
1398
|
+
base_of_object
|
1399
|
+
end
|
1349
1400
|
end
|
1350
1401
|
|
1351
1402
|
# array_of
|
@@ -1393,7 +1444,11 @@ module ActiveLdap
|
|
1393
1444
|
end
|
1394
1445
|
|
1395
1446
|
def collect_modified_attributes(ldap_data, data)
|
1447
|
+
klass = self.class
|
1448
|
+
_dn_attribute = dn_attribute
|
1449
|
+
new_dn_value = nil
|
1396
1450
|
attributes = []
|
1451
|
+
|
1397
1452
|
# Now that all the options will be treated as unique attributes
|
1398
1453
|
# we can see what's changed and add anything that is brand-spankin'
|
1399
1454
|
# new.
|
@@ -1402,23 +1457,26 @@ module ActiveLdap
|
|
1402
1457
|
|
1403
1458
|
next if v == value
|
1404
1459
|
|
1405
|
-
|
1406
|
-
value = self.class.remove_blank_value(value) || []
|
1460
|
+
value = klass.remove_blank_value(value) || []
|
1407
1461
|
next if v == value
|
1408
1462
|
|
1409
|
-
if
|
1463
|
+
if klass.blank_value?(value) and
|
1410
1464
|
schema.attribute(k).binary_required?
|
1411
1465
|
value = [{'binary' => []}]
|
1412
1466
|
end
|
1413
|
-
|
1467
|
+
if k == _dn_attribute
|
1468
|
+
new_dn_value = value[0]
|
1469
|
+
else
|
1470
|
+
attributes.push([:replace, k, value])
|
1471
|
+
end
|
1414
1472
|
end
|
1473
|
+
|
1415
1474
|
data.each do |k, v|
|
1416
1475
|
value = v || []
|
1417
1476
|
next if ldap_data.has_key?(k)
|
1418
1477
|
|
1419
|
-
value =
|
1420
|
-
next if
|
1421
|
-
|
1478
|
+
value = klass.remove_blank_value(value) || []
|
1479
|
+
next if klass.blank_value?(value)
|
1422
1480
|
|
1423
1481
|
# Detect subtypes and account for them
|
1424
1482
|
# REPLACE will function like ADD, but doesn't hit EQUALITY problems
|
@@ -1426,7 +1484,7 @@ module ActiveLdap
|
|
1426
1484
|
attributes.push([:replace, k, value])
|
1427
1485
|
end
|
1428
1486
|
|
1429
|
-
attributes
|
1487
|
+
[new_dn_value, attributes]
|
1430
1488
|
end
|
1431
1489
|
|
1432
1490
|
def collect_all_attributes(data)
|
@@ -1460,18 +1518,21 @@ module ActiveLdap
|
|
1460
1518
|
ldap_data = normalize_data(@ldap_data)
|
1461
1519
|
|
1462
1520
|
# Expand subtypes to real data attributes, but leave @data alone
|
1463
|
-
|
1521
|
+
original_attributes =
|
1522
|
+
connection.entry_attribute(@ldap_data["objectClass"] || []).names
|
1523
|
+
bad_attrs = original_attributes - entry_attribute.names
|
1464
1524
|
data = normalize_data(@data, bad_attrs)
|
1465
1525
|
|
1466
1526
|
success = yield(data, ldap_data)
|
1467
1527
|
|
1468
1528
|
if success
|
1469
|
-
@ldap_data =
|
1529
|
+
@ldap_data = data.clone
|
1470
1530
|
# Delete items disallowed by objectclasses.
|
1471
1531
|
# They should have been removed from ldap.
|
1472
1532
|
bad_attrs.each do |remove_me|
|
1473
1533
|
@ldap_data.delete(remove_me)
|
1474
1534
|
end
|
1535
|
+
@original_dn = dn.clone
|
1475
1536
|
end
|
1476
1537
|
|
1477
1538
|
success
|
@@ -1480,7 +1541,7 @@ module ActiveLdap
|
|
1480
1541
|
def create
|
1481
1542
|
prepare_data_for_saving do |data, ldap_data|
|
1482
1543
|
attributes = collect_all_attributes(data)
|
1483
|
-
add_entry(
|
1544
|
+
add_entry(dn, attributes)
|
1484
1545
|
@new_entry = false
|
1485
1546
|
true
|
1486
1547
|
end
|
@@ -1488,8 +1549,21 @@ module ActiveLdap
|
|
1488
1549
|
|
1489
1550
|
def update
|
1490
1551
|
prepare_data_for_saving do |data, ldap_data|
|
1491
|
-
attributes = collect_modified_attributes(ldap_data, data)
|
1492
|
-
modify_entry(
|
1552
|
+
new_dn_value, attributes = collect_modified_attributes(ldap_data, data)
|
1553
|
+
modify_entry(@original_dn, attributes)
|
1554
|
+
if new_dn_value
|
1555
|
+
old_dn_base = DN.parse(@original_dn).parent
|
1556
|
+
new_dn_base = dn.clone.parent
|
1557
|
+
if old_dn_base == new_dn_base
|
1558
|
+
new_superior = nil
|
1559
|
+
else
|
1560
|
+
new_superior = new_dn_base
|
1561
|
+
end
|
1562
|
+
modify_rdn_entry(@original_dn,
|
1563
|
+
"#{dn_attribute}=#{DN.escape_value(new_dn_value)}",
|
1564
|
+
true,
|
1565
|
+
new_superior)
|
1566
|
+
end
|
1493
1567
|
true
|
1494
1568
|
end
|
1495
1569
|
end
|