class Socialcast::CommandLine::LDAPConnector

Constants

CONTACT_ATTRIBUTES
EMAIL_ATTRIBUTE
MANAGER_ATTRIBUTE
PRIMARY_ATTRIBUTES
PROFILE_PHOTO_ATTRIBUTE
UNIQUE_IDENTIFIER_ATTRIBUTE

Attributes

attribute_mappings[R]
connection_name[R]

Public Class Methods

attribute_mappings_for(connection_name, config) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 19
def self.attribute_mappings_for(connection_name, config)
  config['connections'][connection_name]['mappings'] || config.fetch('mappings', {})
end
new(connection_name, config) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 23
def initialize(connection_name, config)
  @connection_name = connection_name
  @config = config
end

Public Instance Methods

each_photo_hash() { |photo_hash| ... } click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 39
def each_photo_hash
  ldap.open do
    each_ldap_entry(ldap_photo_search_attributes) do |entry|
      photo_hash = build_photo_hash_from_mappings(entry)
      yield photo_hash if photo_hash.present?
    end
  end
end
each_user_hash() { |build_user_hash_from_mappings(entry)| ... } click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 28
def each_user_hash
  ldap.open do
    fetch_group_unique_identifiers
    fetch_dn_to_email_hash

    each_ldap_entry(ldap_user_search_attributes) do |entry|
      yield build_user_hash_from_mappings(entry)
    end
  end
end
fetch_user_hash(identifier, options) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 48
def fetch_user_hash(identifier, options)
  ldap.open do
    fetch_group_unique_identifiers
    fetch_dn_to_email_hash

    options = options.dup
    identifying_field = options.delete(:identifying_field) || UNIQUE_IDENTIFIER_ATTRIBUTE

    filter = if connection_config['filter'].present?
               Net::LDAP::Filter.construct(connection_config['filter'])
             else
               Net::LDAP::Filter.pres("objectclass")
             end

    filter = filter & Net::LDAP::Filter.construct("#{attribute_mappings[identifying_field]}=#{identifier}")

    search(:base => connection_config['basedn'], :filter => filter, :attributes => ldap_user_search_attributes, :size => 1) do |entry|
      return build_user_hash_from_mappings(entry)
    end

    nil
  end
end

Private Instance Methods

add_account_type(entry, user_hash) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 268
def add_account_type(entry, user_hash)
  membership_attribute = permission_mappings.fetch 'attribute_name', 'memberof'
  memberships = entry[membership_attribute]
  external_ldap_groups = Array.wrap(permission_mappings.fetch('account_types', {})['external'])
  if external_ldap_groups.any? { |external_ldap_group| memberships.include?(external_ldap_group) }
    user_hash['account_type'] = 'external'
  else
    user_hash['account_type'] = 'member'
  end
end
add_contact_attributes(entry, user_hash) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 247
def add_contact_attributes(entry, user_hash)
  user_hash['contact_info'] = {}
  CONTACT_ATTRIBUTES.each do |attribute|
    next unless attribute_mappings.has_key?(attribute)
    user_hash['contact_info'][attribute] = grab(entry, attribute_mappings[attribute])
  end
end
add_custom_attributes(entry, user_hash) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 255
def add_custom_attributes(entry, user_hash)
  custom_attributes = attribute_mappings.keys - (PRIMARY_ATTRIBUTES + CONTACT_ATTRIBUTES + [PROFILE_PHOTO_ATTRIBUTE])

  user_hash['custom_fields'] = []
  custom_attributes.each do |attribute|
    if attribute == MANAGER_ATTRIBUTE
      user_hash['custom_fields'] << { 'id' => 'manager_email', 'label' => 'manager_email', 'value' => dereference_mail(entry, attribute_mappings[attribute]) }
    else
      user_hash['custom_fields'] << { 'id' => attribute, 'label' => attribute, 'value' => grab(entry, attribute_mappings[attribute]) }
    end
  end
