activeldap 3.1.1 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -14
- data/benchmark/README.md +64 -0
- data/benchmark/{bench-al.rb → bench-backend.rb} +6 -22
- data/benchmark/bench-instantiate.rb +98 -0
- data/benchmark/config.yaml.sample +2 -2
- data/doc/text/news.textile +38 -0
- data/lib/active_ldap.rb +17 -8
- data/lib/active_ldap/association/has_many_wrap.rb +15 -2
- data/lib/active_ldap/attribute_methods.rb +23 -0
- data/lib/active_ldap/attribute_methods/before_type_cast.rb +24 -0
- data/lib/active_ldap/attribute_methods/dirty.rb +43 -0
- data/lib/active_ldap/attribute_methods/query.rb +31 -0
- data/lib/active_ldap/attribute_methods/read.rb +44 -0
- data/lib/active_ldap/attribute_methods/write.rb +38 -0
- data/lib/active_ldap/attributes.rb +18 -26
- data/lib/active_ldap/base.rb +42 -163
- data/lib/active_ldap/connection.rb +6 -1
- data/lib/active_ldap/get_text.rb +18 -7
- data/lib/active_ldap/operations.rb +63 -49
- data/lib/active_ldap/persistence.rb +17 -0
- data/lib/active_ldap/railtie.rb +3 -0
- data/lib/active_ldap/schema.rb +2 -0
- data/lib/active_ldap/schema/syntaxes.rb +7 -7
- data/lib/active_ldap/validations.rb +2 -2
- data/lib/active_ldap/version.rb +3 -0
- data/lib/active_ldap/xml.rb +24 -7
- data/lib/rails/generators/active_ldap/model/model_generator.rb +3 -3
- data/test/add-phonetic-attribute-options-to-slapd.ldif +10 -0
- data/test/al-test-utils.rb +428 -0
- data/test/command.rb +111 -0
- data/test/config.yaml.sample +6 -0
- data/test/fixtures/lower_case_object_class_schema.rb +802 -0
- data/test/run-test.rb +29 -0
- data/test/test_associations.rb +37 -0
- data/test/test_base.rb +113 -51
- data/test/test_dirty.rb +84 -0
- data/test/test_ldif.rb +0 -1
- data/test/test_load.rb +0 -1
- data/test/test_reflection.rb +7 -14
- data/test/test_syntax.rb +104 -43
- data/test/test_usermod-binary-del.rb +1 -1
- data/test/test_usermod-lang-add.rb +0 -1
- metadata +272 -224
- data/lib/active_ldap/get_text_fallback.rb +0 -60
- data/lib/active_ldap/get_text_support.rb +0 -22
data/Gemfile
CHANGED
@@ -2,17 +2,4 @@
|
|
2
2
|
|
3
3
|
source "http://rubygems.org"
|
4
4
|
|
5
|
-
|
6
|
-
gem 'locale'
|
7
|
-
gem 'fast_gettext'
|
8
|
-
gem 'gettext_i18n_rails'
|
9
|
-
|
10
|
-
group :development, :test do
|
11
|
-
gem 'ruby-ldap'
|
12
|
-
gem 'net-ldap'
|
13
|
-
gem 'jeweler'
|
14
|
-
gem 'test-unit'
|
15
|
-
gem 'test-unit-notify'
|
16
|
-
gem "yard"
|
17
|
-
gem "RedCloth"
|
18
|
-
end
|
5
|
+
gemspec
|
data/benchmark/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# README
|
2
|
+
|
3
|
+
This document describes how to run benchmarks under
|
4
|
+
benchmark/ directory.
|
5
|
+
|
6
|
+
## Configure your LDAP server
|
7
|
+
|
8
|
+
You need a LDAP server to run benchmarks. This is dependes
|
9
|
+
on your environment.
|
10
|
+
|
11
|
+
In this document, we assume that you configure your LDAP
|
12
|
+
server by the following configuration:
|
13
|
+
|
14
|
+
* host: 127.0.0.1
|
15
|
+
* base DN: dc=bench,dc=local
|
16
|
+
* encryption: startTLS
|
17
|
+
* bind DN: cn=admin,dc=local
|
18
|
+
* password: secret
|
19
|
+
|
20
|
+
## Configure ActiveLdap to connect to your LDAP server
|
21
|
+
|
22
|
+
You need an ActiveLdap configuration in
|
23
|
+
benchmark/config.yaml to connect to your LDAP server. There
|
24
|
+
is a sample configuration in
|
25
|
+
benchmark/config.yaml.sample. It's good to start from it.
|
26
|
+
|
27
|
+
% cp benchmark/config.yaml.sample benchmark/config.yaml
|
28
|
+
% editor benchmark/config.yaml
|
29
|
+
|
30
|
+
The configuration uses the same format of ldap.yaml.
|
31
|
+
|
32
|
+
## Run benchmarks
|
33
|
+
|
34
|
+
You just run a bencmark script. It loads
|
35
|
+
benchmark/config.yaml and populate benchmark data automatically.
|
36
|
+
|
37
|
+
% ruby benchmark/bench-backend.rb
|
38
|
+
Populating...
|
39
|
+
|
40
|
+
Rehearsal ---------------------------------------------------------------
|
41
|
+
1x: AL(LDAP) 0.220000 0.000000 0.220000 ( 0.234775)
|
42
|
+
1x: AL(Net::LDAP) 0.280000 0.000000 0.280000 ( 0.273048)
|
43
|
+
1x: AL(LDAP: No Obj) 0.000000 0.000000 0.000000 ( 0.009217)
|
44
|
+
1x: AL(Net::LDAP: No Obj) 0.060000 0.000000 0.060000 ( 0.056727)
|
45
|
+
1x: LDAP 0.000000 0.000000 0.000000 ( 0.003261)
|
46
|
+
1x: Net::LDAP 0.040000 0.000000 0.040000 ( 0.029862)
|
47
|
+
------------------------------------------------------ total: 0.600000sec
|
48
|
+
|
49
|
+
user system total real
|
50
|
+
1x: AL(LDAP) 0.200000 0.000000 0.200000 ( 0.195660)
|
51
|
+
1x: AL(Net::LDAP) 0.220000 0.000000 0.220000 ( 0.213444)
|
52
|
+
1x: AL(LDAP: No Obj) 0.010000 0.000000 0.010000 ( 0.009000)
|
53
|
+
1x: AL(Net::LDAP: No Obj) 0.030000 0.000000 0.030000 ( 0.026847)
|
54
|
+
1x: LDAP 0.000000 0.000000 0.000000 ( 0.003377)
|
55
|
+
1x: Net::LDAP 0.020000 0.000000 0.020000 ( 0.022662)
|
56
|
+
|
57
|
+
Entries processed by Ruby/ActiveLdap + LDAP: 100
|
58
|
+
Entries processed by Ruby/ActiveLdap + Net::LDAP: 100
|
59
|
+
Entries processed by Ruby/ActiveLdap + LDAP: (without object creation): 100
|
60
|
+
Entries processed by Ruby/ActiveLdap + Net::LDAP: (without object creation): 100
|
61
|
+
Entries processed by Ruby/LDAP: 100
|
62
|
+
Entries processed by Net::LDAP: 100
|
63
|
+
|
64
|
+
Cleaning...
|
@@ -7,7 +7,11 @@ require "benchmark"
|
|
7
7
|
|
8
8
|
include ActiveLdap::GetTextSupport
|
9
9
|
|
10
|
-
argv
|
10
|
+
argv = ARGV.dup
|
11
|
+
unless argv.include?("--config")
|
12
|
+
argv.unshift("--config", File.join(base, "config.yaml"))
|
13
|
+
end
|
14
|
+
argv, opts, options = ActiveLdap::Command.parse_options(argv) do |opts, options|
|
11
15
|
options.prefix = "ou=People"
|
12
16
|
|
13
17
|
opts.on("--prefix=PREFIX",
|
@@ -129,27 +133,7 @@ rescue LoadError
|
|
129
133
|
end
|
130
134
|
|
131
135
|
def populate_base
|
132
|
-
|
133
|
-
ActiveLdap::Base.base.split(/,/).reverse_each do |suffix|
|
134
|
-
prefix = suffixes.join(",")
|
135
|
-
suffixes.unshift(suffix)
|
136
|
-
name, value = suffix.split(/=/, 2)
|
137
|
-
next unless name == "dc"
|
138
|
-
dc_class = Class.new(ActiveLdap::Base)
|
139
|
-
dc_class.ldap_mapping :dn_attribute => "dc",
|
140
|
-
:prefix => "",
|
141
|
-
:scope => :base,
|
142
|
-
:classes => ["top", "dcObject", "organization"]
|
143
|
-
dc_class.instance_variable_set("@base", prefix)
|
144
|
-
next if dc_class.exists?(value, :prefix => "dc=#{value}")
|
145
|
-
dc = dc_class.new(value)
|
146
|
-
dc.o = dc.dc
|
147
|
-
begin
|
148
|
-
dc.save
|
149
|
-
rescue ActiveLdap::OperationNotPermitted
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
136
|
+
ActiveLdap::Populate.ensure_base
|
153
137
|
if ActiveLdap::Base.search.empty?
|
154
138
|
raise "Can't populate #{ActiveLdap::Base.base}"
|
155
139
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
base = File.dirname(__FILE__)
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(base))
|
3
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(base, "..", "lib")))
|
4
|
+
|
5
|
+
require "active_ldap"
|
6
|
+
require "benchmark"
|
7
|
+
|
8
|
+
include ActiveLdap::GetTextSupport
|
9
|
+
|
10
|
+
argv = ARGV.dup
|
11
|
+
unless argv.include?("--config")
|
12
|
+
argv.unshift("--config", File.join(base, "config.yaml"))
|
13
|
+
end
|
14
|
+
argv, opts, options = ActiveLdap::Command.parse_options(argv) do |opts, options|
|
15
|
+
options.prefix = "ou=People"
|
16
|
+
|
17
|
+
opts.on("--prefix=PREFIX",
|
18
|
+
_("Specify prefix for benchmarking"),
|
19
|
+
_("(default: %s)") % options.prefix) do |prefix|
|
20
|
+
options.prefix = prefix
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
ActiveLdap::Base.setup_connection
|
25
|
+
config = ActiveLdap::Base.configuration
|
26
|
+
|
27
|
+
LDAP_PREFIX = options.prefix
|
28
|
+
LDAP_USER = config[:bind_dn]
|
29
|
+
LDAP_PASSWORD = config[:password]
|
30
|
+
|
31
|
+
N_USERS = 100
|
32
|
+
|
33
|
+
class ALUser < ActiveLdap::Base
|
34
|
+
ldap_mapping :dn_attribute => 'uid', :prefix => LDAP_PREFIX,
|
35
|
+
:classes => ['posixAccount', 'person']
|
36
|
+
end
|
37
|
+
|
38
|
+
def populate_base
|
39
|
+
ActiveLdap::Populate.ensure_base
|
40
|
+
if ActiveLdap::Base.search.empty?
|
41
|
+
raise "Can't populate #{ActiveLdap::Base.base}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def populate_users
|
46
|
+
ou_class = Class.new(ActiveLdap::Base)
|
47
|
+
ou_class.ldap_mapping :dn_attribute => "ou",
|
48
|
+
:prefix => "",
|
49
|
+
:classes => ["top", "organizationalUnit"]
|
50
|
+
ou_class.new(LDAP_PREFIX.split(/=/)[1]).save!
|
51
|
+
|
52
|
+
N_USERS.times do |i|
|
53
|
+
name = i.to_s
|
54
|
+
user = ALUser.new(name)
|
55
|
+
user.uid_number = 100000 + i
|
56
|
+
user.gid_number = 100000 + i
|
57
|
+
user.cn = name
|
58
|
+
user.sn = name
|
59
|
+
user.home_directory = "/nonexistent"
|
60
|
+
user.save!
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def populate
|
65
|
+
populate_base
|
66
|
+
populate_users
|
67
|
+
end
|
68
|
+
|
69
|
+
def main(do_populate)
|
70
|
+
if do_populate
|
71
|
+
puts(_("Populating..."))
|
72
|
+
dumped_data = ActiveLdap::Base.dump(:scope => :sub)
|
73
|
+
ActiveLdap::Base.delete_all(nil, :scope => :sub)
|
74
|
+
populate
|
75
|
+
puts
|
76
|
+
end
|
77
|
+
|
78
|
+
Benchmark.bmbm(20) do |x|
|
79
|
+
n = 100
|
80
|
+
GC.start
|
81
|
+
x.report("search 100 entries") do
|
82
|
+
n.times {ALUser.search}
|
83
|
+
end
|
84
|
+
GC.start
|
85
|
+
x.report("instantiate 1 entry") do
|
86
|
+
n.times {ALUser.first}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
ensure
|
90
|
+
if do_populate
|
91
|
+
puts
|
92
|
+
puts(_("Cleaning..."))
|
93
|
+
ActiveLdap::Base.delete_all(nil, :scope => :sub)
|
94
|
+
ActiveLdap::Base.load(dumped_data)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
main(LDAP_USER && LDAP_PASSWORD)
|
data/doc/text/news.textile
CHANGED
@@ -1,5 +1,43 @@
|
|
1
1
|
h1. News
|
2
2
|
|
3
|
+
h2(#3-2-0). 3.2.0: 2012-08-29
|
4
|
+
|
5
|
+
* [GitHub:#39] Supported Rails 3.2.8. [Reported by Ben Langfeld]
|
6
|
+
* [GitHub:#13] Don't use deprecated Gem.available?. [Patch by sailesh]
|
7
|
+
* [GitHub:#19] Supported new entry by @ha_many :wrap@. [Patch by Alex Tomlins]
|
8
|
+
* Supported @:only@ option in XML output.
|
9
|
+
* [GitHub:#14] Supported nil as single value. [Reported by n3llyb0y]
|
10
|
+
* [GitHub:#20] Supported ActiveModel::MassAssignmentSecurity.
|
11
|
+
[Reported by mihu]
|
12
|
+
* [GitHub:#24] Supported Ruby 1.9 style Hash syntax in generator.
|
13
|
+
[Patch by ursm]
|
14
|
+
* [GitHub:#25][GitHub:#39] Supported ActiveModel::Dirty.
|
15
|
+
[Patch by mihu][Reported by Ben Langfeld]
|
16
|
+
* [GitHub:#26] Improved speed for dirty. [Patch by mihu]
|
17
|
+
* [GitHub:#28] Improved speed for initialization. [Patch by mihu]
|
18
|
+
* [GitHub:#29] Added .gemspec. [Suggested by mklappstuhl]
|
19
|
+
* [GitHub:#34] Removed an unused method. [Patch by mihu]
|
20
|
+
* [GitHub:#37] Improved will_paginate support. [Patch by Craig White]
|
21
|
+
* [GitHub:#40] Added missing test files to .gemspec. [Reported by Vít Ondruch]
|
22
|
+
* [GitHub:#41] Improved speed for find. [Patch by unixmechanic]
|
23
|
+
* Changed i18n backend to gettext from fast_gettext again.
|
24
|
+
* [GitHub:#42] Fixed a bug that optional second is required for GeneralizedTime.
|
25
|
+
[Reported by masche842]
|
26
|
+
|
27
|
+
h3. Thanks
|
28
|
+
|
29
|
+
* sailesh
|
30
|
+
* Alex Tomlins
|
31
|
+
* n3llyb0y
|
32
|
+
* mihu
|
33
|
+
* ursm
|
34
|
+
* Ben Langfeld
|
35
|
+
* mklappstuhl
|
36
|
+
* Craig White
|
37
|
+
* Vít Ondruch
|
38
|
+
* unixmechanic
|
39
|
+
* masche842
|
40
|
+
|
3
41
|
h2(#3-1-1). 3.1.1: 2011-11-03
|
4
42
|
|
5
43
|
* Supported Rails 3.1.1.
|
data/lib/active_ldap.rb
CHANGED
@@ -2,8 +2,9 @@ require "rubygems"
|
|
2
2
|
require "active_model"
|
3
3
|
require "active_support/core_ext"
|
4
4
|
|
5
|
+
require "active_ldap/version"
|
6
|
+
|
5
7
|
module ActiveLdap
|
6
|
-
VERSION = "3.1.1"
|
7
8
|
autoload :Command, "active_ldap/command"
|
8
9
|
end
|
9
10
|
|
@@ -13,11 +14,6 @@ else
|
|
13
14
|
require 'active_ldap/timeout_stub'
|
14
15
|
end
|
15
16
|
|
16
|
-
begin
|
17
|
-
require "locale"
|
18
|
-
require "fast_gettext"
|
19
|
-
rescue LoadError
|
20
|
-
end
|
21
17
|
require 'active_ldap/get_text'
|
22
18
|
|
23
19
|
require 'active_ldap/compatible'
|
@@ -32,6 +28,12 @@ require 'active_ldap/persistence'
|
|
32
28
|
|
33
29
|
require 'active_ldap/associations'
|
34
30
|
require 'active_ldap/attributes'
|
31
|
+
require 'active_ldap/attribute_methods'
|
32
|
+
require 'active_ldap/attribute_methods/query'
|
33
|
+
require 'active_ldap/attribute_methods/before_type_cast'
|
34
|
+
require 'active_ldap/attribute_methods/read'
|
35
|
+
require 'active_ldap/attribute_methods/write'
|
36
|
+
require 'active_ldap/attribute_methods/dirty'
|
35
37
|
require 'active_ldap/configuration'
|
36
38
|
require 'active_ldap/connection'
|
37
39
|
require 'active_ldap/operations'
|
@@ -50,15 +52,22 @@ require 'active_ldap/callbacks'
|
|
50
52
|
|
51
53
|
|
52
54
|
ActiveLdap::Base.class_eval do
|
55
|
+
include ActiveLdap::Persistence
|
56
|
+
|
53
57
|
include ActiveLdap::Associations
|
58
|
+
include ActiveModel::MassAssignmentSecurity
|
54
59
|
include ActiveLdap::Attributes
|
60
|
+
include ActiveLdap::AttributeMethods
|
61
|
+
include ActiveLdap::AttributeMethods::BeforeTypeCast
|
62
|
+
include ActiveLdap::AttributeMethods::Write
|
63
|
+
include ActiveLdap::AttributeMethods::Dirty
|
64
|
+
include ActiveLdap::AttributeMethods::Query
|
65
|
+
include ActiveLdap::AttributeMethods::Read
|
55
66
|
include ActiveLdap::Configuration
|
56
67
|
include ActiveLdap::Connection
|
57
68
|
include ActiveLdap::Operations
|
58
69
|
include ActiveLdap::ObjectClass
|
59
70
|
|
60
|
-
include ActiveLdap::Persistence
|
61
|
-
|
62
71
|
include ActiveLdap::Acts::Tree
|
63
72
|
|
64
73
|
include ActiveLdap::Validations
|
@@ -18,7 +18,7 @@ module ActiveLdap
|
|
18
18
|
new_value = (old_value + current_value).uniq.sort
|
19
19
|
if old_value != new_value
|
20
20
|
@owner[@options[:wrap]] = new_value
|
21
|
-
@owner.save
|
21
|
+
@owner.save unless @owner.new_entry?
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -34,7 +34,7 @@ module ActiveLdap
|
|
34
34
|
new_value = new_value.uniq.sort
|
35
35
|
if old_value != new_value
|
36
36
|
@owner[@options[:wrap]] = new_value
|
37
|
-
@owner.save
|
37
|
+
@owner.save unless @owner.new_entry?
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -57,6 +57,19 @@ module ActiveLdap
|
|
57
57
|
def foreign_key
|
58
58
|
@options[:primary_key_name] || foreign_class.dn_attribute
|
59
59
|
end
|
60
|
+
|
61
|
+
def add_entries(*entries)
|
62
|
+
result = true
|
63
|
+
load_target
|
64
|
+
|
65
|
+
flatten_deeper(entries).each do |entry|
|
66
|
+
infect_connection(entry)
|
67
|
+
insert_entry(entry) or result = false
|
68
|
+
@target << entry
|
69
|
+
end
|
70
|
+
|
71
|
+
result && self
|
72
|
+
end
|
60
73
|
end
|
61
74
|
end
|
62
75
|
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 != "objectClass"
|
37
|
+
attribute_will_change!(name) unless value == get_attribute(name)
|
38
|
+
end
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|