aboutsummaryrefslogtreecommitdiff
path: root/lib/recaptcha.ex
blob: c9abf38d57b57b31d78a6128dbbc12dd1a60ebb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
defmodule Recaptcha do
  require Elixir.EEx

  @secret_key_errors ~w(missing-input-secret invalid-input-secret)

  EEx.function_from_file :defp, :render_template, "lib/template.html.eex", [:assigns]

  def display(options \\ []) do
    public_key = options[:public_key] || config.public_key
    render_template(public_key: public_key, options: options)
  end

  def verify(remote_ip, response, options \\ [])

  def verify(remote_ip, response, options) when is_tuple(remote_ip) do
    verify(:inet_parse.ntoa(remote_ip), response, options)
  end

  def verify(remote_ip, response, options) do
    case api_response(remote_ip, response, options)  do
      %{"success" => true} ->
        :ok
      %{"success" => false, "error-codes" => error_codes} ->
        handle_error_codes(error_codes)
      %{"success" => false} ->
        :error
    end
  end

  defp api_response(remote_ip, response, options) do
    private_key = options[:private_key] || config.private_key
    timeout = options[:timeout] || 3000
    body_content = URI.encode_query(%{"remoteip"  => to_string(remote_ip),
                                      "response"  => response,
                                      "secret" => private_key})
    headers = ["Content-type": "application/x-www-form-urlencoded"]
    options = [body: body_content, headers: headers, timeout: timeout]
    HTTPotion.post(config.verify_url, options).body |> Poison.decode!
  end

  defp config do
    Application.get_env(:recaptcha, :api_config)
  end

  defp handle_error_codes(error_codes) do
    if Enum.any?(error_codes, fn(code) -> Enum.member?(@secret_key_errors, code) end) do
      raise RuntimeError,
        message: "reCaptcha API has declined the private key. Please make sure you've set the correct private key"
    else
      :error
    end
  end

end