Add OpenAPI spec for AdminAPI.StatusController
authorEgor Kislitsyn <egor@kislitsyn.com>
Thu, 21 May 2020 10:03:38 +0000 (14:03 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Thu, 21 May 2020 13:23:12 +0000 (17:23 +0400)
lib/pleroma/web/admin_api/controllers/fallback_controller.ex
lib/pleroma/web/admin_api/controllers/status_controller.ex
lib/pleroma/web/api_spec/operations/admin/status_operation.ex [new file with mode: 0644]
lib/pleroma/web/api_spec/operations/status_operation.ex
test/web/admin_api/controllers/admin_api_controller_test.exs
test/web/admin_api/controllers/status_controller_test.exs

index 9f7bb92ce74bfb402627ceddc56647e310507d62..82965936da1518b36de460a05249182c10434784 100644 (file)
@@ -8,13 +8,13 @@ defmodule Pleroma.Web.AdminAPI.FallbackController do
   def call(conn, {:error, :not_found}) do
     conn
     |> put_status(:not_found)
-    |> json(dgettext("errors", "Not found"))
+    |> json(%{error: dgettext("errors", "Not found")})
   end
 
   def call(conn, {:error, reason}) do
     conn
     |> put_status(:bad_request)
-    |> json(reason)
+    |> json(%{error: reason})
   end
 
   def call(conn, {:param_cast, _}) do
@@ -26,6 +26,6 @@ defmodule Pleroma.Web.AdminAPI.FallbackController do
   def call(conn, _) do
     conn
     |> put_status(:internal_server_error)
-    |> json(dgettext("errors", "Something went wrong"))
+    |> json(%{error: dgettext("errors", "Something went wrong")})
   end
 end
index 1e9763979ea24eb977d214c3d40410e14223187f..08cb9c10b3da0a696eeb7a31992728ef194c86dc 100644 (file)
@@ -14,8 +14,7 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
 
   require Logger
 
-  @users_page_size 50
-
+  plug(Pleroma.Web.ApiSpec.CastAndValidate)
   plug(OAuthScopesPlug, %{scopes: ["read:statuses"], admin: true} when action in [:index, :show])
 
   plug(
@@ -25,25 +24,22 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
 
-  def index(%{assigns: %{user: _admin}} = conn, params) do
-    godmode = params["godmode"] == "true" || params["godmode"] == true
-    local_only = params["local_only"] == "true" || params["local_only"] == true
-    with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
-    {page, page_size} = page_params(params)
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.StatusOperation
 
+  def index(%{assigns: %{user: _admin}} = conn, params) do
     activities =
       ActivityPub.fetch_statuses(nil, %{
-        "godmode" => godmode,
-        "local_only" => local_only,
-        "limit" => page_size,
-        "offset" => (page - 1) * page_size,
-        "exclude_reblogs" => !with_reblogs && "true"
+        "godmode" => params.godmode,
+        "local_only" => params.local_only,
+        "limit" => params.page_size,
+        "offset" => (params.page - 1) * params.page_size,
+        "exclude_reblogs" => not params.with_reblogs
       })
 
-    render(conn, "index.json", %{activities: activities, as: :activity})
+    render(conn, "index.json", activities: activities, as: :activity)
   end
 
-  def show(conn, %{"id" => id}) do
+  def show(conn, %{id: id}) do
     with %Activity{} = activity <- Activity.get_by_id(id) do
       conn
       |> put_view(MastodonAPI.StatusView)
@@ -53,20 +49,13 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
     end
   end
 
-  def update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do
-    params =
-      params
-      |> Map.take(["sensitive", "visibility"])
-      |> Map.new(fn {key, value} -> {String.to_existing_atom(key), value} end)
-
+  def update(%{assigns: %{user: admin}, body_params: params} = conn, %{id: id}) do
     with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
-      {:ok, sensitive} = Ecto.Type.cast(:boolean, params[:sensitive])
-
       ModerationLog.insert_log(%{
         action: "status_update",
         actor: admin,
         subject: activity,
-        sensitive: sensitive,
+        sensitive: params[:sensitive],
         visibility: params[:visibility]
       })
 
@@ -76,7 +65,7 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
     end
   end
 
-  def delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+  def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
     with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
       ModerationLog.insert_log(%{
         action: "status_delete",
@@ -87,26 +76,4 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
       json(conn, %{})
     end
   end
-
-  defp page_params(params) do
-    {get_page(params["page"]), get_page_size(params["page_size"])}
-  end
-
-  defp get_page(page_string) when is_nil(page_string), do: 1
-
-  defp get_page(page_string) do
-    case Integer.parse(page_string) do
-      {page, _} -> page
-      :error -> 1
-    end
-  end
-
-  defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
-
-  defp get_page_size(page_size_string) do
-    case Integer.parse(page_size_string) do
-      {page_size, _} -> page_size
-      :error -> @users_page_size
-    end
-  end
 end
diff --git a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
new file mode 100644 (file)
index 0000000..0b138dc
--- /dev/null
@@ -0,0 +1,165 @@
+# 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.Admin.StatusOperation do
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Schema
+  alias Pleroma.Web.ApiSpec.Schemas.Account
+  alias Pleroma.Web.ApiSpec.Schemas.ApiError
+  alias Pleroma.Web.ApiSpec.Schemas.FlakeID
+  alias Pleroma.Web.ApiSpec.Schemas.Status
+  alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
+
+  import Pleroma.Web.ApiSpec.Helpers
+  import Pleroma.Web.ApiSpec.StatusOperation, only: [id_param: 0]
+
+  def open_api_operation(action) do
+    operation = String.to_existing_atom("#{action}_operation")
+    apply(__MODULE__, operation, [])
+  end
+
+  def index_operation do
+    %Operation{
+      tags: ["Admin", "Statuses"],
+      operationId: "AdminAPI.StatusController.index",
+      security: [%{"oAuth" => ["read:statuses"]}],
+      parameters: [
+        Operation.parameter(
+          :godmode,
+          :query,
+          %Schema{type: :boolean, default: false},
+          "Allows to see private statuses"
+        ),
+        Operation.parameter(
+          :local_only,
+          :query,
+          %Schema{type: :boolean, default: false},
+          "Excludes remote statuses"
+        ),
+        Operation.parameter(
+          :with_reblogs,
+          :query,
+          %Schema{type: :boolean, default: false},
+          "Allows to see reblogs"
+        ),
+        Operation.parameter(
+          :page,
+          :query,
+          %Schema{type: :integer, default: 1},
+          "Page"
+        ),
+        Operation.parameter(
+          :page_size,
+          :query,
+          %Schema{type: :integer, default: 50},
+          "Number of statuses to return"
+        )
+      ],
+      responses: %{
+        200 =>
+          Operation.response("Array of statuses", "application/json", %Schema{
+            type: :array,
+            items: status()
+          })
+      }
+    }
+  end
+
+  def show_operation do
+    %Operation{
+      tags: ["Admin", "Statuses"],
+      summary: "Show Status",
+      operationId: "AdminAPI.StatusController.show",
+      parameters: [id_param()],
+      security: [%{"oAuth" => ["read:statuses"]}],
+      responses: %{
+        200 => Operation.response("Status", "application/json", Status),
+        404 => Operation.response("Not Found", "application/json", ApiError)
+      }
+    }
+  end
+
+  def update_operation do
+    %Operation{
+      tags: ["Admin", "Statuses"],
+      summary: "Change the scope of an individual reported status",
+      operationId: "AdminAPI.StatusController.update",
+      parameters: [id_param()],
+      security: [%{"oAuth" => ["write:statuses"]}],
+      requestBody: request_body("Parameters", update_request(), required: true),
+      responses: %{
+        200 => Operation.response("Status", "application/json", Status),
+        400 => Operation.response("Error", "application/json", ApiError)
+      }
+    }
+  end
+
+  def delete_operation do
+    %Operation{
+      tags: ["Admin", "Statuses"],
+      summary: "Delete an individual reported status",
+      operationId: "AdminAPI.StatusController.delete",
+      parameters: [id_param()],
+      security: [%{"oAuth" => ["write:statuses"]}],
+      responses: %{
+        200 => empty_object_response(),
+        404 => Operation.response("Not Found", "application/json", ApiError)
+      }
+    }
+  end
+
+  defp status do
+    %Schema{
+      anyOf: [
+        Status,
+        %Schema{
+          type: :object,
+          properties: %{
+            account: %Schema{allOf: [Account, admin_account()]}
+          }
+        }
+      ]
+    }
+  end
+
+  defp admin_account do
+    %Schema{
+      type: :object,
+      properties: %{
+        id: FlakeID,
+        avatar: %Schema{type: :string},
+        nickname: %Schema{type: :string},
+        display_name: %Schema{type: :string},
+        deactivated: %Schema{type: :boolean},
+        local: %Schema{type: :boolean},
+        roles: %Schema{
+          type: :object,
+          properties: %{
+            admin: %Schema{type: :boolean},
+            moderator: %Schema{type: :boolean}
+          }
+        },
+        tags: %Schema{type: :string},
+        confirmation_pending: %Schema{type: :string}
+      }
+    }
+  end
+
+  defp update_request do
+    %Schema{
+      type: :object,
+      properties: %{
+        sensitive: %Schema{
+          type: :boolean,
+          description: "Mark status and attached media as sensitive?"
+        },
+        visibility: VisibilityScope
+      },
+      example: %{
+        "visibility" => "private",
+        "sensitive" => "false"
+      }
+    }
+  end
+end
index 0682ca6e52d1ddbfc2723362273993fdf15ff2ca..ca9db01e550c3baaf2d1bca830b084828d88e2f4 100644 (file)
@@ -487,7 +487,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
     }
   end
 
-  defp id_param do
+  def id_param do
     Operation.parameter(:id, :path, FlakeID, "Status ID",
       example: "9umDrYheeY451cQnEe",
       required: true
index 2c317e0fe55b850a3f0266a1452658a3ae41626f..a0c11a354b75f968503ef55b4e296ea743d8db2d 100644 (file)
@@ -350,7 +350,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
       conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
 
-      assert "Not found" == json_response(conn, 404)
+      assert %{"error" => "Not found"} == json_response(conn, 404)
     end
   end
 
@@ -683,7 +683,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
 
       assert json_response(conn, :bad_request) ==
-               "To send invites you need to set the `invites_enabled` option to true."
+               %{
+                 "error" =>
+                   "To send invites you need to set the `invites_enabled` option to true."
+               }
     end
 
     test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
@@ -693,7 +696,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
 
       assert json_response(conn, :bad_request) ==
-               "To send invites you need to set the `registrations_open` option to false."
+               %{
+                 "error" =>
+                   "To send invites you need to set the `registrations_open` option to false."
+               }
     end
   end
 
@@ -1307,7 +1313,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
         |> json_response(404)
 
-      assert response == "Not found"
+      assert response == %{"error" => "Not found"}
     end
   end
 
@@ -1413,7 +1419,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     test "with invalid token", %{conn: conn} do
       conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
 
-      assert json_response(conn, :not_found) == "Not found"
+      assert json_response(conn, :not_found) == %{"error" => "Not found"}
     end
   end
 
@@ -1440,7 +1446,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     test "returns 404 when report id is invalid", %{conn: conn} do
       conn = get(conn, "/api/pleroma/admin/reports/test")
 
-      assert json_response(conn, :not_found) == "Not found"
+      assert json_response(conn, :not_found) == %{"error" => "Not found"}
     end
   end
 
@@ -1705,7 +1711,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       conn = get(conn, "/api/pleroma/admin/config")
 
       assert json_response(conn, 400) ==
-               "To use this endpoint you need to enable configuration from database."
+               %{
+                 "error" => "To use this endpoint you need to enable configuration from database."
+               }
     end
 
     test "with settings only in db", %{conn: conn} do
@@ -1827,7 +1835,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     conn = post(conn, "/api/pleroma/admin/config", %{"configs" => []})
 
     assert json_response(conn, 400) ==
-             "To use this endpoint you need to enable configuration from database."
+             %{"error" => "To use this endpoint you need to enable configuration from database."}
   end
 
   describe "POST /api/pleroma/admin/config" do
index 8ecc78491288a40d04954ae2cd6a32ba509a6e98..124d8dc2ea7b3b8a81de38b9e0cdf72ccbbf9be1 100644 (file)
@@ -30,7 +30,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
     test "not found", %{conn: conn} do
       assert conn
              |> get("/api/pleroma/admin/statuses/not_found")
-             |> json_response(:not_found)
+             |> json_response_and_validate_schema(:not_found)
     end
 
     test "shows activity", %{conn: conn} do
@@ -39,7 +39,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
       response =
         conn
         |> get("/api/pleroma/admin/statuses/#{activity.id}")
-        |> json_response(200)
+        |> json_response_and_validate_schema(200)
 
       assert response["id"] == activity.id
     end
@@ -55,8 +55,9 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
     test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
       response =
         conn
+        |> put_req_header("content-type", "application/json")
         |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
-        |> json_response(:ok)
+        |> json_response_and_validate_schema(:ok)
 
       assert response["sensitive"]
 
@@ -67,8 +68,9 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
 
       response =
         conn
+        |> put_req_header("content-type", "application/json")
         |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
-        |> json_response(:ok)
+        |> json_response_and_validate_schema(:ok)
 
       refute response["sensitive"]
     end
@@ -76,8 +78,9 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
     test "change visibility flag", %{conn: conn, id: id, admin: admin} do
       response =
         conn
+        |> put_req_header("content-type", "application/json")
         |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "public"})
-        |> json_response(:ok)
+        |> json_response_and_validate_schema(:ok)
 
       assert response["visibility"] == "public"
 
@@ -88,23 +91,29 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
 
       response =
         conn
+        |> put_req_header("content-type", "application/json")
         |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "private"})
