activeldap 1.1.0 → 1.2.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.
- 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
|