defmodule RecycledCloud.LDAP do require Logger require Exldap use GenServer # Every request to the LDAP backend go through this GenServer. def start_link(_) do GenServer.start_link(__MODULE__, :ok, name: __MODULE__) end def init(_) do {:ok, connect()} end def handle_call({:pool, query}, _from, state) do case state do %{status: :ok, conn: ldap_conn} -> result = internal_execute_query(query, ldap_conn) if (result == {:error, :ldap_closed}) do {:reply, result, connect()} else {:reply, result, state} end %{status: :error, conn: nil} -> state = connect() if (state.status == :ok) do result = internal_execute_query(query, state.conn) {:reply, result, state} else error = {:error, "Unable to contact backend"} {:reply, error, state} end end end def handle_call({:single, query}, _from, state) do single_state = connect() case single_state do %{status: :ok, conn: ldap_conn} -> result = internal_execute_query(query, ldap_conn) close(ldap_conn) {:reply, result, state} %{status: :error, conn: nil} -> error = {:error, "Unable to contact backend"} {:reply, error, state} end end def terminate(reason, state) do if (state.status == :ok), do: close(state.conn) IO.inspect(reason) #Logger.info "Terminating LDAP backend: #{reason}." end ### def execute(query), do: GenServer.call(__MODULE__, {:pool, query}) def execute_single(query), do: GenServer.call(__MODULE__, {:single, query}) ### defp internal_execute_query(query, ldap_conn), do: query.(ldap_conn) defp connect do case Exldap.connect do {:ok, ldap_conn} -> Logger.info "Successfuly connected to LDAP server." %{status: :ok, conn: ldap_conn} {:error, err} -> Logger.warning "Failed to connect to LDAP server: #{err}. Authentication will not be possible." %{status: :error, conn: nil} end end defp close(ldap_conn) do ldap_conn |> Exldap.close Logger.debug("An LDAP connection was closed.") end end