Merge branch 'openapi/lists' into 'develop'

Add OpenAPI spec for ListController

See merge request pleroma/pleroma!2453
This commit is contained in:
lain 2020-05-06 08:43:21 +00:00
commit 7fdc7078ae
6 changed files with 265 additions and 53 deletions

View file

@ -11,6 +11,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
alias Pleroma.Web.ApiSpec.Schemas.ActorType
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
alias Pleroma.Web.ApiSpec.Schemas.List
alias Pleroma.Web.ApiSpec.Schemas.Status
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
@ -646,28 +647,12 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
defp list do
%Schema{
title: "List",
description: "Response schema for a list",
type: :object,
properties: %{
id: %Schema{type: :string},
title: %Schema{type: :string}
},
example: %{
"id" => "123",
"title" => "my list"
}
}
end
defp array_of_lists do
%Schema{
title: "ArrayOfLists",
description: "Response schema for lists",
type: :array,
items: list(),
items: List,
example: [
%{"id" => "123", "title" => "my list"},
%{"id" => "1337", "title" => "anotehr list"}

View file

@ -0,0 +1,188 @@
# 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.ListOperation 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.List
import Pleroma.Web.ApiSpec.Helpers
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def index_operation do
%Operation{
tags: ["Lists"],
summary: "Show user's lists",
description: "Fetch all lists that the user owns",
security: [%{"oAuth" => ["read:lists"]}],
operationId: "ListController.index",
responses: %{
200 => Operation.response("Array of List", "application/json", array_of_lists())
}
}
end
def create_operation do
%Operation{
tags: ["Lists"],
summary: "Create a list",
description: "Fetch the list with the given ID. Used for verifying the title of a list.",
operationId: "ListController.create",
requestBody: create_update_request(),
security: [%{"oAuth" => ["write:lists"]}],
responses: %{
200 => Operation.response("List", "application/json", List),
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def show_operation do
%Operation{
tags: ["Lists"],
summary: "Show a single list",
description: "Fetch the list with the given ID. Used for verifying the title of a list.",
operationId: "ListController.show",
parameters: [id_param()],
security: [%{"oAuth" => ["read:lists"]}],
responses: %{
200 => Operation.response("List", "application/json", List),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def update_operation do
%Operation{
tags: ["Lists"],
summary: "Update a list",
description: "Change the title of a list",
operationId: "ListController.update",
parameters: [id_param()],
requestBody: create_update_request(),
security: [%{"oAuth" => ["write:lists"]}],
responses: %{
200 => Operation.response("List", "application/json", List),
422 => Operation.response("Error", "application/json", ApiError)
}
}
end
def delete_operation do
%Operation{
tags: ["Lists"],
summary: "Delete a list",
operationId: "ListController.delete",
parameters: [id_param()],
security: [%{"oAuth" => ["write:lists"]}],
responses: %{
200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
}
}
end
def list_accounts_operation do
%Operation{
tags: ["Lists"],
summary: "View accounts in list",
operationId: "ListController.list_accounts",
parameters: [id_param()],
security: [%{"oAuth" => ["read:lists"]}],
responses: %{
200 =>
Operation.response("Array of Account", "application/json", %Schema{
type: :array,
items: Account
})
}
}
end
def add_to_list_operation do
%Operation{
tags: ["Lists"],
summary: "Add accounts to list",
description: "Add accounts to the given list.",
operationId: "ListController.add_to_list",
parameters: [id_param()],
requestBody: add_remove_accounts_request(),
security: [%{"oAuth" => ["write:lists"]}],
responses: %{
200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
}
}
end
def remove_from_list_operation do
%Operation{
tags: ["Lists"],
summary: "Remove accounts from list",
operationId: "ListController.remove_from_list",
parameters: [id_param()],
requestBody: add_remove_accounts_request(),
security: [%{"oAuth" => ["write:lists"]}],
responses: %{
200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
}
}
end
defp array_of_lists do
%Schema{
title: "ArrayOfLists",
description: "Response schema for lists",
type: :array,
items: List,
example: [
%{"id" => "123", "title" => "my list"},
%{"id" => "1337", "title" => "another list"}
]
}
end
defp id_param do
Operation.parameter(:id, :path, :string, "List ID",
example: "123",
required: true
)
end
defp create_update_request do
request_body(
"Parameters",
%Schema{
description: "POST body for creating or updating a List",
type: :object,
properties: %{
title: %Schema{type: :string, description: "List title"}
},
required: [:title]
},
required: true
)
end
defp add_remove_accounts_request do
request_body(
"Parameters",
%Schema{
description: "POST body for adding/removing accounts to/from a List",
type: :object,
properties: %{
account_ids: %Schema{type: :array, description: "Array of account IDs", items: FlakeID}
},
required: [:account_ids]
},
required: true
)
end
end

View file

@ -0,0 +1,23 @@
# 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.List do
alias OpenApiSpex.Schema
require OpenApiSpex
OpenApiSpex.schema(%{
title: "List",
description: "Represents a list of users",
type: :object,
properties: %{
id: %Schema{type: :string, description: "The internal database ID of the list"},
title: %Schema{type: :string, description: "The user-defined title of the list"}
},
example: %{
"id" => "12249",
"title" => "Friends"
}
})
end

View file

@ -9,20 +9,17 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
alias Pleroma.User
alias Pleroma.Web.MastodonAPI.AccountView
plug(:list_by_id_and_user when action not in [:index, :create])
@oauth_read_actions [:index, :show, :list_accounts]
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:list_by_id_and_user when action not in [:index, :create])
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in @oauth_read_actions)
plug(
OAuthScopesPlug,
%{scopes: ["write:lists"]}
when action not in @oauth_read_actions
)
plug(OAuthScopesPlug, %{scopes: ["write:lists"]} when action not in @oauth_read_actions)
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ListOperation
# GET /api/v1/lists
def index(%{assigns: %{user: user}} = conn, opts) do
lists = Pleroma.List.for_user(user, opts)
@ -30,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
end
# POST /api/v1/lists
def create(%{assigns: %{user: user}} = conn, %{"title" => title}) do
def create(%{assigns: %{user: user}, body_params: %{title: title}} = conn, _) do
with {:ok, %Pleroma.List{} = list} <- Pleroma.List.create(title, user) do
render(conn, "show.json", list: list)
end
@ -42,7 +39,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
end
# PUT /api/v1/lists/:id
def update(%{assigns: %{list: list}} = conn, %{"title" => title}) do
def update(%{assigns: %{list: list}, body_params: %{title: title}} = conn, _) do
with {:ok, list} <- Pleroma.List.rename(list, title) do
render(conn, "show.json", list: list)
end
@ -65,7 +62,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
end
# POST /api/v1/lists/:id/accounts
def add_to_list(%{assigns: %{list: list}} = conn, %{"account_ids" => account_ids}) do
def add_to_list(%{assigns: %{list: list}, body_params: %{account_ids: account_ids}} = conn, _) do
Enum.each(account_ids, fn account_id ->
with %User{} = followed <- User.get_cached_by_id(account_id) do
Pleroma.List.follow(list, followed)
@ -76,7 +73,10 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
end
# DELETE /api/v1/lists/:id/accounts
def remove_from_list(%{assigns: %{list: list}} = conn, %{"account_ids" => account_ids}) do
def remove_from_list(
%{assigns: %{list: list}, body_params: %{account_ids: account_ids}} = conn,
_
) do
Enum.each(account_ids, fn account_id ->
with %User{} = followed <- User.get_cached_by_id(account_id) do
Pleroma.List.unfollow(list, followed)
@ -86,7 +86,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
json(conn, %{})
end
defp list_by_id_and_user(%{assigns: %{user: user}, params: %{"id" => id}} = conn, _) do
defp list_by_id_and_user(%{assigns: %{user: user}, params: %{id: id}} = conn, _) do
case Pleroma.List.get(id, user) do
%Pleroma.List{} = list -> assign(conn, :list, list)
nil -> conn |> render_error(:not_found, "List not found") |> halt()