diff options
Diffstat (limited to 'lib/pleroma/captcha')
| -rw-r--r-- | lib/pleroma/captcha/kocaptcha.ex | 38 | ||||
| -rw-r--r-- | lib/pleroma/captcha/native.ex | 35 | ||||
| -rw-r--r-- | lib/pleroma/captcha/service.ex | 37 |
3 files changed, 110 insertions, 0 deletions
diff --git a/lib/pleroma/captcha/kocaptcha.ex b/lib/pleroma/captcha/kocaptcha.ex new file mode 100644 index 0000000..e786e28 --- /dev/null +++ b/lib/pleroma/captcha/kocaptcha.ex @@ -0,0 +1,38 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Captcha.Kocaptcha do + alias Pleroma.Captcha.Service + @behaviour Service + + @impl Service + def new do + endpoint = Pleroma.Config.get!([__MODULE__, :endpoint]) + + case Pleroma.HTTP.get(endpoint <> "/new") do + {:error, _} -> + %{error: :kocaptcha_service_unavailable} + + {:ok, res} -> + json_resp = Jason.decode!(res.body) + + %{ + type: :kocaptcha, + token: json_resp["token"], + url: endpoint <> json_resp["url"], + answer_data: json_resp["md5"], + seconds_valid: Pleroma.Config.get([Pleroma.Captcha, :seconds_valid]) + } + end + end + + @impl Service + def validate(_token, captcha, answer_data) do + # Here the token is unsed, because the unencrypted captcha answer is just passed to method + if not is_nil(captcha) and + :crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data), + do: :ok, + else: {:error, :invalid} + end +end diff --git a/lib/pleroma/captcha/native.ex b/lib/pleroma/captcha/native.ex new file mode 100644 index 0000000..9ba0f30 --- /dev/null +++ b/lib/pleroma/captcha/native.ex @@ -0,0 +1,35 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Captcha.Native do + alias Pleroma.Captcha.Service + @behaviour Service + + @impl Service + def new do + case Captcha.get() do + :error -> + %{error: :captcha_error} + + {:ok, answer_data, img_binary} -> + %{ + type: :native, + token: token(), + url: "data:image/png;base64," <> Base.encode64(img_binary), + answer_data: answer_data, + seconds_valid: Pleroma.Config.get([Pleroma.Captcha, :seconds_valid]) + } + end + end + + @impl Service + def validate(_token, captcha, captcha) when not is_nil(captcha), do: :ok + def validate(_token, _captcha, _answer), do: {:error, :invalid} + + defp token do + 10 + |> :crypto.strong_rand_bytes() + |> Base.url_encode64(padding: false) + end +end diff --git a/lib/pleroma/captcha/service.ex b/lib/pleroma/captcha/service.ex new file mode 100644 index 0000000..7479760 --- /dev/null +++ b/lib/pleroma/captcha/service.ex @@ -0,0 +1,37 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Captcha.Service do + @doc """ + Request new captcha from a captcha service. + + Returns: + + Type/Name of the service, the token to identify the captcha, + the data of the answer and service-specific data to use the newly created captcha + """ + @callback new() :: %{ + type: atom(), + token: String.t(), + answer_data: any() + } + + @doc """ + Validated the provided captcha solution. + + Arguments: + * `token` the captcha is associated with + * `captcha` solution of the captcha to validate + * `answer_data` is the data needed to validate the answer (presumably encrypted) + + Returns: + + `true` if captcha is valid, `false` if not + """ + @callback validate( + token :: String.t(), + captcha :: String.t(), + answer_data :: any() + ) :: :ok | {:error, String.t()} +end |
