activeldap 4.0.5 → 6.1.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 (57) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +3 -1
  3. data/doc/text/development.md +26 -0
  4. data/doc/text/{news.textile → news.md} +451 -241
  5. data/doc/text/{rails.textile → rails.md} +44 -33
  6. data/doc/text/{tutorial.textile → tutorial.md} +177 -185
  7. data/lib/active_ldap/adapter/base.rb +40 -17
  8. data/lib/active_ldap/adapter/jndi.rb +21 -9
  9. data/lib/active_ldap/adapter/jndi_connection.rb +83 -20
  10. data/lib/active_ldap/adapter/ldap.rb +50 -28
  11. data/lib/active_ldap/adapter/ldap_ext.rb +32 -13
  12. data/lib/active_ldap/adapter/net_ldap.rb +26 -24
  13. data/lib/active_ldap/associations.rb +5 -5
  14. data/lib/active_ldap/attribute_methods/before_type_cast.rb +1 -1
  15. data/lib/active_ldap/attribute_methods/dirty.rb +4 -7
  16. data/lib/active_ldap/attribute_methods/query.rb +1 -1
  17. data/lib/active_ldap/attribute_methods/read.rb +5 -1
  18. data/lib/active_ldap/attribute_methods/write.rb +1 -1
  19. data/lib/active_ldap/attribute_methods.rb +1 -2
  20. data/lib/active_ldap/base.rb +61 -14
  21. data/lib/active_ldap/callbacks.rb +7 -8
  22. data/lib/active_ldap/configuration.rb +27 -3
  23. data/lib/active_ldap/connection.rb +4 -22
  24. data/lib/active_ldap/distinguished_name.rb +1 -1
  25. data/lib/active_ldap/human_readable.rb +5 -4
  26. data/lib/active_ldap/operations.rb +24 -4
  27. data/lib/active_ldap/persistence.rb +3 -2
  28. data/lib/active_ldap/populate.rb +5 -3
  29. data/lib/active_ldap/railties/controller_runtime.rb +1 -2
  30. data/lib/active_ldap/schema/syntaxes.rb +8 -4
  31. data/lib/active_ldap/validations.rb +12 -4
  32. data/lib/active_ldap/version.rb +1 -1
  33. data/lib/active_ldap.rb +0 -7
  34. data/po/en/active-ldap.po +2 -2
  35. data/po/ja/active-ldap.po +3 -3
  36. data/test/add-phonetic-attribute-options-to-slapd.ldif +3 -3
  37. data/test/al-test-utils.rb +125 -38
  38. data/test/command.rb +13 -16
  39. data/test/enable-dynamic-groups.ldif +22 -0
  40. data/test/enable-start-tls.ldif +27 -0
  41. data/test/run-test.rb +0 -4
  42. data/test/test_base.rb +223 -22
  43. data/test/test_base_per_instance.rb +33 -1
  44. data/test/test_callback.rb +10 -8
  45. data/test/test_connection.rb +4 -0
  46. data/test/test_connection_per_class.rb +34 -0
  47. data/test/test_dn.rb +7 -0
  48. data/test/test_entry.rb +1 -0
  49. data/test/test_find.rb +14 -3
  50. data/test/test_supported_control.rb +1 -1
  51. data/test/test_syntax.rb +5 -0
  52. data/test/test_validation.rb +28 -15
  53. metadata +23 -24
  54. data/README.textile +0 -141
  55. data/doc/text/development.textile +0 -54
  56. data/lib/active_ldap/timeout.rb +0 -75
  57. data/lib/active_ldap/timeout_stub.rb +0 -17
@@ -9,8 +9,7 @@ module ActiveLdap
9
9
  def save(*) #:nodoc:
10
10
  succeeded = super
11
11
  if succeeded
12
- @previously_changed = changes
13
- @changed_attributes.clear
12
+ changes_applied
14
13
  end
15
14
  succeeded
16
15
  end
@@ -18,20 +17,18 @@ module ActiveLdap
18
17
  # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
19
18
  def save!(*) #:nodoc:
20
19
  super.tap do
21
- @previously_changed = changes
22
- @changed_attributes.clear
20
+ changes_applied
23
21
  end
24
22
  end
25
23
 
26
24
  # <tt>reload</tt> the record and clears changed attributes.