end
add_groups(entry, user_hash) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 290
def add_groups(entry, user_hash)
  return unless group_membership_mappings.present?

  membership_attribute = permission_mappings.fetch 'attribute_name', 'memberof'
  memberships = entry[membership_attribute]

  mapped_group_dns = (@group_unique_identifiers.keys & memberships)

  user_hash['groups'] = mapped_group_dns.each_with_object([]) do |ldap_group_dn, socialcast_groups|
    socialcast_groups << @group_unique_identifiers[ldap_group_dn]
  end
end
add_primary_attributes(entry, user_hash) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 240
def add_primary_attributes(entry, user_hash)
  PRIMARY_ATTRIBUTES.each do |attribute|
    next unless attribute_mappings.has_key?(attribute)
    user_hash[attribute] = grab(entry, attribute_mappings[attribute])
  end
end
add_roles(entry, user_hash) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 279
def add_roles(entry, user_hash)
  return unless permission_roles_mappings = permission_mappings['roles']
  membership_attribute = permission_mappings.fetch 'attribute_name', 'memberof'
  memberships = entry[membership_attribute]

  user_hash['roles'] = []
  permission_roles_mappings.each_pair do |socialcast_role, ldap_groups|
    user_hash['roles'] << socialcast_role if Array.wrap(ldap_groups).any? { |ldap_group| memberships.include?(ldap_group) }
  end
end
build_photo_hash_from_mappings(entry) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 316
def build_photo_hash_from_mappings(entry)
  photo_hash = HashWithIndifferentAccess.new
  photo_hash[EMAIL_ATTRIBUTE] = grab(entry, attribute_mappings[EMAIL_ATTRIBUTE])
  photo_hash[PROFILE_PHOTO_ATTRIBUTE] = grab(entry, attribute_mappings[PROFILE_PHOTO_ATTRIBUTE])

  return photo_hash if photo_hash[EMAIL_ATTRIBUTE].present? && photo_hash[PROFILE_PHOTO_ATTRIBUTE] && !photo_hash[PROFILE_PHOTO_ATTRIBUTE].empty?
end
build_user_hash_from_mappings(entry) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 303
def build_user_hash_from_mappings(entry)
  user_hash = HashWithIndifferentAccess.new

  add_primary_attributes(entry, user_hash)
  add_contact_attributes(entry, user_hash)
  add_custom_attributes(entry, user_hash)
  add_account_type(entry, user_hash)
  add_roles(entry, user_hash) if user_hash['account_type'] == 'member'
  add_groups(entry, user_hash)

  user_hash
end
connection_config() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 122
def connection_config
  @config["connections"][connection_name]
end
dereference_mail(entry, dn_field) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 203
def dereference_mail(entry, dn_field)
  dn = grab(entry, dn_field)

  @dn_to_email_hash[dn]
end
each_ldap_entry(attributes) { |entry| ... } click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 114
def each_ldap_entry(attributes)
  search(:return_result => false, :filter => connection_config["filter"], :base => connection_config["basedn"], :attributes => attributes) do |entry|
    if grab(entry, attribute_mappings[EMAIL_ATTRIBUTE]).present? || (attribute_mappings.has_key?(UNIQUE_IDENTIFIER_ATTRIBUTE) && grab(entry, attribute_mappings[UNIQUE_IDENTIFIER_ATTRIBUTE]).present?)
      yield entry
    end
  end
end
fetch_dn_to_email_hash() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 228
def fetch_dn_to_email_hash
  @dn_to_email_hash ||= if attribute_mappings[MANAGER_ATTRIBUTE].present?
                          {}.tap do |dn_to_email_hash|
                            each_ldap_entry(ldap_mail_search_attributes) do |entry|
                              dn_to_email_hash[entry.dn] = grab(entry, attribute_mappings[EMAIL_ATTRIBUTE])
                            end
                          end
                        else
                          {}
                        end
