Class | ActiveLdap::Base |
In: |
lib/active_ldap/base.rb
|
Parent: | Object |
Base is the primary class which contains all of the core ActiveLdap functionality. It is meant to only ever be subclassed by extension classes.
VALID_LDAP_MAPPING_OPTIONS | = | [:dn_attribute, :prefix, :scope, :classes, :recommended_classes, :excluded_classes, :sort_by, :order] |
base | -> | base_inheritable |
base= | -> | base_without_parsed_cache_clear= |
scope= | -> | scope_without_validation= |
dn_attribute | -> | dn_attribute_of_class |
respond_to? | -> | respond_to_without_attributes? |
base | -> | base_of_class |
scope | -> | scope_of_class |
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 395 395: def base 396: _base = base_inheritable 397: _base = configuration[:base] if _base.nil? and configuration 398: _base ||= base_inheritable(true) 399: [prefix, _base].find_all do |component| 400: !component.blank? 401: end.join(",") 402: end
# File lib/active_ldap/base.rb, line 405 405: def base=(value) 406: self.base_without_parsed_cache_clear = value 407: @parsed_base = nil 408: end
# File lib/active_ldap/base.rb, line 427 427: def base_class 428: if self == Base or superclass == Base 429: self 430: else 431: superclass.base_class 432: end 433: end
# File lib/active_ldap/base.rb, line 268 268: def self.class_local_attr_accessor(search_ancestors, *syms) 269: syms.flatten.each do |sym| 270: class_eval("def self.\#{sym}(search_superclasses=\#{search_ancestors})\n@\#{sym} ||= nil\nreturn @\#{sym} if @\#{sym}\nif search_superclasses\ntarget = superclass\nvalue = nil\nloop do\nbreak nil unless target.respond_to?(:\#{sym})\nvalue = target.\#{sym}\nbreak if value\ntarget = target.superclass\nend\nvalue\nelse\nnil\nend\nend\ndef \#{sym}; self.class.\#{sym}; end\ndef self.\#{sym}=(value); @\#{sym} = value; end\ndef \#{sym}=(value); self.class.\#{sym} = value; end\n", __FILE__, __LINE__ + 1) 271: end 272: end
# File lib/active_ldap/base.rb, line 350 350: def create(attributes=nil, &block) 351: if attributes.is_a?(Array) 352: attributes.collect {|attrs| create(attrs, &block)} 353: else 354: object = new(attributes, &block) 355: object.save 356: object 357: end 358: end
# File lib/active_ldap/base.rb, line 435 435: def default_search_attribute 436: dn_attribute 437: 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/configuration.rb for defaults for each option
# File lib/active_ldap/base.rb, line 344 344: def establish_connection(config=nil) 345: super 346: ensure_logger 347: nil 348: end
# File lib/active_ldap/base.rb, line 439 439: def inspect 440: if self == Base 441: super 442: else 443: class_names = [] 444: must = [] 445: may = [] 446: class_names = classes.collect do |object_class| 447: must.concat(object_class.must) 448: may.concat(object_class.may) 449: object_class.name 450: end 451: detail = ["objectClass:<#{class_names.join(', ')}>", 452: "must:<#{inspect_attributes(must)}>", 453: "may:<#{inspect_attributes(may)}>"].join(", ") 454: "#{super}(#{detail})" 455: end 456: 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 367 367: def ldap_mapping(options={}) 368: options = options.symbolize_keys 369: validate_ldap_mapping_options(options) 370: 371: self.dn_attribute = options[:dn_attribute] || default_dn_attribute 372: self.dn_attribute = dn_attribute.to_s if dn_attribute.is_a?(Symbol) 373: self.prefix = options[:prefix] || default_prefix 374: self.scope = options[:scope] 375: self.required_classes = options[:classes] 376: self.recommended_classes = options[:recommended_classes] 377: self.excluded_classes = options[:excluded_classes] 378: self.sort_by = options[:sort_by] 379: self.order = options[:order] 380: 381: public_class_method :new 382: end
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 557 557: def initialize(attributes=nil) 558: init_base 559: @new_entry = true 560: initial_classes = required_classes | recommended_classes 561: case attributes 562: when nil 563: self.classes = initial_classes 564: when String, Array, DN 565: self.classes = initial_classes 566: self.dn = attributes 567: when Hash 568: classes, attributes = extract_object_class(attributes) 569: self.classes = classes | initial_classes 570: normalized_attributes = {} 571: attributes.each do |key, value| 572: real_key = to_real_attribute_name(key) || key 573: normalized_attributes[real_key] = value 574: end 575: self.dn = normalized_attributes.delete(dn_attribute) 576: self.attributes = normalized_attributes 577: else 578: format = _("'%s' must be either nil, DN value as ActiveLdap::DN, " \ 579: "String or Array or attributes as Hash") 580: raise ArgumentError, format % attributes.inspect 581: end 582: yield self if block_given? 583: assert_dn_attribute 584: end
# File lib/active_ldap/base.rb, line 410 410: def parsed_base 411: @parsed_base ||= DN.parse(base) 412: end
# File lib/active_ldap/base.rb, line 415 415: def scope=(scope) 416: validate_scope(scope) 417: self.scope_without_validation = scope 418: end
# File lib/active_ldap/base.rb, line 420 420: def validate_scope(scope) 421: scope = scope.to_sym if scope.is_a?(String) 422: return if scope.nil? or scope.is_a?(Symbol) 423: raise ConfigurationError, 424: _("scope '%s' must be a Symbol") % scope.inspect 425: end
# File lib/active_ldap/base.rb, line 521 521: def default_dn_attribute 522: if name.empty? 523: dn_attribute = nil 524: parent_class = ancestors[1] 525: if parent_class.respond_to?(:dn_attribute) 526: dn_attribute = parent_class.dn_attribute 527: end 528: dn_attribute || "cn" 529: else 530: name.demodulize.underscore 531: end 532: end
# File lib/active_ldap/base.rb, line 534 534: def default_prefix 535: if name.empty? 536: nil 537: else 538: "ou=#{name.demodulize.pluralize}" 539: end 540: end
# File lib/active_ldap/base.rb, line 489 489: def ensure_logger 490: @@logger ||= configuration[:logger] 491: # Setup default logger to console 492: if @@logger.nil? 493: require 'logger' 494: @@logger = Logger.new(STDERR) 495: @@logger.progname = 'ActiveLdap' 496: @@logger.level = Logger::UNKNOWN 497: end 498: configuration[:logger] ||= @@logger 499: end
# File lib/active_ldap/base.rb, line 471 471: def inspect_attribute(attribute) 472: syntax = attribute.syntax 473: result = "#{attribute.name}" 474: if syntax and !syntax.description.blank? 475: result << ": #{syntax.description}" 476: end 477: properties = [] 478: properties << "read-only" if attribute.read_only? 479: properties << "binary" if attribute.binary? 480: properties << "binary-required" if attribute.binary_required? 481: result << "(#{properties.join(', ')})" unless properties.empty? 482: result 483: end
# File lib/active_ldap/base.rb, line 459 459: def inspect_attributes(attributes) 460: inspected_attribute_names = {} 461: attributes.collect do |attribute| 462: if inspected_attribute_names.has_key?(attribute.name) 463: nil 464: else 465: inspected_attribute_names[attribute.name] = true 466: inspect_attribute(attribute) 467: end 468: end.compact.join(', ') 469: end
# File lib/active_ldap/base.rb, line 501 501: def instantiate(args) 502: dn, attributes, options = args 503: options ||= {} 504: if self.class == Class 505: klass = self.ancestors[0].to_s.split(':').last 506: real_klass = self.ancestors[0] 507: else 508: klass = self.class.to_s.split(':').last 509: real_klass = self.class 510: end 511: 512: obj = real_klass.allocate 513: conn = options[:connection] || connection 514: obj.connection = conn if conn != connection 515: obj.instance_eval do 516: initialize_by_ldap_data(dn, attributes) 517: end 518: obj 519: end
# File lib/active_ldap/base.rb, line 485 485: def validate_ldap_mapping_options(options) 486: options.assert_valid_keys(VALID_LDAP_MAPPING_OPTIONS) 487: 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 588 588: def ==(comparison_object) 589: comparison_object.equal?(self) or 590: (comparison_object.instance_of?(self.class) and 591: comparison_object.dn == dn and 592: !comparison_object.new_entry?) 593: end
# File lib/active_ldap/base.rb, line 866 866: def [](name, force_array=false) 867: if name == "dn" 868: array_of(dn, force_array) 869: else 870: get_attribute(name, force_array) 871: end 872: end
# File lib/active_ldap/base.rb, line 874 874: def []=(name, value) 875: set_attribute(name, value) 876: end
Return attribute methods so that a program can determine available attributes dynamically without schema awareness
# File lib/active_ldap/base.rb, line 620 620: def attribute_names(normalize=false) 621: entry_attribute.names(normalize) 622: end
# File lib/active_ldap/base.rb, line 624 624: def attribute_present?(name) 625: values = get_attribute(name, true) 626: !values.empty? or values.any? {|x| not (x and x.empty?)} 627: end
This returns the key value pairs in @data with all values cloned
# File lib/active_ldap/base.rb, line 785 785: def attributes 786: Marshal.load(Marshal.dump(@data)) 787: 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 795 795: def attributes=(new_attributes) 796: return if new_attributes.nil? 797: _schema = _local_entry_attribute = nil 798: targets = remove_attributes_protected_from_mass_assignment(new_attributes) 799: targets.each do |key, value| 800: setter = "#{key}=" 801: unless respond_to?(setter) 802: _schema ||= schema 803: attribute = _schema.attribute(key) 804: next if attribute.id.nil? 805: _local_entry_attribute ||= local_entry_attribute 806: _local_entry_attribute.register(attribute) 807: end 808: send(setter, value) 809: end 810: end
# File lib/active_ldap/base.rb, line 925 925: def base 926: [@base, base_of_class].compact.join(",") 927: end
# File lib/active_ldap/base.rb, line 930 930: def base=(object_local_base) 931: @dn = nil 932: @base = object_local_base 933: end
# File lib/active_ldap/base.rb, line 884 884: def bind(config_or_password={}, config_or_ignore=nil, &block) 885: if config_or_password.is_a?(String) 886: config = (config_or_ignore || {}).merge(:password => config_or_password) 887: else 888: config = config_or_password 889: end 890: config = {:bind_dn => dn, :allow_anonymous => false}.merge(config) 891: config[:password_block] ||= block if block_given? 892: establish_connection(config) 893: 894: before_connection = @connection 895: begin 896: @connection = nil 897: connection.connect 898: @connection = connection 899: clear_connection_based_cache 900: clear_association_cache 901: rescue ActiveLdap::Error 902: remove_connection 903: @connection = before_connection 904: raise 905: end 906: true 907: end
# File lib/active_ldap/base.rb, line 909 909: def clear_connection_based_cache 910: @schema = nil 911: @local_entry_attribute = nil 912: clear_object_class_based_cache 913: end
# File lib/active_ldap/base.rb, line 915 915: def clear_object_class_based_cache 916: @entry_attribute = nil 917: @real_names = {} 918: end
# File lib/active_ldap/base.rb, line 671 671: def default_search_attribute 672: self.class.default_search_attribute 673: end
# File lib/active_ldap/base.rb, line 687 687: def delete(options={}) 688: super(dn, options) 689: end
# File lib/active_ldap/base.rb, line 659 659: def dn=(value) 660: set_attribute(dn_attribute, value) 661: @dn = nil 662: end
# File lib/active_ldap/base.rb, line 666 666: def dn_attribute 667: _dn_attribute = @dn_attribute || dn_attribute_of_class 668: to_real_attribute_name(_dn_attribute) || _dn_attribute 669: end
# File lib/active_ldap/base.rb, line 878 878: def each 879: @data.each do |key, values| 880: yield(key.dup, values.dup) 881: end 882: end
Delegates to ==
# File lib/active_ldap/base.rb, line 596 596: def eql?(comparison_object) 597: self == (comparison_object) 598: end
# File lib/active_ldap/base.rb, line 843 843: def have_attribute?(name, except=[]) 844: real_name = to_real_attribute_name(name) 845: real_name and !except.include?(real_name) 846: end
# File lib/active_ldap/base.rb, line 946 946: def inspect 947: object_classes = entry_attribute.object_classes 948: inspected_object_classes = object_classes.collect do |object_class| 949: object_class.name 950: end.join(', ') 951: must_attributes = must.collect(&:name).sort.join(', ') 952: may_attributes = may.collect(&:name).sort.join(', ') 953: inspected_attributes = attribute_names.sort.collect do |name| 954: inspect_attribute(name) 955: end.join(', ') 956: result = "\#<#{self.class} objectClass:<#{inspected_object_classes}>, " 957: result << "must:<#{must_attributes}>, may:<#{may_attributes}>, " 958: result << "#{inspected_attributes}>" 959: result 960: 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 713 713: def method_missing(name, *args, &block) 714: key = name.to_s 715: case key 716: when /=$/ 717: real_key = $PREMATCH 718: if have_attribute?(real_key, ['objectClass']) 719: if args.size != 1 720: raise ArgumentError, 721: _("wrong number of arguments (%d for 1)") % args.size 722: end 723: return set_attribute(real_key, *args, &block) 724: end 725: when /(?:(_before_type_cast)|(\?))?$/ 726: real_key = $PREMATCH 727: before_type_cast = !$1.nil? 728: query = !$2.nil? 729: if have_attribute?(real_key, ['objectClass']) 730: if args.size > 1 731: raise ArgumentError, 732: _("wrong number of arguments (%d for 1)") % args.size 733: end 734: if before_type_cast 735: return get_attribute_before_type_cast(real_key, *args)[1] 736: elsif query 737: return get_attribute_as_query(real_key, *args) 738: else 739: return get_attribute(real_key, *args) 740: end 741: end 742: end 743: super 744: end
Add available attributes to the methods
# File lib/active_ldap/base.rb, line 747 747: def methods(inherited_too=true) 748: target_names = entry_attribute.all_names 749: target_names -= ['objectClass', 'objectClass'.underscore] 750: super + target_names.uniq.collect do |x| 751: [x, "#{x}=", "#{x}?", "#{x}_before_type_cast"] 752: end.flatten 753: end
# File lib/active_ldap/base.rb, line 849 849: def reload 850: clear_association_cache 851: _, attributes = search(:value => id).find do |_dn, _attributes| 852: dn == _dn 853: end 854: if attributes.nil? 855: raise EntryNotFound, _("Can't find DN '%s' to reload") % dn 856: end 857: 858: @ldap_data.update(attributes) 859: classes, attributes = extract_object_class(attributes) 860: self.classes = classes 861: self.attributes = attributes 862: @new_entry = false 863: self 864: end
# File lib/active_ldap/base.rb, line 756 756: def respond_to?(name, include_priv=false) 757: return true if super 758: 759: name = name.to_s 760: return true if have_attribute?(name) 761: return false if /(?:=|\?|_before_type_cast)$/ !~ name 762: have_attribute?($PREMATCH) 763: end
Save and validate this object into LDAP either adding or replacing attributes TODO: Relative DN support
# File lib/active_ldap/base.rb, line 696 696: def save 697: create_or_update 698: end
# File lib/active_ldap/base.rb, line 700 700: def save! 701: unless create_or_update 702: raise EntryNotSaved, _("entry %s can't be saved") % dn 703: end 704: end
# File lib/active_ldap/base.rb, line 941 941: def scope=(scope) 942: self.class.validate_scope(scope) 943: @scope = scope 944: end
# File lib/active_ldap/base.rb, line 816 816: def to_ldif 817: Ldif.new([to_ldif_record]).to_s 818: end
# File lib/active_ldap/base.rb, line 812 812: def to_ldif_record 813: super(dn, normalize_data(@data)) 814: end
# File lib/active_ldap/base.rb, line 820 820: def to_xml(options={}) 821: root = options[:root] || self.class.name.underscore 822: result = "<#{root}>\n" 823: result << " <dn>#{dn}</dn>\n" 824: normalize_data(@data).sort_by {|key, values| key}.each do |key, values| 825: targets = [] 826: values.each do |value| 827: if value.is_a?(Hash) 828: value.each do |option, real_value| 829: targets << [real_value, " #{option}=\"true\""] 830: end 831: else 832: targets << [value] 833: end 834: end 835: targets.sort_by {|value, attr| value}.each do |value, attr| 836: result << " <#{key}#{attr}>#{value}</#{key}>\n" 837: end 838: end 839: result << "</#{root}>\n" 840: result 841: end
Updates a given attribute and saves immediately
# File lib/active_ldap/base.rb, line 766 766: def update_attribute(name, value) 767: send("#{name}=", value) 768: save 769: end
This performs a bulk update of attributes and immediately calls save.
# File lib/active_ldap/base.rb, line 773 773: def update_attributes(attrs) 774: self.attributes = attrs 775: save 776: end
# File lib/active_ldap/base.rb, line 778 778: def update_attributes!(attrs) 779: self.attributes = attrs 780: save! 781: end
Returns the array form of a value, or not an array if false is passed in.
# File lib/active_ldap/base.rb, line 1201 1201: def array_of(value, to_a=true) 1202: case value 1203: when Array 1204: if to_a or value.size > 1 1205: value.collect {|v| array_of(v, false)}.compact 1206: else 1207: if value.empty? 1208: nil 1209: else 1210: array_of(value.first, to_a) 1211: end 1212: end 1213: when Hash 1214: if to_a 1215: [value] 1216: else 1217: result = {} 1218: value.each {|k, v| result[k] = array_of(v, to_a)} 1219: result 1220: end 1221: else 1222: to_a ? [value] : value 1223: end 1224: end
# File lib/active_ldap/base.rb, line 1296 1296: def assert_dn_attribute 1297: unless dn_attribute 1298: raise ConfigurationError, 1299: _("dn_attribute isn't set for this class: %s") % self.class 1300: end 1301: end
# File lib/active_ldap/base.rb, line 977 977: def attribute_name_resolvable_without_connection? 978: @entry_attribute and @local_entry_attribute 979: end
# File lib/active_ldap/base.rb, line 1278 1278: def collect_all_attributes(data) 1279: dn_attr = dn_attribute 1280: dn_value = data[dn_attr] 1281: 1282: attributes = [] 1283: attributes.push([dn_attr, dn_value]) 1284: 1285: oc_value = data['objectClass'] 1286: attributes.push(['objectClass', oc_value]) 1287: data.each do |key, value| 1288: next if value.empty? or key == 'objectClass' or key == dn_attr 1289: 1290: attributes.push([key, value]) 1291: end 1292: 1293: attributes 1294: end
# File lib/active_ldap/base.rb, line 1241 1241: def collect_modified_attributes(ldap_data, data) 1242: attributes = [] 1243: # Now that all the options will be treated as unique attributes 1244: # we can see what's changed and add anything that is brand-spankin' 1245: # new. 1246: ldap_data.each do |k, v| 1247: value = data[k] || [] 1248: 1249: next if v == value 1250: 1251: # Create mod entries 1252: if value.empty? 1253: # Since some types do not have equality matching rules, 1254: # delete doesn't work 1255: # Replacing with nothing is equivalent. 1256: if !data.has_key?(k) and schema.attribute(k).binary_required? 1257: value = [{'binary' => []}] 1258: end 1259: else 1260: # Ditched delete then replace because attribs with no equality 1261: # match rules will fails 1262: end 1263: attributes.push([:replace, k, value]) 1264: end 1265: data.each do |k, v| 1266: value = v || [] 1267: next if ldap_data.has_key?(k) or value.empty? 1268: 1269: # Detect subtypes and account for them 1270: # REPLACE will function like ADD, but doesn't hit EQUALITY problems 1271: # TODO: Added equality(attr) to Schema 1272: attributes.push([:replace, k, value]) 1273: end 1274: 1275: attributes 1276: end
# File lib/active_ldap/base.rb, line 1179 1179: def compute_dn(escape_dn_value=false) 1180: return base if @dn_is_base 1181: 1182: dn_value = id 1183: if dn_value.nil? 1184: raise DistinguishedNameNotSetError.new, 1185: _("%s's DN attribute (%s) isn't set") % [self, dn_attribute] 1186: end 1187: dn_value = DN.escape_value(dn_value) if escape_dn_value 1188: _base = base 1189: _base = nil if _base.empty? 1190: ["#{dn_attribute}=#{dn_value}", _base].compact.join(",") 1191: end
# File lib/active_ldap/base.rb, line 1331 1331: def create 1332: prepare_data_for_saving do |data, ldap_data| 1333: attributes = collect_all_attributes(data) 1334: add_entry(escaped_dn, attributes) 1335: @new_entry = false 1336: true 1337: end 1338: end
# File lib/active_ldap/base.rb, line 1303 1303: def create_or_update 1304: new_entry? ? create : update 1305: 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 1050 1050: def enforce_type(key, value) 1051: # Enforce attribute value formatting 1052: normalize_attribute(key, value)[1] 1053: end
# File lib/active_ldap/base.rb, line 981 981: def entry_attribute 982: @entry_attribute ||= connection.entry_attribute(@data["objectClass"] || []) 983: end
# File lib/active_ldap/base.rb, line 989 989: def extract_object_class(attributes) 990: classes = [] 991: attrs = {} 992: attributes.each do |key, value| 993: key = key.to_s 994: if /\Aobject_?class\z/i =~ key 995: classes.concat(value.to_a) 996: else 997: attrs[key] = value 998: end 999: end 1000: [classes, attributes] 1001: end
# File lib/active_ldap/base.rb, line 1114 1114: def false_value?(value) 1115: value.nil? or value == false or value == [] or 1116: value == "false" or value == "FALSE" or value == "" 1117: end
Return the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1070 1070: def get_attribute(name, force_array=false) 1071: name, value = get_attribute_before_type_cast(name, force_array) 1072: return value if name.nil? 1073: attribute = schema.attribute(name) 1074: type_cast(attribute, value) 1075: end
# File lib/active_ldap/base.rb, line 1105 1105: def get_attribute_as_query(name, force_array=false) 1106: name, value = get_attribute_before_type_cast(name, force_array) 1107: if force_array 1108: value.collect {|x| !false_value?(x)} 1109: else 1110: !false_value?(value) 1111: end 1112: end
# File lib/active_ldap/base.rb, line 1098 1098: def get_attribute_before_type_cast(name, force_array=false) 1099: name = to_real_attribute_name(name) 1100: 1101: value = @data[name] || [] 1102: [name, array_of(value, force_array)] 1103: end
# File lib/active_ldap/base.rb, line 1003 1003: def init_base 1004: init_instance_variables 1005: end
# File lib/active_ldap/base.rb, line 1055 1055: def init_instance_variables 1056: @mutex = Mutex.new 1057: @data = {} # where the r/w entry data is stored 1058: @ldap_data = {} # original ldap entry data 1059: @dn_attribute = nil 1060: @base = nil 1061: @scope = nil 1062: @dn = nil 1063: @connection ||= nil 1064: clear_connection_based_cache 1065: end
# File lib/active_ldap/base.rb, line 1007 1007: def initialize_by_ldap_data(dn, attributes) 1008: init_base 1009: @dn = dn 1010: @new_entry = false 1011: @dn_is_base = false 1012: @ldap_data = attributes 1013: classes, attributes = extract_object_class(attributes) 1014: self.classes = classes 1015: self.dn = dn 1016: self.attributes = attributes 1017: yield self if block_given? 1018: assert_dn_attribute 1019: end
# File lib/active_ldap/base.rb, line 963 963: def inspect_attribute(name) 964: values = get_attribute(name, true) 965: values.collect do |value| 966: if value.is_a?(String) and value.length > 50 967: "#{value[0, 50]}...".inspect 968: elsif value.is_a?(Date) || value.is_a?(Time) 969: "#{value.to_s(:db)}" 970: else 971: value.inspect 972: end 973: end 974: "#{name}: #{values.inspect}" 975: end
# File lib/active_ldap/base.rb, line 1021 1021: def instantiate(args) 1022: dn, attributes, options = args 1023: options ||= {} 1024: 1025: obj = self.class.allocate 1026: obj.connection = options[:connection] || @connection 1027: obj.instance_eval do 1028: initialize_by_ldap_data(dn, attributes) 1029: end 1030: obj 1031: end
# File lib/active_ldap/base.rb, line 985 985: def local_entry_attribute 986: @local_entry_attribute ||= connection.entry_attribute([]) 987: end
# File lib/active_ldap/base.rb, line 1226 1226: def normalize_data(data, except=[]) 1227: _schema = schema 1228: result = {} 1229: data.each do |key, values| 1230: next if except.include?(key) 1231: real_name = to_real_attribute_name(key) 1232: next if real_name and except.include?(real_name) 1233: real_name ||= key 1234: next if _schema.attribute(real_name).id.nil? 1235: result[real_name] ||= [] 1236: result[real_name].concat(enforce_type(real_name, values)) 1237: end 1238: result 1239: end
# File lib/active_ldap/base.rb, line 1307 1307: def prepare_data_for_saving 1308: # Expand subtypes to real ldap_data attributes 1309: # We can't reuse @ldap_data because an exception would leave 1310: # an object in an unknown state 1311: ldap_data = normalize_data(@ldap_data) 1312: 1313: # Expand subtypes to real data attributes, but leave @data alone 1314: bad_attrs = @data.keys - attribute_names 1315: data = normalize_data(@data, bad_attrs) 1316: 1317: success = yield(data, ldap_data) 1318: 1319: if success 1320: @ldap_data = Marshal.load(Marshal.dump(data)) 1321: # Delete items disallowed by objectclasses. 1322: # They should have been removed from ldap. 1323: bad_attrs.each do |remove_me| 1324: @ldap_data.delete(remove_me) 1325: end 1326: end 1327: 1328: success 1329: end
Set the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1122 1122: def set_attribute(name, value) 1123: attr = to_real_attribute_name(name) 1124: attr, value = update_dn(attr, value) if attr == dn_attribute 1125: raise UnknownAttribute.new(name) if attr.nil? 1126: 1127: @data[attr] = value 1128: end
# File lib/active_ldap/base.rb, line 1154 1154: def split_dn_value(value) 1155: dn_value = relative_dn_value = nil 1156: begin 1157: dn_value = value if value.is_a?(DN) 1158: dn_value ||= DN.parse(value) 1159: rescue DistinguishedNameInvalid 1160: dn_value = DN.parse("#{dn_attribute}=#{value}") 1161: end 1162: 1163: begin 1164: relative_dn_value = dn_value - self.class.parsed_base 1165: if relative_dn_value.rdns.empty? 1166: val = [] 1167: bases = dn_value.rdns 1168: else 1169: val, *bases = relative_dn_value.rdns 1170: end 1171: rescue ArgumentError 1172: val, *bases = dn_value.rdns 1173: end 1174: 1175: dn_attribute_name, dn_attribute_value = val.to_a[0] 1176: [dn_attribute_name, dn_attribute_value, bases] 1177: end
# File lib/active_ldap/base.rb, line 1033 1033: def to_real_attribute_name(name, allow_normalized_name=false) 1034: return name if name.nil? 1035: if allow_normalized_name 1036: entry_attribute.normalize(name, allow_normalized_name) || 1037: local_entry_attribute.normalize(name, allow_normalized_name) 1038: else 1039: @real_names[name] ||= 1040: entry_attribute.normalize(name, false) || 1041: local_entry_attribute.normalize(name, false) 1042: end 1043: end
# File lib/active_ldap/base.rb, line 1077 1077: def type_cast(attribute, value) 1078: case value 1079: when Hash 1080: result = {} 1081: value.each do |option, val| 1082: result[option] = type_cast(attribute, val) 1083: end 1084: if result.size == 1 and result.has_key?("binary") 1085: result["binary"] 1086: else 1087: result 1088: end 1089: when Array 1090: value.collect do |val| 1091: type_cast(attribute, val) 1092: end 1093: else 1094: attribute.type_cast(value) 1095: end 1096: end
# File lib/active_ldap/base.rb, line 1340 1340: def update 1341: prepare_data_for_saving do |data, ldap_data| 1342: attributes = collect_modified_attributes(ldap_data, data) 1343: modify_entry(escaped_dn, attributes) 1344: true 1345: end 1346: end
# File lib/active_ldap/base.rb, line 1130 1130: def update_dn(attr, value) 1131: @dn = nil 1132: @dn_is_base = false 1133: return [attr, nil] if value.blank? 1134: 1135: new_dn_attribute, new_value, bases = split_dn_value(value) 1136: if new_dn_attribute.nil? and new_value.nil? 1137: @dn_is_base = true 1138: @base = nil 1139: attr, value = bases[0].to_a[0] 1140: @dn_attribute = attr 1141: else 1142: new_dn_attribute = to_real_attribute_name(new_dn_attribute) 1143: if new_dn_attribute 1144: value = new_value 1145: @base = bases.empty? ? nil : DN.new(*bases).to_s 1146: if dn_attribute != new_dn_attribute 1147: @dn_attribute = attr = new_dn_attribute 1148: end 1149: end 1150: end 1151: [attr, value] 1152: end