27
25
  def reload(*) #:nodoc:
28
26
  super.tap do
29
- @previously_changed.clear
30
- @changed_attributes.clear
27
+ clear_changes_information
31
28
  end
32
29
  end
33
30
 
34
- protected
31
+ private
35
32
  def set_attribute(name, value)
36
33
  if name and name != "objectClass"
37
34
  attribute_will_change!(name) unless value == get_attribute(name)
@@ -8,7 +8,7 @@ module ActiveLdap
8
8
  attribute_method_suffix '?'
9
9
  end
10
10
 
11
- protected
11
+ private
12
12
  def get_attribute_as_query(name, force_array=false)
13
13
  name, value = get_attribute_before_type_cast(name, force_array)
14
14
  if force_array
@@ -3,11 +3,15 @@ module ActiveLdap
3
3
  module Read
4
4
  extend ActiveSupport::Concern
5
5
 
6
- protected
6
+ private
7
7
  def attribute(attr, *args)
8
8
  return get_attribute(attr, args.first)
9
9
  end
10
10
 
11
+ def _read_attribute(name)
12
+ get_attribute(name)
13
+ end
14
+
11
15
  # get_attribute
12
16
  #
13
17
  # Return the value of the attribute called by method_missing?
@@ -7,7 +7,7 @@ module ActiveLdap
7
7
  attribute_method_suffix '='
8
8
  end
9
9
 
10
- protected
10
+ private
11
11
  def attribute=(attr, *args)
12
12
  return set_attribute(attr, args.first)
13
13
  end
@@ -13,8 +13,7 @@ module ActiveLdap
13
13
  end.flatten
14
14
  end
15
15
 
16
- protected
17
-
16
+ private
18
17
  # overiding ActiveModel::AttributeMethods
19
18
  def attribute_method?(method_name)
20
19
  have_attribute?(method_name, ['objectClass'])
@@ -32,6 +32,7 @@
32
32
  require 'English'
33
33
  require 'thread'
34
34
  require 'erb'
35
+ require 'set'
35
36
 
36
37
  module ActiveLdap
37
38
  # OO-interface to LDAP assuming pam/nss_ldap-style organization with
@@ -330,6 +331,7 @@ module ActiveLdap
330
331
  class_local_attr_accessor true, :dn_attribute, :scope, :sort_by, :order
331
332
  class_local_attr_accessor true, :required_classes, :recommended_classes
332
333
  class_local_attr_accessor true, :excluded_classes
334
+ class_local_attr_accessor false, :sub_classes
333
335
 
334
336
  class << self
335
337
  # Hide new in Base
@@ -340,6 +342,7 @@ module ActiveLdap
340
342
  sub_class.module_eval do
341
343
  include GetTextSupport
342
344
  end
345
+ (self.sub_classes ||= []) << sub_class
343
346
  end
344
347
 
345
348
  # Set LDAP connection configuration up. It doesn't connect
@@ -548,6 +551,20 @@ module ActiveLdap
548
551
  defaults.first || name || to_s
549
552
  end
550
553
 
554
+ protected
555
+ def find_real_class(object_classes)
556
+ (sub_classes || []).each do |sub_class|
557
+ real_class = sub_class.find_real_class(object_classes)
558
+ return real_class if real_class
559
+ end
560
+
561
+ if object_classes.superset?(Set.new(classes))
562
+ self
563
+ else
564
+ nil
565
+ end
566
+ end
567
+
551
568
  private
552
569
  def inspect_attributes(attributes)
553
570
  inspected_attribute_names = {}
@@ -594,12 +611,19 @@ module ActiveLdap
594
611
  def instantiate(args)
595
612
  dn, attributes, options = args
596
613
  options ||= {}
597
- if self.class == Class
598
- klass = self.ancestors[0].to_s.split(':').last
599
- real_klass = self.ancestors[0]
614
+
615
+ object_classes_raw =
616
+ attributes["objectClass"] ||
617
+ attributes["objectclass"] ||
618
+ []
619
+ if sub_classes.nil? or object_classes_raw.empty?
620
+ real_klass = self
600
621
  else
601
- klass = self.class.to_s.split(':').last
602
- real_klass = self.class
622
+ object_classes = Set.new
623
+ object_classes_raw.each do |object_class_raw|
624
+ object_classes << schema.object_class(object_class_raw)
625
+ end
626
+ real_klass = find_real_class(object_classes) || self
603
627
  end
