diff options
author | lain <lain@soykaf.club> | 2020-05-07 13:38:34 +0000 |
---|---|---|
committer | lain <lain@soykaf.club> | 2020-05-07 13:38:34 +0000 |
commit | 516ff945cedbfae774f4c8272264a4cf0e453130 (patch) | |
tree | 9a82d0e667b4c3d3095c0fed4de9f94a8bad6d30 /lib | |
parent | 9f2bb22e1550963ed6f1e78adf0774369c9ec829 (diff) | |
parent | 3f867d8e9bf970e180153b411d5924f15c490046 (diff) | |
download | pleroma-516ff945cedbfae774f4c8272264a4cf0e453130.tar.gz |
Merge branch 'openapi/search' into 'develop'
Add OpenAPI spec for SearchController
See merge request pleroma/pleroma!2484
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/web/api_spec/operations/account_operation.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/api_spec/operations/search_operation.ex | 207 | ||||
-rw-r--r-- | lib/pleroma/web/api_spec/schemas/status.ex | 12 | ||||
-rw-r--r-- | lib/pleroma/web/api_spec/schemas/tag.ex | 27 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/controllers/search_controller.ex | 24 |
5 files changed, 253 insertions, 22 deletions
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index 470fc0215..70069d6f9 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -556,11 +556,12 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do } end - defp array_of_accounts do + def array_of_accounts do %Schema{ title: "ArrayOfAccounts", type: :array, - items: Account + items: Account, + example: [Account.schema().example] } end diff --git a/lib/pleroma/web/api_spec/operations/search_operation.ex b/lib/pleroma/web/api_spec/operations/search_operation.ex new file mode 100644 index 000000000..6ea00a9a8 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/search_operation.ex @@ -0,0 +1,207 @@ +# 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.SearchOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.AccountOperation + alias Pleroma.Web.ApiSpec.Schemas.Account + alias Pleroma.Web.ApiSpec.Schemas.BooleanLike + alias Pleroma.Web.ApiSpec.Schemas.FlakeID + alias Pleroma.Web.ApiSpec.Schemas.Status + alias Pleroma.Web.ApiSpec.Schemas.Tag + + import Pleroma.Web.ApiSpec.Helpers + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def account_search_operation do + %Operation{ + tags: ["Search"], + summary: "Search for matching accounts by username or display name", + operationId: "SearchController.account_search", + parameters: [ + Operation.parameter(:q, :query, %Schema{type: :string}, "What to search for", + required: true + ), + Operation.parameter( + :limit, + :query, + %Schema{type: :integer, default: 40}, + "Maximum number of results" + ), + Operation.parameter( + :resolve, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Attempt WebFinger lookup. Use this when `q` is an exact address." + ), + Operation.parameter( + :following, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Only include accounts that the user is following" + ) + ], + responses: %{ + 200 => + Operation.response( + "Array of Account", + "application/json", + AccountOperation.array_of_accounts() + ) + } + } + end + + def search_operation do + %Operation{ + tags: ["Search"], + summary: "Search results", + security: [%{"oAuth" => ["read:search"]}], + operationId: "SearchController.search", + deprecated: true, + parameters: [ + Operation.parameter( + :account_id, + :query, + FlakeID, + "If provided, statuses returned will be authored only by this account" + ), + Operation.parameter( + :type, + :query, + %Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]}, + "Search type" + ), + Operation.parameter(:q, :query, %Schema{type: :string}, "The search query", required: true), + Operation.parameter( + :resolve, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Attempt WebFinger lookup" + ), + Operation.parameter( + :following, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Only include accounts that the user is following" + ), + Operation.parameter( + :offset, + :query, + %Schema{type: :integer}, + "Offset" + ) + | pagination_params() + ], + responses: %{ + 200 => Operation.response("Results", "application/json", results()) + } + } + end + + def search2_operation do + %Operation{ + tags: ["Search"], + summary: "Search results", + security: [%{"oAuth" => ["read:search"]}], + operationId: "SearchController.search2", + parameters: [ + Operation.parameter( + :account_id, + :query, + FlakeID, + "If provided, statuses returned will be authored only by this account" + ), + Operation.parameter( + :type, + :query, + %Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]}, + "Search type" + ), + Operation.parameter(:q, :query, %Schema{type: :string}, "What to search for", + required: true + ), + Operation.parameter( + :resolve, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Attempt WebFinger lookup" + ), + Operation.parameter( + :following, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Only include accounts that the user is following" + ) + | pagination_params() + ], + responses: %{ + 200 => Operation.response("Results", "application/json", results2()) + } + } + end + + defp results2 do + %Schema{ + title: "SearchResults", + type: :object, + properties: %{ + accounts: %Schema{ + type: :array, + items: Account, + description: "Accounts which match the given query" + }, + statuses: %Schema{ + type: :array, + items: Status, + description: "Statuses which match the given query" + }, + hashtags: %Schema{ + type: :array, + items: Tag, + description: "Hashtags which match the given query" + } + }, + example: %{ + "accounts" => [Account.schema().example], + "statuses" => [Status.schema().example], + "hashtags" => [Tag.schema().example] + } + } + end + + defp results do + %Schema{ + title: "SearchResults", + type: :object, + properties: %{ + accounts: %Schema{ + type: :array, + items: Account, + description: "Accounts which match the given query" + }, + statuses: %Schema{ + type: :array, + items: Status, + description: "Statuses which match the given query" + }, + hashtags: %Schema{ + type: :array, + items: %Schema{type: :string}, + description: "Hashtags which match the given query" + } + }, + example: %{ + "accounts" => [Account.schema().example], + "statuses" => [Status.schema().example], + "hashtags" => ["cofe"] + } + } + end +end diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex index 7a804461f..2572c9641 100644 --- a/lib/pleroma/web/api_spec/schemas/status.ex +++ b/lib/pleroma/web/api_spec/schemas/status.ex @@ -9,6 +9,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do alias Pleroma.Web.ApiSpec.Schemas.Emoji alias Pleroma.Web.ApiSpec.Schemas.FlakeID alias Pleroma.Web.ApiSpec.Schemas.Poll + alias Pleroma.Web.ApiSpec.Schemas.Tag alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope require OpenApiSpex @@ -106,16 +107,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do replies_count: %Schema{type: :integer}, sensitive: %Schema{type: :boolean}, spoiler_text: %Schema{type: :string}, - tags: %Schema{ - type: :array, - items: %Schema{ - type: :object, - properties: %{ - name: %Schema{type: :string}, - url: %Schema{type: :string, format: :uri} - } - } - }, + tags: %Schema{type: :array, items: Tag}, uri: %Schema{type: :string, format: :uri}, url: %Schema{type: :string, nullable: true, format: :uri}, visibility: VisibilityScope diff --git a/lib/pleroma/web/api_spec/schemas/tag.ex b/lib/pleroma/web/api_spec/schemas/tag.ex new file mode 100644 index 000000000..e693fb83e --- /dev/null +++ b/lib/pleroma/web/api_spec/schemas/tag.ex @@ -0,0 +1,27 @@ +# 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.Tag do + alias OpenApiSpex.Schema + + require OpenApiSpex + + OpenApiSpex.schema(%{ + title: "Tag", + description: "Represents a hashtag used within the content of a status", + type: :object, + properties: %{ + name: %Schema{type: :string, description: "The value of the hashtag after the # sign"}, + url: %Schema{ + type: :string, + format: :uri, + description: "A link to the hashtag on the instance" + } + }, + example: %{ + name: "cofe", + url: "https://lain.com/tag/cofe" + } + }) +end diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex index cd49da6ad..0e0d54ba4 100644 --- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do use Pleroma.Web, :controller - import Pleroma.Web.ControllerHelper, only: [fetch_integer_param: 2, skip_relationships?: 1] + import Pleroma.Web.ControllerHelper, only: [skip_relationships?: 1] alias Pleroma.Activity alias Pleroma.Plugs.OAuthScopesPlug @@ -18,6 +18,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do require Logger + plug(Pleroma.Web.ApiSpec.CastAndValidate) + # Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search) plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated}) @@ -25,7 +27,9 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do plug(RateLimiter, [name: :search] when action in [:search, :search2, :account_search]) - def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.SearchOperation + + def account_search(%{assigns: %{user: user}} = conn, %{q: query} = params) do accounts = User.search(query, search_options(params, user)) conn @@ -36,7 +40,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do def search2(conn, params), do: do_search(:v2, conn, params) def search(conn, params), do: do_search(:v1, conn, params) - defp do_search(version, %{assigns: %{user: user}} = conn, %{"q" => query} = params) do + defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do options = search_options(params, user) timeout = Keyword.get(Repo.config(), :timeout, 15_000) default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []} @@ -44,7 +48,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do result = default_values |> Enum.map(fn {resource, default_value} -> - if params["type"] in [nil, resource] do + if params[:type] in [nil, resource] do {resource, fn -> resource_search(version, resource, query, options) end} else {resource, fn -> default_value end} @@ -68,11 +72,11 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do defp search_options(params, user) do [ skip_relationships: skip_relationships?(params), - resolve: params["resolve"] == "true", - following: params["following"] == "true", - limit: fetch_integer_param(params, "limit"), - offset: fetch_integer_param(params, "offset"), - type: params["type"], + resolve: params[:resolve], + following: params[:following], + limit: params[:limit], + offset: params[:offset], + type: params[:type], author: get_author(params), for_user: user ] @@ -135,7 +139,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do end end - defp get_author(%{"account_id" => account_id}) when is_binary(account_id), + defp get_author(%{account_id: account_id}) when is_binary(account_id), do: User.get_cached_by_id(account_id) defp get_author(_params), do: nil |