class ZuoraConnect::LDAP::Connection

def authenticate!

def authenticate!
  return false unless @password.present? || @allow_unauthenticated_bind
  @ldap.auth(dn, @password)
  @ldap.bind
end

def authenticated?

def authenticated?
  authenticate!
end

def authorized?

def authorized?
  ZuoraConnect::logger.debug("Authorizing user #{dn}")
  if !authenticated?
    if last_message_bad_credentials?
      ZuoraConnect::logger.debug('Not authorized because of invalid credentials.')
    elsif last_message_expired_credentials?
      ZuoraConnect::logger.debug('Not authorized because of expired credentials.')
    else
      ZuoraConnect::logger.debug('Not authorized because not authenticated.')
    end
    false
  elsif !in_required_groups?
    ZuoraConnect::logger.debug('Not authorized because not in required groups.')
    false
  else
    true
  end
end

def dn

def dn
  @dn ||= begin
            ZuoraConnect::logger.debug("LDAP dn lookup: #{@attribute}=#{@login}")
            ldap_entry = search_for_login
            if ldap_entry.nil?
              @ldap_auth_username_builder.call(@attribute,@login,@ldap)
            else
              ldap_entry.dn
            end
          end
end

def in_required_groups?

def in_required_groups?
  return true unless @check_group_membership || @check_group_membership_without_admin
  return false if @required_groups.nil?
  @required_groups.each do |group|
    if group.is_a?(Array)
      return false unless in_group?(group[1], group[0])
    else
      return false unless in_group?(group)
    end
  end
  true
end

def initialize(params = {})

def initialize(params = {})
  ldap_config = YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env]
  ldap_options = params
  # Allow `ssl: true` shorthand in YAML, but enable more control with `encryption`
  ldap_config['ssl'] = :simple_tls if ldap_config['ssl'] === true
  ldap_options[:encryption] = ldap_config['ssl'].to_sym if ldap_config['ssl']
  ldap_options[:encryption] = ldap_config['encryption'] if ldap_config['encryption']
  @ldap = Net::LDAP.new(ldap_options)
  @ldap.host = ldap_config['host']
  @ldap.port = ldap_config['port']
  @ldap.base = ldap_config['base']
  @attribute = ldap_config['attribute']
  @allow_unauthenticated_bind = ldap_config['allow_unauthenticated_bind']
  @ldap_auth_username_builder = params[:ldap_auth_username_builder]
  @group_base = ldap_config['group_base']
  @check_group_membership = ldap_config.key?('check_group_membership') ? ldap_config['check_group_membership'] : false
  @check_group_membership_without_admin = ldap_config.key?('check_group_membership_without_admin') ? ldap_config['check_group_membership_without_admin'] : false
  @required_groups = ldap_config['required_groups']
  @group_membership_attribute = ldap_config.key?('group_membership_attribute') ? ldap_config['group_membership_attribute'] : 'uniqueMember'
  @required_attributes = ldap_config['require_attribute']
  @required_attributes_presence = ldap_config['require_attribute_presence']
  @ldap.auth ldap_config['admin_user'], ldap_config['admin_password'] if params[:admin]
  @login = params[:login]
  @password = params[:password]
  @new_password = params[:new_password]
end

def last_message_bad_credentials?

def last_message_bad_credentials?
  @ldap.get_operation_result.error_message.to_s.include? 'AcceptSecurityContext error, data 52e'
end

def last_message_expired_credentials?

def last_message_expired_credentials?
  @ldap.get_operation_result.error_message.to_s.include? 'AcceptSecurityContext error, data 773'
end

def search_for_login

def search_for_login
  @login_ldap_entry ||= begin
                          ZuoraConnect::logger.debug("LDAP search for login: #{@attribute}=#{@login}")
                          filter = Net::LDAP::Filter.eq(@attribute.to_s, @login.to_s)
                          ldap_entry = nil
                          match_count = 0
                          @ldap.search(:filter => filter) {|entry| ldap_entry = entry; match_count+=1}
                          op_result= @ldap.get_operation_result
                          if op_result.code!=0
                            ZuoraConnect::logger.debug("LDAP Error #{op_result.code}: #{op_result.message}")
                          end
                          ZuoraConnect::logger.debug("LDAP search yielded #{match_count} matches")
                          ldap_entry
                        end
end