end
fetch_group_unique_identifiers() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 209
def fetch_group_unique_identifiers
  @group_unique_identifiers ||= if group_membership_mappings.present?
                                  {}.tap do |groups|
                                    search_options = {
                                      :return_result => false,
                                      :filter => group_membership_mappings["filter"],
                                      :base => connection_config["basedn"],
                                      :attributes => [group_membership_mappings[UNIQUE_IDENTIFIER_ATTRIBUTE]]
                                    }

                                    search(search_options) do |entry|
                                      groups[grab(entry, "dn")] = grab(entry, group_membership_mappings[UNIQUE_IDENTIFIER_ATTRIBUTE])
                                    end
                                  end
                                else
                                  {}
                                end
end
grab(entry, attribute) click to toggle source

grab a single value of an attribute abstracts away ldap multivalue attributes

# File lib/socialcast/command_line/ldap_connector.rb, line 80
def grab(entry, attribute)
  const_attribute = begin
    attribute.camelize.constantize
  rescue NameError
    attribute
  end

  case const_attribute
  when Hash
    dup_attribute = const_attribute.dup
    value = dup_attribute.delete("value")
    sprintf value, Hash[dup_attribute.map { |k, v| [k, grab(entry, v)] }].symbolize_keys
  when String
    normalize_ldap_value(entry, attribute)
  when Class, Module
    if const_attribute.respond_to?(:run)
      const_attribute.run(entry)
    else
      normalize_ldap_value(entry, attribute)
    end
  end
end
group_membership_mappings() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 199
def group_membership_mappings
  permission_mappings['group_memberships']
end
ldap() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 103
def ldap
  @ldap ||= Net::LDAP.new(:host => connection_config["host"], :port => connection_config["port"], :base => connection_config["basedn"]).tap do |ldap_instance|
    ldap_instance.encryption connection_config['encryption'].to_sym if connection_config['encryption']
    ldap_instance.auth connection_config["username"], connection_config["password"]
  end
end
ldap_mail_search_attributes() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 126
def ldap_mail_search_attributes
  search_attributes [attribute_mappings[LDAPConnector::EMAIL_ATTRIBUTE]]
end
ldap_photo_search_attributes() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 139
def ldap_photo_search_attributes
  search_attributes [attribute_mappings[LDAPConnector::EMAIL_ATTRIBUTE], attribute_mappings[LDAPConnector::PROFILE_PHOTO_ATTRIBUTE]]
end
ldap_user_search_attributes() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 130
def ldap_user_search_attributes
  mappings = attribute_mappings.map do |mapping_key, mapping_value|
    mapping_value unless mapping_key == PROFILE_PHOTO_ATTRIBUTE
  end.compact
  attributes = search_attributes(mappings)
  attributes << permission_mappings.fetch('attribute_name', 'memberof')
  attributes.flatten
end
normalize_ldap_value(entry, attribute) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 190
def normalize_ldap_value(entry, attribute)
  Array.wrap(entry[attribute]).compact.first
end
permission_mappings() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 194
def permission_mappings
  @permission_mappings ||= connection_config['permission_mappings']
  @permission_mappings ||= @config.fetch 'permission_mappings', {}
end
root_namingcontexts() click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 110
def root_namingcontexts
  @root_naming_contexts ||= Array.wrap(@ldap.search_root_dse.namingcontexts)
end
search_attributes(mappings) click to toggle source
# File lib/socialcast/command_line/ldap_connector.rb, line 143
def search_attributes(mappings)
  mappings.map do |mapping_value|
    value = begin
      mapping_value.camelize.constantize
    rescue NameError
      mapping_value
    end

    case value
    when Hash
      dup_mapping_value = value.dup
      dup_mapping_value.delete("value")
      dup_mapping_value.values
    when String
      value
    when Class, Module
      if value.respond_to?(:attributes)
        value.attributes
      else
        mapping_value
      end
    end
  end
end