Add tests for account registration with captcha enabled and improve errors
authorEgor Kislitsyn <egor@kislitsyn.com>
Wed, 29 Apr 2020 16:48:08 +0000 (20:48 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Wed, 29 Apr 2020 17:26:07 +0000 (21:26 +0400)
lib/pleroma/captcha/captcha.ex
lib/pleroma/captcha/kocaptcha.ex
lib/pleroma/captcha/native.ex
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
lib/pleroma/web/twitter_api/twitter_api.ex
test/captcha_test.exs
test/support/captcha_mock.ex
test/web/mastodon_api/controllers/account_controller_test.exs
test/web/twitter_api/twitter_api_test.exs

index cf75c3adc3bb0b41b5c74e82c461d6f312fb2875..e17dc2426e3253f555aea249cdcd90a20674dd1c 100644 (file)
@@ -3,8 +3,6 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Captcha do
-  import Pleroma.Web.Gettext
-
   alias Calendar.DateTime
   alias Plug.Crypto.KeyGenerator
   alias Plug.Crypto.MessageEncryptor
@@ -37,19 +35,14 @@ defmodule Pleroma.Captcha do
 
   @doc false
   def handle_call(:new, _from, state) do
-    enabled = Pleroma.Config.get([__MODULE__, :enabled])
-
-    if !enabled do
+    if not enabled?() do
       {:reply, %{type: :none}, state}
     else
       new_captcha = method().new()
 
-      secret_key_base = Pleroma.Config.get!([Pleroma.Web.Endpoint, :secret_key_base])
-
       # This make salt a little different for two keys
-      token = new_captcha[:token]
-      secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
-      sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
+      {secret, sign_secret} = secret_pair(new_captcha[:token])
+
       # Basically 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 =
@@ -71,44 +64,68 @@ defmodule Pleroma.Captcha do
 
   @doc false
   def handle_call({:validate, token, captcha, answer_data}, _from, state) do
+    {:reply, do_validate(token, captcha, answer_data), state}
+  end
+
+  def enabled?, do: Pleroma.Config.get([__MODULE__, :enabled], false)
+
+  defp seconds_valid, do: Pleroma.Config.get!([__MODULE__, :seconds_valid])
+
+  defp secret_pair(token) 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")
 
+    {secret, sign_secret}
+  end
+
+  defp do_validate(token, captcha, answer_data) do
+    with {:ok, %{at: at, answer_data: answer_md5}} <- validate_answer_data(token, answer_data),
+         :ok <- validate_expiration(at),
+         :ok <- validate_usage(token),
+         :ok <- method().validate(token, captcha, answer_md5),
+         {:ok, _} <- mark_captcha_as_used(token) do
+      :ok
+    end
+  end
+
+  defp validate_answer_data(token, answer_data) do
+    {secret, sign_secret} = secret_pair(token)
+
+    with false <- is_nil(answer_data),
+         {:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret),
+         %{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do
+      {:ok, %{at: at, answer_data: answer_md5}}
+    else
+      _ -> {:error, :invalid_answer_data}
+    end
+  end
+
+  defp validate_expiration(created_at) do
     # 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)
-
-    result =
-      with false <- is_nil(answer_data),
-           {:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret),
-           %{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do
-        try do
-          if DateTime.before?(at, valid_if_after),
-            do: throw({:error, dgettext("errors", "CAPTCHA expired")})
-
-          if not is_nil(Cachex.get!(:used_captcha_cache, token)),
-            do: throw({:error, dgettext("errors", "CAPTCHA already used")})
-
-          res = method().validate(token, captcha, answer_md5)
-          # Throw if an error occurs
-          if res != :ok, do: throw(res)
-
-          # Mark this captcha as used
-          {:ok, _} =
-            Cachex.put(:used_captcha_cache, token, true, ttl: :timer.seconds(seconds_valid))
-
-          :ok
-        catch
-          :throw, e -> e
-        end
-      else
-        _ -> {:error, dgettext("errors", "Invalid answer data")}
-      end
-
-    {:reply, result, state}
+
+    valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid())
+
+    if DateTime.before?(created_at, valid_if_after) do
+      {:error, :expired}
+    else
+      :ok
+    end
+  end
+
+  defp validate_usage(token) do
+    if is_nil(Cachex.get!(:used_captcha_cache, token)) do
+      :ok
+    else
+      {:error, :already_used}
+    end
+  end
+
+  defp mark_captcha_as_used(token) do
+    ttl = seconds_valid() |> :timer.seconds()
+    Cachex.put(:used_captcha_cache, token, true, ttl: ttl)
   end
 
   defp method, do: Pleroma.Config.get!([__MODULE__, :method])
index 06ceb20b6f49237f3a706a838b7744751db1162a..6bc2fa158a2045182b9641c2f04166e168eaded7 100644 (file)
@@ -3,7 +3,6 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Captcha.Kocaptcha do
-  import Pleroma.Web.Gettext
   alias Pleroma.Captcha.Service
   @behaviour Service
 
@@ -13,7 +12,7 @@ defmodule Pleroma.Captcha.Kocaptcha do
 
     case Tesla.get(endpoint <> "/new") do
       {:error, _} ->
-        %{error: dgettext("errors", "Kocaptcha service unavailable")}
+        %{error: :kocaptcha_service_unavailable}
 
       {:ok, res} ->
         json_resp = Jason.decode!(res.body)
@@ -33,6 +32,6 @@ defmodule Pleroma.Captcha.Kocaptcha do
     if not is_nil(captcha) and
          :crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data),
        do: :ok,
-       else: {:error, dgettext("errors", "Invalid CAPTCHA")}
+       else: {:error, :invalid}
   end
 end
index 06c479ca9606fe2530bb0ca986bfcf0ec8e85ab9..a90631d61be6e66b78cfbf4b30886aa788849427 100644 (file)
@@ -3,7 +3,6 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Captcha.Native do
-  import Pleroma.Web.Gettext
   alias Pleroma.Captcha.Service
   @behaviour Service
 
@@ -11,7 +10,7 @@ defmodule Pleroma.Captcha.Native do
   def new do
     case Captcha.get() do
       :error ->
-        %{error: dgettext("errors", "Captcha error")}
+        %{error: :captcha_error}
 
       {:ok, answer_data, img_binary} ->
         %{
@@ -25,7 +24,7 @@ defmodule Pleroma.Captcha.Native do
 
   @impl Service
   def validate(_token, captcha, captcha) when not is_nil(captcha), do: :ok
-  def validate(_token, _captcha, _answer), do: {:error, dgettext("errors", "Invalid CAPTCHA")}
+  def validate(_token, _captcha, _answer), do: {:error, :invalid}
 
   defp token do
     10
index 1eedf02d66a823d0cfc62ce60e2dc964b3252679..61b0e2f633c939599ca1d0ee56cb49e7eb523114 100644 (file)
@@ -94,24 +94,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
 
   @doc "POST /api/v1/accounts"
   def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
-    params =
-      params
-      |> Map.take([
-        :email,
-        :bio,
-        :captcha_solution,
-        :captcha_token,
-        :captcha_answer_data,
-        :token,
-        :password,
-        :fullname
-      ])
-      |> Map.put(:nickname, params.username)
-      |> Map.put(:fullname, Map.get(params, :fullname, params.username))
-      |> Map.put(:confirm, params.password)
-      |> Map.put(:trusted_app, app.trusted)
-
     with :ok <- validate_email_param(params),
+         :ok <- TwitterAPI.validate_captcha(app, params),
          {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
          {:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
       json(conn, %{
@@ -121,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
         created_at: Token.Utils.format_created_at(token)
       })
     else
-      {:error, errors} -> json_response(conn, :bad_request, errors)
+      {:error, error} -> json_response(conn, :bad_request, %{error: error})
     end
   end
 
@@ -133,11 +117,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
     render_error(conn, :forbidden, "Invalid credentials")
   end
 
-  defp validate_email_param(%{:email => email}) when not is_nil(email), do: :ok
+  defp validate_email_param(%{email: email}) when not is_nil(email), do: :ok
 
   defp validate_email_param(_) do
     case Pleroma.Config.get([:instance, :account_activation_required]) do
-      true -> {:error, %{"error" => "Missing parameters"}}
+      true -> {:error, dgettext("errors", "Missing parameter: %{name}", name: "email")}
       _ -> :ok
     end
   end
index a6ef9a310ccb8ee2ad9e05040c78aa29e9e2009d..5cfb385ac3068e84e36de42f7026abfeff5005a9 100644 (file)
@@ -3,54 +3,27 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
+  import Pleroma.Web.Gettext
+
   alias Pleroma.Emails.Mailer
   alias Pleroma.Emails.UserEmail
   alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.UserInviteToken
 
-  require Pleroma.Constants
-
   def register_user(params, opts \\ []) do
     params =
       params
-      |> Map.take([
-        :nickname,
-        :password,
-        :captcha_solution,
-        :captcha_token,
-        :captcha_answer_data,
-        :token,
-        :email,
-        :trusted_app
-      ])
-      |> Map.put(:bio, User.parse_bio(params[:bio] || ""))
-      |> Map.put(:name, params.fullname)
-      |> Map.put(:password_confirmation, params[:confirm])
-
-    case validate_captcha(params) do
-      :ok ->
-        if Pleroma.Config.get([:instance, :registrations_open]) do
-          create_user(params, opts)
-        else
-          create_user_with_invite(params, opts)
-        end
+      |> Map.take([:email, :token, :password])
+      |> Map.put(:bio, params |> Map.get(:bio, "") |> User.parse_bio())
+      |> Map.put(:nickname, params[:username])
+      |> Map.put(:name, Map.get(params, :fullname, params[:username]))
+      |> Map.put(:password_confirmation, params[:password])
 
-      {:error, error} ->
-        # I have no idea how this error handling works
-        {:error, %{error: Jason.encode!(%{captcha: [error]})}}
-    end
-  end
-
-  defp validate_captcha(params) do
-    if params[:trusted_app] || not Pleroma.Config.get([Pleroma.Captcha, :enabled]) do
-      :ok
+    if Pleroma.Config.get([:instance, :registrations_open]) do
+      create_user(params, opts)
     else
-      Pleroma.Captcha.validate(
-        params[:captcha_token],
-        params[:captcha_solution],
-        params[:captcha_answer_data]
-      )
+      create_user_with_invite(params, opts)
     end
   end
 
@@ -75,16 +48,17 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
 
       {:error, changeset} ->
         errors =
-          Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
+          changeset
+          |> Ecto.Changeset.traverse_errors(fn {msg, _opts} -> msg end)
           |> Jason.encode!()
 
-        {:error, %{error: errors}}
+        {:error, errors}
     end
   end
 
   def password_reset(nickname_or_email) do
     with true <- is_binary(nickname_or_email),
-         %User{local: true, email: email} = user when not is_nil(email) <-
+         %User{local: true, email: email} = user when is_binary(email) <-
            User.get_by_nickname_or_email(nickname_or_email),
          {:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do
       user
@@ -106,4 +80,58 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
         {:error, "unknown user"}
     end
   end
+
+  def validate_captcha(app, params) do
+    if app.trusted || not Pleroma.Captcha.enabled?() do
+      :ok
+    else
+      do_validate_captcha(params)
+    end
+  end
+
+  defp do_validate_captcha(params) do
+    with :ok <- validate_captcha_presence(params),
+         :ok <-
+           Pleroma.Captcha.validate(
+             params[:captcha_token],
+             params[:captcha_solution],
+             params[:captcha_answer_data]
+           ) do
+      :ok
+    else
+      {:error, :captcha_error} ->
+        captcha_error(dgettext("errors", "CAPTCHA Error"))
+
+      {:error, :invalid} ->
+        captcha_error(dgettext("errors", "Invalid CAPTCHA"))
+
+      {:error, :kocaptcha_service_unavailable} ->
+        captcha_error(dgettext("errors", "Kocaptcha service unavailable"))
+
+      {:error, :expired} ->
+        captcha_error(dgettext("errors", "CAPTCHA expired"))
+
+      {:error, :already_used} ->
+        captcha_error(dgettext("errors", "CAPTCHA already used"))
+
+      {:error, :invalid_answer_data} ->
+        captcha_error(dgettext("errors", "Invalid answer data"))
+
+      {:error, error} ->
+        captcha_error(error)
+    end
+  end
+
+  defp validate_captcha_presence(params) do
+    [:captcha_solution, :captcha_token, :captcha_answer_data]
+    |> Enum.find_value(:ok, fn key ->
+      unless is_binary(params[key]) do
+        error = dgettext("errors", "Invalid CAPTCHA (Missing parameter: %{name})", name: key)
+        {:error, error}
+      end
+    end)
+  end
+
+  # For some reason FE expects error message to be a serialized JSON
+  defp captcha_error(error), do: {:error, Jason.encode!(%{captcha: [error]})}
 end
index ac1d846e833f7d2f19e281b8e3cdd139afae318c..1ab9019ab756d4caee7d46463f31566d6c730901 100644 (file)
@@ -61,7 +61,7 @@ defmodule Pleroma.CaptchaTest do
 
       assert is_binary(answer)
       assert :ok = Native.validate(token, answer, answer)
-      assert {:error, "Invalid CAPTCHA"} == Native.validate(token, answer, answer <> "foobar")
+      assert {:error, :invalid} == Native.validate(token, answer, answer <> "foobar")
     end
   end
 
@@ -78,6 +78,7 @@ defmodule Pleroma.CaptchaTest do
 
       assert is_binary(answer)
       assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer)
+      Cachex.del(:used_captcha_cache, token)
     end
 
     test "doesn't validate invalid answer" do
@@ -92,7 +93,7 @@ defmodule Pleroma.CaptchaTest do
 
       assert is_binary(answer)
 
-      assert {:error, "Invalid answer data"} =
+      assert {:error, :invalid_answer_data} =
                Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer <> "foobar")
     end
 
@@ -108,7 +109,7 @@ defmodule Pleroma.CaptchaTest do
 
       assert is_binary(answer)
 
-      assert {:error, "Invalid answer data"} =
+      assert {:error, :invalid_answer_data} =
                Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", nil)
     end
   end
index 6dae94edf480e34aba6c3e73fd83ad715ce83da3..7b0c1d5af72c7e3957e124b40b7011901febf7c9 100644 (file)
@@ -6,12 +6,16 @@ defmodule Pleroma.Captcha.Mock do
   alias Pleroma.Captcha.Service
   @behaviour Service
 
+  @solution "63615261b77f5354fb8c4e4986477555"
+
+  def solution, do: @solution
+
   @impl Service
   def new,
     do: %{
       type: :mock,
       token: "afa1815e14e29355e6c8f6b143a39fa2",
-      answer_data: "63615261b77f5354fb8c4e4986477555",
+      answer_data: @solution,
       url: "https://example.org/captcha.png"
     }
 
index ba70ba66c95998c6965710c46de456ab1b15a210..b9da7e92489eddb14e8f34c47a3df70598805aad 100644 (file)
@@ -925,7 +925,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
         |> Map.put(:remote_ip, {127, 0, 0, 5})
         |> post("/api/v1/accounts", Map.delete(valid_params, :email))
 
-      assert json_response_and_validate_schema(res, 400) == %{"error" => "Missing parameters"}
+      assert json_response_and_validate_schema(res, 400) ==
+               %{"error" => "Missing parameter: email"}
 
       res =
         conn
@@ -1093,6 +1094,91 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
     end
   end
 
+  describe "create account with enabled captcha" do
+    setup %{conn: conn} do
+      app_token = insert(:oauth_token, user: nil)
+
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer " <> app_token.token)
+        |> put_req_header("content-type", "multipart/form-data")
+
+      [conn: conn]
+    end
+
+    setup do: clear_config([Pleroma.Captcha, :enabled], true)
+
+    test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
+      %{token: token, answer_data: answer_data} = Pleroma.Captcha.new()
+
+      params = %{
+        username: "lain",
+        email: "lain@example.org",
+        password: "PlzDontHackLain",
+        agreement: true,
+        captcha_solution: Pleroma.Captcha.Mock.solution(),
+        captcha_token: token,
+        captcha_answer_data: answer_data
+      }
+
+      assert %{
+               "access_token" => access_token,
+               "created_at" => _,
+               "scope" => ["read"],
+               "token_type" => "Bearer"
+             } =
+               conn
+               |> post("/api/v1/accounts", params)
+               |> json_response_and_validate_schema(:ok)
+
+      assert Token |> Repo.get_by(token: access_token) |> Repo.preload(:user) |> Map.get(:user)
+
+      Cachex.del(:used_captcha_cache, token)
+    end
+
+    test "returns 400 if any captcha field is not provided", %{conn: conn} do
+      captcha_fields = [:captcha_solution, :captcha_token, :captcha_answer_data]
+
+      valid_params = %{
+        username: "lain",
+        email: "lain@example.org",
+        password: "PlzDontHackLain",
+        agreement: true,
+        captcha_solution: "xx",
+        captcha_token: "xx",
+        captcha_answer_data: "xx"
+      }
+
+      for field <- captcha_fields do
+        expected = %{
+          "error" => "{\"captcha\":[\"Invalid CAPTCHA (Missing parameter: #{field})\"]}"
+        }
+
+        assert expected ==
+                 conn
+                 |> post("/api/v1/accounts", Map.delete(valid_params, field))
+                 |> json_response_and_validate_schema(:bad_request)
+      end
+    end
+
+    test "returns an error if captcha is invalid", %{conn: conn} do
+      params = %{
+        username: "lain",
+        email: "lain@example.org",
+        password: "PlzDontHackLain",
+        agreement: true,
+        captcha_solution: "cofe",
+        captcha_token: "cofe",
+        captcha_answer_data: "cofe"
+      }
+
+      assert %{"error" => "{\"captcha\":[\"Invalid answer data\"]}"} ==
+               conn
+               |> post("/api/v1/accounts", params)
+               |> json_response_and_validate_schema(:bad_request)
+    end
+  end
+
   describe "GET /api/v1/accounts/:id/lists - account_lists" do
     test "returns lists to which the account belongs" do
       %{user: user, conn: conn} = oauth_access(["read:lists"])
index 7926a075789ba6b64168e5e5252048bc4bdd40ec..368533292bdc8b4acfb6aeac8ebe8afc70813b19 100644 (file)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
 
   test "it registers a new user and returns the user." do
     data = %{
-      :nickname => "lain",
+      :username => "lain",
       :email => "lain@wired.jp",
       :fullname => "lain iwakura",
       :password => "bear",
@@ -35,7 +35,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
 
   test "it registers a new user with empty string in bio and returns the user." do
     data = %{
-      :nickname => "lain",
+      :username => "lain",
       :email => "lain@wired.jp",
       :fullname => "lain iwakura",
       :bio => "",
@@ -60,7 +60,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     end
 
     data = %{
-      :nickname => "lain",
+      :username => "lain",
       :email => "lain@wired.jp",
       :fullname => "lain iwakura",
       :bio => "",
@@ -87,7 +87,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
 
   test "it registers a new user and parses mentions in the bio" do
     data1 = %{
-      :nickname => "john",
+      :username => "john",
       :email => "john@gmail.com",
       :fullname => "John Doe",
       :bio => "test",
@@ -98,7 +98,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     {:ok, user1} = TwitterAPI.register_user(data1)
 
     data2 = %{
-      :nickname => "lain",
+      :username => "lain",
       :email => "lain@wired.jp",
       :fullname => "lain iwakura",
       :bio => "@john test",
@@ -123,7 +123,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
       {:ok, invite} = UserInviteToken.create_invite()
 
       data = %{
-        :nickname => "vinny",
+        :username => "vinny",
         :email => "pasta@pizza.vs",
         :fullname => "Vinny Vinesauce",
         :bio => "streamer",
@@ -145,7 +145,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
 
     test "returns error on invalid token" do
       data = %{
-        :nickname => "GrimReaper",
+        :username => "GrimReaper",
         :email => "death@reapers.afterlife",
         :fullname => "Reaper Grim",
         :bio => "Your time has come",
@@ -165,7 +165,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
       UserInviteToken.update_invite!(invite, used: true)
 
       data = %{
-        :nickname => "GrimReaper",
+        :username => "GrimReaper",
         :email => "death@reapers.afterlife",
         :fullname => "Reaper Grim",
         :bio => "Your time has come",
@@ -186,7 +186,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
 
     setup do
       data = %{
-        :nickname => "vinny",
+        :username => "vinny",
         :email => "pasta@pizza.vs",
         :fullname => "Vinny Vinesauce",
         :bio => "streamer",
@@ -250,7 +250,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
       UserInviteToken.update_invite!(invite, uses: 99)
 
       data = %{
-        :nickname => "vinny",
+        :username => "vinny",
         :email => "pasta@pizza.vs",
         :fullname => "Vinny Vinesauce",
         :bio => "streamer",
@@ -269,7 +269,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
                AccountView.render("show.json", %{user: fetched_user})
 
       data = %{
-        :nickname => "GrimReaper",
+        :username => "GrimReaper",
         :email => "death@reapers.afterlife",
         :fullname => "Reaper Grim",
         :bio => "Your time has come",
@@ -292,7 +292,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
       {:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
 
       data = %{
-        :nickname => "vinny",
+        :username => "vinny",
         :email => "pasta@pizza.vs",
         :fullname => "Vinny Vinesauce",
         :bio => "streamer",
@@ -317,7 +317,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
       UserInviteToken.update_invite!(invite, uses: 99)
 
       data = %{
-        :nickname => "vinny",
+        :username => "vinny",
         :email => "pasta@pizza.vs",
         :fullname => "Vinny Vinesauce",
         :bio => "streamer",
@@ -335,7 +335,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
                AccountView.render("show.json", %{user: fetched_user})
 
       data = %{
-        :nickname => "GrimReaper",
+        :username => "GrimReaper",
         :email => "death@reapers.afterlife",
         :fullname => "Reaper Grim",
         :bio => "Your time has come",
@@ -355,7 +355,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
         UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
 
       data = %{
-        :nickname => "GrimReaper",
+        :username => "GrimReaper",
         :email => "death@reapers.afterlife",
         :fullname => "Reaper Grim",
         :bio => "Your time has come",
@@ -377,7 +377,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
       UserInviteToken.update_invite!(invite, uses: 100)
 
       data = %{
-        :nickname => "GrimReaper",
+        :username => "GrimReaper",
         :email => "death@reapers.afterlife",
         :fullname => "Reaper Grim",
         :bio => "Your time has come",
@@ -395,16 +395,15 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
 
   test "it returns the error on registration problems" do
     data = %{
-      :nickname => "lain",
+      :username => "lain",
       :email => "lain@wired.jp",
       :fullname => "lain iwakura",
-      :bio => "close the world.",
-      :password => "bear"
+      :bio => "close the world."
     }
 
-    {:error, error_object} = TwitterAPI.register_user(data)
+    {:error, error} = TwitterAPI.register_user(data)
 
-    assert is_binary(error_object[:error])
+    assert is_binary(error)
     refute User.get_cached_by_nickname("lain")
   end