aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/captcha/captcha.ex
blob: 5630f6b571d2e709d3acee4a0c90c6ac47b94e2c (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
55
56
57
58
59
60
61
62
63
64
65
66
defmodule Pleroma.Captcha do
  use GenServer

  @ets_options [:ordered_set, :private, :named_table, {:read_concurrency, true}]

  @doc false
  def start_link() do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  @doc false
  def init(_) do
    # Create a ETS table to store captchas
    ets_name = Module.concat(method(), Ets)
    ^ets_name = :ets.new(Module.concat(method(), Ets), @ets_options)

    # Clean up old captchas every few minutes
    seconds_retained = Pleroma.Config.get!([__MODULE__, :seconds_retained])
    Process.send_after(self(), :cleanup, 1000 * seconds_retained)

    {:ok, nil}
  end

  @doc """
  Ask the configured captcha service for a new captcha
  """
  def new() do
    GenServer.call(__MODULE__, :new)
  end

  @doc """
  Ask the configured captcha service to validate the captcha
  """
  def validate(token, captcha) do
    GenServer.call(__MODULE__, {:validate, token, captcha})
  end

  @doc false
  def handle_call(:new, _from, state) do
    enabled = Pleroma.Config.get([__MODULE__, :enabled])

    if !enabled do
      {:reply, %{type: :none}, state}
    else
      {:reply, method().new(), state}
    end
  end

  @doc false
  def handle_call({:validate, token, captcha}, _from, state) do
    {:reply, method().validate(token, captcha), state}
  end

  @doc false
  def handle_info(:cleanup, state) do
    :ok = method().cleanup()

    seconds_retained = Pleroma.Config.get!([__MODULE__, :seconds_retained])
    # Schedule the next clenup
    Process.send_after(self(), :cleanup, 1000 * seconds_retained)

    {:noreply, state}
  end

  defp method, do: Pleroma.Config.get!([__MODULE__, :method])
end