Add OpenAPI spec for MarkerController
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 14 Apr 2020 18:50:29 +0000 (22:50 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Tue, 5 May 2020 12:44:16 +0000 (16:44 +0400)
lib/pleroma/web/api_spec/operations/marker_operation.ex [new file with mode: 0644]
lib/pleroma/web/api_spec/schemas/marker.ex [new file with mode: 0644]
lib/pleroma/web/api_spec/schemas/markers_response.ex [new file with mode: 0644]
lib/pleroma/web/api_spec/schemas/markers_upsert_request.ex [new file with mode: 0644]
lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
test/web/mastodon_api/controllers/marker_controller_test.exs

diff --git a/lib/pleroma/web/api_spec/operations/marker_operation.ex b/lib/pleroma/web/api_spec/operations/marker_operation.ex
new file mode 100644 (file)
index 0000000..60adc7c
--- /dev/null
@@ -0,0 +1,52 @@
+# 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.MarkerOperation do
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Schema
+  alias Pleroma.Web.ApiSpec.Helpers
+  alias Pleroma.Web.ApiSpec.Schemas.MarkersResponse
+  alias Pleroma.Web.ApiSpec.Schemas.MarkersUpsertRequest
+
+  def open_api_operation(action) do
+    operation = String.to_existing_atom("#{action}_operation")
+    apply(__MODULE__, operation, [])
+  end
+
+  def index_operation do
+    %Operation{
+      tags: ["markers"],
+      summary: "Get saved timeline position",
+      security: [%{"oAuth" => ["read:statuses"]}],
+      operationId: "MarkerController.index",
+      parameters: [
+        Operation.parameter(
+          :timeline,
+          :query,
+          %Schema{
+            type: :array,
+            items: %Schema{type: :string, enum: ["home", "notifications"]}
+          },
+          "Array of markers to fetch. If not provided, an empty object will be returned."
+        )
+      ],
+      responses: %{
+        200 => Operation.response("Marker", "application/json", MarkersResponse)
+      }
+    }
+  end
+
+  def upsert_operation do
+    %Operation{
+      tags: ["markers"],
+      summary: "Save position in timeline",
+      operationId: "MarkerController.upsert",
+      requestBody: Helpers.request_body("Parameters", MarkersUpsertRequest, required: true),
+      security: [%{"oAuth" => ["follow", "write:blocks"]}],
+      responses: %{
+        200 => Operation.response("Marker", "application/json", MarkersResponse)
+      }
+    }
+  end
+end
diff --git a/lib/pleroma/web/api_spec/schemas/marker.ex b/lib/pleroma/web/api_spec/schemas/marker.ex
new file mode 100644 (file)
index 0000000..64fca59
--- /dev/null
@@ -0,0 +1,31 @@
+# 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.Marker do
+  require OpenApiSpex
+  alias OpenApiSpex.Schema
+
+  OpenApiSpex.schema(%{
+    title: "Marker",
+    description: "Schema for a marker",
+    type: :object,
+    properties: %{
+      last_read_id: %Schema{type: :string},
+      version: %Schema{type: :integer},
+      updated_at: %Schema{type: :string},
+      pleroma: %Schema{
+        type: :object,
+        properties: %{
+          unread_count: %Schema{type: :integer}
+        }
+      }
+    },
+    example: %{
+      "last_read_id" => "35098814",
+      "version" => 361,
+      "updated_at" => "2019-11-26T22:37:25.239Z",
+      "pleroma" => %{"unread_count" => 5}
+    }
+  })
+end
diff --git a/lib/pleroma/web/api_spec/schemas/markers_response.ex b/lib/pleroma/web/api_spec/schemas/markers_response.ex
new file mode 100644 (file)
index 0000000..cb11219
--- /dev/null
@@ -0,0 +1,35 @@
+# 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.MarkersResponse do
+  require OpenApiSpex
+  alias OpenApiSpex.Schema
+
+  alias Pleroma.Web.ApiSpec.Schemas.Marker
+
+  OpenApiSpex.schema(%{
+    title: "MarkersResponse",
+    description: "Response schema for markers",
+    type: :object,
+    properties: %{
+      notifications: %Schema{allOf: [Marker], nullable: true},
+      home: %Schema{allOf: [Marker], nullable: true}
+    },
+    items: %Schema{type: :string},
+    example: %{
+      "notifications" => %{
+        "last_read_id" => "35098814",
+        "version" => 361,
+        "updated_at" => "2019-11-26T22:37:25.239Z",
+        "pleroma" => %{"unread_count" => 0}
+      },
+      "home" => %{
+        "last_read_id" => "103206604258487607",
+        "version" => 468,
+        "updated_at" => "2019-11-26T22:37:25.235Z",
+        "pleroma" => %{"unread_count" => 10}
+      }
+    }
+  })
+end
diff --git a/lib/pleroma/web/api_spec/schemas/markers_upsert_request.ex b/lib/pleroma/web/api_spec/schemas/markers_upsert_request.ex
new file mode 100644 (file)
index 0000000..97dcc24
--- /dev/null
@@ -0,0 +1,35 @@
+# 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.MarkersUpsertRequest do
+  require OpenApiSpex
+  alias OpenApiSpex.Schema
+
+  OpenApiSpex.schema(%{
+    title: "MarkersUpsertRequest",
+    description: "Request schema for marker upsert",
+    type: :object,
+    properties: %{
+      notifications: %Schema{
+        type: :object,
+        properties: %{
+          last_read_id: %Schema{type: :string}
+        }
+      },
+      home: %Schema{
+        type: :object,
+        properties: %{
+          last_read_id: %Schema{type: :string}
+        }
+      }
+    },
+    example: %{
+      "home" => %{
+        "last_read_id" => "103194548672408537",
+        "version" => 462,
+        "updated_at" => "2019-11-24T19:39:39.337Z"
+      }
+    }
+  })
+end
index 9f9d4574ee28db18bdb197b080e30e3d8bf10738..b94171b365d429a07d582ee4006361cc4713dc63 100644 (file)
@@ -15,15 +15,23 @@ defmodule Pleroma.Web.MastodonAPI.MarkerController do
   plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :upsert)
 
   action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+  plug(OpenApiSpex.Plug.CastAndValidate)