604
628
 
605
629
  obj = real_klass.allocate
@@ -827,6 +851,8 @@ module ActiveLdap
827
851
 
828
852
  _schema = _local_entry_attribute = nil
829
853
  targets = sanitize_for_mass_assignment(new_attributes)
854
+ have_dn = false
855
+ dn_value = nil
830
856
  targets.each do |key, value|
831
857
  setter = "#{key}="
832
858
  unless respond_to?(setter)
@@ -836,8 +862,15 @@ module ActiveLdap
836
862
  _local_entry_attribute ||= local_entry_attribute
837
863
  _local_entry_attribute.register(attribute)
838
864
  end
839
- send(setter, value)
865
+ case setter
866
+ when "dn=", "id="
867
+ have_dn = true
868
+ dn_value = value
869
+ else
870
+ send(setter, value)
871
+ end
840
872
  end
873
+ self.dn = dn_value if have_dn
841
874
  end
842
875
 
843
876
  def to_ldif_record
@@ -922,9 +955,7 @@ module ActiveLdap
922
955
  def clear_object_class_based_cache
923
956
  @entry_attribute = nil
924
957
  @real_names = {}
925
- @changed_attributes.reject! do |key, _|
926
- not attribute_method?(key)
927
- end
958
+ clear_changes_information
928
959
  end
929
960
 
930
961
  def clear_removed_attributes_data(removed_attributes)
@@ -1093,7 +1124,7 @@ module ActiveLdap
1093
1124
  end
1094
1125
  set_attribute(key, value)
1095
1126
  end
1096
- @changed_attributes.clear
1127
+ clear_changes_information
1097
1128
  end
1098
1129
  private :initialize_attributes
1099
1130
 
@@ -1143,8 +1174,6 @@ module ActiveLdap
1143
1174
  @dn_split_value = nil
1144
1175
  @connection ||= nil
1145
1176
  @_hashing = false
1146
- @previously_changed = []
1147
- @changed_attributes = {}
1148
1177
  clear_connection_based_cache
1149
1178
  end
1150
1179
 
@@ -1261,6 +1290,7 @@ module ActiveLdap
1261
1290
  end
1262
1291
 
1263
1292
  def compute_base
1293
+ ensure_update_dn
1264
1294
  base_of_class = self.class.base
1265
1295
  if @base_value.nil?
1266
1296
  base_of_class
@@ -1352,7 +1382,14 @@ module ActiveLdap
1352
1382
  if k == _dn_attribute
1353
1383
  new_dn_value = value[0]
1354
1384
  else
1355
- attributes.push([:replace, k, value])
1385
+ if (v.size == 1 and value.size == 1) or force_replace?(k)
1386
+ attributes.push([:replace, k, value])
1387
+ else
1388
+ removed_values = v - value
1389
+ added_values = value - v
1390
+ attributes.push([:delete, k, removed_values]) unless removed_values.empty?
1391
+ attributes.push([:add, k, added_values]) unless added_values.empty?
1392
+ end
1356
1393
  end
1357
1394
  end
1358
1395
 
@@ -1366,12 +1403,22 @@ module ActiveLdap
1366
1403
  # Detect subtypes and account for them
1367
1404
  # REPLACE will function like ADD, but doesn't hit EQUALITY problems
1368
1405
  # TODO: Added equality(attr) to Schema
1369
- attributes.push([:replace, k, value])
1406
+ if force_replace?(k)
1407
+ attributes.push([:replace, k, value])
1408
+ else
1409
+ attributes.push([:add, k, value])
1410
+ end
1370
1411
  end
1371
1412
 
1372
1413
  [new_dn_value, attributes]
1373
1414
  end
1374
1415
 
1416
+ def force_replace?(k)
1417
+ attribute = schema.attribute(k)
1418
+ attribute.single_value? or
1419
+ attribute.binary? # TODO: this should probably explicitly check for fields with no equality matching rule instead
1420
+ end
1421
+
1375
1422
  def collect_all_attributes(data)
1376
1423
  dn_attr = dn_attribute
1377
1424
  dn_value = data[dn_attr]
@@ -14,13 +14,12 @@ module ActiveLdap
14
14
  included do
