Base is the primary class which contains all of the core ActiveLdap functionality. It is meant to only ever be subclassed by extension classes.
# File lib/active_ldap/base.rb, line 506 506: def abstract_class? 507: defined?(@abstract_class) && @abstract_class 508: end
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 433: def base 434: @base ||= compute_base 435: end
# File lib/active_ldap/base.rb, line 438 438: def base=(value) 439: self.inheritable_base = value 440: @base = nil 441: end
# File lib/active_ldap/base.rb, line 466 466: def base_class 467: if self == Base or superclass == Base 468: self 469: else 470: superclass.base_class 471: end 472: end
# File lib/active_ldap/base.rb, line 298 298: def self.class_local_attr_accessor(search_ancestors, *syms) 299: syms.flatten.each do |sym| 300: 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) 301: end 302: end
# File lib/active_ldap/base.rb, line 510 510: def class_of_active_ldap_descendant(klass) 511: if klass.superclass == Base or klass.superclass.abstract_class? 512: klass 513: elsif klass.superclass.nil? 514: raise Error, _("%s doesn't belong in a hierarchy descending " "from ActiveLdap") % (name || to_s) 515: else 516: class_of_active_ldap_descendant(klass.superclass) 517: end 518: end
# File lib/active_ldap/base.rb, line 389 389: def create(attributes=nil, &block) 390: if attributes.is_a?(Array) 391: attributes.collect {|attrs| create(attrs, &block)} 392: else 393: object = new(attributes, &block) 394: object.save 395: object 396: end 397: end
# File lib/active_ldap/base.rb, line 474 474: def default_search_attribute 475: dn_attribute 476: end
establish_connection is deprecated since 1.1.0. Please use setup_connection() instead.
# File lib/active_ldap/base.rb, line 380 380: def establish_connection(config=nil) 381: message = 382: _("ActiveLdap::Base.establish_connection has been deprecated " "since 1.1.0. " "Please use ActiveLdap::Base.setup_connection instead.") 383: ActiveSupport::Deprecation.warn(message) 384: setup_connection(config) 385: end
# File lib/active_ldap/base.rb, line 540 540: def human_name(options={}) 541: defaults = self_and_descendants_from_active_ldap.collect do |klass| 542: if klass.name.blank? 543: nil 544: else 545: :"#{klass.name.underscore}" 546: end 547: end 548: defaults << name.humanize 549: defaults = defaults.compact 550: defaults.first || name || to_s 551: end
Hide new in Base
# File lib/active_ldap/base.rb, line 333 333: def inherited(sub_class) 334: super 335: sub_class.module_eval do 336: include GetTextSupport 337: end 338: end
# File lib/active_ldap/base.rb, line 478 478: def inspect 479: if self == Base 480: super 481: elsif abstract_class? 482: "#{super}(abstract)" 483: else 484: detail = nil 485: begin 486: must = [] 487: may = [] 488: class_names = classes.collect do |object_class| 489: must.concat(object_class.must) 490: may.concat(object_class.may) 491: object_class.name 492: end 493: detail = ["objectClass:<#{class_names.join(', ')}>", 494: "must:<#{inspect_attributes(must)}>", 495: "may:<#{inspect_attributes(may)}>"].join(", ") 496: rescue ActiveLdap::ConnectionNotSetup 497: detail = "not-connected" 498: rescue ActiveLdap::Error 499: detail = "connection-failure" 500: end 501: "#{super}(#{detail})" 502: end 503: end
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 406: def ldap_mapping(options={}) 407: options = options.symbolize_keys 408: validate_ldap_mapping_options(options) 409: 410: self.dn_attribute = options[:dn_attribute] || default_dn_attribute 411: self.dn_attribute = dn_attribute.to_s if dn_attribute.is_a?(Symbol) 412: self.prefix = options[:prefix] || default_prefix 413: self.scope = options[:scope] 414: self.required_classes = options[:classes] 415: self.recommended_classes = options[:recommended_classes] 416: self.excluded_classes = options[:excluded_classes] 417: self.sort_by = options[:sort_by] 418: self.order = options[:order] 419: 420: public_class_method :new 421: end
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 670: def initialize(attributes=nil) 671: init_base 672: @new_entry = true 673: initial_classes = required_classes | recommended_classes 674: case attributes 675: when nil 676: self.classes = initial_classes 677: when String, Array, DN 678: self.classes = initial_classes 679: self.dn = attributes 680: when Hash 681: classes, attributes = extract_object_class(attributes) 682: self.classes = classes | initial_classes 683: normalized_attributes = {} 684: attributes.each do |key, value| 685: real_key = to_real_attribute_name(key) || key 686: normalized_attributes[real_key] = value 687: end 688: self.dn = normalized_attributes.delete(dn_attribute) 689: self.attributes = normalized_attributes 690: else 691: format = _("'%s' must be either nil, DN value as ActiveLdap::DN, " "String or Array or attributes as Hash") 692: raise ArgumentError, format % attributes.inspect 693: end 694: yield self if block_given? 695: end
# File lib/active_ldap/base.rb, line 443 443: def prefix 444: @prefix ||= inheritable_prefix and DN.parse(inheritable_prefix) 445: end
# File lib/active_ldap/base.rb, line 447 447: def prefix=(value) 448: self.inheritable_prefix = value 449: @prefix = nil 450: @base = nil 451: end
# File lib/active_ldap/base.rb, line 454 454: def scope=(scope) 455: validate_scope(scope) 456: self.scope_without_validation = scope 457: end
# File lib/active_ldap/base.rb, line 521 521: def self_and_descendants_from_active_ldap 522: klass = self 523: classes = [klass] 524: while klass != klass.base_class 525: classes << klass = klass.superclass 526: end 527: classes 528: rescue 529: [self] 530: end
Connect and bind to LDAP creating a class variable for use by all ActiveLdap objects.
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 372: def setup_connection(config=nil) 373: super 374: ensure_logger 375: nil 376: end
# File lib/active_ldap/base.rb, line 459 459: def validate_scope(scope) 460: scope = scope.to_sym if scope.is_a?(String) 461: return if scope.nil? or scope.is_a?(Symbol) 462: raise ConfigurationError, 463: _("scope '%s' must be a Symbol") % scope.inspect 464: end
# File lib/active_ldap/base.rb, line 633 633: def compute_base 634: _base = inheritable_base 635: _base = configuration[:base] if _base.nil? and configuration 636: if _base.nil? 637: target = superclass 638: loop do 639: break unless target.respond_to?(:base) 640: _base = target.base 641: break if _base 642: target = target.superclass 643: end 644: end 645: _prefix = prefix 646: 647: _base ||= connection.naming_contexts.first 648: return _prefix if _base.blank? 649: 650: _base = DN.parse(_base) 651: _base = _prefix + _base if _prefix 652: _base 653: end
# File lib/active_ldap/base.rb, line 616 616: def default_dn_attribute 617: dn_attribute = nil 618: parent_class = ancestors[1] 619: if parent_class.respond_to?(:dn_attribute) 620: dn_attribute = parent_class.dn_attribute 621: end 622: dn_attribute || "cn" 623: end
# File lib/active_ldap/base.rb, line 625 625: def default_prefix 626: if name.blank? 627: nil 628: else 629: "ou=#{name.demodulize.pluralize}" 630: end 631: end
# File lib/active_ldap/base.rb, line 584 584: def ensure_logger 585: @@logger ||= configuration[:logger] 586: # Setup default logger to console 587: if @@logger.nil? 588: require 'logger' 589: @@logger = Logger.new(STDERR) 590: @@logger.progname = 'ActiveLdap' 591: @@logger.level = Logger::ERROR 592: end 593: configuration[:logger] ||= @@logger 594: end
# File lib/active_ldap/base.rb, line 566 566: def inspect_attribute(attribute) 567: syntax = attribute.syntax 568: result = "#{attribute.name}" 569: if syntax and !syntax.description.blank? 570: result << ": #{syntax.description}" 571: end 572: properties = [] 573: properties << "read-only" if attribute.read_only? 574: properties << "binary" if attribute.binary? 575: properties << "binary-required" if attribute.binary_required? 576: result << "(#{properties.join(', ')})" unless properties.empty? 577: result 578: end
# File lib/active_ldap/base.rb, line 554 554: def inspect_attributes(attributes) 555: inspected_attribute_names = {} 556: attributes.collect do |attribute| 557: if inspected_attribute_names.has_key?(attribute.name) 558: nil 559: else 560: inspected_attribute_names[attribute.name] = true 561: inspect_attribute(attribute) 562: end 563: end.compact.join(', ') 564: end
# File lib/active_ldap/base.rb, line 596 596: def instantiate(args) 597: dn, attributes, options = args 598: options ||= {} 599: if self.class == Class 600: klass = self.ancestors[0].to_s.split(':').last 601: real_klass = self.ancestors[0] 602: else 603: klass = self.class.to_s.split(':').last 604: real_klass = self.class 605: end 606: 607: obj = real_klass.allocate 608: conn = options[:connection] || connection 609: obj.connection = conn if conn != connection 610: obj.instance_eval do 611: initialize_by_ldap_data(dn, attributes) 612: end 613: obj 614: end
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 700: def ==(comparison_object) 701: comparison_object.equal?(self) or 702: (comparison_object.instance_of?(self.class) and 703: comparison_object.dn == dn and 704: !comparison_object.new_entry?) 705: end
# File lib/active_ldap/base.rb, line 983 983: def [](name, force_array=false) 984: if name == "dn" 985: array_of(dn, force_array) 986: else 987: get_attribute(name, force_array) 988: end 989: end
# File lib/active_ldap/base.rb, line 991 991: def []=(name, value) 992: set_attribute(name, value) 993: end
attributes
Return attribute methods so that a program can determine available attributes dynamically without schema awareness
# File lib/active_ldap/base.rb, line 742 742: def attribute_names(normalize=false) 743: entry_attribute.names(normalize) 744: end
# File lib/active_ldap/base.rb, line 746 746: def attribute_present?(name) 747: values = get_attribute(name, true) 748: !values.empty? or values.any? {|x| !(x and x.empty?)} 749: end
This returns the key value pairs in @data with all values cloned
# File lib/active_ldap/base.rb, line 903 903: def attributes 904: @simplified_data ||= simplify_data(@data) 905: @simplified_data.clone 906: end
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 914: def attributes=(new_attributes) 915: return if new_attributes.blank? 916: _schema = _local_entry_attribute = nil 917: targets = remove_attributes_protected_from_mass_assignment(new_attributes) 918: targets.each do |key, value| 919: setter = "#{key}=" 920: unless respond_to?(setter) 921: _schema ||= schema 922: attribute = _schema.attribute(key) 923: next if attribute.id.nil? 924: _local_entry_attribute ||= local_entry_attribute 925: _local_entry_attribute.register(attribute) 926: end 927: send(setter, value) 928: end 929: end
# File lib/active_ldap/base.rb, line 1041 1041: def base 1042: @base ||= compute_base 1043: end
# File lib/active_ldap/base.rb, line 1045 1045: def base=(object_local_base) 1046: ensure_update_dn 1047: @dn = nil 1048: @base = nil 1049: @base_value = object_local_base 1050: end
# File lib/active_ldap/base.rb, line 1001 1001: def bind(config_or_password={}, config_or_ignore=nil, &block) 1002: if config_or_password.is_a?(String) 1003: config = (config_or_ignore || {}).merge(:password => config_or_password) 1004: else 1005: config = config_or_password 1006: end 1007: config = {:bind_dn => dn, :allow_anonymous => false}.merge(config) 1008: config[:password_block] ||= block if block_given? 1009: setup_connection(config) 1010: 1011: before_connection = @connection 1012: begin 1013: @connection = nil 1014: connection.connect 1015: @connection = connection 1016: clear_connection_based_cache 1017: clear_association_cache 1018: rescue ActiveLdap::Error 1019: remove_connection 1020: @connection = before_connection 1021: raise 1022: end 1023: true 1024: end
# File lib/active_ldap/base.rb, line 1026 1026: def clear_connection_based_cache 1027: @schema = nil 1028: @local_entry_attribute = nil 1029: clear_object_class_based_cache 1030: end
# File lib/active_ldap/base.rb, line 1032 1032: def clear_object_class_based_cache 1033: @entry_attribute = nil 1034: @real_names = {} 1035: end
# File lib/active_ldap/base.rb, line 793 793: def default_search_attribute 794: self.class.default_search_attribute 795: end
# File lib/active_ldap/base.rb, line 805 805: def delete(options={}) 806: super(dn, options) 807: end
# File lib/active_ldap/base.rb, line 1062 1062: def delete_all(options={}) 1063: super({:base => dn}.merge(options || {})) 1064: end
destroy
Delete this entry from LDAP
# File lib/active_ldap/base.rb, line 800 800: def destroy 801: self.class.delete(dn) 802: @new_entry = true 803: end
# File lib/active_ldap/base.rb, line 1066 1066: def destroy_all(options={}) 1067: super({:base => dn}.merge(options || {})) 1068: end
dn
Return the authoritative dn
# File lib/active_ldap/base.rb, line 769 769: def dn 770: @dn ||= compute_dn 771: end
# File lib/active_ldap/base.rb, line 781 781: def dn=(value) 782: set_attribute(dn_attribute_with_fallback, value) 783: end
# File lib/active_ldap/base.rb, line 787 787: def dn_attribute 788: ensure_update_dn 789: _dn_attribute = @dn_attribute || dn_attribute_of_class 790: to_real_attribute_name(_dn_attribute) || _dn_attribute 791: end
# File lib/active_ldap/base.rb, line 995 995: def each 996: @data.each do |key, values| 997: yield(key.dup, values.dup) 998: end 999: end
Delegates to ==
# File lib/active_ldap/base.rb, line 708 708: def eql?(comparison_object) 709: self == (comparison_object) 710: end
exist?
Return whether the entry exists in LDAP or not
# File lib/active_ldap/base.rb, line 754 754: def exist? 755: self.class.exists?(dn) 756: end
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 716: def hash 717: return super if @_hashing # workaround for GetText :< 718: _dn = nil 719: begin 720: @_hashing = true 721: _dn = dn 722: rescue DistinguishedNameInvalid, DistinguishedNameNotSetError 723: return super 724: ensure 725: @_hashing = false 726: end 727: _dn.hash 728: end
# File lib/active_ldap/base.rb, line 960 960: def have_attribute?(name, except=[]) 961: real_name = to_real_attribute_name(name) 962: !real_name.nil? and !except.include?(real_name) 963: end
# File lib/active_ldap/base.rb, line 773 773: def id 774: get_attribute(dn_attribute_with_fallback) 775: end
# File lib/active_ldap/base.rb, line 1070 1070: def inspect 1071: object_classes = entry_attribute.object_classes 1072: inspected_object_classes = object_classes.collect do |object_class| 1073: object_class.name 1074: end.join(', ') 1075: must_attributes = must.collect(&:name).sort.join(', ') 1076: may_attributes = may.collect(&:name).sort.join(', ') 1077: inspected_attributes = attribute_names.sort.collect do |name| 1078: inspect_attribute(name) 1079: end.join(', ') 1080: result = "\#<#{self.class} objectClass:<#{inspected_object_classes}>, " 1081: result << "must:<#{must_attributes}>, may:<#{may_attributes}>, " 1082: result << "#{inspected_attributes}>" 1083: result 1084: end
# File lib/active_ldap/base.rb, line 730 730: def may 731: entry_attribute.may 732: end
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 831: def method_missing(name, *args, &block) 832: key = name.to_s 833: case key 834: when /=$/ 835: real_key = $PREMATCH 836: if have_attribute?(real_key, ['objectClass']) 837: if args.size != 1 838: raise ArgumentError, 839: _("wrong number of arguments (%d for 1)") % args.size 840: end 841: return set_attribute(real_key, *args, &block) 842: end 843: when /(?:(_before_type_cast)|(\?))?$/ 844: real_key = $PREMATCH 845: before_type_cast = !$1.nil? 846: query = !$2.nil? 847: if have_attribute?(real_key, ['objectClass']) 848: if args.size > 1 849: raise ArgumentError, 850: _("wrong number of arguments (%d for 1)") % args.size 851: end 852: if before_type_cast 853: return get_attribute_before_type_cast(real_key, *args)[1] 854: elsif query 855: return get_attribute_as_query(real_key, *args) 856: else 857: return get_attribute(real_key, *args) 858: end 859: end 860: end 861: super 862: end
Add available attributes to the methods
# File lib/active_ldap/base.rb, line 865 865: def methods(inherited_too=true) 866: target_names = entry_attribute.all_names 867: target_names -= ['objectClass', 'objectClass'.underscore] 868: super + target_names.uniq.collect do |x| 869: [x, "#{x}=", "#{x}?", "#{x}_before_type_cast"] 870: end.flatten 871: end
# File lib/active_ldap/base.rb, line 734 734: def must 735: entry_attribute.must 736: end
new_entry?
Return whether the entry is new entry in LDAP or not
# File lib/active_ldap/base.rb, line 762 762: def new_entry? 763: @new_entry 764: end
# File lib/active_ldap/base.rb, line 966 966: def reload 967: clear_association_cache 968: _, attributes = search(:value => id).find do |_dn, _attributes| 969: dn == _dn 970: end 971: if attributes.nil? 972: raise EntryNotFound, _("Can't find DN '%s' to reload") % dn 973: end 974: 975: @ldap_data.update(attributes) 976: classes, attributes = extract_object_class(attributes) 977: self.classes = classes 978: self.attributes = attributes 979: @new_entry = false 980: self 981: end
# File lib/active_ldap/base.rb, line 874 874: def respond_to?(name, include_priv=false) 875: return true if super 876: 877: name = name.to_s 878: return true if have_attribute?(name, ["objectClass"]) 879: return false if /(?:=|\?|_before_type_cast)$/ !~ name 880: have_attribute?($PREMATCH, ["objectClass"]) 881: end
# File lib/active_ldap/base.rb, line 818 818: def save! 819: unless create_or_update 820: raise EntryNotSaved, _("entry %s can't be saved") % dn 821: end 822: end
# File lib/active_ldap/base.rb, line 1037 1037: def schema 1038: @schema ||= super 1039: end
# File lib/active_ldap/base.rb, line 1053 1053: def scope 1054: @scope || scope_of_class 1055: end
# File lib/active_ldap/base.rb, line 1057 1057: def scope=(scope) 1058: self.class.validate_scope(scope) 1059: @scope = scope 1060: end
# File lib/active_ldap/base.rb, line 935 935: def to_ldif 936: Ldif.new([to_ldif_record]).to_s 937: end
# File lib/active_ldap/base.rb, line 931 931: def to_ldif_record 932: super(dn, normalize_data(@data)) 933: end
# File lib/active_ldap/base.rb, line 777 777: def to_param 778: id 779: end
# File lib/active_ldap/base.rb, line 956 956: def to_s 957: to_ldif 958: end
# File lib/active_ldap/base.rb, line 939 939: def to_xml(options={}) 940: options = options.dup 941: options[:root] ||= (self.class.name || '').underscore 942: options[:root] = 'anonymous' if options[:root].blank? 943: except = options[:except] 944: if except 945: options[:except] = except.collect do |name| 946: if name.to_s.downcase == "dn" 947: "dn" 948: else 949: to_real_attribute_name(name) 950: end 951: end.compact 952: end 953: XML.new(dn, normalize_data(@data), schema).to_s(options) 954: end
Updates a given attribute and saves immediately
# File lib/active_ldap/base.rb, line 884 884: def update_attribute(name, value) 885: send("#{name}=", value) 886: save 887: end
This performs a bulk update of attributes and immediately calls #.
# File lib/active_ldap/base.rb, line 891 891: def update_attributes(attrs) 892: self.attributes = attrs 893: save 894: end
Returns the array form of a value, or not an array if false is passed in.
# File lib/active_ldap/base.rb, line 1413 1413: def array_of(value, to_a=true) 1414: case value 1415: when Array 1416: if to_a or value.size > 1 1417: value.collect {|v| array_of(v, false)}.compact 1418: else 1419: if value.empty? 1420: nil 1421: else 1422: array_of(value.first, to_a) 1423: end 1424: end 1425: when Hash 1426: if to_a 1427: [value] 1428: else 1429: result = {} 1430: value.each {|k, v| result[k] = array_of(v, to_a)} 1431: result 1432: end 1433: else 1434: to_a ? [value] : value 1435: end 1436: end
# File lib/active_ldap/base.rb, line 1116 1116: def attribute_name_resolvable_without_connection? 1117: @entry_attribute and @local_entry_attribute 1118: end
# File lib/active_ldap/base.rb, line 1510 1510: def collect_all_attributes(data) 1511: dn_attr = dn_attribute 1512: dn_value = data[dn_attr] 1513: 1514: attributes = [] 1515: attributes.push([dn_attr, dn_value]) 1516: 1517: oc_value = data['objectClass'] 1518: attributes.push(['objectClass', oc_value]) 1519: except_keys = ['objectClass', dn_attr].collect(&:downcase) 1520: data.each do |key, value| 1521: next if except_keys.include?(key.downcase) 1522: value = self.class.remove_blank_value(value) 1523: next if self.class.blank_value?(value) 1524: 1525: attributes.push([key, value]) 1526: end 1527: 1528: attributes 1529: end
# File lib/active_ldap/base.rb, line 1466 1466: def collect_modified_attributes(ldap_data, data) 1467: klass = self.class 1468: _dn_attribute = dn_attribute 1469: new_dn_value = nil 1470: attributes = [] 1471: 1472: # Now that all the options will be treated as unique attributes 1473: # we can see what's changed and add anything that is brand-spankin' 1474: # new. 1475: ldap_data.each do |k, v| 1476: value = data[k] || [] 1477: 1478: next if v == value 1479: 1480: value = klass.remove_blank_value(value) || [] 1481: next if v == value 1482: 1483: if klass.blank_value?(value) and 1484: schema.attribute(k).binary_required? 1485: value = [{'binary' => []}] 1486: end 1487: if k == _dn_attribute 1488: new_dn_value = value[0] 1489: else 1490: attributes.push([:replace, k, value]) 1491: end 1492: end 1493: 1494: data.each do |k, v| 1495: value = v || [] 1496: next if ldap_data.has_key?(k) 1497: 1498: value = klass.remove_blank_value(value) || [] 1499: next if klass.blank_value?(value) 1500: 1501: # Detect subtypes and account for them 1502: # REPLACE will function like ADD, but doesn't hit EQUALITY problems 1503: # TODO: Added equality(attr) to Schema 1504: attributes.push([:replace, k, value]) 1505: end 1506: 1507: [new_dn_value, attributes] 1508: end
# File lib/active_ldap/base.rb, line 1398 1398: def compute_base 1399: base_of_class = self.class.base 1400: if @base_value.nil? 1401: base_of_class 1402: else 1403: base_of_object = DN.parse(@base_value) 1404: base_of_object += base_of_class if base_of_class 1405: base_of_object 1406: end 1407: end
# File lib/active_ldap/base.rb, line 1382 1382: def compute_dn 1383: return base if @dn_is_base 1384: 1385: ensure_update_dn 1386: dn_value = id 1387: if dn_value.nil? 1388: format = _("%s's DN attribute (%s) isn't set") 1389: message = format % [self.inspect, dn_attribute] 1390: raise DistinguishedNameNotSetError.new, message 1391: end 1392: dn_value = DN.escape_value(dn_value.to_s) 1393: _base = base 1394: _base = nil if _base.blank? 1395: DN.parse(["#{dn_attribute}=#{dn_value}", _base].compact.join(",")) 1396: end
# File lib/active_ldap/base.rb, line 1563 1563: def create 1564: prepare_data_for_saving do |data, ldap_data| 1565: attributes = collect_all_attributes(data) 1566: add_entry(dn, attributes) 1567: @new_entry = false 1568: true 1569: end 1570: end
# File lib/active_ldap/base.rb, line 1531 1531: def create_or_update 1532: new_entry? ? create : update 1533: end
# File lib/active_ldap/base.rb, line 1087 1087: def dn_attribute_with_fallback 1088: begin 1089: dn_attribute 1090: rescue DistinguishedNameInvalid 1091: _dn_attribute = @dn_attribute || dn_attribute_of_class 1092: _dn_attribute = to_real_attribute_name(_dn_attribute) || _dn_attribute 1093: raise if _dn_attribute.nil? 1094: _dn_attribute 1095: end 1096: end
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 1194: def enforce_type(key, value) 1195: # Enforce attribute value formatting 1196: normalize_attribute(key, value)[1] 1197: end
# File lib/active_ldap/base.rb, line 1372 1372: def ensure_update_dn 1373: return unless need_update_dn? 1374: @mutex.synchronize do 1375: if @dn_split_value 1376: update_dn(*@dn_split_value) 1377: @dn_split_value = nil 1378: end 1379: end 1380: end
# File lib/active_ldap/base.rb, line 1120 1120: def entry_attribute 1121: @entry_attribute ||= 1122: connection.entry_attribute(find_object_class_values(@data) || []) 1123: end
# File lib/active_ldap/base.rb, line 1129 1129: def extract_object_class(attributes) 1130: classes = [] 1131: attrs = {} 1132: attributes.each do |key, value| 1133: key = key.to_s 1134: if /\Aobject_?class\z/ =~ key 1135: classes.concat(value.to_a) 1136: else 1137: attrs[key] = value 1138: end 1139: end 1140: [classes, attributes] 1141: end
# File lib/active_ldap/base.rb, line 1262 1262: def false_value?(value) 1263: value.nil? or value == false or value == [] or 1264: value == "false" or value == "FALSE" or value == "" 1265: end
# File lib/active_ldap/base.rb, line 1112 1112: def find_object_class_values(data) 1113: data["objectClass"] || data["objectclass"] 1114: end
Return the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1217 1217: def get_attribute(name, force_array=false) 1218: name, value = get_attribute_before_type_cast(name, force_array) 1219: return value if name.nil? 1220: attribute = schema.attribute(name) 1221: type_cast(attribute, value) 1222: end
# File lib/active_ldap/base.rb, line 1253 1253: def get_attribute_as_query(name, force_array=false) 1254: name, value = get_attribute_before_type_cast(name, force_array) 1255: if force_array 1256: value.collect {|x| !false_value?(x)} 1257: else 1258: !false_value?(value) 1259: end 1260: end
# File lib/active_ldap/base.rb, line 1245 1245: def get_attribute_before_type_cast(name, force_array=false) 1246: name = to_real_attribute_name(name) 1247: 1248: value = @data[name] 1249: value = [] if value.nil? 1250: [name, array_of(value, force_array)] 1251: end
# File lib/active_ldap/base.rb, line 1143 1143: def init_base 1144: init_instance_variables 1145: end
# File lib/active_ldap/base.rb, line 1199 1199: def init_instance_variables 1200: @mutex = Mutex.new 1201: @data = {} # where the r/w entry data is stored 1202: @ldap_data = {} # original ldap entry data 1203: @dn_attribute = nil 1204: @base = nil 1205: @scope = nil 1206: @dn = nil 1207: @dn_is_base = false 1208: @dn_split_value = nil 1209: @connection ||= nil 1210: @_hashing = false 1211: clear_connection_based_cache 1212: end
# File lib/active_ldap/base.rb, line 1147 1147: def initialize_by_ldap_data(dn, attributes) 1148: init_base 1149: dn = Compatible.convert_to_utf8_encoded_object(dn) 1150: attributes = Compatible.convert_to_utf8_encoded_object(attributes) 1151: @original_dn = dn.clone 1152: @dn = dn 1153: @base = nil 1154: @base_value = nil 1155: @new_entry = false 1156: @dn_is_base = false 1157: @ldap_data = attributes 1158: classes, attributes = extract_object_class(attributes) 1159: self.classes = classes 1160: self.dn = dn 1161: self.attributes = attributes 1162: yield self if block_given? 1163: end
# File lib/active_ldap/base.rb, line 1098 1098: def inspect_attribute(name) 1099: values = get_attribute(name, true) 1100: values.collect do |value| 1101: if value.is_a?(String) and value.length > 50 1102: "#{value[0, 50]}...".inspect 1103: elsif value.is_a?(Date) || value.is_a?(Time) 1104: "#{value.to_s(:db)}" 1105: else 1106: value.inspect 1107: end 1108: end 1109: "#{name}: #{values.inspect}" 1110: end
# File lib/active_ldap/base.rb, line 1165 1165: def instantiate(args) 1166: dn, attributes, options = args 1167: options ||= {} 1168: 1169: obj = self.class.allocate 1170: obj.connection = options[:connection] || @connection 1171: obj.instance_eval do 1172: initialize_by_ldap_data(dn, attributes) 1173: end 1174: obj 1175: end
# File lib/active_ldap/base.rb, line 1125 1125: def local_entry_attribute 1126: @local_entry_attribute ||= connection.entry_attribute([]) 1127: end
# File lib/active_ldap/base.rb, line 1368 1368: def need_update_dn? 1369: not @dn_split_value.nil? 1370: end
# File lib/active_ldap/base.rb, line 1438 1438: def normalize_data(data, except=[]) 1439: _schema = schema 1440: result = {} 1441: data.each do |key, values| 1442: next if except.include?(key) 1443: real_name = to_real_attribute_name(key) 1444: next if real_name and except.include?(real_name) 1445: real_name ||= key 1446: next if _schema.attribute(real_name).id.nil? 1447: result[real_name] ||= [] 1448: result[real_name].concat(enforce_type(real_name, values)) 1449: end 1450: result 1451: end
# File lib/active_ldap/base.rb, line 1535 1535: def prepare_data_for_saving 1536: # Expand subtypes to real ldap_data attributes 1537: # We can't reuse @ldap_data because an exception would leave 1538: # an object in an unknown state 1539: ldap_data = normalize_data(@ldap_data) 1540: 1541: # Expand subtypes to real data attributes, but leave @data alone 1542: object_classes = find_object_class_values(@ldap_data) || [] 1543: original_attributes = 1544: connection.entry_attribute(object_classes).names 1545: bad_attrs = original_attributes - entry_attribute.names 1546: data = normalize_data(@data, bad_attrs) 1547: 1548: success = yield(data, ldap_data) 1549: 1550: if success 1551: @ldap_data = data.clone 1552: # Delete items disallowed by objectclasses. 1553: # They should have been removed from ldap. 1554: bad_attrs.each do |remove_me| 1555: @ldap_data.delete(remove_me) 1556: end 1557: @original_dn = dn.clone 1558: end 1559: 1560: success 1561: end
# File lib/active_ldap/base.rb, line 1288 1288: def register_new_dn_attribute(name, value) 1289: @dn = nil 1290: @dn_is_base = false 1291: if value.blank? 1292: @dn_split_value = nil 1293: [name, nil] 1294: else 1295: new_name, new_value, raw_new_value, new_bases = split_dn_value(value) 1296: @dn_split_value = [new_name, new_value, new_bases] 1297: if new_name.nil? and new_value.nil? 1298: new_name, raw_new_value = new_bases[0].to_a[0] 1299: end 1300: [to_real_attribute_name(new_name) || name, 1301: raw_new_value || value] 1302: end 1303: end
Set the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1270 1270: def set_attribute(name, value) 1271: real_name = to_real_attribute_name(name) 1272: _dn_attribute = nil 1273: valid_dn_attribute = true 1274: begin 1275: _dn_attribute = dn_attribute 1276: rescue DistinguishedNameInvalid 1277: valid_dn_attribute = false 1278: end 1279: if valid_dn_attribute and real_name == _dn_attribute 1280: real_name, value = register_new_dn_attribute(real_name, value) 1281: end 1282: raise UnknownAttribute.new(name) if real_name.nil? 1283: 1284: @data[real_name] = value 1285: @simplified_data = nil 1286: end
# File lib/active_ldap/base.rb, line 1453 1453: def simplify_data(data) 1454: _schema = schema 1455: result = {} 1456: data.each do |key, values| 1457: attribute = _schema.attribute(key) 1458: if attribute.single_value? and values.is_a?(Array) and values.size == 1 1459: values = values[0] 1460: end 1461: result[key] = type_cast(attribute, values) 1462: end 1463: result 1464: end
# File lib/active_ldap/base.rb, line 1331 1331: def split_dn_value(value) 1332: dn_value = relative_dn_value = nil 1333: begin 1334: dn_value = value if value.is_a?(DN) 1335: dn_value ||= DN.parse(value) 1336: rescue DistinguishedNameInvalid 1337: begin 1338: dn_value = DN.parse("#{dn_attribute}=#{value}") 1339: rescue DistinguishedNameInvalid 1340: return [nil, value, value, []] 1341: end 1342: end 1343: 1344: val = bases = nil 1345: begin 1346: relative_dn_value = dn_value 1347: base_of_class = self.class.base 1348: relative_dn_value -= base_of_class if base_of_class 1349: if relative_dn_value.rdns.empty? 1350: val = [] 1351: bases = dn_value.rdns 1352: else 1353: val, *bases = relative_dn_value.rdns 1354: end 1355: rescue ArgumentError 1356: val, *bases = dn_value.rdns 1357: end 1358: 1359: dn_attribute_name, dn_attribute_value = val.to_a[0] 1360: escaped_dn_attribute_value = nil 1361: unless dn_attribute_value.nil? 1362: escaped_dn_attribute_value = DN.escape_value(dn_attribute_value) 1363: end 1364: [dn_attribute_name, escaped_dn_attribute_value, 1365: dn_attribute_value, bases] 1366: end
# File lib/active_ldap/base.rb, line 1177 1177: def to_real_attribute_name(name, allow_normalized_name=true) 1178: return name if name.nil? 1179: if allow_normalized_name 1180: entry_attribute.normalize(name, allow_normalized_name) || 1181: local_entry_attribute.normalize(name, allow_normalized_name) 1182: else 1183: @real_names[name] ||= 1184: entry_attribute.normalize(name, false) || 1185: local_entry_attribute.normalize(name, false) 1186: end 1187: end
# File lib/active_ldap/base.rb, line 1224 1224: def type_cast(attribute, value) 1225: case value 1226: when Hash 1227: result = {} 1228: value.each do |option, val| 1229: result[option] = type_cast(attribute, val) 1230: end 1231: if result.size == 1 and result.has_key?("binary") 1232: result["binary"] 1233: else 1234: result 1235: end 1236: when Array 1237: value.collect do |val| 1238: type_cast(attribute, val) 1239: end 1240: else 1241: attribute.type_cast(value) 1242: end 1243: end
# File lib/active_ldap/base.rb, line 1572 1572: def update 1573: prepare_data_for_saving do |data, ldap_data| 1574: new_dn_value, attributes = collect_modified_attributes(ldap_data, data) 1575: modify_entry(@original_dn, attributes) 1576: if new_dn_value 1577: old_dn_base = DN.parse(@original_dn).parent 1578: new_dn_base = dn.clone.parent 1579: if old_dn_base == new_dn_base 1580: new_superior = nil 1581: else 1582: new_superior = new_dn_base 1583: end 1584: modify_rdn_entry(@original_dn, 1585: "#{dn_attribute}=#{DN.escape_value(new_dn_value)}", 1586: true, 1587: new_superior) 1588: end 1589: true 1590: end 1591: end
# File lib/active_ldap/base.rb, line 1305 1305: def update_dn(new_name, new_value, bases) 1306: if new_name.nil? and new_value.nil? 1307: @dn_is_base = true 1308: @base = nil 1309: @base_value = nil 1310: attr, value = bases[0].to_a[0] 1311: @dn_attribute = attr 1312: else 1313: new_name ||= @dn_attribute || dn_attribute_of_class 1314: new_name = to_real_attribute_name(new_name) 1315: if new_name.nil? 1316: new_name = @dn_attribute || dn_attribute_of_class 1317: new_name = to_real_attribute_name(new_name) 1318: end 1319: new_bases = bases.empty? ? nil : DN.new(*bases).to_s 1320: dn_components = ["#{new_name}=#{new_value}", 1321: new_bases, 1322: self.class.base.to_s] 1323: dn_components = dn_components.find_all {|component| !component.blank?} 1324: DN.parse(dn_components.join(',')) 1325: @base = nil 1326: @base_value = new_bases 1327: @dn_attribute = new_name 1328: end 1329: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.