From 4dca712e90a81a1a754608eb4f8e22dae99eb755 Mon Sep 17 00:00:00 2001
From: Egor Kislitsyn <egor@kislitsyn.com>
Date: Mon, 13 Apr 2020 22:44:52 +0400
Subject: [PATCH] Add OpenAPI spec for DomainBlockController

---
 lib/pleroma/web/api_spec.ex                   |  2 +-
 .../operations/domain_block_operation.ex      | 64 +++++++++++++++++++
 .../api_spec/schemas/domain_block_request.ex  | 20 ++++++
 .../schemas/domain_blocks_response.ex         | 16 +++++
 .../controllers/domain_block_controller.ex    |  7 +-
 .../domain_block_controller_test.exs          | 20 +++++-
 6 files changed, 124 insertions(+), 5 deletions(-)
 create mode 100644 lib/pleroma/web/api_spec/operations/domain_block_operation.ex
 create mode 100644 lib/pleroma/web/api_spec/schemas/domain_block_request.ex
 create mode 100644 lib/pleroma/web/api_spec/schemas/domain_blocks_response.ex

diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex
index 41e48a085..3890489e3 100644
--- a/lib/pleroma/web/api_spec.ex
+++ b/lib/pleroma/web/api_spec.ex
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.ApiSpec do
               password: %OpenApiSpex.OAuthFlow{
                 authorizationUrl: "/oauth/authorize",
                 tokenUrl: "/oauth/token",
-                scopes: %{"read" => "read"}
+                scopes: %{"read" => "read", "write" => "write", "follow" => "follow"}
               }
             }
           }
diff --git a/lib/pleroma/web/api_spec/operations/domain_block_operation.ex b/lib/pleroma/web/api_spec/operations/domain_block_operation.ex
new file mode 100644
index 000000000..dd14837c3
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/domain_block_operation.ex
@@ -0,0 +1,64 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Schema
+  alias Pleroma.Web.ApiSpec.Helpers
+  alias Pleroma.Web.ApiSpec.Schemas.DomainBlockRequest
+  alias Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse
+
+  def open_api_operation(action) do
+    operation = String.to_existing_atom("#{action}_operation")
+    apply(__MODULE__, operation, [])
+  end
+
+  def index_operation do
+    %Operation{
+      tags: ["domain_blocks"],
+      summary: "Fetch domain blocks",
+      description: "View domains the user has blocked.",
+      security: [%{"oAuth" => ["follow", "read:blocks"]}],
+      operationId: "DomainBlockController.index",
+      responses: %{
+        200 => Operation.response("Domain blocks", "application/json", DomainBlocksResponse)
+      }
+    }
+  end
+
+  def create_operation do
+    %Operation{
+      tags: ["domain_blocks"],
+      summary: "Block a domain",
+      description: """
+      Block a domain to:
+
+      - hide all public posts from it
+      - hide all notifications from it
+      - remove all followers from it
+      - prevent following new users from it (but does not remove existing follows)
+      """,
+      operationId: "DomainBlockController.create",
+      requestBody: Helpers.request_body("Parameters", DomainBlockRequest, required: true),
+      security: [%{"oAuth" => ["follow", "write:blocks"]}],
+      responses: %{
+        200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
+      }
+    }
+  end
+
+  def delete_operation do
+    %Operation{
+      tags: ["domain_blocks"],
+      summary: "Unblock a domain",
+      description: "Remove a domain block, if it exists in the user's array of blocked domains.",
+      operationId: "DomainBlockController.delete",
+      requestBody: Helpers.request_body("Parameters", DomainBlockRequest, required: true),
+      security: [%{"oAuth" => ["follow", "write:blocks"]}],
+      responses: %{
+        200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
+      }
+    }
+  end
+end
diff --git a/lib/pleroma/web/api_spec/schemas/domain_block_request.ex b/lib/pleroma/web/api_spec/schemas/domain_block_request.ex
new file mode 100644
index 000000000..ee9238361
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/domain_block_request.ex
@@ -0,0 +1,20 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.DomainBlockRequest do
+  alias OpenApiSpex.Schema
+  require OpenApiSpex
+
+  OpenApiSpex.schema(%{
+    title: "DomainBlockRequest",
+    type: :object,
+    properties: %{
+      domain: %Schema{type: :string}
+    },
+    required: [:domain],
+    example: %{
+      "domain" => "facebook.com"
+    }
+  })
+end
diff --git a/lib/pleroma/web/api_spec/schemas/domain_blocks_response.ex b/lib/pleroma/web/api_spec/schemas/domain_blocks_response.ex
new file mode 100644
index 000000000..d895aca4e
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/domain_blocks_response.ex
@@ -0,0 +1,16 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse do
+  require OpenApiSpex
+  alias OpenApiSpex.Schema
+
+  OpenApiSpex.schema(%{
+    title: "DomainBlocksResponse",
+    description: "Response schema for domain blocks",
+    type: :array,
+    items: %Schema{type: :string},
+    example: ["google.com", "facebook.com"]
+  })
+end
diff --git a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
index e4156cbe6..84de79413 100644
--- a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
@@ -8,6 +8,9 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
   alias Pleroma.Plugs.OAuthScopesPlug
   alias Pleroma.User
 
+  plug(OpenApiSpex.Plug.CastAndValidate)
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DomainBlockOperation
+
   plug(
     OAuthScopesPlug,
     %{scopes: ["follow", "read:blocks"]} when action == :index
@@ -26,13 +29,13 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
   end
 
   @doc "POST /api/v1/domain_blocks"
-  def create(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
+  def create(%{assigns: %{user: blocker}, body_params: %{domain: domain}} = conn, _params) do
     User.block_domain(blocker, domain)
     json(conn, %{})
   end
 
   @doc "DELETE /api/v1/domain_blocks"
-  def delete(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
+  def delete(%{assigns: %{user: blocker}, body_params: %{domain: domain}} = conn, _params) do
     User.unblock_domain(blocker, domain)
     json(conn, %{})
   end
diff --git a/test/web/mastodon_api/controllers/domain_block_controller_test.exs b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
index 8d24b3b88..d66190c90 100644
--- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs
+++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
@@ -6,20 +6,29 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
   use Pleroma.Web.ConnCase
 
   alias Pleroma.User
+  alias Pleroma.Web.ApiSpec
+  alias Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse
 
   import Pleroma.Factory
+  import OpenApiSpex.TestAssertions
 
   test "blocking / unblocking a domain" do
     %{user: user, conn: conn} = oauth_access(["write:blocks"])
     other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
 
-    ret_conn = post(conn, "/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
+    ret_conn =
+      conn
+      |> put_req_header("content-type", "application/json")
+      |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
 
     assert %{} = json_response(ret_conn, 200)
     user = User.get_cached_by_ap_id(user.ap_id)
     assert User.blocks?(user, other_user)
 
-    ret_conn = delete(conn, "/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
+    ret_conn =
+      conn
+      |> put_req_header("content-type", "application/json")
+      |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
 
     assert %{} = json_response(ret_conn, 200)
     user = User.get_cached_by_ap_id(user.ap_id)
@@ -41,5 +50,12 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
 
     assert "bad.site" in domain_blocks
     assert "even.worse.site" in domain_blocks
+    assert_schema(domain_blocks, "DomainBlocksResponse", ApiSpec.spec())
+  end
+
+  test "DomainBlocksResponse example matches schema" do
+    api_spec = ApiSpec.spec()
+    schema = DomainBlocksResponse.schema()
+    assert_schema(schema.example, "DomainBlocksResponse", api_spec)
   end
 end