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 |
abstract_class | [RW] |
# File lib/active_ldap/base.rb, line 493 493: def abstract_class? 494: defined?(@abstract_class) && @abstract_class 495: 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 427 427: def base 428: _base = base_inheritable 429: _base = configuration[:base] if _base.nil? and configuration 430: _base ||= base_inheritable(true) 431: [prefix, _base].find_all do |component| 432: !component.blank? 433: end.join(",") 434: end
# File lib/active_ldap/base.rb, line 437 437: def base=(value) 438: self.base_without_parsed_cache_clear = value 439: @parsed_base = nil 440: end
# File lib/active_ldap/base.rb, line 459 459: def base_class 460: if self == Base or superclass == Base 461: self 462: else 463: superclass.base_class 464: end 465: end
# File lib/active_ldap/base.rb, line 290 290: def self.class_local_attr_accessor(search_ancestors, *syms) 291: syms.flatten.each do |sym| 292: 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\n", __FILE__, __LINE__ + 1) 293: end 294: end
# File lib/active_ldap/base.rb, line 497 497: def class_of_active_ldap_descendant(klass) 498: if klass.superclass == Base or klass.superclass.abstract_class? 499: klass 500: elsif klass.superclass.nil? 501: raise Error, _("%s doesn't belong in a hierarchy descending " \ 502: "from ActiveLdap") % (name || to_s) 503: else 504: class_of_active_ldap_descendant(klass.superclass) 505: end 506: end
# File lib/active_ldap/base.rb, line 382 382: def create(attributes=nil, &block) 383: if attributes.is_a?(Array) 384: attributes.collect {|attrs| create(attrs, &block)} 385: else 386: object = new(attributes, &block) 387: object.save 388: object 389: end 390: end
# File lib/active_ldap/base.rb, line 467 467: def default_search_attribute 468: dn_attribute 469: end
establish_connection is deprecated since 1.1.0. Please use setup_connection() instead.
# File lib/active_ldap/base.rb, line 373 373: def establish_connection(config=nil) 374: message = 375: _("ActiveLdap::Base.establish_connection has been deprecated " \ 376: "since 1.1.0. " \ 377: "Please use ActiveLdap::Base.setup_connection instead.") 378: ActiveSupport::Deprecation.warn(message) 379: setup_connection(config) 380: end
# File lib/active_ldap/base.rb, line 527 527: def human_name(options={}) 528: defaults = self_and_descendants_from_active_ldap.collect do |klass| 529: if klass.name.blank? 530: nil 531: else 532: "#{klass.name.underscore}""#{klass.name.underscore}" 533: end 534: end 535: defaults << name.humanize 536: defaults = defaults.compact 537: defaults.first || name || to_s 538: end
# File lib/active_ldap/base.rb, line 471 471: def inspect 472: if self == Base 473: super 474: elsif abstract_class? 475: "#{super}(abstract)" 476: else 477: class_names = [] 478: must = [] 479: may = [] 480: class_names = classes.collect do |object_class| 481: must.concat(object_class.must) 482: may.concat(object_class.may) 483: object_class.name 484: end 485: detail = ["objectClass:<#{class_names.join(', ')}>", 486: "must:<#{inspect_attributes(must)}>", 487: "may:<#{inspect_attributes(may)}>"].join(", ") 488: "#{super}(#{detail})" 489: end 490: 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 399 399: def ldap_mapping(options={}) 400: options = options.symbolize_keys 401: validate_ldap_mapping_options(options) 402: 403: self.dn_attribute = options[:dn_attribute] || default_dn_attribute 404: self.dn_attribute = dn_attribute.to_s if dn_attribute.is_a?(Symbol) 405: self.prefix = options[:prefix] || default_prefix 406: self.scope = options[:scope] 407: self.required_classes = options[:classes] 408: self.recommended_classes = options[:recommended_classes] 409: self.excluded_classes = options[:excluded_classes] 410: self.sort_by = options[:sort_by] 411: self.order = options[:order] 412: 413: public_class_method :new 414: 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 635 635: def initialize(attributes=nil) 636: init_base 637: @new_entry = true 638: initial_classes = required_classes | recommended_classes 639: case attributes 640: when nil 641: self.classes = initial_classes 642: when String, Array, DN 643: self.classes = initial_classes 644: self.dn = attributes 645: when Hash 646: classes, attributes = extract_object_class(attributes) 647: self.classes = classes | initial_classes 648: normalized_attributes = {} 649: attributes.each do |key, value| 650: real_key = to_real_attribute_name(key) || key 651: normalized_attributes[real_key] = value 652: end 653: self.dn = normalized_attributes.delete(dn_attribute) 654: self.attributes = normalized_attributes 655: else 656: format = _("'%s' must be either nil, DN value as ActiveLdap::DN, " \ 657: "String or Array or attributes as Hash") 658: raise ArgumentError, format % attributes.inspect 659: end 660: yield self if block_given? 661: end
# File lib/active_ldap/base.rb, line 442 442: def parsed_base 443: @parsed_base ||= DN.parse(base) 444: end
# File lib/active_ldap/base.rb, line 447 447: def scope=(scope) 448: validate_scope(scope) 449: self.scope_without_validation = scope 450: end
# File lib/active_ldap/base.rb, line 508 508: def self_and_descendants_from_active_ldap 509: klass = self 510: classes = [klass] 511: while klass != klass.base_class 512: classes << klass = klass.superclass 513: end 514: classes 515: rescue 516: [self] 517: 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 365 365: def setup_connection(config=nil) 366: super 367: ensure_logger 368: nil 369: end
# File lib/active_ldap/base.rb, line 452 452: def validate_scope(scope) 453: scope = scope.to_sym if scope.is_a?(String) 454: return if scope.nil? or scope.is_a?(Symbol) 455: raise ConfigurationError, 456: _("scope '%s' must be a Symbol") % scope.inspect 457: end
# File lib/active_ldap/base.rb, line 603 603: def default_dn_attribute 604: dn_attribute = nil 605: parent_class = ancestors[1] 606: if parent_class.respond_to?(:dn_attribute) 607: dn_attribute = parent_class.dn_attribute 608: end 609: dn_attribute || "cn" 610: end
# File lib/active_ldap/base.rb, line 612 612: def default_prefix 613: if name.blank? 614: nil 615: else 616: "ou=#{name.demodulize.pluralize}" 617: end 618: end
# File lib/active_ldap/base.rb, line 571 571: def ensure_logger 572: @@logger ||= configuration[:logger] 573: # Setup default logger to console 574: if @@logger.nil? 575: require 'logger' 576: @@logger = Logger.new(STDERR) 577: @@logger.progname = 'ActiveLdap' 578: @@logger.level = Logger::UNKNOWN 579: end 580: configuration[:logger] ||= @@logger 581: end
# File lib/active_ldap/base.rb, line 553 553: def inspect_attribute(attribute) 554: syntax = attribute.syntax 555: result = "#{attribute.name}" 556: if syntax and !syntax.description.blank? 557: result << ": #{syntax.description}" 558: end 559: properties = [] 560: properties << "read-only" if attribute.read_only? 561: properties << "binary" if attribute.binary? 562: properties << "binary-required" if attribute.binary_required? 563: result << "(#{properties.join(', ')})" unless properties.empty? 564: result 565: end
# File lib/active_ldap/base.rb, line 541 541: def inspect_attributes(attributes) 542: inspected_attribute_names = {} 543: attributes.collect do |attribute| 544: if inspected_attribute_names.has_key?(attribute.name) 545: nil 546: else 547: inspected_attribute_names[attribute.name] = true 548: inspect_attribute(attribute) 549: end 550: end.compact.join(', ') 551: end
# File lib/active_ldap/base.rb, line 583 583: def instantiate(args) 584: dn, attributes, options = args 585: options ||= {} 586: if self.class == Class 587: klass = self.ancestors[0].to_s.split(':').last 588: real_klass = self.ancestors[0] 589: else 590: klass = self.class.to_s.split(':').last 591: real_klass = self.class 592: end 593: 594: obj = real_klass.allocate 595: conn = options[:connection] || connection 596: obj.connection = conn if conn != connection 597: obj.instance_eval do 598: initialize_by_ldap_data(dn, attributes) 599: end 600: obj 601: end
# File lib/active_ldap/base.rb, line 567 567: def validate_ldap_mapping_options(options) 568: options.assert_valid_keys(VALID_LDAP_MAPPING_OPTIONS) 569: 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 665 665: def ==(comparison_object) 666: comparison_object.equal?(self) or 667: (comparison_object.instance_of?(self.class) and 668: comparison_object.dn == dn and 669: !comparison_object.new_entry?) 670: end
# File lib/active_ldap/base.rb, line 941 941: def [](name, force_array=false) 942: if name == "dn" 943: array_of(dn, force_array) 944: else 945: get_attribute(name, force_array) 946: end 947: end
# File lib/active_ldap/base.rb, line 949 949: def []=(name, value) 950: set_attribute(name, value) 951: end
Return attribute methods so that a program can determine available attributes dynamically without schema awareness
# File lib/active_ldap/base.rb, line 697 697: def attribute_names(normalize=false) 698: entry_attribute.names(normalize) 699: end
# File lib/active_ldap/base.rb, line 701 701: def attribute_present?(name) 702: values = get_attribute(name, true) 703: !values.empty? or values.any? {|x| !(x and x.empty?)} 704: end
This returns the key value pairs in @data with all values cloned
# File lib/active_ldap/base.rb, line 863 863: def attributes 864: Marshal.load(Marshal.dump(@data)) 865: 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 873 873: def attributes=(new_attributes) 874: return if new_attributes.blank? 875: _schema = _local_entry_attribute = nil 876: targets = remove_attributes_protected_from_mass_assignment(new_attributes) 877: targets.each do |key, value| 878: setter = "#{key}=" 879: unless respond_to?(setter) 880: _schema ||= schema 881: attribute = _schema.attribute(key) 882: next if attribute.id.nil? 883: _local_entry_attribute ||= local_entry_attribute 884: _local_entry_attribute.register(attribute) 885: end 886: send(setter, value) 887: end 888: end
# File lib/active_ldap/base.rb, line 1000 1000: def base 1001: ensure_update_dn 1002: [@base, base_of_class].find_all do |component| 1003: not component.blank? 1004: end.join(",") 1005: end
# File lib/active_ldap/base.rb, line 1007 1007: def base=(object_local_base) 1008: ensure_update_dn 1009: @dn = nil 1010: @base = object_local_base 1011: end
# File lib/active_ldap/base.rb, line 959 959: def bind(config_or_password={}, config_or_ignore=nil, &block) 960: if config_or_password.is_a?(String) 961: config = (config_or_ignore || {}).merge(:password => config_or_password) 962: else 963: config = config_or_password 964: end 965: config = {:bind_dn => dn, :allow_anonymous => false}.merge(config) 966: config[:password_block] ||= block if block_given? 967: setup_connection(config) 968: 969: before_connection = @connection 970: begin 971: @connection = nil 972: connection.connect 973: @connection = connection 974: clear_connection_based_cache 975: clear_association_cache 976: rescue ActiveLdap::Error 977: remove_connection 978: @connection = before_connection 979: raise 980: end 981: true 982: end
# File lib/active_ldap/base.rb, line 984 984: def clear_connection_based_cache 985: @schema = nil 986: @local_entry_attribute = nil 987: clear_object_class_based_cache 988: end
# File lib/active_ldap/base.rb, line 990 990: def clear_object_class_based_cache 991: @entry_attribute = nil 992: @real_names = {} 993: end
# File lib/active_ldap/base.rb, line 749 749: def default_search_attribute 750: self.class.default_search_attribute 751: end
# File lib/active_ldap/base.rb, line 765 765: def delete(options={}) 766: super(dn, options) 767: end
# File lib/active_ldap/base.rb, line 736 736: def dn=(value) 737: set_attribute(dn_attribute_with_fallback, value) 738: @dn = nil 739: end
# File lib/active_ldap/base.rb, line 743 743: def dn_attribute 744: ensure_update_dn 745: _dn_attribute = @dn_attribute || dn_attribute_of_class 746: to_real_attribute_name(_dn_attribute) || _dn_attribute 747: end
# File lib/active_ldap/base.rb, line 953 953: def each 954: @data.each do |key, values| 955: yield(key.dup, values.dup) 956: end 957: end
Delegates to ==
# File lib/active_ldap/base.rb, line 673 673: def eql?(comparison_object) 674: self == (comparison_object) 675: end
# File lib/active_ldap/base.rb, line 918 918: def have_attribute?(name, except=[]) 919: real_name = to_real_attribute_name(name) 920: !real_name.nil? and !except.include?(real_name) 921: end
# File lib/active_ldap/base.rb, line 728 728: def id 729: get_attribute(dn_attribute_with_fallback) 730: end
# File lib/active_ldap/base.rb, line 1023 1023: def inspect 1024: object_classes = entry_attribute.object_classes 1025: inspected_object_classes = object_classes.collect do |object_class| 1026: object_class.name 1027: end.join(', ') 1028: must_attributes = must.collect(&:name).sort.join(', ') 1029: may_attributes = may.collect(&:name).sort.join(', ') 1030: inspected_attributes = attribute_names.sort.collect do |name| 1031: inspect_attribute(name) 1032: end.join(', ') 1033: result = "\#<#{self.class} objectClass:<#{inspected_object_classes}>, " 1034: result << "must:<#{must_attributes}>, may:<#{may_attributes}>, " 1035: result << "#{inspected_attributes}>" 1036: result 1037: 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 791 791: def method_missing(name, *args, &block) 792: key = name.to_s 793: case key 794: when /=$/ 795: real_key = $PREMATCH 796: if have_attribute?(real_key, ['objectClass']) 797: if args.size != 1 798: raise ArgumentError, 799: _("wrong number of arguments (%d for 1)") % args.size 800: end 801: return set_attribute(real_key, *args, &block) 802: end 803: when /(?:(_before_type_cast)|(\?))?$/ 804: real_key = $PREMATCH 805: before_type_cast = !$1.nil? 806: query = !$2.nil? 807: if have_attribute?(real_key, ['objectClass']) 808: if args.size > 1 809: raise ArgumentError, 810: _("wrong number of arguments (%d for 1)") % args.size 811: end 812: if before_type_cast 813: return get_attribute_before_type_cast(real_key, *args)[1] 814: elsif query 815: return get_attribute_as_query(real_key, *args) 816: else 817: return get_attribute(real_key, *args) 818: end 819: end 820: end 821: super 822: end
Add available attributes to the methods
# File lib/active_ldap/base.rb, line 825 825: def methods(inherited_too=true) 826: target_names = entry_attribute.all_names 827: target_names -= ['objectClass', 'objectClass'.underscore] 828: super + target_names.uniq.collect do |x| 829: [x, "#{x}=", "#{x}?", "#{x}_before_type_cast"] 830: end.flatten 831: end
# File lib/active_ldap/base.rb, line 924 924: def reload 925: clear_association_cache 926: _, attributes = search(:value => id).find do |_dn, _attributes| 927: dn == _dn 928: end 929: if attributes.nil? 930: raise EntryNotFound, _("Can't find DN '%s' to reload") % dn 931: end 932: 933: @ldap_data.update(attributes) 934: classes, attributes = extract_object_class(attributes) 935: self.classes = classes 936: self.attributes = attributes 937: @new_entry = false 938: self 939: end
# File lib/active_ldap/base.rb, line 834 834: def respond_to?(name, include_priv=false) 835: return true if super 836: 837: name = name.to_s 838: return true if have_attribute?(name) 839: return false if /(?:=|\?|_before_type_cast)$/ !~ name 840: have_attribute?($PREMATCH) 841: end
Save and validate this object into LDAP either adding or replacing attributes TODO: Relative DN support
# File lib/active_ldap/base.rb, line 774 774: def save 775: create_or_update 776: end
# File lib/active_ldap/base.rb, line 778 778: def save! 779: unless create_or_update 780: raise EntryNotSaved, _("entry %s can't be saved") % dn 781: end 782: end
# File lib/active_ldap/base.rb, line 1018 1018: def scope=(scope) 1019: self.class.validate_scope(scope) 1020: @scope = scope 1021: end
# File lib/active_ldap/base.rb, line 894 894: def to_ldif 895: Ldif.new([to_ldif_record]).to_s 896: end
# File lib/active_ldap/base.rb, line 890 890: def to_ldif_record 891: super(dn, normalize_data(@data)) 892: end
# File lib/active_ldap/base.rb, line 898 898: def to_xml(options={}) 899: options = options.dup 900: options[:root] ||= (self.class.name || '').underscore 901: except = options[:except] 902: if except 903: options[:except] = except.collect do |name| 904: if name.to_s.downcase == "dn" 905: "dn" 906: else 907: to_real_attribute_name(name) 908: end 909: end.compact 910: end 911: XML.new(dn, normalize_data(@data), schema).to_s(options) 912: end
Updates a given attribute and saves immediately
# File lib/active_ldap/base.rb, line 844 844: def update_attribute(name, value) 845: send("#{name}=", value) 846: save 847: end
This performs a bulk update of attributes and immediately calls save.
# File lib/active_ldap/base.rb, line 851 851: def update_attributes(attrs) 852: self.attributes = attrs 853: save 854: end
# File lib/active_ldap/base.rb, line 856 856: def update_attributes!(attrs) 857: self.attributes = attrs 858: save! 859: end
Returns the array form of a value, or not an array if false is passed in.
# File lib/active_ldap/base.rb, line 1344 1344: def array_of(value, to_a=true) 1345: case value 1346: when Array 1347: if to_a or value.size > 1 1348: value.collect {|v| array_of(v, false)}.compact 1349: else 1350: if value.empty? 1351: nil 1352: else 1353: array_of(value.first, to_a) 1354: end 1355: end 1356: when Hash 1357: if to_a 1358: [value] 1359: else 1360: result = {} 1361: value.each {|k, v| result[k] = array_of(v, to_a)} 1362: result 1363: end 1364: else 1365: to_a ? [value] : value 1366: end 1367: end
# File lib/active_ldap/base.rb, line 1065 1065: def attribute_name_resolvable_without_connection? 1066: @entry_attribute and @local_entry_attribute 1067: end
# File lib/active_ldap/base.rb, line 1429 1429: def collect_all_attributes(data) 1430: dn_attr = dn_attribute 1431: dn_value = data[dn_attr] 1432: 1433: attributes = [] 1434: attributes.push([dn_attr, dn_value]) 1435: 1436: oc_value = data['objectClass'] 1437: attributes.push(['objectClass', oc_value]) 1438: data.each do |key, value| 1439: next if key == 'objectClass' or key == dn_attr 1440: value = self.class.remove_blank_value(value) 1441: next if self.class.blank_value?(value) 1442: 1443: attributes.push([key, value]) 1444: end 1445: 1446: attributes 1447: end
# File lib/active_ldap/base.rb, line 1384 1384: def collect_modified_attributes(ldap_data, data) 1385: attributes = [] 1386: # Now that all the options will be treated as unique attributes 1387: # we can see what's changed and add anything that is brand-spankin' 1388: # new. 1389: ldap_data.each do |k, v| 1390: value = data[k] || [] 1391: 1392: next if v == value 1393: 1394: x = value 1395: value = self.class.remove_blank_value(value) || [] 1396: next if v == value 1397: 1398: # Create mod entries 1399: if self.class.blank_value?(value) 1400: # Since some types do not have equality matching rules, 1401: # delete doesn't work 1402: # Replacing with nothing is equivalent. 1403: if !data.has_key?(k) and schema.attribute(k).binary_required? 1404: value = [{'binary' => []}] 1405: end 1406: else 1407: # Ditched delete then replace because attribs with no equality 1408: # match rules will fails 1409: end 1410: attributes.push([:replace, k, value]) 1411: end 1412: data.each do |k, v| 1413: value = v || [] 1414: next if ldap_data.has_key?(k) 1415: 1416: value = self.class.remove_blank_value(value) || [] 1417: next if self.class.blank_value?(value) 1418: 1419: 1420: # Detect subtypes and account for them 1421: # REPLACE will function like ADD, but doesn't hit EQUALITY problems 1422: # TODO: Added equality(attr) to Schema 1423: attributes.push([:replace, k, value]) 1424: end 1425: 1426: attributes 1427: end
# File lib/active_ldap/base.rb, line 1320 1320: def compute_dn(escape_dn_value=false) 1321: return base if @dn_is_base 1322: 1323: ensure_update_dn 1324: dn_value = id 1325: if dn_value.nil? 1326: format =_("%s's DN attribute (%s) isn't set") 1327: message = format % [self.inspect, dn_attribute] 1328: raise DistinguishedNameNotSetError.new, message 1329: end 1330: dn_value = DN.escape_value(dn_value.to_s) if escape_dn_value 1331: _base = base 1332: _base = nil if _base.blank? 1333: ["#{dn_attribute}=#{dn_value}", _base].compact.join(",") 1334: end
# File lib/active_ldap/base.rb, line 1477 1477: def create 1478: prepare_data_for_saving do |data, ldap_data| 1479: attributes = collect_all_attributes(data) 1480: add_entry(escaped_dn, attributes) 1481: @new_entry = false 1482: true 1483: end 1484: end
# File lib/active_ldap/base.rb, line 1449 1449: def create_or_update 1450: new_entry? ? create : update 1451: end
# File lib/active_ldap/base.rb, line 1040 1040: def dn_attribute_with_fallback 1041: begin 1042: dn_attribute 1043: rescue DistinguishedNameInvalid 1044: _dn_attribute = @dn_attribute || dn_attribute_of_class 1045: _dn_attribute = to_real_attribute_name(_dn_attribute) || _dn_attribute 1046: raise if _dn_attribute.nil? 1047: _dn_attribute 1048: end 1049: 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 1139 1139: def enforce_type(key, value) 1140: # Enforce attribute value formatting 1141: normalize_attribute(key, value)[1] 1142: end
# File lib/active_ldap/base.rb, line 1310 1310: def ensure_update_dn 1311: return unless need_update_dn? 1312: @mutex.synchronize do 1313: if @dn_split_value 1314: update_dn(*@dn_split_value) 1315: @dn_split_value = nil 1316: end 1317: end 1318: end
# File lib/active_ldap/base.rb, line 1069 1069: def entry_attribute 1070: @entry_attribute ||= connection.entry_attribute(@data["objectClass"] || []) 1071: end
# File lib/active_ldap/base.rb, line 1077 1077: def extract_object_class(attributes) 1078: classes = [] 1079: attrs = {} 1080: attributes.each do |key, value| 1081: key = key.to_s 1082: if /\Aobject_?class\z/i =~ key 1083: classes.concat(value.to_a) 1084: else 1085: attrs[key] = value 1086: end 1087: end 1088: [classes, attributes] 1089: end
# File lib/active_ldap/base.rb, line 1205 1205: def false_value?(value) 1206: value.nil? or value == false or value == [] or 1207: value == "false" or value == "FALSE" or value == "" 1208: end
Return the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1161 1161: def get_attribute(name, force_array=false) 1162: name, value = get_attribute_before_type_cast(name, force_array) 1163: return value if name.nil? 1164: attribute = schema.attribute(name) 1165: type_cast(attribute, value) 1166: end
# File lib/active_ldap/base.rb, line 1196 1196: def get_attribute_as_query(name, force_array=false) 1197: name, value = get_attribute_before_type_cast(name, force_array) 1198: if force_array 1199: value.collect {|x| !false_value?(x)} 1200: else 1201: !false_value?(value) 1202: end 1203: end
# File lib/active_ldap/base.rb, line 1189 1189: def get_attribute_before_type_cast(name, force_array=false) 1190: name = to_real_attribute_name(name) 1191: 1192: value = @data[name] || [] 1193: [name, array_of(value, force_array)] 1194: end
# File lib/active_ldap/base.rb, line 1091 1091: def init_base 1092: init_instance_variables 1093: end
# File lib/active_ldap/base.rb, line 1144 1144: def init_instance_variables 1145: @mutex = Mutex.new 1146: @data = {} # where the r/w entry data is stored 1147: @ldap_data = {} # original ldap entry data 1148: @dn_attribute = nil 1149: @base = nil 1150: @scope = nil 1151: @dn = nil 1152: @dn_is_base = false 1153: @dn_split_value = nil 1154: @connection ||= nil 1155: clear_connection_based_cache 1156: end
# File lib/active_ldap/base.rb, line 1095 1095: def initialize_by_ldap_data(dn, attributes) 1096: init_base 1097: dn = Compatible.convert_to_utf8_encoded_object(dn) 1098: attributes = Compatible.convert_to_utf8_encoded_object(attributes) 1099: @dn = dn 1100: @new_entry = false 1101: @dn_is_base = false 1102: @ldap_data = attributes 1103: classes, attributes = extract_object_class(attributes) 1104: self.classes = classes 1105: self.dn = dn 1106: self.attributes = attributes 1107: yield self if block_given? 1108: end
# File lib/active_ldap/base.rb, line 1051 1051: def inspect_attribute(name) 1052: values = get_attribute(name, true) 1053: values.collect do |value| 1054: if value.is_a?(String) and value.length > 50 1055: "#{value[0, 50]}...".inspect 1056: elsif value.is_a?(Date) || value.is_a?(Time) 1057: "#{value.to_s(:db)}" 1058: else 1059: value.inspect 1060: end 1061: end 1062: "#{name}: #{values.inspect}" 1063: end
# File lib/active_ldap/base.rb, line 1110 1110: def instantiate(args) 1111: dn, attributes, options = args 1112: options ||= {} 1113: 1114: obj = self.class.allocate 1115: obj.connection = options[:connection] || @connection 1116: obj.instance_eval do 1117: initialize_by_ldap_data(dn, attributes) 1118: end 1119: obj 1120: end
# File lib/active_ldap/base.rb, line 1073 1073: def local_entry_attribute 1074: @local_entry_attribute ||= connection.entry_attribute([]) 1075: end
# File lib/active_ldap/base.rb, line 1306 1306: def need_update_dn? 1307: not @dn_split_value.nil? 1308: end
# File lib/active_ldap/base.rb, line 1369 1369: def normalize_data(data, except=[]) 1370: _schema = schema 1371: result = {} 1372: data.each do |key, values| 1373: next if except.include?(key) 1374: real_name = to_real_attribute_name(key) 1375: next if real_name and except.include?(real_name) 1376: real_name ||= key 1377: next if _schema.attribute(real_name).id.nil? 1378: result[real_name] ||= [] 1379: result[real_name].concat(enforce_type(real_name, values)) 1380: end 1381: result 1382: end
# File lib/active_ldap/base.rb, line 1453 1453: def prepare_data_for_saving 1454: # Expand subtypes to real ldap_data attributes 1455: # We can't reuse @ldap_data because an exception would leave 1456: # an object in an unknown state 1457: ldap_data = normalize_data(@ldap_data) 1458: 1459: # Expand subtypes to real data attributes, but leave @data alone 1460: bad_attrs = @data.keys - attribute_names 1461: data = normalize_data(@data, bad_attrs) 1462: 1463: success = yield(data, ldap_data) 1464: 1465: if success 1466: @ldap_data = Marshal.load(Marshal.dump(data)) 1467: # Delete items disallowed by objectclasses. 1468: # They should have been removed from ldap. 1469: bad_attrs.each do |remove_me| 1470: @ldap_data.delete(remove_me) 1471: end 1472: end 1473: 1474: success 1475: end
# File lib/active_ldap/base.rb, line 1230 1230: def register_new_dn_attribute(name, value) 1231: @dn = nil 1232: @dn_is_base = false 1233: if value.blank? 1234: @dn_split_value = nil 1235: [name, nil] 1236: else 1237: new_name, new_value, raw_new_value, new_bases = split_dn_value(value) 1238: @dn_split_value = [new_name, new_value, new_bases] 1239: if new_name.nil? and new_value.nil? 1240: new_name, raw_new_value = new_bases[0].to_a[0] 1241: end 1242: [to_real_attribute_name(new_name) || name, 1243: raw_new_value || value] 1244: end 1245: end
Set the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1213 1213: def set_attribute(name, value) 1214: real_name = to_real_attribute_name(name) 1215: _dn_attribute = nil 1216: valid_dn_attribute = true 1217: begin 1218: _dn_attribute = dn_attribute 1219: rescue DistinguishedNameInvalid 1220: valid_dn_attribute = false 1221: end 1222: if valid_dn_attribute and real_name == _dn_attribute 1223: real_name, value = register_new_dn_attribute(real_name, value) 1224: end 1225: raise UnknownAttribute.new(name) if real_name.nil? 1226: 1227: @data[real_name] = value 1228: end
# File lib/active_ldap/base.rb, line 1271 1271: def split_dn_value(value) 1272: dn_value = relative_dn_value = nil 1273: begin 1274: dn_value = value if value.is_a?(DN) 1275: dn_value ||= DN.parse(value) 1276: rescue DistinguishedNameInvalid 1277: begin 1278: dn_value = DN.parse("#{dn_attribute}=#{value}") 1279: rescue DistinguishedNameInvalid 1280: return [nil, value, value, []] 1281: end 1282: end 1283: 1284: val = bases = nil 1285: begin 1286: relative_dn_value = dn_value - self.class.parsed_base 1287: if relative_dn_value.rdns.empty? 1288: val = [] 1289: bases = dn_value.rdns 1290: else 1291: val, *bases = relative_dn_value.rdns 1292: end 1293: rescue ArgumentError 1294: val, *bases = dn_value.rdns 1295: end 1296: 1297: dn_attribute_name, dn_attribute_value = val.to_a[0] 1298: escaped_dn_attribute_value = nil 1299: unless dn_attribute_value.nil? 1300: escaped_dn_attribute_value = DN.escape_value(dn_attribute_value) 1301: end 1302: [dn_attribute_name, escaped_dn_attribute_value, 1303: dn_attribute_value, bases] 1304: end
# File lib/active_ldap/base.rb, line 1122 1122: def to_real_attribute_name(name, allow_normalized_name=true) 1123: return name if name.nil? 1124: if allow_normalized_name 1125: entry_attribute.normalize(name, allow_normalized_name) || 1126: local_entry_attribute.normalize(name, allow_normalized_name) 1127: else 1128: @real_names[name] ||= 1129: entry_attribute.normalize(name, false) || 1130: local_entry_attribute.normalize(name, false) 1131: end 1132: end
# File lib/active_ldap/base.rb, line 1168 1168: def type_cast(attribute, value) 1169: case value 1170: when Hash 1171: result = {} 1172: value.each do |option, val| 1173: result[option] = type_cast(attribute, val) 1174: end 1175: if result.size == 1 and result.has_key?("binary") 1176: result["binary"] 1177: else 1178: result 1179: end 1180: when Array 1181: value.collect do |val| 1182: type_cast(attribute, val) 1183: end 1184: else 1185: attribute.type_cast(value) 1186: end 1187: end
# File lib/active_ldap/base.rb, line 1486 1486: def update 1487: prepare_data_for_saving do |data, ldap_data| 1488: attributes = collect_modified_attributes(ldap_data, data) 1489: modify_entry(escaped_dn, attributes) 1490: true 1491: end 1492: end
# File lib/active_ldap/base.rb, line 1247 1247: def update_dn(new_name, new_value, bases) 1248: if new_name.nil? and new_value.nil? 1249: @dn_is_base = true 1250: @base = nil 1251: attr, value = bases[0].to_a[0] 1252: @dn_attribute = attr 1253: else 1254: new_name ||= @dn_attribute || dn_attribute_of_class 1255: new_name = to_real_attribute_name(new_name) 1256: if new_name.nil? 1257: new_name = @dn_attribute || dn_attribute_of_class 1258: new_name = to_real_attribute_name(new_name) 1259: end 1260: new_bases = bases.empty? ? nil : DN.new(*bases).to_s 1261: dn_components = ["#{new_name}=#{new_value}", 1262: new_bases, 1263: base_of_class] 1264: dn_components = dn_components.find_all {|component| !component.blank?} 1265: DN.parse(dn_components.join(',')) 1266: @base = new_bases 1267: @dn_attribute = new_name 1268: end 1269: end