in dev, allow dev FE
[akkoma] / lib / pleroma / captcha / kocaptcha.ex
index f881c7b652a00303608763dd692e0d7d788de10f..eac6dfa365a4c0d8b536ea4f3c08f508611b0ab4 100644 (file)
@@ -1,73 +1,38 @@
-defmodule Pleroma.Captcha.Kocaptcha do
-  alias Plug.Crypto.KeyGenerator
-  alias Plug.Crypto.MessageEncryptor
-  alias Calendar.DateTime
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 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
+  def new do
     endpoint = Pleroma.Config.get!([__MODULE__, :endpoint])
 
-    case Tesla.get(endpoint <> "/new") do
+    case Pleroma.HTTP.get(endpoint <> "/new") do
       {:error, _} ->
-        %{error: "Kocaptcha service unavailable"}
+        %{error: :kocaptcha_service_unavailable}
 
       {:ok, res} ->
-        json_resp = Poison.decode!(res.body)
-
-        token = json_resp["token"]
-        answer_md5 = json_resp["md5"]
-
-        secret_key_base = Pleroma.Config.get!([Pleroma.Web.Endpoint, :secret_key_base])
-
-        # This make salt a little different for two keys
-        secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
-        sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
-        # Basicallty copy what Phoenix.Token does here, add the time to
-        # the actual data and make it a binary to then encrypt it
-        encrypted_captcha_answer =
-          %{
-            at: DateTime.now_utc(),
-            answer_md5: answer_md5
-          }
-          |> :erlang.term_to_binary()
-          |> MessageEncryptor.encrypt(secret, sign_secret)
+        json_resp = Jason.decode!(res.body)
 
         %{
           type: :kocaptcha,
-          token: token,
+          token: json_resp["token"],
           url: endpoint <> json_resp["url"],
-          answer_data: encrypted_captcha_answer
+          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
-    secret_key_base = Pleroma.Config.get!([Pleroma.Web.Endpoint, :secret_key_base])
-    secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
-    sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
-
-    # If the time found is less than (current_time - seconds_valid), then the time has already passed.
-    # Later we check that the time found is more than the presumed invalidatation time, that means
-    # that the data is still valid and the captcha can be checked
-    seconds_valid = Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid])
-    valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid)
-
-    with {:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret),
-         %{at: at, answer_md5: answer_md5} <- :erlang.binary_to_term(data) do
-      if DateTime.after?(at, valid_if_after) do
-        if not is_nil(captcha) and
-             :crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_md5),
-           do: :ok,
-           else: {:error, "Invalid CAPTCHA"}
-      else
-        {:error, "CAPTCHA expired"}
-      end
-    else
-      _ -> {:error, "Invalid answer data"}
-    end
+  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