Allow account registration without an email
authorEgor Kislitsyn <egor@kislitsyn.com>
Wed, 26 Feb 2020 16:13:53 +0000 (20:13 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Wed, 26 Feb 2020 16:13:53 +0000 (20:13 +0400)
CHANGELOG.md
lib/pleroma/user.ex
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
test/user_test.exs
test/web/mastodon_api/controllers/account_controller_test.exs

index 08bb7e1c78aec560582b0a734d6ccff38c11908e..a924d4083c21443ed201d02716653026e9fb5aee 100644 (file)
@@ -35,6 +35,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Rate limiter is now disabled for localhost/socket (unless remoteip plug is enabled)
 - Logger: default log level changed from `warn` to `info`.
 - Config mix task `migrate_to_db` truncates `config` table before migrating the config file.
+- Allow account registration without an email
 <details>
   <summary>API Changes</summary>
 
index 56e599ecc9494050a8db2cabd1531f4fc4049e1d..5271d8dbeb975865b453f17283c821a29e2e5282 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.User do
@@ -530,7 +530,14 @@ defmodule Pleroma.User do
   end
 
   def maybe_validate_required_email(changeset, true), do: changeset
-  def maybe_validate_required_email(changeset, _), do: validate_required(changeset, [:email])
+
+  def maybe_validate_required_email(changeset, _) do
+    if Pleroma.Config.get([:instance, :account_activation_required]) do
+      validate_required(changeset, [:email])
+    else
+      changeset
+    end
+  end
 
   defp put_ap_id(changeset) do
     ap_id = ap_id(%User{nickname: get_field(changeset, :nickname)})
index 38d14256f53aeeb1bfbd8a5d996c5433e66a2fd0..88c997b9f75e2510262c6a945f3d9de514a7c10c 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.MastodonAPI.AccountController do
@@ -76,7 +76,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   @doc "POST /api/v1/accounts"
   def create(
         %{assigns: %{app: app}} = conn,
-        %{"username" => nickname, "email" => _, "password" => _, "agreement" => true} = params
+        %{"username" => nickname, "password" => _, "agreement" => true} = params
       ) do
     params =
       params
@@ -93,7 +93,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
       |> Map.put("bio", params["bio"] || "")
       |> Map.put("confirm", params["password"])
 
-    with {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
+    with :ok <- validate_email_param(params),
+         {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
          {:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
       json(conn, %{
         token_type: "Bearer",
@@ -114,6 +115,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
     render_error(conn, :forbidden, "Invalid credentials")
   end
 
+  defp validate_email_param(%{"email" => _}), do: :ok
+
+  defp validate_email_param(_) do
+    case Pleroma.Config.get([:instance, :account_activation_required]) do
+      true -> {:error, %{"error" => "Missing parameters"}}
+      _ -> :ok
+    end
+  end
+
   @doc "GET /api/v1/accounts/verify_credentials"
   def verify_credentials(%{assigns: %{user: user}} = conn, _) do
     chat_token = Phoenix.Token.sign(conn, "user socket", user.id)
index 2fc42a90d48b8de94223cb17a69c96a7bff37ad2..b07fed42bac84b2eb9b0830887e0ad4f74893f4c 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.UserTest do
@@ -412,7 +412,11 @@ defmodule Pleroma.UserTest do
       assert activity.actor == welcome_user.ap_id
     end
 
-    test "it requires an email, name, nickname and password, bio is optional" do
+    clear_config([:instance, :account_activation_required])
+
+    test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
+      Pleroma.Config.put([:instance, :account_activation_required], true)
+
       @full_user_data
       |> Map.keys()
       |> Enum.each(fn key ->
@@ -423,6 +427,19 @@ defmodule Pleroma.UserTest do
       end)
     end
 
+    test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
+      Pleroma.Config.put([:instance, :account_activation_required], false)
+
+      @full_user_data
+      |> Map.keys()
+      |> Enum.each(fn key ->
+        params = Map.delete(@full_user_data, key)
+        changeset = User.register_changeset(%User{}, params)
+
+        assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
+      end)
+    end
+
     test "it restricts certain nicknames" do
       [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
 
index 8625bb9cf00ae410e2ba866df2c5e3c2be2f0315..ff7cb88d10234661848f6c6d6b3e58d92969dfc1 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
@@ -601,6 +601,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
       [valid_params: valid_params]
     end
 
+    clear_config([:instance, :account_activation_required])
+
     test "Account registration via Application", %{conn: conn} do
       conn =
         post(conn, "/api/v1/apps", %{
@@ -731,7 +733,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
       assert json_response(res, 200)
 
       [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
-      |> Stream.zip(valid_params)
+      |> Stream.zip(Map.delete(valid_params, :email))
       |> Enum.each(fn {ip, {attr, _}} ->
         res =
           conn
@@ -743,6 +745,52 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
       end)
     end
 
+    test "returns bad_request if missing email params when :account_activation_required is enabled",
+         %{conn: conn, valid_params: valid_params} do
+      Pleroma.Config.put([:instance, :account_activation_required], true)
+
+      app_token = insert(:oauth_token, user: nil)
+      conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+
+      res =
+        conn
+        |> Map.put(:remote_ip, {127, 0, 0, 5})
+        |> post("/api/v1/accounts", Map.delete(valid_params, :email))
+
+      assert json_response(res, 400) == %{"error" => "Missing parameters"}
+
+      res =
+        conn
+        |> Map.put(:remote_ip, {127, 0, 0, 6})
+        |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
+
+      assert json_response(res, 400) == %{"error" => "{\"email\":[\"can't be blank\"]}"}
+    end
+
+    test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
+      app_token = insert(:oauth_token, user: nil)
+      conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+
+      res =
+        conn
+        |> Map.put(:remote_ip, {127, 0, 0, 7})
+        |> post("/api/v1/accounts", Map.delete(valid_params, :email))
+
+      assert json_response(res, 200)
+    end
+
+    test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
+      app_token = insert(:oauth_token, user: nil)
+      conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+
+      res =
+        conn
+        |> Map.put(:remote_ip, {127, 0, 0, 8})
+        |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
+
+      assert json_response(res, 200)
+    end
+
     test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
       conn = put_req_header(conn, "authorization", "Bearer " <> "invalid-token")