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, :sort_by, :order] |
base | -> | base_inheritable |
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 318 318: def base 319: _base = base_inheritable 320: _base = configuration[:base] if _base.nil? and configuration 321: _base ||= base_inheritable(true) 322: [prefix, _base].find_all do |component| 323: !component.blank? 324: end.join(",") 325: end
# File lib/active_ldap/base.rb, line 340 340: def base_class 341: if self == Base or superclass == Base 342: self 343: else 344: superclass.base_class 345: end 346: end
# File lib/active_ldap/base.rb, line 201 201: def self.class_local_attr_accessor(search_ancestors, *syms) 202: syms.flatten.each do |sym| 203: 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) 204: end 205: end
# File lib/active_ldap/base.rb, line 275 275: def create(attributes=nil, &block) 276: if attributes.is_a?(Array) 277: attributes.collect {|attrs| create(attrs, &block)} 278: else 279: object = new(attributes, &block) 280: object.save 281: object 282: end 283: end
# File lib/active_ldap/base.rb, line 348 348: def default_search_attribute 349: dn_attribute 350: 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 269 269: def establish_connection(config=nil) 270: super 271: ensure_logger 272: nil 273: 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 292 292: def ldap_mapping(options={}) 293: options = options.symbolize_keys 294: validate_ldap_mapping_options(options) 295: 296: self.dn_attribute = options[:dn_attribute] || default_dn_attribute 297: self.prefix = options[:prefix] || default_prefix 298: self.scope = options[:scope] 299: self.required_classes = options[:classes] 300: self.recommended_classes = options[:recommended_classes] 301: self.sort_by = options[:sort_by] 302: self.order = options[:order] 303: 304: public_class_method :new 305: 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 424 424: def initialize(attributes=nil) 425: init_base 426: @new_entry = true 427: initial_classes = required_classes | recommended_classes 428: if attributes.nil? 429: apply_object_class(initial_classes) 430: elsif attributes.is_a?(String) or attributes.is_a?(Array) 431: apply_object_class(initial_classes) 432: self.dn = attributes 433: elsif attributes.is_a?(Hash) 434: classes, attributes = extract_object_class(attributes) 435: apply_object_class(classes | initial_classes) 436: normalized_attributes = {} 437: attributes.each do |key, value| 438: real_key = to_real_attribute_name(key) || key 439: normalized_attributes[real_key] = value 440: end 441: self.dn = normalized_attributes[dn_attribute] 442: self.attributes = normalized_attributes 443: else 444: message = _("'%s' must be either nil, DN value as String or Array " \ 445: "or attributes as Hash") % attributes.inspect 446: raise ArgumentError, message 447: end 448: yield self if block_given? 449: assert_dn_attribute 450: end
# File lib/active_ldap/base.rb, line 328 328: def scope=(scope) 329: validate_scope(scope) 330: self.scope_without_validation = scope 331: end
# File lib/active_ldap/base.rb, line 333 333: def validate_scope(scope) 334: scope = scope.to_sym if scope.is_a?(String) 335: return if scope.nil? or scope.is_a?(Symbol) 336: raise ConfigurationError, 337: _("scope '%s' must be a Symbol") % scope.inspect 338: end
# File lib/active_ldap/base.rb, line 389 389: def default_dn_attribute 390: if name.empty? 391: dn_attribute = nil 392: parent_class = ancestors[1] 393: if parent_class.respond_to?(:dn_attribute) 394: dn_attribute = parent_class.dn_attribute 395: end 396: dn_attribute || "cn" 397: else 398: Inflector.underscore(Inflector.demodulize(name)) 399: end 400: end
# File lib/active_ldap/base.rb, line 402 402: def default_prefix 403: if name.empty? 404: nil 405: else 406: "ou=#{Inflector.pluralize(Inflector.demodulize(name))}" 407: end 408: end
# File lib/active_ldap/base.rb, line 357 357: def ensure_logger 358: @@logger ||= configuration[:logger] 359: # Setup default logger to console 360: if @@logger.nil? 361: require 'logger' 362: @@logger = Logger.new(STDERR) 363: @@logger.progname = 'ActiveLdap' 364: @@logger.level = Logger::UNKNOWN 365: end 366: configuration[:logger] ||= @@logger 367: end
# File lib/active_ldap/base.rb, line 369 369: def instantiate(args) 370: dn, attributes, options = args 371: options ||= {} 372: if self.class == Class 373: klass = self.ancestors[0].to_s.split(':').last 374: real_klass = self.ancestors[0] 375: else 376: klass = self.class.to_s.split(':').last 377: real_klass = self.class 378: end 379: 380: obj = real_klass.allocate 381: conn = options[:connection] || connection 382: obj.connection = conn if conn != connection 383: obj.instance_eval do 384: initialize_by_ldap_data(dn, attributes) 385: end 386: obj 387: end
# File lib/active_ldap/base.rb, line 353 353: def validate_ldap_mapping_options(options) 354: options.assert_valid_keys(VALID_LDAP_MAPPING_OPTIONS) 355: 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 454 454: def ==(comparison_object) 455: comparison_object.equal?(self) or 456: (comparison_object.instance_of?(self.class) and 457: comparison_object.dn == dn and 458: !comparison_object.new_entry?) 459: end
# File lib/active_ldap/base.rb, line 745 745: def [](name, force_array=false) 746: if name == "dn" 747: array_of(dn, force_array) 748: else 749: get_attribute(name, force_array) 750: end 751: end
# File lib/active_ldap/base.rb, line 753 753: def []=(name, value) 754: set_attribute(name, value) 755: end
Return attribute methods so that a program can determine available attributes dynamically without schema awareness
# File lib/active_ldap/base.rb, line 488 488: def attribute_names(normalize=false) 489: ensure_apply_object_class 490: names = @attribute_names.keys 491: if normalize 492: names.collect do |name| 493: to_real_attribute_name(name) 494: end.uniq 495: else 496: names 497: end 498: end
# File lib/active_ldap/base.rb, line 500 500: def attribute_present?(name) 501: values = get_attribute(name, true) 502: !values.empty? or values.any? {|x| not (x and x.empty?)} 503: end
This returns the key value pairs in @data with all values cloned
# File lib/active_ldap/base.rb, line 669 669: def attributes 670: Marshal.load(Marshal.dump(@data)) 671: 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 679 679: def attributes=(new_attributes) 680: return if new_attributes.nil? 681: _schema = nil 682: targets = remove_attributes_protected_from_mass_assignment(new_attributes) 683: targets.each do |key, value| 684: setter = "#{key}=" 685: unless respond_to?(setter) 686: _schema ||= schema 687: attribute = _schema.attribute(key) 688: next if attribute.id.nil? 689: define_attribute_methods(attribute) 690: end 691: send(setter, value) 692: end 693: end
# File lib/active_ldap/base.rb, line 795 795: def base 796: [@base, base_of_class].compact.join(",") 797: end
# File lib/active_ldap/base.rb, line 800 800: def base=(object_local_base) 801: @base = object_local_base 802: end
# File lib/active_ldap/base.rb, line 763 763: def bind(config_or_password={}, &block) 764: if config_or_password.is_a?(String) 765: config = {:password => config_or_password} 766: elsif config_or_password.respond_to?(:call) 767: config = {:password_block => config_or_password} 768: else 769: config = config_or_password 770: end 771: config = {:bind_dn => dn, :allow_anonymous => false}.merge(config) 772: config[:password_block] ||= block if block_given? 773: establish_connection(config) 774: 775: before_connection = @connection 776: begin 777: @connection = nil 778: connection.connect 779: @connection = connection 780: @schema = nil 781: clear_association_cache 782: rescue ActiveLdap::Error 783: remove_connection 784: @connection = before_connection 785: raise 786: end 787: true 788: end
# File lib/active_ldap/base.rb, line 554 554: def default_search_attribute 555: self.class.default_search_attribute 556: end
# File lib/active_ldap/base.rb, line 570 570: def delete(options={}) 571: super(dn, options) 572: end
Return the authoritative dn
# File lib/active_ldap/base.rb, line 523 523: def dn 524: return base if @dn_is_base 525: 526: dn_value = id 527: if dn_value.nil? 528: raise DistinguishedNameNotSetError.new, 529: _("%s's DN attribute (%s) isn't set") % [self, dn_attribute] 530: end 531: _base = base 532: _base = nil if _base.empty? 533: ["#{dn_attribute}=#{dn_value}", _base].compact.join(",") 534: end
# File lib/active_ldap/base.rb, line 544 544: def dn=(value) 545: set_attribute(dn_attribute, value) 546: end
# File lib/active_ldap/base.rb, line 550 550: def dn_attribute 551: @dn_attribute || dn_attribute_of_class 552: end
# File lib/active_ldap/base.rb, line 757 757: def each 758: @data.each do |key, values| 759: yield(key.dup, values.dup) 760: end 761: end
Delegates to ==
# File lib/active_ldap/base.rb, line 462 462: def eql?(comparison_object) 463: self == (comparison_object) 464: end
# File lib/active_ldap/base.rb, line 722 722: def have_attribute?(name, except=[]) 723: real_name = to_real_attribute_name(name) 724: real_name and !except.include?(real_name) 725: end
# File lib/active_ldap/base.rb, line 815 815: def inspect 816: abbreviate_instance_variables do 817: super 818: end 819: end
# File lib/active_ldap/base.rb, line 474 474: def may 475: ensure_apply_object_class 476: @may 477: 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 596 596: def method_missing(name, *args, &block) 597: ensure_apply_object_class 598: 599: key = name.to_s 600: case key 601: when /=$/ 602: real_key = $PREMATCH 603: if have_attribute?(real_key, ['objectClass']) 604: if args.size != 1 605: raise ArgumentError, 606: _("wrong number of arguments (%d for 1)") % args.size 607: end 608: return set_attribute(real_key, *args, &block) 609: end 610: when /(?:(_before_type_cast)|(\?))?$/ 611: real_key = $PREMATCH 612: before_type_cast = !$1.nil? 613: query = !$2.nil? 614: if have_attribute?(real_key, ['objectClass']) 615: if args.size > 1 616: raise ArgumentError, 617: _("wrong number of arguments (%d for 1)") % args.size 618: end 619: if before_type_cast 620: return get_attribute_before_type_cast(real_key, *args)[1] 621: elsif query 622: return get_attribute_as_query(real_key, *args) 623: else 624: return get_attribute(real_key, *args) 625: end 626: end 627: end 628: super 629: end
Add available attributes to the methods
# File lib/active_ldap/base.rb, line 632 632: def methods(inherited_too=true) 633: ensure_apply_object_class 634: target_names = @attribute_names.keys + @attribute_aliases.keys 635: target_names -= ['objectClass', Inflector.underscore('objectClass')] 636: super + target_names.uniq.collect do |x| 637: [x, "#{x}=", "#{x}?", "#{x}_before_type_cast"] 638: end.flatten 639: end
# File lib/active_ldap/base.rb, line 479 479: def must 480: ensure_apply_object_class 481: @must 482: end
# File lib/active_ldap/base.rb, line 821 821: def pretty_print(q) 822: abbreviate_instance_variables do 823: q.pp_object(self) 824: end 825: end
# File lib/active_ldap/base.rb, line 728 728: def reload 729: clear_association_cache 730: _, attributes = search(:value => id).find do |_dn, _attributes| 731: dn == _dn 732: end 733: if attributes.nil? 734: raise EntryNotFound, _("Can't find DN '%s' to reload") % dn 735: end 736: 737: @ldap_data.update(attributes) 738: classes, attributes = extract_object_class(attributes) 739: apply_object_class(classes) 740: self.attributes = attributes 741: @new_entry = false 742: self 743: end
# File lib/active_ldap/base.rb, line 642 642: def respond_to?(name, include_priv=false) 643: have_attribute?(name.to_s) or 644: (/(?:=|\?|_before_type_cast)$/ =~ name.to_s and 645: have_attribute?($PREMATCH)) or 646: super 647: end
Save and validate this object into LDAP either adding or replacing attributes TODO: Relative DN support
# File lib/active_ldap/base.rb, line 579 579: def save 580: create_or_update 581: end
# File lib/active_ldap/base.rb, line 583 583: def save! 584: unless create_or_update 585: raise EntryNotSaved, _("entry %s can't be saved") % dn 586: end 587: end
# File lib/active_ldap/base.rb, line 810 810: def scope=(scope) 811: self.class.validate_scope(scope) 812: @scope = scope 813: end
# File lib/active_ldap/base.rb, line 695 695: def to_ldif 696: super(dn, normalize_data(@data)) 697: end
# File lib/active_ldap/base.rb, line 699 699: def to_xml(options={}) 700: root = options[:root] || Inflector.underscore(self.class.name) 701: result = "<#{root}>\n" 702: result << " <dn>#{dn}</dn>\n" 703: normalize_data(@data).sort_by {|key, values| key}.each do |key, values| 704: targets = [] 705: values.each do |value| 706: if value.is_a?(Hash) 707: value.each do |option, real_value| 708: targets << [real_value, " #{option}=\"true\""] 709: end 710: else 711: targets << [value] 712: end 713: end 714: targets.sort_by {|value, attr| value}.each do |value, attr| 715: result << " <#{key}#{attr}>#{value}</#{key}>\n" 716: end 717: end 718: result << "</#{root}>\n" 719: result 720: end
Updates a given attribute and saves immediately
# File lib/active_ldap/base.rb, line 650 650: def update_attribute(name, value) 651: send("#{name}=", value) 652: save 653: end
This performs a bulk update of attributes and immediately calls save.
# File lib/active_ldap/base.rb, line 657 657: def update_attributes(attrs) 658: self.attributes = attrs 659: save 660: end
# File lib/active_ldap/base.rb, line 662 662: def update_attributes!(attrs) 663: self.attributes = attrs 664: save! 665: end
# File lib/active_ldap/base.rb, line 828 828: def abbreviate_instance_variables 829: @abbreviating ||= nil 830: connection, @connection = @connection, nil 831: schema, @schema = @schema, nil 832: attribute_schemata, @attribute_schemata = @attribute_schemata, nil 833: must, may = @must, @may 834: object_classes = @object_classes 835: unless @abbreviating 836: @abbreviating = true 837: @must, @may = @must.collect(&:name), @may.collect(&:name) 838: @object_classes = @object_classes.collect(&:name) 839: end 840: yield 841: ensure 842: @connection = connection 843: @schema = schema 844: @attribute_schemata = attribute_schemata 845: @must = must 846: @may = may 847: @object_classes = object_classes 848: @abbreviating = false 849: end
objectClass= special case for updating appropriately This updates the objectClass entry in @data. It also updating all required and allowed attributes while removing defined attributes that are no longer valid given the new objectclasses.
# File lib/active_ldap/base.rb, line 950 950: def apply_object_class(val) 951: new_oc = val 952: new_oc = [val] if new_oc.class != Array 953: new_oc = new_oc.uniq 954: return new_oc if @last_oc == new_oc 955: 956: # Store for caching purposes 957: @last_oc = new_oc.dup 958: 959: # Set the actual objectClass data 960: define_attribute_methods(schema.attribute('objectClass')) 961: replace_class(*new_oc) 962: 963: # Build |data| from schema 964: # clear attribute name mapping first 965: @attribute_schemata = {} 966: @attribute_names = {} 967: @normalized_attribute_names = {} 968: @attribute_aliases = {} 969: @must = [] 970: @may = [] 971: @object_classes = [] 972: new_oc.each do |objc| 973: # get all attributes for the class 974: object_class = schema.object_class(objc) 975: @object_classes << object_class 976: @must.concat(object_class.must) 977: @may.concat(object_class.may) 978: end 979: @must.uniq! 980: @may.uniq! 981: (@must + @may).each do |attr| 982: # Update attr_method with appropriate 983: define_attribute_methods(attr) 984: end 985: end
Returns the array form of a value, or not an array if false is passed in.
# File lib/active_ldap/base.rb, line 1127 1127: def array_of(value, to_a=true) 1128: case value 1129: when Array 1130: if to_a or value.size > 1 1131: value.collect {|v| array_of(v, to_a)} 1132: else 1133: if value.empty? 1134: nil 1135: else 1136: array_of(value.first, to_a) 1137: end 1138: end 1139: when Hash 1140: if to_a 1141: [value] 1142: else 1143: result = {} 1144: value.each {|k, v| result[k] = array_of(v, to_a)} 1145: result 1146: end 1147: else 1148: to_a ? [value.to_s] : value.to_s 1149: end 1150: end
# File lib/active_ldap/base.rb, line 1222 1222: def assert_dn_attribute 1223: unless dn_attribute 1224: raise ConfigurationError, 1225: _("dn_attribute isn't set for this class: %s") % self.class 1226: end 1227: end
# File lib/active_ldap/base.rb, line 1204 1204: def collect_all_attributes(data) 1205: dn_attr = to_real_attribute_name(dn_attribute) 1206: dn_value = data[dn_attr] 1207: 1208: attributes = [] 1209: attributes.push([:add, dn_attr, dn_value]) 1210: 1211: oc_value = data['objectClass'] 1212: attributes.push([:add, 'objectClass', oc_value]) 1213: data.each do |key, value| 1214: next if value.empty? or key == 'objectClass' or key == dn_attr 1215: 1216: attributes.push([:add, key, value]) 1217: end 1218: 1219: attributes 1220: end
# File lib/active_ldap/base.rb, line 1167 1167: def collect_modified_attributes(ldap_data, data) 1168: attributes = [] 1169: # Now that all the options will be treated as unique attributes 1170: # we can see what's changed and add anything that is brand-spankin' 1171: # new. 1172: ldap_data.each do |k, v| 1173: value = data[k] || [] 1174: 1175: next if v == value 1176: 1177: # Create mod entries 1178: if value.empty? 1179: # Since some types do not have equality matching rules, 1180: # delete doesn't work 1181: # Replacing with nothing is equivalent. 1182: if !data.has_key?(k) and schema.attribute(k).binary_required? 1183: value = [{'binary' => []}] 1184: end 1185: else 1186: # Ditched delete then replace because attribs with no equality 1187: # match rules will fails 1188: end 1189: attributes.push([:replace, k, value]) 1190: end 1191: data.each do |k, v| 1192: value = v || [] 1193: next if ldap_data.has_key?(k) or value.empty? 1194: 1195: # Detect subtypes and account for them 1196: # REPLACE will function like ADD, but doesn't hit EQUALITY problems 1197: # TODO: Added equality(attr) to Schema 1198: attributes.push([:replace, k, value]) 1199: end 1200: 1201: attributes 1202: end
# File lib/active_ldap/base.rb, line 1257 1257: def create 1258: prepare_data_for_saving do |data, ldap_data| 1259: attributes = collect_all_attributes(data) 1260: add_entry(dn, attributes) 1261: @new_entry = false 1262: true 1263: end 1264: end
# File lib/active_ldap/base.rb, line 1229 1229: def create_or_update 1230: new_entry? ? create : update 1231: end
Make a method entry for every alias of a valid attribute and map it onto the first attribute passed in.
# File lib/active_ldap/base.rb, line 1112 1112: def define_attribute_methods(attribute) 1113: real_name = attribute.name 1114: return if @attribute_schemata.has_key?(real_name) 1115: @attribute_schemata[real_name] = attribute 1116: ([real_name] + attribute.aliases).each do |name| 1117: @attribute_names[name] = real_name 1118: @attribute_aliases[Inflector.underscore(name)] = real_name 1119: @normalized_attribute_names[normalize_attribute_name(name)] = real_name 1120: end 1121: 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 921 921: def enforce_type(key, value) 922: ensure_apply_object_class 923: # Enforce attribute value formatting 924: normalize_attribute(key, value)[1] 925: end
# File lib/active_ldap/base.rb, line 910 910: def ensure_apply_object_class 911: current_object_class = @data['objectClass'] 912: return if current_object_class.nil? or current_object_class == @last_oc 913: apply_object_class(current_object_class) 914: end
# File lib/active_ldap/base.rb, line 851 851: def extract_object_class(attributes) 852: classes = [] 853: attrs = attributes.stringify_keys.reject do |key, value| 854: if key == 'objectClass' or 855: key.underscore == 'object_class' or 856: key.downcase == 'objectclass' 857: classes |= [value].flatten 858: true 859: else 860: false 861: end 862: end 863: [classes, attrs] 864: end
# File lib/active_ldap/base.rb, line 1033 1033: def false_value?(value) 1034: value.nil? or value == false or value == [] or 1035: value == "false" or value == "FALSE" or value == "" 1036: end
Return the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 990 990: def get_attribute(name, force_array=false) 991: name, value = get_attribute_before_type_cast(name, force_array) 992: attribute = schema.attribute(name) 993: type_cast(attribute, value) 994: end
# File lib/active_ldap/base.rb, line 1024 1024: def get_attribute_as_query(name, force_array=false) 1025: name, value = get_attribute_before_type_cast(name, force_array) 1026: if force_array 1027: value.collect {|x| !false_value?(x)} 1028: else 1029: !false_value?(value) 1030: end 1031: end
# File lib/active_ldap/base.rb, line 1013 1013: def get_attribute_before_type_cast(name, force_array=false) 1014: name = to_real_attribute_name(name) 1015: 1016: value = @data[name] || [] 1017: if force_array 1018: [name, value.dup] 1019: else 1020: [name, array_of(value.dup, false)] 1021: end 1022: end
# File lib/active_ldap/base.rb, line 927 927: def init_instance_variables 928: @mutex = Mutex.new 929: @data = {} # where the r/w entry data is stored 930: @ldap_data = {} # original ldap entry data 931: @attribute_schemata = {} 932: @attribute_names = {} # list of valid method calls for attributes used 933: # for dereferencing 934: @normalized_attribute_names = {} # list of normalized attribute name 935: @attribute_aliases = {} # aliases of @attribute_names 936: @last_oc = false # for use in other methods for "caching" 937: @dn_attribute = nil 938: @base = nil 939: @scope = nil 940: @connection ||= nil 941: end
# File lib/active_ldap/base.rb, line 870 870: def initialize_by_ldap_data(dn, attributes) 871: init_base 872: @new_entry = false 873: @dn_is_base = false 874: @ldap_data = attributes 875: classes, attributes = extract_object_class(attributes) 876: apply_object_class(classes) 877: self.dn = dn 878: self.attributes = attributes 879: yield self if block_given? 880: assert_dn_attribute 881: end
# File lib/active_ldap/base.rb, line 883 883: def instantiate(args) 884: dn, attributes, options = args 885: options ||= {} 886: 887: obj = self.class.allocate 888: obj.connection = options[:connection] || @connection 889: obj.instance_eval do 890: initialize_by_ldap_data(dn, attributes) 891: end 892: obj 893: end
# File lib/active_ldap/base.rb, line 1152 1152: def normalize_data(data, except=[]) 1153: _schema = schema 1154: result = {} 1155: data.each do |key, values| 1156: next if except.include?(key) 1157: real_name = to_real_attribute_name(key) 1158: next if real_name and except.include?(real_name) 1159: real_name ||= key 1160: next if _schema.attribute(real_name).id.nil? 1161: result[real_name] ||= [] 1162: result[real_name].concat(values) 1163: end 1164: result 1165: end
# File lib/active_ldap/base.rb, line 1233 1233: def prepare_data_for_saving 1234: # Expand subtypes to real ldap_data attributes 1235: # We can't reuse @ldap_data because an exception would leave 1236: # an object in an unknown state 1237: ldap_data = normalize_data(@ldap_data) 1238: 1239: # Expand subtypes to real data attributes, but leave @data alone 1240: bad_attrs = @data.keys - attribute_names 1241: data = normalize_data(@data, bad_attrs) 1242: 1243: success = yield(data, ldap_data) 1244: 1245: if success 1246: @ldap_data = Marshal.load(Marshal.dump(data)) 1247: # Delete items disallowed by objectclasses. 1248: # They should have been removed from ldap. 1249: bad_attrs.each do |remove_me| 1250: @ldap_data.delete(remove_me) 1251: end 1252: end 1253: 1254: success 1255: end
Set the value of the attribute called by method_missing?
# File lib/active_ldap/base.rb, line 1041 1041: def set_attribute(name, value) 1042: attr = to_real_attribute_name(name) 1043: attr, value = update_dn(attr, value) if attr == dn_attribute 1044: raise UnknownAttribute.new(name) if attr.nil? 1045: 1046: case value 1047: when nil, "" 1048: value = [] 1049: when Array 1050: value = value.collect {|c| c.blank? ? [] : c}.flatten 1051: when String 1052: value = [value] 1053: when Numeric 1054: value = [value.to_s] 1055: end 1056: 1057: @data[attr] = enforce_type(attr, value) 1058: end
# File lib/active_ldap/base.rb, line 1083 1083: def split_dn_value(value) 1084: dn_value = relative_dn_value = nil 1085: begin 1086: dn_value = DN.parse(value) 1087: rescue DistinguishedNameInvalid 1088: dn_value = DN.parse("#{dn_attribute}=#{value}") 1089: end 1090: 1091: begin 1092: relative_dn_value = dn_value - DN.parse(base_of_class) 1093: if relative_dn_value.rdns.empty? 1094: val = [] 1095: bases = dn_value.rdns 1096: else 1097: val, *bases = relative_dn_value.rdns 1098: end 1099: rescue ArgumentError 1100: val, *bases = dn_value.rdns 1101: end 1102: 1103: dn_attribute_name, dn_attribute_value = val.to_a[0] 1104: [dn_attribute_name, dn_attribute_value, 1105: bases.empty? ? nil : DN.new(*bases).to_s] 1106: end
# File lib/active_ldap/base.rb, line 895 895: def to_real_attribute_name(name, allow_normalized_name=false) 896: return name if name.nil? 897: ensure_apply_object_class 898: name = name.to_s 899: real_name = @attribute_names[name] 900: real_name ||= @attribute_aliases[Inflector.underscore(name)] 901: if real_name 902: real_name 903: elsif allow_normalized_name 904: @normalized_attribute_names[normalize_attribute_name(name)] 905: else 906: nil 907: end 908: end
# File lib/active_ldap/base.rb, line 996 996: def type_cast(attribute, value) 997: case value 998: when Hash 999: result = {} 1000: value.each do |option, val| 1001: result[option] = type_cast(attribute, val) 1002: end 1003: result 1004: when Array 1005: value.collect do |val| 1006: type_cast(attribute, val) 1007: end 1008: else 1009: attribute.type_cast(value) 1010: end 1011: end
# File lib/active_ldap/base.rb, line 1266 1266: def update 1267: prepare_data_for_saving do |data, ldap_data| 1268: attributes = collect_modified_attributes(ldap_data, data) 1269: modify_entry(dn, attributes) 1270: true 1271: end 1272: end
# File lib/active_ldap/base.rb, line 1060 1060: def update_dn(attr, value) 1061: @dn_is_base = false 1062: return [attr, value] if value.blank? 1063: 1064: new_dn_attribute, new_value, base = split_dn_value(value) 1065: if new_dn_attribute.nil? and new_value.nil? 1066: @dn_is_base = true 1067: @base = nil 1068: attr, value = DN.parse(base).rdns[0].to_a[0] 1069: @dn_attribute = attr 1070: else 1071: new_dn_attribute = to_real_attribute_name(new_dn_attribute) 1072: if new_dn_attribute 1073: value = new_value 1074: @base = base 1075: if dn_attribute != new_dn_attribute 1076: @dn_attribute = attr = new_dn_attribute 1077: end 1078: end 1079: end 1080: [attr, value] 1081: end