activeldap 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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