philomena/lib/philomena_web/plugs/check_captcha_plug.ex
2020-09-12 13:43:16 -04:00

71 lines
1.7 KiB
Elixir

defmodule PhilomenaWeb.CheckCaptchaPlug do
import Plug.Conn
import Phoenix.Controller
def init([]), do: false
def call(conn, _opts) do
case captcha_enabled?() do
true -> maybe_check_captcha(conn, conn.assigns.current_user)
false -> conn
end
end
defp maybe_check_captcha(conn, nil) do
case valid_solution?(conn.params) do
true ->
conn
false ->
conn
|> put_flash(
:error,
"There was an error verifying you're not a robot. Please try again."
)
|> do_failure_response(ajax?(conn))
|> halt()
end
end
defp maybe_check_captcha(conn, _user), do: conn
defp valid_solution?(%{"h-captcha-response" => captcha_token}) do
{:ok, %{body: body, status: 200}} =
Philomena.Http.post(
"https://hcaptcha.com/siteverify",
URI.encode_query(%{"response" => captcha_token, "secret" => hcaptcha_secret_key()}),
[{"Content-Type", "application/x-www-form-urlencoded"}]
)
body
|> Jason.decode!()
|> Map.get("success", false)
end
defp valid_solution?(_params), do: false
defp do_failure_response(conn, true) do
conn
|> put_status(:multiple_choices)
|> text("")
end
defp do_failure_response(conn, _false) do
redirect(conn, external: conn.assigns.referrer)
end
def ajax?(conn) do
case get_req_header(conn, "x-requested-with") do
[value] -> String.downcase(value) == "xmlhttprequest"
_ -> false
end
end
def captcha_enabled? do
Application.get_env(:philomena, :captcha) != false
end
def hcaptcha_secret_key do
Application.get_env(:philomena, :hcaptcha_secret_key)
end
end