15
15
  extend ActiveModel::Callbacks
16
16
  include ActiveModel::Validations::Callbacks
17
-
17
+ singleton_class.class_eval do
18
+ prepend CallbackedInstantiatable
19
+ end
20
+
18
21
  define_model_callbacks :initialize, :find, :touch, :only => :after
19
22
  define_model_callbacks :save, :create, :update, :destroy
20
-
21
- class << self
22
- alias_method_chain :instantiate, :callbacks
23
- end
24
23
  end
25
24
 
26
25
  module ClassMethods
@@ -33,9 +32,9 @@ module ActiveLdap
33
32
  end
34
33
  end
35
34
 
36
- module ClassMethods
37
- def instantiate_with_callbacks(record)
38
- object = instantiate_without_callbacks(record)
35
+ module CallbackedInstantiatable
36
+ def instantiate(record)
37
+ object = super(record)
39
38
  object.run_callbacks(:find)
40
39
  object.run_callbacks(:initialize)
41
40
  object
@@ -27,6 +27,7 @@ module ActiveLdap
27
27
  DEFAULT_CONFIG[:host] = '127.0.0.1'
28
28
  DEFAULT_CONFIG[:port] = nil
29
29
  DEFAULT_CONFIG[:method] = :plain # :ssl, :tls, :plain allowed
30
+ DEFAULT_CONFIG[:tls_options] = nil
30
31
 
31
32
  DEFAULT_CONFIG[:bind_dn] = nil
32
33
  DEFAULT_CONFIG[:password_block] = nil
@@ -47,6 +48,15 @@ module ActiveLdap
47
48
  DEFAULT_CONFIG[:retry_on_timeout] = true
48
49
  DEFAULT_CONFIG[:follow_referrals] = true
49
50
 
51
+ # 500 is the default size limit value of OpenLDAP 2.4:
52
+ # https://openldap.org/doc/admin24/limits.html#Global%20Limits
53
+ #
54
+ # We may change this when we find LDAP server that its the default
55
+ # size limit is smaller than 500.
56
+ DEFAULT_CONFIG[:page_size] = 500
57
+ # Whether using paged results if available.
58
+ DEFAULT_CONFIG[:use_paged_results] = true
59
+
50
60
  DEFAULT_CONFIG[:logger] = nil
51
61
 
52
62
  module ClassMethods
@@ -91,8 +101,8 @@ module ActiveLdap
91
101
  @@defined_configurations
92
102
  end
93
103
 
94
- def remove_configuration_by_configuration(config)
95
- @@defined_configurations.delete_if {|key, value| value == config}
104
+ def remove_configuration_by_key(key)
105
+ @@defined_configurations.delete(key)
96
106
  end
97
107
 
98
108
  CONNECTION_CONFIGURATION_KEYS = [:uri, :base, :adapter]
@@ -102,8 +112,22 @@ module ActiveLdap
102
112
  end
103
113
  end
104
114
 
115
+ def parent_configuration(target)
116
+ if target.is_a?(Base)
117
+ target = target.class
118
+ else
119
+ target = target.superclass
120
+ end
121
+ while target <= Base
122
+ config = defined_configurations[target.active_connection_key]
123
+ return config if config
124
+ target = target.superclass
125
+ end
126
+ default_configuration
127
+ end
128
+
105
129
  def merge_configuration(user_configuration, target=self)
106
- configuration = default_configuration
130
+ configuration = parent_configuration(target).dup
107
131
  prepare_configuration(user_configuration).each do |key, value|
108
132
  case key
109
133
  when :base
@@ -6,7 +6,7 @@ module ActiveLdap
6
6
 
7
7
  module ClassMethods
8
8
  @@active_connections = {}
9
- @@allow_concurrency = false
9
+ @@allow_concurrency = true
10
10
 
11
11
  def thread_safe_active_connections
12
12
  @@active_connections[Thread.current.object_id] ||= {}
@@ -135,7 +135,7 @@ module ActiveLdap
135
135
  end
136
136
  config = configuration(key)
137
137
  conn = active_connections[key]
138
- remove_configuration_by_configuration(config)
138
+ remove_configuration_by_key(key)
139
139
  active_connections.delete_if {|_key, value| value == conn}
140
140
  conn.disconnect! if conn
141
141
  config
