Parent

Methods

Included Modules

Class/Module Index [+]

Quicksearch

ActiveLdap::Base

Base

Base is the primary class which contains all of the core ActiveLdap functionality. It is meant to only ever be subclassed by extension classes.

Attributes

abstract_class[RW]

Public Class Methods

abstract_class?() click to toggle source
# File lib/active_ldap/base.rb, line 506
def abstract_class?
  defined?(@abstract_class) && @abstract_class
end
base() click to toggle source

Base.base

This method when included into Base provides an inheritable, overwritable configuration setting

This should be a string with the base of the ldap server such as 'dc=example,dc=com', and it should be overwritten by including configuration.rb into this class. When subclassing, the specified prefix will be concatenated.

# File lib/active_ldap/base.rb, line 433
def base
  @base ||= compute_base
end
Also aliased as: parsed_base
base=(value) click to toggle source
# File lib/active_ldap/base.rb, line 438
def base=(value)
  self.inheritable_base = value
  @base = nil
end
base_class() click to toggle source
# File lib/active_ldap/base.rb, line 466
def base_class
  if self == Base or superclass == Base
    self
  else
    superclass.base_class
  end
end
class_local_attr_accessor(search_ancestors, *syms) click to toggle source
# File lib/active_ldap/base.rb, line 298
def self.class_local_attr_accessor(search_ancestors, *syms)
  syms.flatten.each do |sym|
    class_eval(          def self.#{sym}(search_superclasses=#{search_ancestors})            @#{sym} ||= nil            return @#{sym} if @#{sym}            if search_superclasses              target = superclass              value = nil              loop do                break nil unless target.respond_to?(:#{sym})                value = target.#{sym}                break if value                target = target.superclass              end              value            else              nil            end          end          def #{sym}; self.class.#{sym}; end          def self.#{sym}=(value); @#{sym} = value; end, __FILE__, __LINE__ + 1)
  end
end
class_of_active_ldap_descendant(klass) click to toggle source
# File lib/active_ldap/base.rb, line 510
def class_of_active_ldap_descendant(klass)
  if klass.superclass == Base or klass.superclass.abstract_class?
    klass
  elsif klass.superclass.nil?
    raise Error, _("%s doesn't belong in a hierarchy descending "                           "from ActiveLdap") % (name || to_s)
  else
    class_of_active_ldap_descendant(klass.superclass)
  end
end
create(attributes=nil, &block) click to toggle source
# File lib/active_ldap/base.rb, line 389
def create(attributes=nil, &block)
  if attributes.is_a?(Array)
    attributes.collect {|attrs| create(attrs, &block)}
  else
    object = new(attributes, &block)
    object.save
    object
  end
end
default_search_attribute() click to toggle source
# File lib/active_ldap/base.rb, line 474
def default_search_attribute
  dn_attribute
end
establish_connection(config=nil) click to toggle source

establish_connection is deprecated since 1.1.0. Please use setup_connection() instead.

# File lib/active_ldap/base.rb, line 380
def establish_connection(config=nil)
  message =
    _("ActiveLdap::Base.establish_connection has been deprecated "              "since 1.1.0. "              "Please use ActiveLdap::Base.setup_connection instead.")
  ActiveSupport::Deprecation.warn(message)
  setup_connection(config)
end
human_name(options={}) click to toggle source
# File lib/active_ldap/base.rb, line 540
def human_name(options={})
  defaults = self_and_descendants_from_active_ldap.collect do |klass|
    if klass.name.blank?
      nil
    else
      :"#{klass.name.underscore}"
    end
  end
  defaults << name.humanize
  defaults = defaults.compact
  defaults.first || name || to_s
end
inherited(sub_class) click to toggle source

Hide new in Base

# File lib/active_ldap/base.rb, line 333
def inherited(sub_class)
  super
  sub_class.module_eval do
    include GetTextSupport
  end
end
inspect() click to toggle source
# File lib/active_ldap/base.rb, line 478
def inspect
  if self == Base
    super
  elsif abstract_class?
    "#{super}(abstract)"
  else
    detail = nil
    begin
      must = []
      may = []
      class_names = classes.collect do |object_class|
        must.concat(object_class.must)
        may.concat(object_class.may)
        object_class.name
      end
      detail = ["objectClass:<#{class_names.join(', ')}>",
                "must:<#{inspect_attributes(must)}>",
                "may:<#{inspect_attributes(may)}>"].join(", ")
    rescue ActiveLdap::ConnectionNotSetup
      detail = "not-connected"
    rescue ActiveLdap::Error
      detail = "connection-failure"
    end
    "#{super}(#{detail})"
  end
end
ldap_mapping(options={}) click to toggle source

This class function is used to setup all mappings between the subclass and ldap for use in activeldap

Example:

ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People',
             :classes => ['top', 'posixAccount'],
             :scope => :sub
# File lib/active_ldap/base.rb, line 406
def ldap_mapping(options={})
  options = options.symbolize_keys
  validate_ldap_mapping_options(options)

  self.dn_attribute = options[:dn_attribute] || default_dn_attribute
  self.dn_attribute = dn_attribute.to_s if dn_attribute.is_a?(Symbol)
  self.prefix = options[:prefix] || default_prefix
  self.scope = options[:scope]
  self.required_classes = options[:classes]
  self.recommended_classes = options[:recommended_classes]
  self.excluded_classes = options[:excluded_classes]
  self.sort_by = options[:sort_by]
  self.order = options[:order]

  public_class_method :new
end
new(attributes=nil) click to toggle source

new

Creates a new instance of Base initializing all class and all initialization. Defines local defaults. See examples If multiple values exist for dn_attribute, the first one put here will be authoritative

# File lib/active_ldap/base.rb, line 670
def initialize(attributes=nil)
  init_base
  @new_entry = true
  initial_classes = required_classes | recommended_classes
  case attributes
  when nil
    self.classes = initial_classes
  when String, Array, DN
    self.classes = initial_classes
    self.dn = attributes
  when Hash
    classes, attributes = extract_object_class(attributes)
    self.classes = classes | initial_classes
    normalized_attributes = {}
    attributes.each do |key, value|
      real_key = to_real_attribute_name(key) || key
      normalized_attributes[real_key] = value
    end
    self.dn = normalized_attributes.delete(dn_attribute)
    self.attributes = normalized_attributes
  else
    format = _("'%s' must be either nil, DN value as ActiveLdap::DN, "                     "String or Array or attributes as Hash")
    raise ArgumentError, format % attributes.inspect
  end
  yield self if block_given?
end
parsed_base() click to toggle source
Alias for: base
prefix() click to toggle source
# File lib/active_ldap/base.rb, line 443
def prefix
  @prefix ||= inheritable_prefix and DN.parse(inheritable_prefix)
end
prefix=(value) click to toggle source
# File lib/active_ldap/base.rb, line 447
def prefix=(value)
  self.inheritable_prefix = value
  @prefix = nil
  @base = nil
end
scope=(scope) click to toggle source
# File lib/active_ldap/base.rb, line 454
def scope=(scope)
  validate_scope(scope)
  self.scope_without_validation = scope
end
Also aliased as: scope_without_validation=
scope_without_validation=(scope) click to toggle source
Alias for: scope=
self_and_descendants_from_active_ldap() click to toggle source
# File lib/active_ldap/base.rb, line 521
def self_and_descendants_from_active_ldap
  klass = self
  classes = [klass]
  while klass != klass.base_class
    classes << klass = klass.superclass
  end
  classes
rescue
  [self]
end
setup_connection(config=nil) click to toggle source

Connect and bind to LDAP creating a class variable for use by all ActiveLdap objects.

config

config must be a hash that may contain any of the following fields: :password_block, :logger, :host, :port, :base, :bind_dn, :try_sasl, :allow_anonymous :bind_dn specifies the DN to bind with. :password_block specifies a Proc object that will yield a String to

be used as the password when called.

:logger specifies a logger object (Logger, Log4r::Logger and s on) :host sets the LDAP server hostname :port sets the LDAP server port :base overwrites Base.base - this affects EVERYTHING :try_sasl indicates that a SASL bind should be attempted when binding

to the server (default: false)

:sasl_mechanisms is an array of SASL mechanism to try

(default: ["GSSAPI", "CRAM-MD5", "EXTERNAL"])

:allow_anonymous indicates that a true anonymous bind is allowed when

trying to bind to the server (default: true)

:retries - indicates the number of attempts to reconnect that will be

undertaken when a stale connection occurs. -1 means infinite.

:sasl_quiet - if true, sets @sasl_quiet on the Ruby/LDAP connection :method - whether to use :ssl, :tls, or :plain (unencrypted) :retry_wait - seconds to wait before retrying a connection :scope - dictates how to find objects. ONELEVEL by default to

avoid dn_attr collisions across OUs. Think before changing.

:timeout - time in seconds - defaults to disabled. This CAN interrupt

search() requests. Be warned.

:retry_on_timeout - whether to reconnect when timeouts occur. Defaults

to true

See lib/active_ldap/configuration.rb for defaults for each option

# File lib/active_ldap/base.rb, line 372
def setup_connection(config=nil)
  super
  ensure_logger
  nil
end
validate_scope(scope) click to toggle source
# File lib/active_ldap/base.rb, line 459
def validate_scope(scope)
  scope = scope.to_sym if scope.is_a?(String)
  return if scope.nil? or scope.is_a?(Symbol)
  raise ConfigurationError,
          _("scope '%s' must be a Symbol") % scope.inspect
end

Private Class Methods

compute_base() click to toggle source
# File lib/active_ldap/base.rb, line 633
def compute_base
  _base = inheritable_base
  _base = configuration[:base] if _base.nil? and configuration
  if _base.nil?
    target = superclass
    loop do
      break unless target.respond_to?(:base)
      _base = target.base
      break if _base
      target = target.superclass
    end
  end
  _prefix = prefix

  _base ||= connection.naming_contexts.first
  return _prefix if _base.blank?

  _base = DN.parse(_base)
  _base = _prefix + _base if _prefix
  _base
end
default_dn_attribute() click to toggle source
# File lib/active_ldap/base.rb, line 616
def default_dn_attribute
  dn_attribute = nil
  parent_class = ancestors[1]
  if parent_class.respond_to?(:dn_attribute)
    dn_attribute = parent_class.dn_attribute
  end
  dn_attribute || "cn"
end
default_prefix() click to toggle source
# File lib/active_ldap/base.rb, line 625
def default_prefix
  if name.blank?
    nil
  else
    "ou=#{name.demodulize.pluralize}"
  end
end
ensure_logger() click to toggle source
# File lib/active_ldap/base.rb, line 584
def ensure_logger
  @@logger ||= configuration[:logger]
  # Setup default logger to console
  if @@logger.nil?
    require 'logger'
    @@logger = Logger.new(STDERR)
    @@logger.progname = 'ActiveLdap'
    @@logger.level = Logger::ERROR
  end
  configuration[:logger] ||= @@logger
end
inspect_attribute(attribute) click to toggle source
# File lib/active_ldap/base.rb, line 566
def inspect_attribute(attribute)
  syntax = attribute.syntax
  result = "#{attribute.name}"
  if syntax and !syntax.description.blank?
    result << ": #{syntax.description}"
  end
  properties = []
  properties << "read-only" if attribute.read_only?
  properties << "binary" if attribute.binary?
  properties << "binary-required" if attribute.binary_required?
  result << "(#{properties.join(', ')})" unless properties.empty?
  result
end
inspect_attributes(attributes) click to toggle source
# File lib/active_ldap/base.rb, line 554
def inspect_attributes(attributes)
  inspected_attribute_names = {}
  attributes.collect do |attribute|
    if inspected_attribute_names.has_key?(attribute.name)
      nil
    else
      inspected_attribute_names[attribute.name] = true
      inspect_attribute(attribute)
    end
  end.compact.join(', ')
end
instantiate(args) click to toggle source
# File lib/active_ldap/base.rb, line 596
def instantiate(args)
  dn, attributes, options = args
  options ||= {}
  if self.class == Class
    klass = self.ancestors[0].to_s.split(':').last
    real_klass = self.ancestors[0]
  else
    klass = self.class.to_s.split(':').last
    real_klass = self.class
  end

  obj = real_klass.allocate
  conn = options[:connection] || connection
  obj.connection = conn if conn != connection
  obj.instance_eval do
    initialize_by_ldap_data(dn, attributes)
  end
  obj
end
validate_ldap_mapping_options(options) click to toggle source
# File lib/active_ldap/base.rb, line 580
def validate_ldap_mapping_options(options)
  options.assert_valid_keys(VALID_LDAP_MAPPING_OPTIONS)
end

Public Instance Methods

==(comparison_object) click to toggle source

Returns true if the comparison_object is the same object, or is of the same type and has the same dn.

# File lib/active_ldap/base.rb, line 700
def ==(comparison_object)
  comparison_object.equal?(self) or
    (comparison_object.instance_of?(self.class) and
     comparison_object.dn == dn and
     !comparison_object.new_entry?)
end
[](name, force_array=false) click to toggle source
# File lib/active_ldap/base.rb, line 983
def [](name, force_array=false)
  if name == "dn"
    array_of(dn, force_array)
  else
    get_attribute(name, force_array)
  end
end
[]=(name, value) click to toggle source
# File lib/active_ldap/base.rb, line 991
def []=(name, value)
  set_attribute(name, value)
end
attribute_names(normalize=false) click to toggle source

attributes

Return attribute methods so that a program can determine available attributes dynamically without schema awareness

# File lib/active_ldap/base.rb, line 742
def attribute_names(normalize=false)
  entry_attribute.names(normalize)
end
attribute_present?(name) click to toggle source
# File lib/active_ldap/base.rb, line 746
def attribute_present?(name)
  values = get_attribute(name, true)
  !values.empty? or values.any? {|x| !(x and x.empty?)}
end
attributes() click to toggle source

This returns the key value pairs in @data with all values cloned

# File lib/active_ldap/base.rb, line 903
def attributes
  @simplified_data ||= simplify_data(@data)
  @simplified_data.clone
end
attributes=(new_attributes) click to toggle source

This allows a bulk update to the attributes of a record without forcing an immediate save or validation.

It is unwise to attempt objectClass updates this way. Also be sure to only pass in key-value pairs of your choosing. Do not let URL/form hackers supply the keys.

# File lib/active_ldap/base.rb, line 914
def attributes=(new_attributes)
  return if new_attributes.blank?
  _schema = _local_entry_attribute = nil
  targets = remove_attributes_protected_from_mass_assignment(new_attributes)
  targets.each do |key, value|
    setter = "#{key}="
    unless respond_to?(setter)
      _schema ||= schema
      attribute = _schema.attribute(key)
      next if attribute.id.nil?
      _local_entry_attribute ||= local_entry_attribute
      _local_entry_attribute.register(attribute)
    end
    send(setter, value)
  end
end
base() click to toggle source
# File lib/active_ldap/base.rb, line 1041
def base
  @base ||= compute_base
end
base=(object_local_base) click to toggle source
# File lib/active_ldap/base.rb, line 1045
def base=(object_local_base)
  ensure_update_dn
  @dn = nil
  @base = nil
  @base_value = object_local_base
end
bind(config_or_password={}, config_or_ignore=nil, &block) click to toggle source
# File lib/active_ldap/base.rb, line 1001
def bind(config_or_password={}, config_or_ignore=nil, &block)
  if config_or_password.is_a?(String)
    config = (config_or_ignore || {}).merge(:password => config_or_password)
  else
    config = config_or_password
  end
  config = {:bind_dn => dn, :allow_anonymous => false}.merge(config)
  config[:password_block] ||= block if block_given?
  setup_connection(config)

  before_connection = @connection
  begin
    @connection = nil
    connection.connect
    @connection = connection
    clear_connection_based_cache
    clear_association_cache
  rescue ActiveLdap::Error
    remove_connection
    @connection = before_connection
    raise
  end
  true
end
clear_connection_based_cache() click to toggle source
# File lib/active_ldap/base.rb, line 1026
def clear_connection_based_cache
  @schema = nil
  @local_entry_attribute = nil
  clear_object_class_based_cache
end
clear_object_class_based_cache() click to toggle source
# File lib/active_ldap/base.rb, line 1032
def clear_object_class_based_cache
  @entry_attribute = nil
  @real_names = {}
end
default_search_attribute() click to toggle source
# File lib/active_ldap/base.rb, line 793
def default_search_attribute
  self.class.default_search_attribute
end
delete(options={}) click to toggle source
# File lib/active_ldap/base.rb, line 805
def delete(options={})
  super(dn, options)
end
delete_all(options={}) click to toggle source
# File lib/active_ldap/base.rb, line 1062
def delete_all(options={})
  super({:base => dn}.merge(options || {}))
end
destroy() click to toggle source

destroy

Delete this entry from LDAP

# File lib/active_ldap/base.rb, line 800
def destroy
  self.class.delete(dn)
  @new_entry = true
end
destroy_all(options={}) click to toggle source
# File lib/active_ldap/base.rb, line 1066
def destroy_all(options={})
  super({:base => dn}.merge(options || {}))
end
dn() click to toggle source

dn

Return the authoritative dn

# File lib/active_ldap/base.rb, line 769
def dn
  @dn ||= compute_dn
end
dn=(value) click to toggle source
# File lib/active_ldap/base.rb, line 781
def dn=(value)
  set_attribute(dn_attribute_with_fallback, value)
end
Also aliased as: id=
dn_attribute() click to toggle source
# File lib/active_ldap/base.rb, line 787
def dn_attribute
  ensure_update_dn
  _dn_attribute = @dn_attribute || dn_attribute_of_class
  to_real_attribute_name(_dn_attribute) || _dn_attribute
end
Also aliased as: dn_attribute_of_class
dn_attribute_of_class() click to toggle source
Alias for: dn_attribute
each() click to toggle source
# File lib/active_ldap/base.rb, line 995
def each
  @data.each do |key, values|
    yield(key.dup, values.dup)
  end
end
eql?(comparison_object) click to toggle source

Delegates to ==

# File lib/active_ldap/base.rb, line 708
def eql?(comparison_object)
  self == (comparison_object)
end
exist?() click to toggle source

exist?

Return whether the entry exists in LDAP or not

# File lib/active_ldap/base.rb, line 754
def exist?
  self.class.exists?(dn)
end
Also aliased as: exists?
exists?() click to toggle source
Alias for: exist?
has_attribute?(name, except=[]) click to toggle source
Alias for: have_attribute?
hash() click to toggle source

Delegates to id in order to allow two records of the same type and id to work with something like:

[ User.find("a"), User.find("b"), User.find("c") ] &
  [ User.find("a"), User.find("d") ] # => [ User.find("a") ]
# File lib/active_ldap/base.rb, line 716
def hash
  return super if @_hashing # workaround for GetText :<
  _dn = nil
  begin
    @_hashing = true
    _dn = dn
  rescue DistinguishedNameInvalid, DistinguishedNameNotSetError
    return super
  ensure
    @_hashing = false
  end
  _dn.hash
end
have_attribute?(name, except=[]) click to toggle source
# File lib/active_ldap/base.rb, line 960
def have_attribute?(name, except=[])
  real_name = to_real_attribute_name(name)
  !real_name.nil? and !except.include?(real_name)
end
Also aliased as: has_attribute?
id() click to toggle source
# File lib/active_ldap/base.rb, line 773
def id
  get_attribute(dn_attribute_with_fallback)
end
id=(value) click to toggle source
Alias for: dn=
inspect() click to toggle source
# File lib/active_ldap/base.rb, line 1070
def inspect
  object_classes = entry_attribute.object_classes
  inspected_object_classes = object_classes.collect do |object_class|
    object_class.name
  end.join(', ')
  must_attributes = must.collect(&:name).sort.join(', ')
  may_attributes = may.collect(&:name).sort.join(', ')
  inspected_attributes = attribute_names.sort.collect do |name|
    inspect_attribute(name)
  end.join(', ')
  result = "\#<#{self.class} objectClass:<#{inspected_object_classes}>, "
  result << "must:<#{must_attributes}>, may:<#{may_attributes}>, "
  result << "#{inspected_attributes}>"
  result
end
may() click to toggle source
# File lib/active_ldap/base.rb, line 730
def may
  entry_attribute.may
end
method_missing(name, *args, &block) click to toggle source

method_missing

If a given method matches an attribute or an attribute alias then call the appropriate method. TODO: Determine if it would be better to define each allowed method

using class_eval instead of using method_missing.  This would
give tab completion in irb.
# File lib/active_ldap/base.rb, line 831
def method_missing(name, *args, &block)
  key = name.to_s
  case key
  when /=$/
    real_key = $PREMATCH
    if have_attribute?(real_key, ['objectClass'])
      if args.size != 1
        raise ArgumentError,
                _("wrong number of arguments (%d for 1)") % args.size
      end
      return set_attribute(real_key, *args, &block)
    end
  when /(?:(_before_type_cast)|(\?))?$/
    real_key = $PREMATCH
    before_type_cast = !$1.nil?
    query = !$2.nil?
    if have_attribute?(real_key, ['objectClass'])
      if args.size > 1
        raise ArgumentError,
          _("wrong number of arguments (%d for 1)") % args.size
      end
      if before_type_cast
        return get_attribute_before_type_cast(real_key, *args)[1]
      elsif query
        return get_attribute_as_query(real_key, *args)
      else
        return get_attribute(real_key, *args)
      end
    end
  end
  super
end
methods(inherited_too=true) click to toggle source

Add available attributes to the methods

# File lib/active_ldap/base.rb, line 865
def methods(inherited_too=true)
  target_names = entry_attribute.all_names
  target_names -= ['objectClass', 'objectClass'.underscore]
  super + target_names.uniq.collect do |x|
    [x, "#{x}=", "#{x}?", "#{x}_before_type_cast"]
  end.flatten
end
must() click to toggle source
# File lib/active_ldap/base.rb, line 734
def must
  entry_attribute.must
end
new_entry?() click to toggle source

new_entry?

Return whether the entry is new entry in LDAP or not

# File lib/active_ldap/base.rb, line 762
def new_entry?
  @new_entry
end
reload() click to toggle source
# File lib/active_ldap/base.rb, line 966
def reload
  clear_association_cache
  _, attributes = search(:value => id).find do |_dn, _attributes|
    dn == _dn
  end
  if attributes.nil?
    raise EntryNotFound, _("Can't find DN '%s' to reload") % dn
  end

  @ldap_data.update(attributes)
  classes, attributes = extract_object_class(attributes)
  self.classes = classes
  self.attributes = attributes
  @new_entry = false
  self
end
respond_to?(name, include_priv=false) click to toggle source
# File lib/active_ldap/base.rb, line 874
def respond_to?(name, include_priv=false)
  return true if super

  name = name.to_s
  return true if have_attribute?(name, ["objectClass"])
  return false if /(?:=|\?|_before_type_cast)$/ !~ name
  have_attribute?($PREMATCH, ["objectClass"])
end
respond_to_without_attributes?(name, include_priv=false) click to toggle source
Alias for: respond_to?
save() click to toggle source

save

Save and validate this object into LDAP either adding or replacing attributes TODO: Relative DN support

# File lib/active_ldap/base.rb, line 814
def save
  create_or_update
end
save!() click to toggle source
# File lib/active_ldap/base.rb, line 818
def save!
  unless create_or_update
    raise EntryNotSaved, _("entry %s can't be saved") % dn
  end
end
schema() click to toggle source
# File lib/active_ldap/base.rb, line 1037
def schema
  @schema ||= super
end
scope() click to toggle source
# File lib/active_ldap/base.rb, line 1053
def scope
  @scope || scope_of_class
end
Also aliased as: scope_of_class
scope=(scope) click to toggle source
# File lib/active_ldap/base.rb, line 1057
def scope=(scope)
  self.class.validate_scope(scope)
  @scope = scope
end
scope_of_class() click to toggle source
Alias for: scope
to_ldif() click to toggle source
# File lib/active_ldap/base.rb, line 935
def to_ldif
  Ldif.new([to_ldif_record]).to_s
end
to_ldif_record() click to toggle source
# File lib/active_ldap/base.rb, line 931
def to_ldif_record
  super(dn, normalize_data(@data))
end
to_param() click to toggle source
# File lib/active_ldap/base.rb, line 777
def to_param
  id
end
to_s() click to toggle source
# File lib/active_ldap/base.rb, line 956
def to_s
  to_ldif
end
to_xml(options={}) click to toggle source
# File lib/active_ldap/base.rb, line 939
def to_xml(options={})
  options = options.dup
  options[:root] ||= (self.class.name || '').underscore
  options[:root] = 'anonymous' if options[:root].blank?
  except = options[:except]
  if except
    options[:except] = except.collect do |name|
      if name.to_s.downcase == "dn"
        "dn"
      else
        to_real_attribute_name(name)
      end
    end.compact
  end
  XML.new(dn, normalize_data(@data), schema).to_s(options)
end
update_attribute(name, value) click to toggle source

Updates a given attribute and saves immediately

# File lib/active_ldap/base.rb, line 884
def update_attribute(name, value)
  send("#{name}=", value)
  save
end
update_attributes(attrs) click to toggle source

This performs a bulk update of attributes and immediately calls save.

# File lib/active_ldap/base.rb, line 891
def update_attributes(attrs)
  self.attributes = attrs
  save
end
update_attributes!(attrs) click to toggle source
# File lib/active_ldap/base.rb, line 896
def update_attributes!(attrs)
  self.attributes = attrs
  save!
end

Private Instance Methods

array_of(value, to_a=true) click to toggle source

array_of

Returns the array form of a value, or not an array if false is passed in.

# File lib/active_ldap/base.rb, line 1413
def array_of(value, to_a=true)
  case value
  when Array
    if to_a or value.size > 1
      value.collect {|v| array_of(v, false)}.compact
    else
      if value.empty?
        nil
      else
        array_of(value.first, to_a)
      end
    end
  when Hash
    if to_a
      [value]
    else
      result = {}
      value.each {|k, v| result[k] = array_of(v, to_a)}
      result
    end
  else
    to_a ? [value] : value
  end
end
attribute_name_resolvable_without_connection?() click to toggle source
# File lib/active_ldap/base.rb, line 1116
def attribute_name_resolvable_without_connection?
  @entry_attribute and @local_entry_attribute
end
collect_all_attributes(data) click to toggle source
# File lib/active_ldap/base.rb, line 1510
def collect_all_attributes(data)
  dn_attr = dn_attribute
  dn_value = data[dn_attr]

  attributes = []
  attributes.push([dn_attr, dn_value])

  oc_value = data['objectClass']
  attributes.push(['objectClass', oc_value])
  except_keys = ['objectClass', dn_attr].collect(&:downcase)
  data.each do |key, value|
    next if except_keys.include?(key.downcase)
    value = self.class.remove_blank_value(value)
    next if self.class.blank_value?(value)

    attributes.push([key, value])
  end

  attributes
end
collect_modified_attributes(ldap_data, data) click to toggle source
# File lib/active_ldap/base.rb, line 1466
def collect_modified_attributes(ldap_data, data)
  klass = self.class
  _dn_attribute = dn_attribute
  new_dn_value = nil
  attributes = []

  # Now that all the options will be treated as unique attributes
  # we can see what's changed and add anything that is brand-spankin'
  # new.
  ldap_data.each do |k, v|
    value = data[k] || []

    next if v == value

    value = klass.remove_blank_value(value) || []
    next if v == value

    if klass.blank_value?(value) and
        schema.attribute(k).binary_required?
      value = [{'binary' => []}]
    end
    if k == _dn_attribute
      new_dn_value = value[0]
    else
      attributes.push([:replace, k, value])
    end
  end

  data.each do |k, v|
    value = v || []
    next if ldap_data.has_key?(k)

    value = klass.remove_blank_value(value) || []
    next if klass.blank_value?(value)

    # Detect subtypes and account for them
    # REPLACE will function like ADD, but doesn't hit EQUALITY problems
    # TODO: Added equality(attr) to Schema
    attributes.push([:replace, k, value])
  end

  [new_dn_value, attributes]
end
compute_base() click to toggle source
# File lib/active_ldap/base.rb, line 1398
def compute_base
  base_of_class = self.class.base
  if @base_value.nil?
    base_of_class
  else
    base_of_object = DN.parse(@base_value)
    base_of_object += base_of_class if base_of_class
    base_of_object
  end
end
compute_dn() click to toggle source
# File lib/active_ldap/base.rb, line 1382
def compute_dn
  return base if @dn_is_base

  ensure_update_dn
  dn_value = id
  if dn_value.nil?
    format = _("%s's DN attribute (%s) isn't set")
    message = format % [self.inspect, dn_attribute]
    raise DistinguishedNameNotSetError.new, message
  end
  dn_value = DN.escape_value(dn_value.to_s)
  _base = base
  _base = nil if _base.blank?
  DN.parse(["#{dn_attribute}=#{dn_value}", _base].compact.join(","))
end
create() click to toggle source
# File lib/active_ldap/base.rb, line 1563
def create
  prepare_data_for_saving do |data, ldap_data|
    attributes = collect_all_attributes(data)
    add_entry(dn, attributes)
    @new_entry = false
    true
  end
end
create_or_update() click to toggle source
# File lib/active_ldap/base.rb, line 1531
def create_or_update
  new_entry? ? create : update
end
dn_attribute_with_fallback() click to toggle source
# File lib/active_ldap/base.rb, line 1087
def dn_attribute_with_fallback
  begin
    dn_attribute
  rescue DistinguishedNameInvalid
    _dn_attribute = @dn_attribute || dn_attribute_of_class
    _dn_attribute = to_real_attribute_name(_dn_attribute) || _dn_attribute
    raise if _dn_attribute.nil?
    _dn_attribute
  end
end
enforce_type(key, value) click to toggle source

enforce_type

enforce_type applies your changes without attempting to write to LDAP. This means that if you set userCertificate to somebinary value, it will wrap it up correctly.

# File lib/active_ldap/base.rb, line 1194
def enforce_type(key, value)
  # Enforce attribute value formatting
  normalize_attribute(key, value)[1]
end
ensure_update_dn() click to toggle source
# File lib/active_ldap/base.rb, line 1372
def ensure_update_dn
  return unless need_update_dn?
  @mutex.synchronize do
    if @dn_split_value
      update_dn(*@dn_split_value)
      @dn_split_value = nil
    end
  end
end
entry_attribute() click to toggle source
# File lib/active_ldap/base.rb, line 1120
def entry_attribute
  @entry_attribute ||=
    connection.entry_attribute(find_object_class_values(@data) || [])
end
extract_object_class(attributes) click to toggle source
# File lib/active_ldap/base.rb, line 1129
def extract_object_class(attributes)
  classes = []
  attrs = {}
  attributes.each do |key, value|
    key = key.to_s
    if /\Aobject_?class\z/ =~ key
      classes.concat(value.to_a)
    else
      attrs[key] = value
    end
  end
  [classes, attributes]
end
false_value?(value) click to toggle source
# File lib/active_ldap/base.rb, line 1262
def false_value?(value)
  value.nil? or value == false or value == [] or
    value == "false" or value == "FALSE" or value == ""
end
find_object_class_values(data) click to toggle source
# File lib/active_ldap/base.rb, line 1112
def find_object_class_values(data)
  data["objectClass"] || data["objectclass"]
end
get_attribute(name, force_array=false) click to toggle source

get_attribute

Return the value of the attribute called by method_missing?

# File lib/active_ldap/base.rb, line 1217
def get_attribute(name, force_array=false)
  name, value = get_attribute_before_type_cast(name, force_array)
  return value if name.nil?
  attribute = schema.attribute(name)
  type_cast(attribute, value)
end
get_attribute_as_query(name, force_array=false) click to toggle source
# File lib/active_ldap/base.rb, line 1253
def get_attribute_as_query(name, force_array=false)
  name, value = get_attribute_before_type_cast(name, force_array)
  if force_array
    value.collect {|x| !false_value?(x)}
  else
    !false_value?(value)
  end
end
get_attribute_before_type_cast(name, force_array=false) click to toggle source
# File lib/active_ldap/base.rb, line 1245
def get_attribute_before_type_cast(name, force_array=false)
  name = to_real_attribute_name(name)

  value = @data[name]
  value = [] if value.nil?
  [name, array_of(value, force_array)]
end
init_base() click to toggle source
# File lib/active_ldap/base.rb, line 1143
def init_base
  init_instance_variables
end
init_instance_variables() click to toggle source
# File lib/active_ldap/base.rb, line 1199
def init_instance_variables
  @mutex = Mutex.new
  @data = {} # where the r/w entry data is stored
  @ldap_data = {} # original ldap entry data
  @dn_attribute = nil
  @base = nil
  @scope = nil
  @dn = nil
  @dn_is_base = false
  @dn_split_value = nil
  @connection ||= nil
  @_hashing = false
  clear_connection_based_cache
end
initialize_by_ldap_data(dn, attributes) click to toggle source
# File lib/active_ldap/base.rb, line 1147
def initialize_by_ldap_data(dn, attributes)
  init_base
  dn = Compatible.convert_to_utf8_encoded_object(dn)
  attributes = Compatible.convert_to_utf8_encoded_object(attributes)
  @original_dn = dn.clone
  @dn = dn
  @base = nil
  @base_value = nil
  @new_entry = false
  @dn_is_base = false
  @ldap_data = attributes
  classes, attributes = extract_object_class(attributes)
  self.classes = classes
  self.dn = dn
  self.attributes = attributes
  yield self if block_given?
end
inspect_attribute(name) click to toggle source
# File lib/active_ldap/base.rb, line 1098
def inspect_attribute(name)
  values = get_attribute(name, true)
  values.collect do |value|
    if value.is_a?(String) and value.length > 50
      "#{value[0, 50]}...".inspect
    elsif value.is_a?(Date) || value.is_a?(Time)
      "#{value.to_s(:db)}"
    else
      value.inspect
    end
  end
  "#{name}: #{values.inspect}"
end
instantiate(args) click to toggle source
# File lib/active_ldap/base.rb, line 1165
def instantiate(args)
  dn, attributes, options = args
  options ||= {}

  obj = self.class.allocate
  obj.connection = options[:connection] || @connection
  obj.instance_eval do
    initialize_by_ldap_data(dn, attributes)
  end
  obj
end
local_entry_attribute() click to toggle source
# File lib/active_ldap/base.rb, line 1125
def local_entry_attribute
  @local_entry_attribute ||= connection.entry_attribute([])
end
need_update_dn?() click to toggle source
# File lib/active_ldap/base.rb, line 1368
def need_update_dn?
  not @dn_split_value.nil?
end
normalize_data(data, except=[]) click to toggle source
# File lib/active_ldap/base.rb, line 1438
def normalize_data(data, except=[])
  _schema = schema
  result = {}
  data.each do |key, values|
    next if except.include?(key)
    real_name = to_real_attribute_name(key)
    next if real_name and except.include?(real_name)
    real_name ||= key
    next if _schema.attribute(real_name).id.nil?
    result[real_name] ||= []
    result[real_name].concat(enforce_type(real_name, values))
  end
  result
end
prepare_data_for_saving() click to toggle source
# File lib/active_ldap/base.rb, line 1535
def prepare_data_for_saving
  # Expand subtypes to real ldap_data attributes
  # We can't reuse @ldap_data because an exception would leave
  # an object in an unknown state
  ldap_data = normalize_data(@ldap_data)

  # Expand subtypes to real data attributes, but leave @data alone
  object_classes = find_object_class_values(@ldap_data) || []
  original_attributes =
    connection.entry_attribute(object_classes).names
  bad_attrs = original_attributes - entry_attribute.names
  data = normalize_data(@data, bad_attrs)

  success = yield(data, ldap_data)

  if success
    @ldap_data = data.clone
    # Delete items disallowed by objectclasses.
    # They should have been removed from ldap.
    bad_attrs.each do |remove_me|
      @ldap_data.delete(remove_me)
    end
    @original_dn = dn.clone
  end

  success
end
register_new_dn_attribute(name, value) click to toggle source
# File lib/active_ldap/base.rb, line 1288
def register_new_dn_attribute(name, value)
  @dn = nil
  @dn_is_base = false
  if value.blank?
    @dn_split_value = nil
    [name, nil]
  else
    new_name, new_value, raw_new_value, new_bases = split_dn_value(value)
    @dn_split_value = [new_name, new_value, new_bases]
    if new_name.nil? and new_value.nil?
      new_name, raw_new_value = new_bases[0].to_a[0]
    end
    [to_real_attribute_name(new_name) || name,
     raw_new_value || value]
  end
end
set_attribute(name, value) click to toggle source

set_attribute

Set the value of the attribute called by method_missing?

# File lib/active_ldap/base.rb, line 1270
def set_attribute(name, value)
  real_name = to_real_attribute_name(name)
  _dn_attribute = nil
  valid_dn_attribute = true
  begin
    _dn_attribute = dn_attribute
  rescue DistinguishedNameInvalid
    valid_dn_attribute = false
  end
  if valid_dn_attribute and real_name == _dn_attribute
    real_name, value = register_new_dn_attribute(real_name, value)
  end
  raise UnknownAttribute.new(name) if real_name.nil?

  @data[real_name] = value
  @simplified_data = nil
end
simplify_data(data) click to toggle source
# File lib/active_ldap/base.rb, line 1453
def simplify_data(data)
  _schema = schema
  result = {}
  data.each do |key, values|
    attribute = _schema.attribute(key)
    if attribute.single_value? and values.is_a?(Array) and values.size == 1
      values = values[0]
    end
    result[key] = type_cast(attribute, values)
  end
  result
end
split_dn_value(value) click to toggle source
# File lib/active_ldap/base.rb, line 1331
def split_dn_value(value)
  dn_value = relative_dn_value = nil
  begin
    dn_value = value if value.is_a?(DN)
    dn_value ||= DN.parse(value)
  rescue DistinguishedNameInvalid
    begin
      dn_value = DN.parse("#{dn_attribute}=#{value}")
    rescue DistinguishedNameInvalid
      return [nil, value, value, []]
    end
  end

  val = bases = nil
  begin
    relative_dn_value = dn_value
    base_of_class = self.class.base
    relative_dn_value -= base_of_class if base_of_class
    if relative_dn_value.rdns.empty?
      val = []
      bases = dn_value.rdns
    else
      val, *bases = relative_dn_value.rdns
    end
  rescue ArgumentError
    val, *bases = dn_value.rdns
  end

  dn_attribute_name, dn_attribute_value = val.to_a[0]
  escaped_dn_attribute_value = nil
  unless dn_attribute_value.nil?
    escaped_dn_attribute_value = DN.escape_value(dn_attribute_value)
  end
  [dn_attribute_name, escaped_dn_attribute_value,
   dn_attribute_value, bases]
end
to_real_attribute_name(name, allow_normalized_name=true) click to toggle source
# File lib/active_ldap/base.rb, line 1177
def to_real_attribute_name(name, allow_normalized_name=true)
  return name if name.nil?
  if allow_normalized_name
    entry_attribute.normalize(name, allow_normalized_name) ||
      local_entry_attribute.normalize(name, allow_normalized_name)
  else
    @real_names[name] ||=
      entry_attribute.normalize(name, false) ||
      local_entry_attribute.normalize(name, false)
  end
end
type_cast(attribute, value) click to toggle source
# File lib/active_ldap/base.rb, line 1224
def type_cast(attribute, value)
  case value
  when Hash
    result = {}
    value.each do |option, val|
      result[option] = type_cast(attribute, val)
    end
    if result.size == 1 and result.has_key?("binary")
      result["binary"]
    else
      result
    end
  when Array
    value.collect do |val|
      type_cast(attribute, val)
    end
  else
    attribute.type_cast(value)
  end
end
update() click to toggle source
# File lib/active_ldap/base.rb, line 1572
def update
  prepare_data_for_saving do |data, ldap_data|
    new_dn_value, attributes = collect_modified_attributes(ldap_data, data)
    modify_entry(@original_dn, attributes)
    if new_dn_value
      old_dn_base = DN.parse(@original_dn).parent
      new_dn_base = dn.clone.parent
      if old_dn_base == new_dn_base
        new_superior = nil
      else
        new_superior = new_dn_base
      end
      modify_rdn_entry(@original_dn,
                       "#{dn_attribute}=#{DN.escape_value(new_dn_value)}",
                       true,
                       new_superior)
    end
    true
  end
end
update_dn(new_name, new_value, bases) click to toggle source
# File lib/active_ldap/base.rb, line 1305
def update_dn(new_name, new_value, bases)
  if new_name.nil? and new_value.nil?
    @dn_is_base = true
    @base = nil
    @base_value = nil
    attr, value = bases[0].to_a[0]
    @dn_attribute = attr
  else
    new_name ||= @dn_attribute || dn_attribute_of_class
    new_name = to_real_attribute_name(new_name)
    if new_name.nil?
      new_name = @dn_attribute || dn_attribute_of_class
      new_name = to_real_attribute_name(new_name)
    end
    new_bases = bases.empty? ? nil : DN.new(*bases).to_s
    dn_components = ["#{new_name}=#{new_value}",
                     new_bases,
                     self.class.base.to_s]
    dn_components = dn_components.find_all {|component| !component.blank?}
    DN.parse(dn_components.join(','))
    @base = nil
    @base_value = new_bases
    @dn_attribute = new_name
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.