+
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MarkerOperation
 
   # GET /api/v1/markers
   def index(%{assigns: %{user: user}} = conn, params) do
-    markers = Pleroma.Marker.get_markers(user, params["timeline"])
+    markers = Pleroma.Marker.get_markers(user, params[:timeline])
     render(conn, "markers.json", %{markers: markers})
   end
 
   # POST /api/v1/markers
-  def upsert(%{assigns: %{user: user}} = conn, params) do
+  def upsert(%{assigns: %{user: user}, body_params: params} = conn, _) do
+    params =
+      params
+      |> Map.from_struct()
+      |> Map.new(fn {key, value} -> {to_string(key), value} end)
+
     with {:ok, result} <- Pleroma.Marker.upsert(user, params),
          markers <- Map.values(result) do
       render(conn, "markers.json", %{markers: markers})
index 919f295bdfda940814326f4df9075b239e4bcb82..1c85ed032ef3b1f641887ae8e6f7e5325399e3c1 100644 (file)
@@ -4,8 +4,10 @@
 
 defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
   use Pleroma.Web.ConnCase
+  alias Pleroma.Web.ApiSpec
 
   import Pleroma.Factory
+  import OpenApiSpex.TestAssertions
 
   describe "GET /api/v1/markers" do
     test "gets markers with correct scopes", %{conn: conn} do
@@ -22,7 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
         conn
         |> assign(:user, user)
         |> assign(:token, token)
-        |> get("/api/v1/markers", %{timeline: ["notifications"]})
+        |> get("/api/v1/markers?timeline[]=notifications")
         |> json_response(200)
 
       assert response == %{
@@ -32,6 +34,8 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
                  "version" => 0
                }
              }
+
+      assert_schema(response, "MarkersResponse", ApiSpec.spec())
     end
 
     test "gets markers with missed scopes", %{conn: conn} do
@@ -60,6 +64,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
         conn
         |> assign(:user, user)
         |> assign(:token, token)
+        |> put_req_header("content-type", "application/json")
         |> post("/api/v1/markers", %{
           home: %{last_read_id: "777"},
           notifications: %{"last_read_id" => "69420"}
@@ -73,6 +78,8 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
                  "version" => 0
                }
              } = response
+
+      assert_schema(response, "MarkersResponse", ApiSpec.spec())
     end
 
     test "updates exist marker", %{conn: conn} do
@@ -89,6 +96,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
         conn
         |> assign(:user, user)
         |> assign(:token, token)
+        |> put_req_header("content-type", "application/json")
         |> post("/api/v1/markers", %{
           home: %{last_read_id: "777"},
           notifications: %{"last_read_id" => "69888"}
@@ -102,6 +110,8 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
                  "version" => 0
                }
              }
+
+      assert_schema(response, "MarkersResponse", ApiSpec.spec())
     end
 
     test "creates a marker with missed scopes", %{conn: conn} do