activeldap 3.1.1 → 3.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.
Files changed (45) hide show
  1. data/Gemfile +1 -14
  2. data/benchmark/README.md +64 -0
  3. data/benchmark/{bench-al.rb → bench-backend.rb} +6 -22
  4. data/benchmark/bench-instantiate.rb +98 -0
  5. data/benchmark/config.yaml.sample +2 -2
  6. data/doc/text/news.textile +38 -0
  7. data/lib/active_ldap.rb +17 -8
  8. data/lib/active_ldap/association/has_many_wrap.rb +15 -2
  9. data/lib/active_ldap/attribute_methods.rb +23 -0
  10. data/lib/active_ldap/attribute_methods/before_type_cast.rb +24 -0
  11. data/lib/active_ldap/attribute_methods/dirty.rb +43 -0
  12. data/lib/active_ldap/attribute_methods/query.rb +31 -0
  13. data/lib/active_ldap/attribute_methods/read.rb +44 -0
  14. data/lib/active_ldap/attribute_methods/write.rb +38 -0
  15. data/lib/active_ldap/attributes.rb +18 -26
  16. data/lib/active_ldap/base.rb +42 -163
  17. data/lib/active_ldap/connection.rb +6 -1
  18. data/lib/active_ldap/get_text.rb +18 -7
  19. data/lib/active_ldap/operations.rb +63 -49
  20. data/lib/active_ldap/persistence.rb +17 -0
  21. data/lib/active_ldap/railtie.rb +3 -0
  22. data/lib/active_ldap/schema.rb +2 -0
  23. data/lib/active_ldap/schema/syntaxes.rb +7 -7
  24. data/lib/active_ldap/validations.rb +2 -2
  25. data/lib/active_ldap/version.rb +3 -0
  26. data/lib/active_ldap/xml.rb +24 -7
  27. data/lib/rails/generators/active_ldap/model/model_generator.rb +3 -3
  28. data/test/add-phonetic-attribute-options-to-slapd.ldif +10 -0
  29. data/test/al-test-utils.rb +428 -0
  30. data/test/command.rb +111 -0
  31. data/test/config.yaml.sample +6 -0
  32. data/test/fixtures/lower_case_object_class_schema.rb +802 -0
  33. data/test/run-test.rb +29 -0
  34. data/test/test_associations.rb +37 -0
  35. data/test/test_base.rb +113 -51
  36. data/test/test_dirty.rb +84 -0
  37. data/test/test_ldif.rb +0 -1
  38. data/test/test_load.rb +0 -1
  39. data/test/test_reflection.rb +7 -14
  40. data/test/test_syntax.rb +104 -43
  41. data/test/test_usermod-binary-del.rb +1 -1
  42. data/test/test_usermod-lang-add.rb +0 -1
  43. metadata +272 -224
  44. data/lib/active_ldap/get_text_fallback.rb +0 -60
  45. 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
- gem 'activemodel', '~> 3.1.0'
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
@@ -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, opts, options = ActiveLdap::Command.parse_options do |opts, options|
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
- suffixes = []
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)
@@ -1,5 +1,5 @@
1
1
  host: 127.0.0.1
2
- base: dc=bench,dc=localcomain
2
+ base: dc=bench,dc=local
3
3
  method: :tls
4
- bind_dn: cn=user-name,dc=localdomain
4
+ bind_dn: cn=admin,dc=local
5
5
  password: secret
@@ -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.
@@ -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