app/helpers/zuora_connect/LDAP/connection.rb



# Copied from devise lib and deleted not useful functionality

module ZuoraConnect
  module LDAP
    class Connection
      attr_reader :ldap, :login

      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 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 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

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

      def authenticated?
        authenticate!
      end

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

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

      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 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
    end
  end
end