@@ -165,11 +165,11 @@ module ActiveLdap
165
165
  connection.schema
166
166
  end
167
167
 
168
- private
169
168
  def active_connection_key(k=self)
170
169
  k.name.blank? ? k.object_id : k.name
171
170
  end
172
171
 
172
+ private
173
173
  def determine_active_connection_name
174
174
  key = active_connection_key
175
175
  if active_connections[key] or configuration(key)
@@ -197,27 +197,9 @@ module ActiveLdap
197
197
  if Object.respond_to?(:java)
198
198
  "jndi"
199
199
  else
200
- ruby_ldap_available = false
201
- $LOAD_PATH.each do |path|
202
- if File.exist?(File.join(path, "ldap", "ldif.rb"))
203
- ruby_ldap_available = true
204
- break
205
- end
206
- end
207
- if !ruby_ldap_available and Object.const_defined?(:Gem)
208
- ruby_ldap_available = gem_available?("ruby-ldap")
209
- end
210
- if ruby_ldap_available
211
- "ldap"
212
- else
213
- "net-ldap"
214
- end
200
+ "net-ldap"
215
201
  end
216
202
  end
217
-
218
- def gem_available?(name)
219
- not Gem::Specification.find_all_by_name(name).empty?
220
- end
221
203
  end
222
204
 
223
205
  def setup_connection(config=nil)
@@ -62,7 +62,7 @@ module ActiveLdap
62
62
 
63
63
  HEX_PAIR = "(?:[\\da-fA-F]{2})"
