From 524d04d9218f8e72bf88ab5e7d4b407452ae40bc Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 19 May 2020 15:53:18 +0400 Subject: [PATCH] Add OpenAPI spec for PleromaAPI.ScrobbleController --- .../operations/pleroma_scrobble_operation.ex | 102 ++++++++++++++++++ lib/pleroma/web/common_api/common_api.ex | 11 +- .../controllers/scrobble_controller.ex | 27 +++-- lib/pleroma/web/router.ex | 4 +- test/web/common_api/common_api_test.exs | 18 ++-- .../controllers/scrobble_controller_test.exs | 26 ++--- 6 files changed, 147 insertions(+), 41 deletions(-) create mode 100644 lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex diff --git a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex new file mode 100644 index 000000000..779b8f84c --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex @@ -0,0 +1,102 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Reference + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.Account + alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope + + import Pleroma.Web.ApiSpec.Helpers + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def create_operation do + %Operation{ + tags: ["Scrobbles"], + summary: "Gets user mascot image", + security: [%{"oAuth" => ["write"]}], + operationId: "PleromaAPI.ScrobbleController.create", + requestBody: request_body("Parameters", create_request(), requried: true), + responses: %{ + 200 => Operation.response("Scrobble", "application/json", scrobble()) + } + } + end + + def index_operation do + %Operation{ + tags: ["Scrobbles"], + summary: "Requests a list of current and recent Listen activities for an account", + operationId: "PleromaAPI.ScrobbleController.index", + parameters: [ + %Reference{"$ref": "#/components/parameters/accountIdOrNickname"} | pagination_params() + ], + security: [%{"oAuth" => ["read"]}], + responses: %{ + 200 => + Operation.response("Array of Scrobble", "application/json", %Schema{ + type: :array, + items: scrobble() + }) + } + } + end + + defp create_request do + %Schema{ + type: :object, + required: [:title], + properties: %{ + title: %Schema{type: :string, description: "The title of the media playing"}, + album: %Schema{type: :string, description: "The album of the media playing"}, + artist: %Schema{type: :string, description: "The artist of the media playing"}, + length: %Schema{type: :integer, description: "The length of the media playing"}, + visibility: %Schema{ + allOf: [VisibilityScope], + default: "public", + description: "Scrobble visibility" + } + }, + example: %{ + "title" => "Some Title", + "artist" => "Some Artist", + "album" => "Some Album", + "length" => 180_000 + } + } + end + + defp scrobble do + %Schema{ + type: :object, + properties: %{ + id: %Schema{type: :string}, + account: Account, + title: %Schema{type: :string, description: "The title of the media playing"}, + album: %Schema{type: :string, description: "The album of the media playing"}, + artist: %Schema{type: :string, description: "The artist of the media playing"}, + length: %Schema{ + type: :integer, + description: "The length of the media playing", + nullable: true + }, + created_at: %Schema{type: :string, format: :"date-time"} + }, + example: %{ + "id" => "1234", + "account" => Account.schema().example, + "title" => "Some Title", + "artist" => "Some Artist", + "album" => "Some Album", + "length" => 180_000, + "created_at" => "2019-09-28T12:40:45.000Z" + } + } + end +end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 7c94f16b6..447dbe4e6 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -347,11 +347,14 @@ def check_expiry_date(expiry_str) do |> check_expiry_date() end - def listen(user, %{"title" => _} = data) do - with visibility <- data["visibility"] || "public", - {to, cc} <- get_to_and_cc(user, [], nil, visibility, nil), + def listen(user, data) do + visibility = Map.get(data, :visibility, "public") + + with {to, cc} <- get_to_and_cc(user, [], nil, visibility, nil), listen_data <- - Map.take(data, ["album", "artist", "title", "length"]) + data + |> Map.take([:album, :artist, :title, :length]) + |> Map.new(fn {key, value} -> {to_string(key), value} end) |> Map.put("type", "Audio") |> Map.put("to", to) |> Map.put("cc", cc) diff --git a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex index 22da6c0ad..35a37f69e 100644 --- a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do use Pleroma.Web, :controller - import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, fetch_integer_param: 2] + import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User @@ -13,22 +13,18 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.StatusView + plug(Pleroma.Web.ApiSpec.CastAndValidate) + plug( OAuthScopesPlug, - %{scopes: ["read"], fallback: :proceed_unauthenticated} when action == :user_scrobbles + %{scopes: ["read"], fallback: :proceed_unauthenticated} when action == :index ) - plug(OAuthScopesPlug, %{scopes: ["write"]} when action != :user_scrobbles) + plug(OAuthScopesPlug, %{scopes: ["write"]} when action == :create) - def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do - params = - if !params["length"] do - params - else - params - |> Map.put("length", fetch_integer_param(params, "length")) - end + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaScrobbleOperation + def create(%{assigns: %{user: user}, body_params: params} = conn, _) do with {:ok, activity} <- CommonAPI.listen(user, params) do conn |> put_view(StatusView) @@ -41,9 +37,12 @@ def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do end end - def user_scrobbles(%{assigns: %{user: reading_user}} = conn, params) do - with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do - params = Map.put(params, "type", ["Listen"]) + def index(%{assigns: %{user: reading_user}} = conn, %{id: id} = params) do + with %User{} = user <- User.get_cached_by_nickname_or_id(id, for: reading_user) do + params = + params + |> Map.new(fn {key, value} -> {to_string(key), value} end) + |> Map.put("type", ["Listen"]) activities = ActivityPub.fetch_user_abstract_activities(user, reading_user, params) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d77a61361..369c54cf4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -325,7 +325,7 @@ defmodule Pleroma.Web.Router do get("/mascot", MascotController, :show) put("/mascot", MascotController, :update) - post("/scrobble", ScrobbleController, :new_scrobble) + post("/scrobble", ScrobbleController, :create) end scope [] do @@ -345,7 +345,7 @@ defmodule Pleroma.Web.Router do scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do pipe_through(:api) - get("/accounts/:id/scrobbles", ScrobbleController, :user_scrobbles) + get("/accounts/:id/scrobbles", ScrobbleController, :index) end scope "/api/v1", Pleroma.Web.MastodonAPI do diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index fd8299013..52e95397c 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -841,10 +841,10 @@ test "returns a valid activity" do {:ok, activity} = CommonAPI.listen(user, %{ - "title" => "lain radio episode 1", - "album" => "lain radio", - "artist" => "lain", - "length" => 180_000 + title: "lain radio episode 1", + album: "lain radio", + artist: "lain", + length: 180_000 }) object = Object.normalize(activity) @@ -859,11 +859,11 @@ test "respects visibility=private" do {:ok, activity} = CommonAPI.listen(user, %{ - "title" => "lain radio episode 1", - "album" => "lain radio", - "artist" => "lain", - "length" => 180_000, - "visibility" => "private" + title: "lain radio episode 1", + album: "lain radio", + artist: "lain", + length: 180_000, + visibility: "private" }) object = Object.normalize(activity) diff --git a/test/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/web/pleroma_api/controllers/scrobble_controller_test.exs index 1b945040c..f39c07ac6 100644 --- a/test/web/pleroma_api/controllers/scrobble_controller_test.exs +++ b/test/web/pleroma_api/controllers/scrobble_controller_test.exs @@ -12,14 +12,16 @@ test "works correctly" do %{conn: conn} = oauth_access(["write"]) conn = - post(conn, "/api/v1/pleroma/scrobble", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/scrobble", %{ "title" => "lain radio episode 1", "artist" => "lain", "album" => "lain radio", "length" => "180000" }) - assert %{"title" => "lain radio episode 1"} = json_response(conn, 200) + assert %{"title" => "lain radio episode 1"} = json_response_and_validate_schema(conn, 200) end end @@ -29,28 +31,28 @@ test "works correctly" do {:ok, _activity} = CommonAPI.listen(user, %{ - "title" => "lain radio episode 1", - "artist" => "lain", - "album" => "lain radio" + title: "lain radio episode 1", + artist: "lain", + album: "lain radio" }) {:ok, _activity} = CommonAPI.listen(user, %{ - "title" => "lain radio episode 2", - "artist" => "lain", - "album" => "lain radio" + title: "lain radio episode 2", + artist: "lain", + album: "lain radio" }) {:ok, _activity} = CommonAPI.listen(user, %{ - "title" => "lain radio episode 3", - "artist" => "lain", - "album" => "lain radio" + title: "lain radio episode 3", + artist: "lain", + album: "lain radio" }) conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles") - result = json_response(conn, 200) + result = json_response_and_validate_schema(conn, 200) assert length(result) == 3 end