-        |> json_response(:ok)
+        |> json_response_and_validate_schema(:ok)
 
       assert response["visibility"] == "private"
 
       response =
         conn
+        |> put_req_header("content-type", "application/json")
         |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "unlisted"})
-        |> json_response(:ok)
+        |> json_response_and_validate_schema(:ok)
 
       assert response["visibility"] == "unlisted"
     end
 
     test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
-      conn = put(conn, "/api/pleroma/admin/statuses/#{id}", %{visibility: "test"})
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "test"})
 
-      assert json_response(conn, :bad_request) == "Unsupported visibility"
+      assert %{"error" => "test - Invalid value for enum."} =
+               json_response_and_validate_schema(conn, :bad_request)
     end
   end
 
@@ -118,7 +127,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
     test "deletes status", %{conn: conn, id: id, admin: admin} do
       conn
       |> delete("/api/pleroma/admin/statuses/#{id}")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
       refute Activity.get_by_id(id)
 
@@ -131,7 +140,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
     test "returns 404 when the status does not exist", %{conn: conn} do
       conn = delete(conn, "/api/pleroma/admin/statuses/test")
 
-      assert json_response(conn, :not_found) == "Not found"
+      assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
     end
   end
 
@@ -151,7 +160,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
       response =
         conn
         |> get("/api/pleroma/admin/statuses")
-        |> json_response(200)
+        |> json_response_and_validate_schema(200)
 
       refute "private" in Enum.map(response, & &1["visibility"])
       assert length(response) == 3
@@ -166,7 +175,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
       response =
         conn
         |> get("/api/pleroma/admin/statuses?local_only=true")
-        |> json_response(200)
+        |> json_response_and_validate_schema(200)
 
       assert length(response) == 1
     end
@@ -179,7 +188,7 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
       {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"})
       {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"})
       conn = get(conn, "/api/pleroma/admin/statuses?godmode=true")
-      assert json_response(conn, 200) |> length() == 3
+      assert json_response_and_validate_schema(conn, 200) |> length() == 3
     end
   end
 end