64
64
  STRING_CHARS_RE = /[^,=\+<>\#;\\\"]*/ #
65
- PAIR_RE = /\\([,=\+<>\#;]|\\|\"|(#{HEX_PAIR}))/ #
65
+ PAIR_RE = /\\([,=\+<>\#;]|\\|\"| |(#{HEX_PAIR}))/ #
66
66
  HEX_STRING_RE = /\#(#{HEX_PAIR}+)/ #
67
67
  def scan_attribute_value(scanner)
68
68
  if scanner.scan(HEX_STRING_RE)
@@ -17,11 +17,12 @@ module ActiveLdap
17
17
  if attribute_or_name.is_a?(Schema::Attribute)
18
18
  name = attribute_or_name.name
19
19
  else
20
- attribute = schema.attribute(attribute_or_name.to_s)
20
+ attribute_name = attribute_or_name.to_s
21
+ attribute = schema.attribute(attribute_name)
21
22
  return nil if attribute.id.nil?
22
- if attribute.name == attribute_or_name or
23
- attribute.aliases.include?(attribute_or_name.to_s)
24
- name = attribute_or_name
23
+ if attribute.name == attribute_name or
24
+ attribute.aliases.include?(attribute_name)
25
+ name = attribute_name
25
26
  else
26
27
  return nil
27
28
  end
@@ -22,9 +22,23 @@ module ActiveLdap
22
22
  end
23
23
 
24
24
  module Common
25
- VALID_SEARCH_OPTIONS = [:attribute, :value, :filter, :prefix,
26
- :classes, :scope, :limit, :attributes,
27
- :sort_by, :order, :connection, :base, :offset]
25
+ VALID_SEARCH_OPTIONS = [
26
+ :attribute,
27
+ :value,
28
+ :filter,
29
+ :prefix,
30
+ :classes,
31
+ :scope,
32
+ :limit,
33
+ :attributes,
34
+ :sort_by,
35
+ :order,
36
+ :connection,
37
+ :base,
38
+ :offset,
39
+ :use_paged_results,
40
+ :page_size,
41
+ ]
28
42
 
29
43
  def search(options={}, &block)
30
44
  validate_search_options(options)
@@ -62,6 +76,8 @@ module ActiveLdap
62
76
  :attributes => requested_attributes,
63
77
  :sort_by => options[:sort_by] || sort_by,
64
78
  :order => options[:order] || order,
79
+ :use_paged_results => options[:use_paged_results],
80
+ :page_size => options[:page_size],
65
81
  }
66
82
  options[:connection] ||= connection
67
83
  values = []
@@ -96,10 +112,11 @@ module ActiveLdap
96
112
  }
97
113
 
98
114
  attribute = attr || ensure_search_attribute
115
+ escaped_value = DN.escape_value(value)
99
116
  options_for_non_leaf = {
100
117
  :attribute => attr,
101
118
  :value => value,
102
- :prefix => ["#{attribute}=#{value}", prefix].compact.join(","),
119
+ :prefix => ["#{attribute}=#{escaped_value}", prefix].compact.join(","),
103
120
  :limit => 1,
104
121
  :scope => :base,
105
122
  }
@@ -291,6 +308,9 @@ module ActiveLdap
291
308
  offset = options.delete(:offset) || offset
292
309
  options[:attributes] = options.delete(:attributes) || ['*']
293
310
  options[:attributes] |= ['objectClass']
311
+ if options.delete(:include_operational_attributes)
312
+ options[:attributes] |= ["+"]
313
+ end
294
314
  results = search(options).collect do |dn, attrs|
295
315
  instantiate([dn, attrs, {:connection => options[:connection]}])
296
316
  end
@@ -81,9 +81,10 @@ module ActiveLdap
81
81
  end
82
82
  end
83
83
 
84
- def reload
84
+ def reload(options={})
85
85
  clear_association_cache
86
- _, attributes = search(:value => id).find do |_dn, _attributes|
86
+ search_options = options.merge(value: id)
87
+ _, attributes = search(search_options).find do |_dn, _attributes|
87
88
  dn == _dn
88
89
  end
89
90
  if attributes.nil?
@@ -1,9 +1,11 @@
1
1
  module ActiveLdap
2
2
  module Populate
3
3
  module_function
4
- def ensure_base(base_class=nil)
4
+ def ensure_base(base_class=nil, options={})
5
5
  base_class ||= Base
6
6
  return unless base_class.search(:scope => :base).empty?
7
+ dc_base_class = options[:dc_base_class] || base_class
8
+ ou_base_class = options[:ou_base_class] || base_class
7
9
 
8
10
  base_dn = DN.parse(base_class.base)
9
11
  suffixes = []
@@ -15,11 +17,11 @@ module ActiveLdap
15
17
  begin
16
18
  case name.downcase
17
19
  when "dc"
18
- ensure_dc(value, prefix, base_class)
20
+ ensure_dc(value, prefix, dc_base_class)
19
21
  when "ou"
20
22
  ensure_ou(value,
21
23
  :base => prefix,
22
- :base_class => base_class)
24
+ :base_class => ou_base_class)
23
25
  end
24
26
  rescue ActiveLdap::OperationNotPermitted
25
27
  end
@@ -6,8 +6,7 @@ module ActiveLdap
6
6
  module ControllerRuntime #:nodoc:
7
7
  extend ActiveSupport::Concern
8
8
 
9
- protected
10
-
9
+ private
11
10
  attr_internal :ldap_runtime
12
11
 
13
12
  def process_action(action, *args)
@@ -192,11 +192,11 @@ module ActiveLdap
192
192
  fraction = fraction.to_f if fraction
193
193
  time_zone = match_data[-1]
194
194
  arguments = [
195
- year, month, day, hour, minute, second, fraction, time_zone,
195
+ value, year, month, day, hour, minute, second, fraction, time_zone,
196
196
  Time.now,
197
197
  ]
198
- if Time.method(:make_time).arity == 10
199
- arguments.unshift(value)
198
+ if Time.method(:make_time).arity == 11
199
+ arguments[2, 0] = nil
200
200
  end
201
201
  begin
202
202
  Time.send(:make_time, *arguments)
@@ -222,7 +222,11 @@ module ActiveLdap
222
222
  if value.gmt?
223
223
  normalized_value + "Z"
224
224
  else
225
- normalized_value + ("%+03d%02d" % value.gmtoff.divmod(3600))
225
+ # for timezones with non-zero minutes, such as IST which is +0530,
226
+ # divmod(3600) will give wrong value of 1800
227
+
228
+ offset = value.gmtoff / 60 # in minutes
229
+ normalized_value + ("%+03d%02d" % offset.divmod(60))
226
230
  end
227
231
  else
228
232
  value
@@ -53,15 +53,23 @@ module ActiveLdap
53
53
  errors.empty? && output
54
54
  end
55
55
 
56
- def save(*)
57
- valid? ? super : false
56
+ def save(**options)
57
+ perform_validations(options) ? super : false
58
58
  end
59
59
 
60
- def save!(*)
61
- valid? ? super : raise(EntryInvalid.new(self))
60
+ def save!(**options)
61
+ perform_validations(options) ? super : raise(EntryInvalid.new(self))
62
62
  end
63
63
 
64
64
  private
65
+ def perform_validations(options)
66
+ if options[:validate] == false
67
+ true
68
+ else
69
+ valid?(options[:context])
70
+ end
71
+ end
72
+
65
73
  def format_validation_message(format, parameters)
66
74
  format % parameters
67
75
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveLdap
2
- VERSION = "4.0.5"
2
+ VERSION = "6.1.0"
3
3
  end
data/lib/active_ldap.rb CHANGED
@@ -1,4 +1,3 @@
1
- require "rubygems"
2
1
  require "active_model"
3
2
  require "active_support/core_ext"
4
3
 
@@ -8,12 +7,6 @@ module ActiveLdap
8
7
  autoload :Command, "active_ldap/command"
9
8
  end
10
9
 
11
- if RUBY_PLATFORM.match('linux')
12
- require 'active_ldap/timeout'
13
- else
14
- require 'active_ldap/timeout_stub'
15
- end
16
-
17
10
  require 'active_ldap/get_text'
18
11
 
19
12
  require 'active_ldap/compatible'
data/po/en/active-ldap.po CHANGED
@@ -7,7 +7,7 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: Ruby/ActiveLdap 1.1.1\n"
9
9
  "POT-Creation-Date: 2009-08-04 23:26+0900\n"
10
- "PO-Revision-Date: 2009-02-25 08:40+0900\n"
10
+ "PO-Revision-Date: 2016-05-13 21:52+0900\n"
11
11
  "Last-Translator: Kouhei Sutou <kou@cozmixng.org>\n"
12
12
  "Language-Team: English\n"
13
13
  "MIME-Version: 1.0\n"
@@ -3524,7 +3524,7 @@ msgstr ""
3524
3524
 
3525
3525
  #: lib/active_ldap/adapter/base.rb:579
3526
3526
  msgid ""
3527
- "Reconnect to server failed: %s\n"
3527
+ "Reconnect to server failed: %s: %s\n"
3528
3528
  "Reconnect to server failed backtrace:\n"
3529
3529
  "%s"
3530
3530
  msgstr ""
data/po/ja/active-ldap.po CHANGED
@@ -7,7 +7,7 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: Ruby/ActiveLdap 1.1.1\n"
9
9
  "POT-Creation-Date: 2009-08-04 23:26+0900\n"
10
- "PO-Revision-Date: 2009-08-04 23:28+0900\n"
10
+ "PO-Revision-Date: 2016-05-13 21:53+0900\n"
11
11
  "Last-Translator: Kouhei Sutou <kou@cozmixng.org>\n"
12
12
  "Language-Team: Japanese\n"
13
13
  "MIME-Version: 1.0\n"
@@ -3533,11 +3533,11 @@ msgstr "再接続を試みています"
3533
3533
 
3534
3534
  #: lib/active_ldap/adapter/base.rb:579
3535
3535
  msgid ""
3536
- "Reconnect to server failed: %s\n"
3536
+ "Reconnect to server failed: %s: %s\n"
3537
3537
  "Reconnect to server failed backtrace:\n"
3538
3538
  "%s"
3539
3539
  msgstr ""
3540
- "サーバへの再接続が失敗しました: %s\n"
3540
+ "サーバへの再接続が失敗しました: %s: %s\n"
3541
3541
  "サーバへの再接続失敗時のバックトレース:\n"
3542
3542
  "%s"
3543
3543
 
@@ -1,6 +1,6 @@
1
- # Your LDAP server need to accept 'phonetic' attribute option for test.
2
- # This is a LDIF file for OpenLDAP to do the confiugration.
3
- # You can use this file by the following command linne on Debian GNU/Linux
1
+ # Your LDAP server needs to accept 'phonetic' attribute option for test.
2
+ # This is a LDIF file for OpenLDAP to do the configuration.
3
+ # You can use this file by the following command line on Debian GNU/Linux
4
4
  # or Ubuntu:
5
5
  # % sudo -H ldapmodify -Y EXTERNAL -H ldapi:/// -f test/add-phonetic-attribute-options-to-slapd.ldif
6
6
  version: 1