Packages

LDAP / LDAPS directory monitor, with its dashboard panel bundled in the same package as a separate module (Integrations.Ldap.Display, #299) — one install, both halves; a release without raven_web simply runs the monitor headless.

Current section

Files

Jump to
raven_integration_ldap lib integrations ldap display.ex
Raw

lib/integrations/ldap/display.ex

defmodule Integrations.Ldap.Display do
@moduledoc """
Dashboard panel for `Integrations.Ldap` (same package).
Nested under the monitor's own namespace deliberately — the package's
top-level module name never changes, and this module's name is
guaranteed distinct from any separately-published standalone display
package. `Display.BundledDefault` auto-hooks this whenever
`Integrations.Ldap` starts, the same as if they were still one module.
"""
use CodeNameRaven.Display, category: :infrastructure, size_hint: :medium
@impl true
def display_name, do: "LDAP"
@impl true
def compatible_monitors, do: [Integrations.Ldap]
@impl true
def render(assigns) do
result = assigns[:result]
assigns = Map.merge(assigns, %{result: result})
~H"""
<div class="space-y-3">
<div class="flex items-start justify-between gap-2">
<div class="min-w-0">
<h2 class="text-sm font-semibold text-base-content truncate">
<%= @config.name || ldap_title(@config.params) %>
</h2>
<p class="text-xs font-mono text-base-content/40 truncate">
<%= ldap_title(@config.params) %>
</p>
</div>
<CodeNameRaven.MonitorComponents.status_chip status={@status} />
</div>
<div :if={@result} class="flex gap-2 flex-wrap">
<CodeNameRaven.MonitorComponents.stat
label="Latency"
value={"#{@result.latency_ms} ms"} />
<CodeNameRaven.MonitorComponents.stat
:if={@result.bind_attempted}
label="Bind"
value={if @result.bind_ok, do: "OK", else: "Failed"} />
<CodeNameRaven.MonitorComponents.stat
:if={@result.search_attempted}
label="Results"
value={"#{@result.result_count}"} />
</div>
<CodeNameRaven.MonitorComponents.error_message message={@last_error} />
<CodeNameRaven.MonitorComponents.check_time checked_at={@last_checked_at} />
</div>
"""
end
# ---------------------------------------------------------------------------
# Shared helpers — duplicated verbatim from Monitor (same package):
# ldap_title/1 needs effective_port/1, which pulls in ssl?/1, truthy?/1,
# truthy?/2, get_param/2, and parse_int/2 with it. See #299.
# ---------------------------------------------------------------------------
defp ldap_title(params) do
host = params[:host] || params["host"] || "?"
port = effective_port(params)
"#{host}:#{port}"
end
defp effective_port(params) do
case get_param(params, :port) do
nil -> if ssl?(params), do: 636, else: 389
p -> parse_int(p, 389)
end
end
defp ssl?(params), do: truthy?(get_param(params, :ssl))
defp truthy?("true"), do: true
defp truthy?(true), do: true
defp truthy?(_), do: false
defp get_param(params, key) when is_atom(key) do
v = case Map.fetch(params, key) do
{:ok, val} -> val
:error -> params[to_string(key)]
end
if is_binary(v) and String.trim(v) == "", do: nil, else: v
end
defp parse_int(v, _) when is_integer(v), do: v
defp parse_int(v, default) when is_binary(v) do
case Integer.parse(v) do
{n, _} -> n
:error -> default
end
end
defp parse_int(_, default), do: default
end