Merge branch 'bugfix/notice-external-redirect' into 'develop'
authorHaelwenn <contact+git.pleroma.social@hacktivis.me>
Thu, 4 Feb 2021 14:26:03 +0000 (14:26 +0000)
committerHaelwenn <contact+git.pleroma.social@hacktivis.me>
Thu, 4 Feb 2021 14:26:03 +0000 (14:26 +0000)
Redirect non-local activities when /notice/:id is used

See merge request pleroma/pleroma!3300

65 files changed:
.gitlab-ci.yml
CHANGELOG.md
benchmarks/load_testing/fetcher.ex
config/config.exs
config/emoji.txt
docs/development/API/admin_api.md
lib/mix/tasks/pleroma/openapi_spec.ex [new file with mode: 0644]
lib/pleroma/emoji/loader.ex
lib/pleroma/filter.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
lib/pleroma/web/admin_api/views/status_view.ex
lib/pleroma/web/api_spec.ex
lib/pleroma/web/api_spec/helpers.ex
lib/pleroma/web/api_spec/operations/account_operation.ex
lib/pleroma/web/api_spec/operations/admin/chat_operation.ex
lib/pleroma/web/api_spec/operations/admin/config_operation.ex
lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex
lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex
lib/pleroma/web/api_spec/operations/admin/invite_operation.ex
lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex
lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex
lib/pleroma/web/api_spec/operations/admin/relay_operation.ex
lib/pleroma/web/api_spec/operations/admin/report_operation.ex
lib/pleroma/web/api_spec/operations/admin/status_operation.ex
lib/pleroma/web/api_spec/operations/app_operation.ex
lib/pleroma/web/api_spec/operations/chat_operation.ex
lib/pleroma/web/api_spec/operations/conversation_operation.ex
lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex
lib/pleroma/web/api_spec/operations/domain_block_operation.ex
lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex
lib/pleroma/web/api_spec/operations/filter_operation.ex
lib/pleroma/web/api_spec/operations/follow_request_operation.ex
lib/pleroma/web/api_spec/operations/instance_operation.ex
lib/pleroma/web/api_spec/operations/list_operation.ex
lib/pleroma/web/api_spec/operations/media_operation.ex
lib/pleroma/web/api_spec/operations/notification_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_instances_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex
lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex
lib/pleroma/web/api_spec/operations/report_operation.ex
lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex
lib/pleroma/web/api_spec/operations/status_operation.ex
lib/pleroma/web/api_spec/operations/subscription_operation.ex
lib/pleroma/web/api_spec/operations/timeline_operation.ex
lib/pleroma/web/api_spec/operations/user_import_operation.ex
lib/pleroma/web/api_spec/schemas/account.ex
lib/pleroma/web/api_spec/schemas/account_relationship.ex
lib/pleroma/web/api_spec/schemas/scheduled_status.ex
lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
lib/pleroma/workers/purge_expired_filter.ex [new file with mode: 0644]
lib/pleroma/workers/scheduled_activity_worker.ex
test/config/emoji.txt [new file with mode: 0644]
test/pleroma/config/deprecation_warnings_test.exs
test/pleroma/filter_test.exs
test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs
test/pleroma/web/mastodon_api/controllers/filter_controller_test.exs
test/pleroma/web/mastodon_api/controllers/status_controller_test.exs
test/pleroma/workers/purge_expired_filter_test.exs [new file with mode: 0644]
test/pleroma/workers/scheduled_activity_worker_test.exs
test/support/factory.ex

index 9ef3ddd0dd7830dc785e4b217e146945a676f441..0fec893684a316ad4ecf15db972b2381a458ca17 100644 (file)
@@ -34,6 +34,14 @@ build:
   - mix deps.get
   - mix compile --force
 
+spec-build:
+  stage: test
+  artifacts:
+    paths:
+    - spec.json
+  script:
+  - mix pleroma.openapi_spec spec.json
+
 benchmark:
   stage: benchmark
   when: manual
@@ -155,6 +163,20 @@ review_app:
     - (ssh -t dokku@pleroma.online -- certs:add "$CI_ENVIRONMENT_SLUG" /home/dokku/server.crt /home/dokku/server.key) || true
     - git push -f dokku@pleroma.online:$CI_ENVIRONMENT_SLUG $CI_COMMIT_SHA:refs/heads/master
 
+spec-deploy:
+  stage: deploy
+  artifacts:
+    paths:
+    - spec.json
+  only:
+    - develop@pleroma/pleroma
+  image: alpine:latest
+  before_script:
+    - apk add curl
+  script:
+    - curl -X POST -F"token=$API_DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline
+  
 stop_review_app:
   image: alpine:3.9
   stage: deploy
index e9dfac97ea6b30da6559af0c5418c9dc7f70d922..1dbdb3f4e04175052b9396185b8718742a49afbc 100644 (file)
@@ -10,20 +10,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 - **Breaking**: Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm`
 - **Breaking**: Changed `mix pleroma.user toggle_activated` to `mix pleroma.user activate/deactivate`
-- **Breaking**: AdminAPI changed User field `confirmation_pending` to `is_confirmed`
-- **Breaking**: AdminAPI changed User field `approval_pending` to `is_approved`
-- **Breaking**: AdminAPI changed User field `deactivated` to `is_active`
 - Polls now always return a `voters_count`, even if they are single-choice.
 - Admin Emails: The ap id is used as the user link in emails now.
 - Improved registration workflow for email confirmation and account approval modes.
 - Search: When using Postgres 11+, Pleroma will use the `websearch_to_tsvector` function to parse search queries.
 - Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators.
-- Admin API: Reports now ordered by newest
 - Deprecated `Pleroma.Uploaders.S3, :public_endpoint`. Now `Pleroma.Upload, :base_url` is the standard configuration key for all uploaders.
 - Improved Apache webserver support: updated sample configuration, MediaProxy cache invalidation verified with the included sample script
 - Improve OAuth 2.0 provider support. A missing `fqn` field was added to the response, but does not expose the user's email address.
 - Provide redirect of external posts from `/notice/:id` to their original URL
 
+<details>
+  <summary>API Changes</summary>
+
+- **Breaking:** AdminAPI changed User field `confirmation_pending` to `is_confirmed`
+- **Breaking:** AdminAPI changed User field `approval_pending` to `is_approved`
+- **Breaking**: AdminAPI changed User field `deactivated` to `is_active`
+- **Breaking:** AdminAPI `GET /api/pleroma/admin/users/:nickname_or_id/statuses` changed response format and added the number of total users posts.
+- **Breaking:** AdminAPI `GET /api/pleroma/admin/instances/:instance/statuses` changed response format and added the number of total users posts.
+- Admin API: Reports now ordered by newest
+
+</details>
+
 ### Added
 
 - Reports now generate notifications for admins and mods.
@@ -73,6 +81,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
   - Mastodon API: Fixed last_status.account being not filled with account data.
   - Mastodon API: Fix not being able to add or remove multiple users at once in lists.
   - Mastodon API: Fixed own_votes being not returned with poll data.
+  - Mastodon API: Fixed creation of scheduled posts with polls.
+  - Mastodon API: Support for expires_in/expires_at in the Filters.
 </details>
 
 ## Unreleased (Patch)
index dfbd916bef3757ef988803a2e20fe82139705e4b..607b7d4cb662c01718115f97f5767a13f870cf20 100644 (file)
@@ -33,10 +33,11 @@ defmodule Pleroma.LoadTesting.Fetcher do
   end
 
   defp create_filter(user) do
-    Pleroma.Filter.create(%Pleroma.Filter{
+    Pleroma.Filter.create(%{
       user_id: user.id,
       phrase: "must be filtered",
-      hide: true
+      hide: true,
+      context: ["home"]
     })
   end
 
index b9af250c5f2f1e28fb6d1fcad718512e7946e8a0..0fbca06f3f8f8d2cd35c0cdef8a39c0fb378efea 100644 (file)
@@ -543,6 +543,7 @@ config :pleroma, Oban,
   queues: [
     activity_expiration: 10,
     token_expiration: 5,
+    filter_expiration: 1,
     backup: 1,
     federator_incoming: 50,
     federator_outgoing: 50,
index a2c5add2e873728aef8e878a04bc74d4a50c4e03..52b714ee5d28e0ad3c90c40e1531d0aff3cdc6d8 100644 (file)
@@ -1,4 +1,3 @@
 firefox, /emoji/Firefox.gif, Gif,Fun
 blank, /emoji/blank.png, Fun
 dinosaur, /emoji/dino walking.gif, Gif
-external_emoji, https://example.com/emoji.png
index 5253dc6689cce569d3cb78514d9bf7969e49e167..04a1814016cf86c03b85bbc2c16064242a82297f 100644 (file)
@@ -287,7 +287,18 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
   - *optional* `with_reblogs`: `true`/`false` – allows to see reblogs (default is false)
 - Response:
   - On failure: `Not found`
-  - On success: JSON array of user's latest statuses
+ - On success: JSON, where:
+    - `total`: total count of the statuses for the user
+    - `activities`: list of the statuses for the user
+
+```json
+{
+  "total" : 1,
+  "activities": [
+    // activities list
+  ]
+}
+```
 
 ## `GET /api/pleroma/admin/instances/:instance/statuses`
 
@@ -300,7 +311,18 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
   - *optional* `with_reblogs`: `true`/`false` – allows to see reblogs (default is false)
 - Response:
   - On failure: `Not found`
-  - On success: JSON array of instance's latest statuses
+  - On success: JSON, where:
+    - `total`: total count of the statuses for the instance
+    - `activities`: list of the statuses for the instance
+
+```json
+{
+  "total" : 1,
+  "activities": [
+    // activities list
+  ]
+}
+```
 
 ## `GET /api/pleroma/admin/statuses`
 
diff --git a/lib/mix/tasks/pleroma/openapi_spec.ex b/lib/mix/tasks/pleroma/openapi_spec.ex
new file mode 100644 (file)
index 0000000..524bf51
--- /dev/null
@@ -0,0 +1,6 @@
+defmodule Mix.Tasks.Pleroma.OpenapiSpec do
+  def run([path]) do
+    spec = Pleroma.Web.ApiSpec.spec(server_specific: false) |> Jason.encode!()
+    File.write(path, spec)
+  end
+end
index 028cf5ea86487a9802ddde3eb002cc5d0929b90d..cc25dabf926255aa395ffd5fe81555e404d4b987 100644 (file)
@@ -77,10 +77,19 @@ defmodule Pleroma.Emoji.Loader do
     # it should run even if there are no emoji packs
     shortcode_globs = Config.get([:emoji, :shortcode_globs], [])
 
+    # for testing emoji.txt entries we do not want exposed in normal operation
+    test_emoji =
+      if Mix.env() == :test do
+        load_from_file("test/config/emoji.txt", emoji_groups)
+      else
+        []
+      end
+
     emojis_txt =
       (load_from_file("config/emoji.txt", emoji_groups) ++
          load_from_file("config/custom_emoji.txt", emoji_groups) ++
-         load_from_globs(shortcode_globs, emoji_groups))
+         load_from_globs(shortcode_globs, emoji_groups) ++
+         test_emoji)
       |> Enum.reject(fn value -> value == nil end)
 
     Enum.map(emojis ++ emojis_txt, &prepare_emoji/1)
index fc531f7fcdd7eef6e5821e066143bde394303424..82b9caf9b5c8e4589ed97d395f15fda29ec3d636 100644 (file)
@@ -11,6 +11,9 @@ defmodule Pleroma.Filter do
   alias Pleroma.Repo
   alias Pleroma.User
 
+  @type t() :: %__MODULE__{}
+  @type format() :: :postgres | :re
+
   schema "filters" do
     belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
     field(:filter_id, :integer)
@@ -18,15 +21,16 @@ defmodule Pleroma.Filter do
     field(:whole_word, :boolean, default: true)
     field(:phrase, :string)
     field(:context, {:array, :string})
-    field(:expires_at, :utc_datetime)
+    field(:expires_at, :naive_datetime)
 
     timestamps()
   end
 
+  @spec get(integer() | String.t(), User.t()) :: t() | nil
   def get(id, %{id: user_id} = _user) do
     query =
       from(
-        f in Pleroma.Filter,
+        f in __MODULE__,
         where: f.filter_id == ^id,
         where: f.user_id == ^user_id
       )
@@ -34,14 +38,17 @@ defmodule Pleroma.Filter do
     Repo.one(query)
   end
 
+  @spec get_active(Ecto.Query.t() | module()) :: Ecto.Query.t()
   def get_active(query) do
     from(f in query, where: is_nil(f.expires_at) or f.expires_at > ^NaiveDateTime.utc_now())
   end
 
+  @spec get_irreversible(Ecto.Query.t()) :: Ecto.Query.t()
   def get_irreversible(query) do
     from(f in query, where: f.hide)
   end
 
+  @spec get_filters(Ecto.Query.t() | module(), User.t()) :: [t()]
   def get_filters(query \\ __MODULE__, %User{id: user_id}) do
     query =
       from(
@@ -53,7 +60,32 @@ defmodule Pleroma.Filter do
     Repo.all(query)
   end
 
-  def create(%Pleroma.Filter{user_id: user_id, filter_id: nil} = filter) do
+  @spec create(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
+  def create(attrs \\ %{}) do
+    Repo.transaction(fn -> create_with_expiration(attrs) end)
+  end
+
+  defp create_with_expiration(attrs) do
+    with {:ok, filter} <- do_create(attrs),
+         {:ok, _} <- maybe_add_expiration_job(filter) do
+      filter
+    else
+      {:error, error} -> Repo.rollback(error)
+    end
+  end
+
+  defp do_create(attrs) do
+    %__MODULE__{}
+    |> cast(attrs, [:phrase, :context, :hide, :expires_at, :whole_word, :user_id, :filter_id])
+    |> maybe_add_filter_id()
+    |> validate_required([:phrase, :context, :user_id, :filter_id])
+    |> maybe_add_expires_at(attrs)
+    |> Repo.insert()
+  end
+
+  defp maybe_add_filter_id(%{changes: %{filter_id: _}} = changeset), do: changeset
+
+  defp maybe_add_filter_id(%{changes: %{user_id: user_id}} = changeset) do
     # If filter_id wasn't given, use the max filter_id for this user plus 1.
     # XXX This could result in a race condition if a user tries to add two
     # different filters for their account from two different clients at the
@@ -61,7 +93,7 @@ defmodule Pleroma.Filter do
 
     max_id_query =
       from(
-        f in Pleroma.Filter,
+        f in __MODULE__,
         where: f.user_id == ^user_id,
         select: max(f.filter_id)
       )
@@ -76,34 +108,92 @@ defmodule Pleroma.Filter do
           max_id + 1
       end
 
-    filter
-    |> Map.put(:filter_id, filter_id)
-    |> Repo.insert()
+    change(changeset, filter_id: filter_id)
+  end
+
+  # don't override expires_at, if passed expires_at and expires_in
+  defp maybe_add_expires_at(%{changes: %{expires_at: %NaiveDateTime{} = _}} = changeset, _) do
+    changeset
   end
 
-  def create(%Pleroma.Filter{} = filter) do
-    Repo.insert(filter)
+  defp maybe_add_expires_at(changeset, %{expires_in: expires_in})
+       when is_integer(expires_in) and expires_in > 0 do
+    expires_at =
+      NaiveDateTime.utc_now()
+      |> NaiveDateTime.add(expires_in)
+      |> NaiveDateTime.truncate(:second)
+
+    change(changeset, expires_at: expires_at)
   end
 
-  def delete(%Pleroma.Filter{id: filter_key} = filter) when is_number(filter_key) do
-    Repo.delete(filter)
+  defp maybe_add_expires_at(changeset, %{expires_in: nil}) do
+    change(changeset, expires_at: nil)
   end
 
-  def delete(%Pleroma.Filter{id: filter_key} = filter) when is_nil(filter_key) do
-    %Pleroma.Filter{id: id} = get(filter.filter_id, %{id: filter.user_id})
+  defp maybe_add_expires_at(changeset, _), do: changeset
 
-    filter
-    |> Map.put(:id, id)
-    |> Repo.delete()
+  defp maybe_add_expiration_job(%{expires_at: %NaiveDateTime{} = expires_at} = filter) do
+    Pleroma.Workers.PurgeExpiredFilter.enqueue(%{
+      filter_id: filter.id,
+      expires_at: DateTime.from_naive!(expires_at, "Etc/UTC")
+    })
   end
 
-  def update(%Pleroma.Filter{} = filter, params) do
+  defp maybe_add_expiration_job(_), do: {:ok, nil}
+
+  @spec delete(t()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
+  def delete(%__MODULE__{} = filter) do
+    Repo.transaction(fn -> delete_with_expiration(filter) end)
+  end
+
+  defp delete_with_expiration(filter) do
+    with {:ok, _} <- maybe_delete_old_expiration_job(filter, nil),
+         {:ok, filter} <- Repo.delete(filter) do
+      filter
+    else
+      {:error, error} -> Repo.rollback(error)
+    end
+  end
+
+  @spec update(t(), map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
+  def update(%__MODULE__{} = filter, params) do
+    Repo.transaction(fn -> update_with_expiration(filter, params) end)
+  end
+
+  defp update_with_expiration(filter, params) do
+    with {:ok, updated} <- do_update(filter, params),
+         {:ok, _} <- maybe_delete_old_expiration_job(filter, updated),
+         {:ok, _} <-
+           maybe_add_expiration_job(updated) do
+      updated
+    else
+      {:error, error} -> Repo.rollback(error)
+    end
+  end
+
+  defp do_update(filter, params) do
     filter
     |> cast(params, [:phrase, :context, :hide, :expires_at, :whole_word])
     |> validate_required([:phrase, :context])
+    |> maybe_add_expires_at(params)
     |> Repo.update()
   end
 
+  defp maybe_delete_old_expiration_job(%{expires_at: nil}, _), do: {:ok, nil}
+
+  defp maybe_delete_old_expiration_job(%{expires_at: expires_at}, %{expires_at: expires_at}) do
+    {:ok, nil}
+  end
+
+  defp maybe_delete_old_expiration_job(%{id: id}, _) do
+    with %Oban.Job{} = job <- Pleroma.Workers.PurgeExpiredFilter.get_expiration(id) do
+      Repo.delete(job)
+    else
+      nil -> {:ok, nil}
+    end
+  end
+
+  @spec compose_regex(User.t() | [t()], format()) :: String.t() | Regex.t() | nil
   def compose_regex(user_or_filters, format \\ :postgres)
 
   def compose_regex(%User{} = user, format) do
index 98051032aca1b10cb23353be274017556eed7449..1a84375fb38166c5d1b9f5e2002736e330c3d2c1 100644 (file)
@@ -591,7 +591,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> Enum.reverse()
   end
 
-  def fetch_user_activities(user, reading_user, params \\ %{}) do
+  def fetch_user_activities(user, reading_user, params \\ %{})
+
+  def fetch_user_activities(user, reading_user, %{total: true} = params) do
+    result = fetch_activities_for_user(user, reading_user, params)
+
+    Keyword.put(result, :items, Enum.reverse(result[:items]))
+  end
+
+  def fetch_user_activities(user, reading_user, params) do
+    user
+    |> fetch_activities_for_user(reading_user, params)
+    |> Enum.reverse()
+  end
+
+  defp fetch_activities_for_user(user, reading_user, params) do
     params =
       params
       |> Map.put(:type, ["Create", "Announce"])
@@ -616,10 +630,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     }
     |> user_activities_recipients()
     |> fetch_activities(params, pagination_type)
-    |> Enum.reverse()
+  end
+
+  def fetch_statuses(reading_user, %{total: true} = params) do
+    result = fetch_activities_for_reading_user(reading_user, params)
+    Keyword.put(result, :items, Enum.reverse(result[:items]))
   end
 
   def fetch_statuses(reading_user, params) do
+    reading_user
+    |> fetch_activities_for_reading_user(params)
+    |> Enum.reverse()
+  end
+
+  defp fetch_activities_for_reading_user(reading_user, params) do
     params = Map.put(params, :type, ["Create", "Announce"])
 
     %{
@@ -628,7 +652,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     }
     |> user_activities_recipients()
     |> fetch_activities(params, :offset)
-    |> Enum.reverse()
   end
 
   defp user_activities_recipients(%{godmode: true}), do: []
index 709c863ecc77181b5bb7ba1331677fb4e0c9c16a..8f89f066ab2eefce89654a58cb5b958bb1b97a18 100644 (file)
@@ -85,17 +85,18 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
     with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
     {page, page_size} = page_params(params)
 
-    activities =
+    result =
       ActivityPub.fetch_statuses(nil, %{
         instance: instance,
         limit: page_size,
         offset: (page - 1) * page_size,
-        exclude_reblogs: not with_reblogs
+        exclude_reblogs: not with_reblogs,
+        total: true
       })
 
     conn
     |> put_view(AdminAPI.StatusView)
-    |> render("index.json", %{activities: activities, as: :activity})
+    |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity})
   end
 
   def list_user_statuses(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = params) do
@@ -105,18 +106,19 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
     with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
       {page, page_size} = page_params(params)
 
-      activities =
+      result =
         ActivityPub.fetch_user_activities(user, nil, %{
           limit: page_size,
           offset: (page - 1) * page_size,
           godmode: godmode,
           exclude_reblogs: not with_reblogs,
-          pagination_type: :offset
+          pagination_type: :offset,
+          total: true
         })
 
       conn
       |> put_view(AdminAPI.StatusView)
-      |> render("index.json", %{activities: activities, as: :activity})
+      |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity})
     else
       _ -> {:error, :not_found}
     end
index 361fa5b0d604dbcd6f1dec13154c55d7c3232e6a..48d639b410bcb0ee230d195e5d9cdae5a0845482 100644 (file)
@@ -13,6 +13,10 @@ defmodule Pleroma.Web.AdminAPI.StatusView do
 
   defdelegate merge_account_views(user), to: AdminAPI.AccountView
 
+  def render("index.json", %{total: total} = opts) do
+    %{total: total, activities: safe_render_many(opts.activities, __MODULE__, "show.json", opts)}
+  end
+
   def render("index.json", opts) do
     safe_render_many(opts.activities, __MODULE__, "show.json", opts)
   end
index 0645585971cbd5063f5dd6d5dc59daf35ecf8806..81b7bc9e843049b66f8979b4f8142cf8089ec8a6 100644 (file)
@@ -11,10 +11,10 @@ defmodule Pleroma.Web.ApiSpec do
   @behaviour OpenApi
 
   @impl OpenApi
-  def spec do
+  def spec(opts \\ []) do
     %OpenApi{
       servers:
-        if Phoenix.Endpoint.server?(:pleroma, Endpoint) do
+        if opts[:server_specific] do
           [
             # Populate the Server info from a phoenix endpoint
             OpenApiSpex.Server.from_endpoint(Endpoint)
@@ -23,9 +23,25 @@ defmodule Pleroma.Web.ApiSpec do
           []
         end,
       info: %OpenApiSpex.Info{
-        title: "Pleroma",
-        description: Application.spec(:pleroma, :description) |> to_string(),
-        version: Application.spec(:pleroma, :vsn) |> to_string()
+        title: "Pleroma API",
+        description: """
+        This is documentation for client Pleroma API. Most of the endpoints and entities come
+        from Mastodon API and have custom extensions on top.
+
+        While this document aims to be a complete guide to the client API Pleroma exposes,
+        the details are still being worked out. Some endpoints may have incomplete or poorly worded documentation.
+        You might want to check the following resources if something is not clear:
+        - [Legacy Pleroma-specific endpoint documentation](https://docs-develop.pleroma.social/backend/development/API/pleroma_api/)
+        - [Mastodon API documentation](https://docs.joinmastodon.org/client/intro/)
+        - [Differences in Mastodon API responses from vanilla Mastodon](https://docs-develop.pleroma.social/backend/development/API/differences_in_mastoapi_responses/)
+
+        Please report such occurences on our [issue tracker](https://git.pleroma.social/pleroma/pleroma/-/issues). Feel free to submit API questions or proposals there too!
+        """,
+        version: Application.spec(:pleroma, :vsn) |> to_string(),
+        extensions: %{
+          # Logo path should be picked so that the path exists both on Pleroma instances and on api.pleroma.social
+          "x-logo": %{"url" => "/static/logo.svg", "altText" => "Pleroma logo"}
+        }
       },
       # populate the paths from a phoenix router
       paths: OpenApiSpex.Paths.from_router(Router),
@@ -45,15 +61,73 @@ defmodule Pleroma.Web.ApiSpec do
                 authorizationUrl: "/oauth/authorize",
                 tokenUrl: "/oauth/token",
                 scopes: %{
-                  "read" => "read",
-                  "write" => "write",
-                  "follow" => "follow",
-                  "push" => "push"
+                  # TODO: Document granular scopes
+                  "read" => "Read everything",
+                  "write" => "Write everything",
+                  "follow" => "Manage relationships",
+                  "push" => "Web Push API subscriptions"
                 }
               }
             }
           }
         }
+      },
+      extensions: %{
+        # Redoc-specific extension, every time a new tag is added it should be reflected here,
+        # otherwise it won't be shown.
+        "x-tagGroups": [
+          %{
+            "name" => "Accounts",
+            "tags" => ["Account actions", "Retrieve account information", "Scrobbles"]
+          },
+          %{
+            "name" => "Administration",
+            "tags" => [
+              "Chat administration",
+              "Emoji packs",
+              "Frontend managment",
+              "Instance configuration",
+              "Instance documents",
+              "Invites",
+              "MediaProxy cache",
+              "OAuth application managment",
+              "Report managment",
+              "Relays",
+              "Status administration"
+            ]
+          },
+          %{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
+          %{
+            "name" => "Current account",
+            "tags" => [
+              "Account credentials",
+              "Backups",
+              "Blocks and mutes",
+              "Data import",
+              "Domain blocks",
+              "Follow requests",
+              "Mascot",
+              "Markers",
+              "Notifications"
+            ]
+          },
+          %{"name" => "Instance", "tags" => ["Custom emojis"]},
+          %{"name" => "Messaging", "tags" => ["Chats", "Conversations"]},
+          %{
+            "name" => "Statuses",
+            "tags" => [
+              "Emoji reactions",
+              "Lists",
+              "Polls",
+              "Timelines",
+              "Retrieve status information",
+              "Scheduled statuses",
+              "Search",
+              "Status actions"
+            ]
+          },
+          %{"name" => "Miscellaneous", "tags" => ["Reports", "Suggestions"]}
+        ]
       }
     }
     # discover request/response schemas from path specs
index 6babe0b28bfb237ceff2f50e1cfed0df87188738..6f67339e61a021e48efef0d86ad5bfbb8c68f6b4 100644 (file)
@@ -63,7 +63,7 @@ defmodule Pleroma.Web.ApiSpec.Helpers do
       :with_relationships,
       :query,
       BooleanLike,
-      "Embed relationships into accounts."
+      "Embed relationships into accounts. **If this parameter is not set account's `pleroma.relationship` is going to be `null`.**"
     )
   end
 
index 3d451cd5af5e23d5cc3b76912fc176f54d0ae8e8..54e5ebc76e2ae943e02b3026d85799f7cf511641 100644 (file)
@@ -26,7 +26,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
   @spec create_operation() :: Operation.t()
   def create_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account credentials"],
       summary: "Register an account",
       description:
         "Creates a user and account records. Returns an account access token for the app that initiated the request. The app should save this token for later, and should wait for the user to confirm their account by clicking a link in their email inbox.",
@@ -43,7 +43,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def verify_credentials_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account credentials"],
       description: "Test to make sure that the user token works.",
       summary: "Verify account credentials",
       operationId: "AccountController.verify_credentials",
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def update_credentials_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account credentials"],
       summary: "Update account credentials",
       description: "Update the user's display and preferences.",
       operationId: "AccountController.update_credentials",
@@ -71,8 +71,8 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def relationships_operation do
     %Operation{
-      tags: ["accounts"],
-      summary: "Check relationships to other accounts",
+      tags: ["Retrieve account information"],
+      summary: "Relationship with current account",
       operationId: "AccountController.relationships",
       description: "Find out whether a given account is followed, blocked, muted, etc.",
       security: [%{"oAuth" => ["read:follows"]}],
@@ -95,7 +95,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def show_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Retrieve account information"],
       summary: "Account",
       operationId: "AccountController.show",
       description: "View information about a profile.",
@@ -113,8 +113,8 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def statuses_operation do
     %Operation{
-      tags: ["accounts"],
       summary: "Statuses",
+      tags: ["Retrieve account information"],
       operationId: "AccountController.statuses",
       description:
         "Statuses posted to the given account. Public (for public statuses only), or user token + `read:statuses` (for private statuses the user is authorized to see)",
@@ -160,7 +160,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def followers_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Retrieve account information"],
       summary: "Followers",
       operationId: "AccountController.followers",
       security: [%{"oAuth" => ["read:accounts"]}],
@@ -179,7 +179,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def following_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Retrieve account information"],
       summary: "Following",
       operationId: "AccountController.following",
       security: [%{"oAuth" => ["read:accounts"]}],
@@ -196,7 +196,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def lists_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Retrieve account information"],
       summary: "Lists containing this account",
       operationId: "AccountController.lists",
       security: [%{"oAuth" => ["read:lists"]}],
@@ -208,7 +208,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def follow_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Follow",
       operationId: "AccountController.follow",
       security: [%{"oAuth" => ["follow", "write:follows"]}],
@@ -241,7 +241,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def unfollow_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Unfollow",
       operationId: "AccountController.unfollow",
       security: [%{"oAuth" => ["follow", "write:follows"]}],
@@ -257,7 +257,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def mute_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Mute",
       operationId: "AccountController.mute",
       security: [%{"oAuth" => ["follow", "write:mutes"]}],
@@ -287,7 +287,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def unmute_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Unmute",
       operationId: "AccountController.unmute",
       security: [%{"oAuth" => ["follow", "write:mutes"]}],
@@ -301,7 +301,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def block_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Block",
       operationId: "AccountController.block",
       security: [%{"oAuth" => ["follow", "write:blocks"]}],
@@ -316,7 +316,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def unblock_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Unblock",
       operationId: "AccountController.unblock",
       security: [%{"oAuth" => ["follow", "write:blocks"]}],
@@ -330,7 +330,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def follow_by_uri_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Account actions"],
       summary: "Follow by URI",
       operationId: "AccountController.follows",
       security: [%{"oAuth" => ["follow", "write:follows"]}],
@@ -345,8 +345,8 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def mutes_operation do
     %Operation{
-      tags: ["accounts"],
-      summary: "Muted accounts",
+      tags: ["Blocks and mutes"],
+      summary: "Retrieve list of mutes",
       operationId: "AccountController.mutes",
       description: "Accounts the user has muted.",
       security: [%{"oAuth" => ["follow", "read:mutes"]}],
@@ -359,8 +359,8 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def blocks_operation do
     %Operation{
-      tags: ["accounts"],
-      summary: "Blocked users",
+      tags: ["Blocks and mutes"],
+      summary: "Retrieve list of blocks",
       operationId: "AccountController.blocks",
       description: "View your blocks. See also accounts/:id/{block,unblock}",
       security: [%{"oAuth" => ["read:blocks"]}],
@@ -373,7 +373,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def endorsements_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Retrieve account information"],
       summary: "Endorsements",
       operationId: "AccountController.endorsements",
       description: "Not implemented",
@@ -386,7 +386,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
 
   def identity_proofs_operation do
     %Operation{
-      tags: ["accounts"],
+      tags: ["Retrieve account information"],
       summary: "Identity proofs",
       operationId: "AccountController.identity_proofs",
       # Validators complains about unused path params otherwise
index 8062da9879184f8214e677bbd0232f773ff60e50..cbe4b89720ff664ddb5591bd550426033855dc7d 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do
 
   def delete_message_operation do
     %Operation{
-      tags: ["admin", "chat"],
+      tags: ["Chat administration"],
       summary: "Delete an individual chat message",
       operationId: "AdminAPI.ChatController.delete_message",
       parameters: [
@@ -41,8 +41,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do
 
   def messages_operation do
     %Operation{
-      tags: ["admin", "chat"],
-      summary: "Get the most recent messages of the chat",
+      tags: ["Chat administration"],
+      summary: "Get chat's messages",
       operationId: "AdminAPI.ChatController.messages",
       parameters:
         [Operation.parameter(:id, :path, :string, "The ID of the Chat")] ++
@@ -65,7 +65,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do
 
   def show_operation do
     %Operation{
-      tags: ["chat"],
+      tags: ["Chat administration"],
       summary: "Create a chat",
       operationId: "AdminAPI.ChatController.show",
       parameters: [
index 323539ca5a374d7c340954eeb6ad3db39d5be803..b8ccc1d00fe425cdf72c70d613204315830c5db7 100644 (file)
@@ -16,8 +16,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ConfigOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Admin", "Config"],
-      summary: "Get list of merged default settings with saved in database",
+      tags: ["Instance configuration"],
+      summary: "Retrieve instance configuration",
       operationId: "AdminAPI.ConfigController.show",
       parameters: [
         Operation.parameter(
@@ -38,8 +38,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ConfigOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Admin", "Config"],
-      summary: "Update config settings",
+      tags: ["Instance configuration"],
+      summary: "Update instance configuration",
       operationId: "AdminAPI.ConfigController.update",
       security: [%{"oAuth" => ["write"]}],
       parameters: admin_api_params(),
@@ -71,8 +71,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ConfigOperation do
 
   def descriptions_operation do
     %Operation{
-      tags: ["Admin", "Config"],
-      summary: "Get JSON with config descriptions.",
+      tags: ["Instance configuration"],
+      summary: "Retrieve config description",
       operationId: "AdminAPI.ConfigController.descriptions",
       security: [%{"oAuth" => ["read"]}],
       parameters: admin_api_params(),
index 05e2fe2bef7fecef5fcd02ed51b60525ca4dc140..b149becf9bcee480c2e5e2f13a9a03e29c14daae 100644 (file)
@@ -16,8 +16,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
-      summary: "Get a list of available frontends",
+      tags: ["Frontend managment"],
+      summary: "Retrieve a list of available frontends",
       operationId: "AdminAPI.FrontendController.index",
       security: [%{"oAuth" => ["read"]}],
       responses: %{
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
 
   def install_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
+      tags: ["Frontend managment"],
       summary: "Install a frontend",
       operationId: "AdminAPI.FrontendController.install",
       security: [%{"oAuth" => ["read"]}],
index 0e1fdec088bd8152fb2d26959baa23cc2b487cea..3e89abfb587ee136a4fae9abeaaaa1a2a51520bd 100644 (file)
@@ -15,8 +15,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Admin", "InstanceDocument"],
-      summary: "Get the instance document",
+      tags: ["Instance documents"],
+      summary: "Retrieve an instance document",
       operationId: "AdminAPI.InstanceDocumentController.show",
       security: [%{"oAuth" => ["read"]}],
       parameters: [
@@ -36,8 +36,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Admin", "InstanceDocument"],
-      summary: "Update the instance document",
+      tags: ["Instance documents"],
+      summary: "Update an instance document",
       operationId: "AdminAPI.InstanceDocumentController.update",
       security: [%{"oAuth" => ["write"]}],
       requestBody: Helpers.request_body("Parameters", update_request()),
@@ -74,8 +74,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Admin", "InstanceDocument"],
-      summary: "Get the instance document",
+      tags: ["Instance documents"],
+      summary: "Delete an instance document",
       operationId: "AdminAPI.InstanceDocumentController.delete",
       security: [%{"oAuth" => ["write"]}],
       parameters: [
index 0ce7bcc451f9dad4b7db5d9564abb68920612bce..60d69c7673e16dc889ac50cb7d27715c7c949740 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "Invites"],
+      tags: ["Invites"],
       summary: "Get a list of generated invites",
       operationId: "AdminAPI.InviteController.index",
       security: [%{"oAuth" => ["read:invites"]}],
@@ -48,7 +48,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Admin", "Invites"],
+      tags: ["Invites"],
       summary: "Create an account registration invite token",
       operationId: "AdminAPI.InviteController.create",
       security: [%{"oAuth" => ["write:invites"]}],
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
 
   def revoke_operation do
     %Operation{
-      tags: ["Admin", "Invites"],
+      tags: ["Invites"],
       summary: "Revoke invite by token",
       operationId: "AdminAPI.InviteController.revoke",
       security: [%{"oAuth" => ["write:invites"]}],
@@ -96,7 +96,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
 
   def email_operation do
     %Operation{
-      tags: ["Admin", "Invites"],
+      tags: ["Invites"],
       summary: "Sends registration invite via email",
       operationId: "AdminAPI.InviteController.email",
       security: [%{"oAuth" => ["write:invites"]}],
index e16356a479fe14fb467b0da9b0ebd3f24ffc835a..675504ee08f3293d8756a16af52745fda1efaa74 100644 (file)
@@ -16,8 +16,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "MediaProxyCache"],
-      summary: "Fetch a paginated list of all banned MediaProxy URLs in Cachex",
+      tags: ["MediaProxy cache"],
+      summary: "Retrieve a list of banned MediaProxy URLs",
       operationId: "AdminAPI.MediaProxyCacheController.index",
       security: [%{"oAuth" => ["read:media_proxy_caches"]}],
       parameters: [
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
       responses: %{
         200 =>
           Operation.response(
-            "Array of banned MediaProxy URLs in Cachex",
+            "Array of MediaProxy URLs",
             "application/json",
             %Schema{
               type: :object,
@@ -68,8 +68,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Admin", "MediaProxyCache"],
-      summary: "Remove a banned MediaProxy URL from Cachex",
+      tags: ["MediaProxy cache"],
+      summary: "Remove a banned MediaProxy URL",
       operationId: "AdminAPI.MediaProxyCacheController.delete",
       security: [%{"oAuth" => ["write:media_proxy_caches"]}],
       parameters: admin_api_params(),
@@ -94,8 +94,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
 
   def purge_operation do
     %Operation{
-      tags: ["Admin", "MediaProxyCache"],
-      summary: "Purge and optionally ban a MediaProxy URL",
+      tags: ["MediaProxy cache"],
+      summary: "Purge a URL from MediaProxy cache and optionally ban it",
       operationId: "AdminAPI.MediaProxyCacheController.purge",
       security: [%{"oAuth" => ["write:media_proxy_caches"]}],
       parameters: admin_api_params(),
index f1b32343db3759184ff0d3bda419604b46e41fb7..2f3bee4f0b6b9a3374b47443e7f7418e5c8404b5 100644 (file)
@@ -16,8 +16,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
 
   def index_operation do
     %Operation{
-      summary: "List OAuth apps",
-      tags: ["Admin", "oAuth Apps"],
+      summary: "Retrieve a list of OAuth applications",
+      tags: ["OAuth application managment"],
       operationId: "AdminAPI.OAuthAppController.index",
       security: [%{"oAuth" => ["write"]}],
       parameters: [
@@ -69,8 +69,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Admin", "oAuth Apps"],
-      summary: "Create OAuth App",
+      tags: ["OAuth application managment"],
+      summary: "Create an OAuth application",
       operationId: "AdminAPI.OAuthAppController.create",
       requestBody: request_body("Parameters", create_request()),
       parameters: admin_api_params(),
@@ -84,8 +84,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Admin", "oAuth Apps"],
-      summary: "Update OAuth App",
+      tags: ["OAuth application managment"],
+      summary: "Update OAuth application",
       operationId: "AdminAPI.OAuthAppController.update",
       parameters: [id_param() | admin_api_params()],
       security: [%{"oAuth" => ["write"]}],
@@ -102,8 +102,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Admin", "oAuth Apps"],
-      summary: "Delete OAuth App",
+      tags: ["OAuth application managment"],
+      summary: "Delete OAuth application",
       operationId: "AdminAPI.OAuthAppController.delete",
       parameters: [id_param() | admin_api_params()],
       security: [%{"oAuth" => ["write"]}],
index 7a17072e1624de0a142f2decdad605c5c631630b..c47f18f0cee6caa4b439135ef974db5516686fec 100644 (file)
@@ -15,8 +15,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "Relays"],
-      summary: "List Relays",
+      tags: ["Relays"],
+      summary: "Retrieve a list of relays",
       operationId: "AdminAPI.RelayController.index",
       security: [%{"oAuth" => ["read"]}],
       parameters: admin_api_params(),
@@ -37,8 +37,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
 
   def follow_operation do
     %Operation{
-      tags: ["Admin", "Relays"],
-      summary: "Follow a Relay",
+      tags: ["Relays"],
+      summary: "Follow a relay",
       operationId: "AdminAPI.RelayController.follow",
       security: [%{"oAuth" => ["write:follows"]}],
       parameters: admin_api_params(),
@@ -51,8 +51,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
 
   def unfollow_operation do
     %Operation{
-      tags: ["Admin", "Relays"],
-      summary: "Unfollow a Relay",
+      tags: ["Relays"],
+      summary: "Unfollow a relay",
       operationId: "AdminAPI.RelayController.unfollow",
       security: [%{"oAuth" => ["write:follows"]}],
       parameters: admin_api_params(),
index e7acfa27107da71c48324284ce459bf8e19fac18..cfa892d296abba21076839d4b95630e6835d1811 100644 (file)
@@ -19,8 +19,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
-      summary: "Get a list of reports",
+      tags: ["Report managment"],
+      summary: "Retrieve a list of reports",
       operationId: "AdminAPI.ReportController.index",
       security: [%{"oAuth" => ["read:reports"]}],
       parameters: [
@@ -69,8 +69,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
-      summary: "Get an individual report",
+      tags: ["Report managment"],
+      summary: "Retrieve a report",
       operationId: "AdminAPI.ReportController.show",
       parameters: [id_param() | admin_api_params()],
       security: [%{"oAuth" => ["read:reports"]}],
@@ -83,8 +83,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
-      summary: "Change the state of one or multiple reports",
+      tags: ["Report managment"],
+      summary: "Change state of specified reports",
       operationId: "AdminAPI.ReportController.update",
       security: [%{"oAuth" => ["write:reports"]}],
       parameters: admin_api_params(),
@@ -99,8 +99,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
 
   def notes_create_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
-      summary: "Create report note",
+      tags: ["Report managment"],
+      summary: "Add a note to the report",
       operationId: "AdminAPI.ReportController.notes_create",
       parameters: [id_param() | admin_api_params()],
       requestBody:
@@ -120,8 +120,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
 
   def notes_delete_operation do
     %Operation{
-      tags: ["Admin", "Reports"],
-      summary: "Delete report note",
+      tags: ["Report managment"],
+      summary: "Delete note attached to the report",
       operationId: "AdminAPI.ReportController.notes_delete",
       parameters: [
         Operation.parameter(:report_id, :path, :string, "Report ID"),
index 34a0bce07575fa42b37a8e14eeca835a0d68018b..bbfbd8f930bcb69a6f9efb4bd0742d49c7230bc4 100644 (file)
@@ -21,8 +21,9 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
+      tags: ["Status administration"],
       operationId: "AdminAPI.StatusController.index",
+      summary: "Get all statuses",
       security: [%{"oAuth" => ["read:statuses"]}],
       parameters: [
         Operation.parameter(
@@ -69,8 +70,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      summary: "Show Status",
+      tags: ["Status adminitration)"],
+      summary: "Get status",
       operationId: "AdminAPI.StatusController.show",
       parameters: [id_param() | admin_api_params()],
       security: [%{"oAuth" => ["read:statuses"]}],
@@ -83,8 +84,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      summary: "Change the scope of an individual reported status",
+      tags: ["Status adminitration)"],
+      summary: "Change the scope of a status",
       operationId: "AdminAPI.StatusController.update",
       parameters: [id_param() | admin_api_params()],
       security: [%{"oAuth" => ["write:statuses"]}],
@@ -98,8 +99,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Admin", "Statuses"],
-      summary: "Delete an individual reported status",
+      tags: ["Status adminitration)"],
+      summary: "Delete status",
       operationId: "AdminAPI.StatusController.delete",
       parameters: [id_param() | admin_api_params()],
       security: [%{"oAuth" => ["write:statuses"]}],
index 7587e488edc41b848bdf0468f03d4f85a9e9be39..dfb1c71706c4c4ed6b6be97f986f1c6af97aa81d 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.AppOperation do
   @spec create_operation() :: Operation.t()
   def create_operation do
     %Operation{
-      tags: ["apps"],
+      tags: ["Applications"],
       summary: "Create an application",
       description: "Create a new application to obtain OAuth2 credentials",
       operationId: "AppController.create",
@@ -45,8 +45,8 @@ defmodule Pleroma.Web.ApiSpec.AppOperation do
 
   def verify_credentials_operation do
     %Operation{
-      tags: ["apps"],
-      summary: "Verify your app works",
+      tags: ["Applications"],
+      summary: "Verify the application works",
       description: "Confirm that the app's OAuth2 credentials work.",
       operationId: "AppController.verify_credentials",
       security: [%{"oAuth" => ["read"]}],
index e5ee6e695c510f53517a024cff5e7016fad66379..b4970017256ea9e5211655a6b5c75add5c77a216 100644 (file)
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def mark_as_read_operation do
     %Operation{
-      tags: ["chat"],
+      tags: ["Chats"],
       summary: "Mark all messages in the chat as read",
       operationId: "ChatController.mark_as_read",
       parameters: [Operation.parameter(:id, :path, :string, "The ID of the Chat")],
@@ -43,8 +43,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def mark_message_as_read_operation do
     %Operation{
-      tags: ["chat"],
-      summary: "Mark one message in the chat as read",
+      tags: ["Chats"],
+      summary: "Mark a message as read",
       operationId: "ChatController.mark_message_as_read",
       parameters: [
         Operation.parameter(:id, :path, :string, "The ID of the Chat"),
@@ -68,8 +68,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def show_operation do
     %Operation{
-      tags: ["chat"],
-      summary: "Create a chat",
+      tags: ["Chats"],
+      summary: "Retrieve a chat",
       operationId: "ChatController.show",
       parameters: [
         Operation.parameter(
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def create_operation do
     %Operation{
-      tags: ["chat"],
+      tags: ["Chats"],
       summary: "Create a chat",
       operationId: "ChatController.create",
       parameters: [
@@ -130,8 +130,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def index_operation do
     %Operation{
-      tags: ["chat"],
-      summary: "Get a list of chats that you participated in",
+      tags: ["Chats"],
+      summary: "Retrieve list of chats",
       operationId: "ChatController.index",
       parameters: [
         Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
@@ -150,8 +150,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def messages_operation do
     %Operation{
-      tags: ["chat"],
-      summary: "Get the most recent messages of the chat",
+      tags: ["Chats"],
+      summary: "Retrieve chat's messages",
       operationId: "ChatController.messages",
       parameters:
         [Operation.parameter(:id, :path, :string, "The ID of the Chat")] ++
@@ -175,7 +175,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def post_chat_message_operation do
     %Operation{
-      tags: ["chat"],
+      tags: ["Chats"],
       summary: "Post a message to the chat",
       operationId: "ChatController.post_chat_message",
       parameters: [
@@ -202,8 +202,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
 
   def delete_message_operation do
     %Operation{
-      tags: ["chat"],
-      summary: "delete_message",
+      tags: ["Chats"],
+      summary: "Delete message",
       operationId: "ChatController.delete_message",
       parameters: [
         Operation.parameter(:id, :path, :string, "The ID of the Chat"),
index 15fc3d66d48a3580f6b73b809156b8339c9684bf..367f4125a4a3f72c3f76becdcc726bbe72d6f352 100644 (file)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.ApiSpec.ConversationOperation do
   def index_operation do
     %Operation{
       tags: ["Conversations"],
-      summary: "Show conversation",
+      summary: "List of conversations",
       security: [%{"oAuth" => ["read:statuses"]}],
       operationId: "ConversationController.index",
       parameters: [
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.ApiSpec.ConversationOperation do
   def mark_as_read_operation do
     %Operation{
       tags: ["Conversations"],
-      summary: "Mark as read",
+      summary: "Mark conversation as read",
       operationId: "ConversationController.mark_as_read",
       parameters: [
         Operation.parameter(:id, :path, :string, "Conversation ID",
index 541c1ff1ba695d0ae7399ed94cc1cc51faae4ca3..98da1a6dec2390825bdfaba32d40ee7a51a4469a 100644 (file)
@@ -14,8 +14,8 @@ defmodule Pleroma.Web.ApiSpec.CustomEmojiOperation do
 
   def index_operation do
     %Operation{
-      tags: ["custom_emojis"],
-      summary: "List custom custom emojis",
+      tags: ["Custom emojis"],
+      summary: "Retrieve a list of custom emojis",
       description: "Returns custom emojis that are available on the server.",
       operationId: "CustomEmojiController.index",
       responses: %{
index 2be54e3595e9588d2d5b724e40181878f37c68a1..f124e7fe5df0d83a628332c44aace65a5869e3ee 100644 (file)
@@ -14,9 +14,8 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
 
   def index_operation do
     %Operation{
-      tags: ["domain_blocks"],
-      summary: "Fetch domain blocks",
-      description: "View domains the user has blocked.",
+      tags: ["Domain blocks"],
+      summary: "Retrieve a list of blocked domains",
       security: [%{"oAuth" => ["follow", "read:blocks"]}],
       operationId: "DomainBlockController.index",
       responses: %{
@@ -34,7 +33,7 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
   # Supporting domain query parameter is deprecated in Mastodon API
   def create_operation do
     %Operation{
-      tags: ["domain_blocks"],
+      tags: ["Domain blocks"],
       summary: "Block a domain",
       description: """
       Block a domain to:
@@ -55,7 +54,7 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
   # Supporting domain query parameter is deprecated in Mastodon API
   def delete_operation do
     %Operation{
-      tags: ["domain_blocks"],
+      tags: ["Domain blocks"],
       summary: "Unblock a domain",
       description: "Remove a domain block, if it exists in the user's array of blocked domains.",
       operationId: "DomainBlockController.delete",
index e1aa7d4cafff1626e7f7ba0538b7f639a5e7bc42..a7b306a30871e349f7fab93daa527e71612a6b15 100644 (file)
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Emoji Reactions"],
+      tags: ["Emoji reactions"],
       summary:
         "Get an object of emoji to account mappings with accounts that reacted to the post",
       parameters: [
@@ -42,7 +42,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Emoji Reactions"],
+      tags: ["Emoji reactions"],
       summary: "React to a post with a unicode emoji",
       parameters: [
         Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
@@ -61,7 +61,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Emoji Reactions"],
+      tags: ["Emoji reactions"],
       summary: "Remove a reaction to a post with a unicode emoji",
       parameters: [
         Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
@@ -78,7 +78,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
   end
 
   defp array_of_reactions_response do
-    Operation.response("Array of Emoji Reactions", "application/json", %Schema{
+    Operation.response("Array of Emoji reactions", "application/json", %Schema{
       type: :array,
       items: emoji_reaction(),
       example: [emoji_reaction().example]
index c5b0c035b72bae0de2e8b51ab323dab921861328..5102921bc35eae7607554c2052ca45eea09190e3 100644 (file)
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ApiSpec.FilterOperation do
   alias OpenApiSpex.Operation
   alias OpenApiSpex.Schema
   alias Pleroma.Web.ApiSpec.Helpers
+  alias Pleroma.Web.ApiSpec.Schemas.ApiError
   alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
 
   def open_api_operation(action) do
@@ -15,57 +16,64 @@ defmodule Pleroma.Web.ApiSpec.FilterOperation do
 
   def index_operation do
     %Operation{
-      tags: ["apps"],
-      summary: "View all filters",
+      tags: ["Filters"],
+      summary: "All filters",
       operationId: "FilterController.index",
       security: [%{"oAuth" => ["read:filters"]}],
       responses: %{
-        200 => Operation.response("Filters", "application/json", array_of_filters())
+        200 => Operation.response("Filters", "application/json", array_of_filters()),
+        403 => Operation.response("Error", "application/json", ApiError)
       }
     }
   end
 
   def create_operation do
     %Operation{
-      tags: ["apps"],
+      tags: ["Filters"],
       summary: "Create a filter",
       operationId: "FilterController.create",
       requestBody: Helpers.request_body("Parameters", create_request(), required: true),
       security: [%{"oAuth" => ["write:filters"]}],
-      responses: %{200 => Operation.response("Filter", "application/json", filter())}
+      responses: %{
+        200 => Operation.response("Filter", "application/json", filter()),
+        403 => Operation.response("Error", "application/json", ApiError)
+      }
     }
   end
 
   def show_operation do
     %Operation{
-      tags: ["apps"],
-      summary: "View all filters",
+      tags: ["Filters"],
+      summary: "Filter",
       parameters: [id_param()],
       operationId: "FilterController.show",
       security: [%{"oAuth" => ["read:filters"]}],
       responses: %{
-        200 => Operation.response("Filter", "application/json", filter())
+        200 => Operation.response("Filter", "application/json", filter()),
+        403 => Operation.response("Error", "application/json", ApiError),
+        404 => Operation.response("Error", "application/json", ApiError)
       }
     }
   end
 
   def update_operation do
     %Operation{
-      tags: ["apps"],
+      tags: ["Filters"],
       summary: "Update a filter",
       parameters: [id_param()],
       operationId: "FilterController.update",
       requestBody: Helpers.request_body("Parameters", update_request(), required: true),
       security: [%{"oAuth" => ["write:filters"]}],
       responses: %{
-        200 => Operation.response("Filter", "application/json", filter())
+        200 => Operation.response("Filter", "application/json", filter()),
+        403 => Operation.response("Error", "application/json", ApiError)
       }
     }
   end
 
   def delete_operation do
     %Operation{
-      tags: ["apps"],
+      tags: ["Filters"],
       summary: "Remove a filter",
       parameters: [id_param()],
       operationId: "FilterController.delete",
@@ -75,7 +83,8 @@ defmodule Pleroma.Web.ApiSpec.FilterOperation do
           Operation.response("Filter", "application/json", %Schema{
             type: :object,
             description: "Empty object"
-          })
+          }),
+        403 => Operation.response("Error", "application/json", ApiError)
       }
     }
   end
@@ -210,15 +219,13 @@ defmodule Pleroma.Web.ApiSpec.FilterOperation do
           nullable: true,
           description: "Consider word boundaries?",
           default: true
+        },
+        expires_in: %Schema{
+          nullable: true,
+          type: :integer,
+          description:
+            "Number of seconds from now the filter should expire. Otherwise, null for a filter that doesn't expire."
         }
-        # TODO: probably should implement filter expiration
-        # expires_in: %Schema{
-        #   type: :string,
-        #   format: :"date-time",
-        #   description:
-        #     "ISO 8601 Datetime for when the filter expires. Otherwise,
-        #  null for a filter that doesn't expire."
-        # }
       },
       required: [:phrase, :context],
       example: %{
index fc849bcb2c1955fe242c5478216e8b95d8b9d0f8..7840196999513dea1498560380f02b45bd06587b 100644 (file)
@@ -15,8 +15,8 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Follow Requests"],
-      summary: "Pending Follows",
+      tags: ["Follow requests"],
+      summary: "Retrieve follow requests",
       security: [%{"oAuth" => ["read:follows", "follow"]}],
       operationId: "FollowRequestController.index",
       responses: %{
@@ -32,8 +32,8 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
 
   def authorize_operation do
     %Operation{
-      tags: ["Follow Requests"],
-      summary: "Accept Follow",
+      tags: ["Follow requests"],
+      summary: "Accept follow request",
       operationId: "FollowRequestController.authorize",
       parameters: [id_param()],
       security: [%{"oAuth" => ["follow", "write:follows"]}],
@@ -45,8 +45,8 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
 
   def reject_operation do
     %Operation{
-      tags: ["Follow Requests"],
-      summary: "Reject Follow",
+      tags: ["Follow requests"],
+      summary: "Reject follow request",
       operationId: "FollowRequestController.reject",
       parameters: [id_param()],
       security: [%{"oAuth" => ["follow", "write:follows"]}],
index 8ca82b95c3e987ee83cae92f64660268dd048550..9384acc323dee587a4f248f8414b17eeb3b0e174 100644 (file)
@@ -14,7 +14,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
   def show_operation do
     %Operation{
       tags: ["Instance"],
-      summary: "Fetch instance",
+      summary: "Retrieve instance information",
       description: "Information about the server",
       operationId: "InstanceController.show",
       responses: %{
@@ -26,7 +26,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
   def peers_operation do
     %Operation{
       tags: ["Instance"],
-      summary: "List of known hosts",
+      summary: "Retrieve list of known instances",
       operationId: "InstanceController.peers",
       responses: %{
         200 => Operation.response("Array of domains", "application/json", array_of_domains())
index 62a67cc201c97c17ad9ca3dfb9d2a7a8117da198..8a6e92b99f0e23294b6e7b67814a6baef12e9845 100644 (file)
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
   def index_operation do
     %Operation{
       tags: ["Lists"],
-      summary: "Show user's lists",
+      summary: "Retrieve a list of lists",
       description: "Fetch all lists that the user owns",
       security: [%{"oAuth" => ["read:lists"]}],
       operationId: "ListController.index",
@@ -33,7 +33,7 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
   def create_operation do
     %Operation{
       tags: ["Lists"],
-      summary: "Create  a list",
+      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(),
@@ -49,7 +49,7 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
   def show_operation do
     %Operation{
       tags: ["Lists"],
-      summary: "Show a single list",
+      summary: "Retrieve a list",
       description: "Fetch the list with the given ID. Used for verifying the title of a list.",
       operationId: "ListController.show",
       parameters: [id_param()],
@@ -93,7 +93,7 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
   def list_accounts_operation do
     %Operation{
       tags: ["Lists"],
-      summary: "View accounts in list",
+      summary: "Retrieve accounts in list",
       operationId: "ListController.list_accounts",
       parameters: [id_param()],
       security: [%{"oAuth" => ["read:lists"]}],
index 7de0d7da5c1e1aabb179ec0ee2e65c43d37cf10f..85aa14869e524c7b22b3ccc0eac5f0babfed8f82 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.MediaOperation do
 
   def create_operation do
     %Operation{
-      tags: ["media"],
+      tags: ["Media attachments"],
       summary: "Upload media as attachment",
       description: "Creates an attachment to be used with a new status.",
       operationId: "MediaController.create",
@@ -56,8 +56,8 @@ defmodule Pleroma.Web.ApiSpec.MediaOperation do
 
   def update_operation do
     %Operation{
-      tags: ["media"],
-      summary: "Upload media as attachment",
+      tags: ["Media attachments"],
+      summary: "Update attachment",
       description: "Creates an attachment to be used with a new status.",
       operationId: "MediaController.update",
       security: [%{"oAuth" => ["write:media"]}],
@@ -97,8 +97,8 @@ defmodule Pleroma.Web.ApiSpec.MediaOperation do
 
   def show_operation do
     %Operation{
-      tags: ["media"],
-      summary: "Show Uploaded media attachment",
+      tags: ["Media attachments"],
+      summary: "Attachment",
       operationId: "MediaController.show",
       parameters: [id_param()],
       security: [%{"oAuth" => ["read:media"]}],
@@ -112,8 +112,8 @@ defmodule Pleroma.Web.ApiSpec.MediaOperation do
 
   def create2_operation do
     %Operation{
-      tags: ["media"],
-      summary: "Upload media as attachment",
+      tags: ["Media attachments"],
+      summary: "Upload media as attachment (v2)",
       description: "Creates an attachment to be used with a new status.",
       operationId: "MediaController.create2",
       security: [%{"oAuth" => ["write:media"]}],
index b7e3912645932ca213015b0d08e4bf3faef69985..ec88eabe1f28d65f57bd590de6eaab77b811a2bc 100644 (file)
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
   def index_operation do
     %Operation{
       tags: ["Notifications"],
-      summary: "Get all notifications",
+      summary: "Retrieve a list of notifications",
       description:
         "Notifications concerning the user. This API returns Link headers containing links to the next/previous page. However, the links can also be constructed dynamically using query params and `id` values.",
       operationId: "NotificationController.index",
@@ -74,7 +74,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
   def show_operation do
     %Operation{
       tags: ["Notifications"],
-      summary: "Get a single notification",
+      summary: "Retrieve a notification",
       description: "View information about a notification with a given ID.",
       operationId: "NotificationController.show",
       security: [%{"oAuth" => ["read:notifications"]}],
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
   def dismiss_operation do
     %Operation{
       tags: ["Notifications"],
-      summary: "Dismiss a single notification",
+      summary: "Dismiss a notification",
       description: "Clear a single notification from the server.",
       operationId: "NotificationController.dismiss",
       parameters: [id_param()],
index caa13afee8541ff4053c288ba8fd93cf130b1bb8..ad49f64261748ee0f0e2a1cdb73cadfa4bd15e17 100644 (file)
@@ -18,8 +18,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
 
   def confirmation_resend_operation do
     %Operation{
-      tags: ["Accounts"],
-      summary: "Resend confirmation email. Expects `email` or `nickname`",
+      tags: ["Account credentials"],
+      summary: "Resend confirmation email",
+      description: "Expects `email` or `nickname`.",
       operationId: "PleromaAPI.AccountController.confirmation_resend",
       parameters: [
         Operation.parameter(:email, :query, :string, "Email of that needs to be verified",
@@ -41,8 +42,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
 
   def favourites_operation do
     %Operation{
-      tags: ["Accounts"],
-      summary: "Returns favorites timeline of any user",
+      tags: ["Retrieve account information"],
+      summary: "Favorites",
+      description:
+        "Only returns data if the user has opted into sharing it. See `hide_favorites` in [Update account credentials](#operation/AccountController.update_credentials).",
       operationId: "PleromaAPI.AccountController.favourites",
       parameters: [id_param() | pagination_params()],
       security: [%{"oAuth" => ["read:favourites"]}],
@@ -61,8 +64,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
 
   def subscribe_operation do
     %Operation{
-      tags: ["Accounts"],
-      summary: "Subscribe to receive notifications for all statuses posted by a user",
+      tags: ["Account actions"],
+      summary: "Subscribe",
+      description: "Receive notifications for all statuses posted by the account.",
       operationId: "PleromaAPI.AccountController.subscribe",
       parameters: [id_param()],
       security: [%{"oAuth" => ["follow", "write:follows"]}],
@@ -75,8 +79,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
 
   def unsubscribe_operation do
     %Operation{
-      tags: ["Accounts"],
-      summary: "Unsubscribe to stop receiving notifications from user statuses",
+      tags: ["Account actions"],
+      summary: "Unsubscribe",
+      description: "Stop receiving notifications for all statuses posted by the account.",
       operationId: "PleromaAPI.AccountController.unsubscribe",
       parameters: [id_param()],
       security: [%{"oAuth" => ["follow", "write:follows"]}],
index 7752f46763cc1602aebdef71bfbee3b2692fd43a..12fb8ed3629af0f3134ae107124b81e866a78b7f 100644 (file)
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaConversationOperation do
   def show_operation do
     %Operation{
       tags: ["Conversations"],
-      summary: "The conversation with the given ID",
+      summary: "Conversation",
       parameters: [
         Operation.parameter(:id, :path, :string, "Conversation ID",
           example: "123",
@@ -37,7 +37,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaConversationOperation do
   def statuses_operation do
     %Operation{
       tags: ["Conversations"],
-      summary: "Timeline for a given conversation",
+      summary: "Timeline for conversation",
       parameters: [
         Operation.parameter(:id, :path, :string, "Conversation ID",
           example: "123",
@@ -61,7 +61,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaConversationOperation do
   def update_operation do
     %Operation{
       tags: ["Conversations"],
-      summary: "Update a conversation. Used to change the set of recipients.",
+      summary: "Update conversation",
+      description: "Change set of recipients for the conversation.",
       parameters: [
         Operation.parameter(:id, :path, :string, "Conversation ID",
           example: "123",
@@ -86,7 +87,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaConversationOperation do
   def mark_as_read_operation do
     %Operation{
       tags: ["Conversations"],
-      summary: "Marks all user's conversations as read",
+      summary: "Marks all conversations as read",
       security: [%{"oAuth" => ["write:conversations"]}],
       operationId: "PleromaAPI.ConversationController.mark_as_read",
       responses: %{
index 83981f4e71c09dd8fb4bff94c8e67fd5c6aecfe6..bed9511ef578f259bbf1e48ffda0add0cbb428dd 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Add new file to the pack",
       operationId: "PleromaAPI.EmojiPackController.add_file",
       security: [%{"oAuth" => ["write"]}],
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Add new file to the pack",
       operationId: "PleromaAPI.EmojiPackController.update_file",
       security: [%{"oAuth" => ["write"]}],
@@ -106,7 +106,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Delete emoji file from pack",
       operationId: "PleromaAPI.EmojiPackController.delete_file",
       security: [%{"oAuth" => ["write"]}],
index ceff3f67afc0f012e82c837574adf117fc639260..48dafa5f2c33de03f1ce8d28dddbad58613eacfc 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def remote_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Make request to another instance for emoji packs list",
       security: [%{"oAuth" => ["write"]}],
       parameters: [
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Lists local custom emoji packs",
       operationId: "PleromaAPI.EmojiPackController.index",
       parameters: [
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Show emoji pack",
       operationId: "PleromaAPI.EmojiPackController.show",
       parameters: [
@@ -97,7 +97,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def archive_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Requests a local pack archive from the instance",
       operationId: "PleromaAPI.EmojiPackController.archive",
       parameters: [name_param()],
@@ -115,7 +115,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def download_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Download pack from another instance",
       operationId: "PleromaAPI.EmojiPackController.download",
       security: [%{"oAuth" => ["write"]}],
@@ -145,7 +145,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Create an empty pack",
       operationId: "PleromaAPI.EmojiPackController.create",
       security: [%{"oAuth" => ["write"]}],
@@ -161,7 +161,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Delete a custom emoji pack",
       operationId: "PleromaAPI.EmojiPackController.delete",
       security: [%{"oAuth" => ["write"]}],
@@ -177,7 +177,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Updates (replaces) pack metadata",
       operationId: "PleromaAPI.EmojiPackController.update",
       security: [%{"oAuth" => ["write"]}],
@@ -193,7 +193,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def import_from_filesystem_operation do
     %Operation{
-      tags: ["Emoji Packs"],
+      tags: ["Emoji packs"],
       summary: "Imports packs from filesystem",
       operationId: "PleromaAPI.EmojiPackController.import",
       security: [%{"oAuth" => ["write"]}],
index c9519f7699881879668c4ba17c8da088fa0baf6b..612113147c0bb451c487bdd51311d516e469e726 100644 (file)
@@ -13,8 +13,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaInstancesOperation do
 
   def show_operation do
     %Operation{
-      tags: ["PleromaInstances"],
-      summary: "Instances federation status",
+      tags: ["Instance"],
+      summary: "Retrieve federation status",
       description: "Information about instances deemed unreachable by the server",
       operationId: "PleromaInstances.show",
       responses: %{
index 226d950547658acac06ed744fd3a63590d985981..6191cb97d0270443933f932238afb7d0f771056e 100644 (file)
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaMascotOperation do
   def show_operation do
     %Operation{
       tags: ["Mascot"],
-      summary: "Gets user mascot image",
+      summary: "Retrieve mascot",
       security: [%{"oAuth" => ["read:accounts"]}],
       operationId: "PleromaAPI.MascotController.show",
       responses: %{
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaMascotOperation do
   def update_operation do
     %Operation{
       tags: ["Mascot"],
-      summary: "Set/clear user avatar image",
+      summary: "Set or clear mascot",
       description:
         "Behaves exactly the same as `POST /api/v1/upload`. Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.",
       operationId: "PleromaAPI.MascotController.update",
index c26fb273654146cd3f7a95f7ecfd84d3bf93ba1b..1dda3924095d3e93c67738f73673cd197bb12acb 100644 (file)
@@ -18,7 +18,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaNotificationOperation do
   def mark_as_read_operation do
     %Operation{
       tags: ["Notifications"],
-      summary: "Mark notifications as read. Query parameters are mutually exclusive.",
+      summary: "Mark notifications as read",
+      description: "Query parameters are mutually exclusive.",
       requestBody:
         request_body("Parameters", %Schema{
           type: :object,
@@ -32,7 +33,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaNotificationOperation do
       responses: %{
         200 =>
           Operation.response(
-            "A Notification or array of Motifications",
+            "A Notification or array of Notifications",
             "application/json",
             %Schema{
               anyOf: [
index 792d5cb5171d05e84b3d91d13441d92a1a1a9c35..b744efa60cb2014e8a074c1ec00b735404530da4 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do
 
   def create_operation do
     %Operation{
-      tags: ["reports"],
+      tags: ["Reports"],
       summary: "File a report",
       description: "Report problematic users to your moderators",
       operationId: "ReportController.create",
index 873ed3a80bc712c99508a73decd111dc491fa17c..b9c5b35c15a020a1c41dcffaf4478d3e3171531b 100644 (file)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.ApiSpec.ScheduledActivityOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Scheduled Statuses"],
+      tags: ["Scheduled statuses"],
       summary: "View scheduled statuses",
       security: [%{"oAuth" => ["read:statuses"]}],
       parameters: pagination_params(),
@@ -35,7 +35,7 @@ defmodule Pleroma.Web.ApiSpec.ScheduledActivityOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Scheduled Statuses"],
+      tags: ["Scheduled statuses"],
       summary: "View a single scheduled status",
       security: [%{"oAuth" => ["read:statuses"]}],
       parameters: [id_param()],
@@ -49,7 +49,7 @@ defmodule Pleroma.Web.ApiSpec.ScheduledActivityOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Scheduled Statuses"],
+      tags: ["Scheduled statuses"],
       summary: "Schedule a status",
       operationId: "ScheduledActivity.update",
       security: [%{"oAuth" => ["write:statuses"]}],
@@ -75,7 +75,7 @@ defmodule Pleroma.Web.ApiSpec.ScheduledActivityOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Scheduled Statuses"],
+      tags: ["Scheduled statuses"],
       summary: "Cancel a scheduled status",
       security: [%{"oAuth" => ["write:statuses"]}],
       parameters: [id_param()],
index fd29f5139882137eb12d9642f7e7c4a3da37b624..40edc747d9083ad79229ceadcca18ec8dd332cf4 100644 (file)
@@ -22,8 +22,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def index_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "Get multiple statuses by IDs",
+      tags: ["Retrieve status information"],
+      summary: "Multiple statuses",
       security: [%{"oAuth" => ["read:statuses"]}],
       parameters: [
         Operation.parameter(
@@ -48,7 +48,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Publish new status",
       security: [%{"oAuth" => ["write:statuses"]}],
       description: "Post a new status",
@@ -68,8 +68,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "View specific status",
+      tags: ["Retrieve status information"],
+      summary: "Status",
       description: "View information about a status",
       operationId: "StatusController.show",
       security: [%{"oAuth" => ["read:statuses"]}],
@@ -91,8 +91,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "Delete status",
+      tags: ["Status actions"],
+      summary: "Delete",
       security: [%{"oAuth" => ["write:statuses"]}],
       description: "Delete one of your own statuses",
       operationId: "StatusController.delete",
@@ -107,8 +107,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def reblog_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "Boost",
+      tags: ["Status actions"],
+      summary: "Reblog",
       security: [%{"oAuth" => ["write:statuses"]}],
       description: "Share a status",
       operationId: "StatusController.reblog",
@@ -129,8 +129,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def unreblog_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "Undo boost",
+      tags: ["Status actions"],
+      summary: "Undo reblog",
       security: [%{"oAuth" => ["write:statuses"]}],
       description: "Undo a reshare of a status",
       operationId: "StatusController.unreblog",
@@ -144,7 +144,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def favourite_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Favourite",
       security: [%{"oAuth" => ["write:favourites"]}],
       description: "Add a status to your favourites list",
@@ -159,7 +159,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def unfavourite_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Undo favourite",
       security: [%{"oAuth" => ["write:favourites"]}],
       description: "Remove a status from your favourites list",
@@ -174,7 +174,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def pin_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Pin to profile",
       security: [%{"oAuth" => ["write:accounts"]}],
       description: "Feature one of your own public statuses at the top of your profile",
@@ -189,8 +189,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def unpin_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "Unpin to profile",
+      tags: ["Status actions"],
+      summary: "Unpin from profile",
       security: [%{"oAuth" => ["write:accounts"]}],
       description: "Unfeature a status from the top of your profile",
       operationId: "StatusController.unpin",
@@ -204,7 +204,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def bookmark_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Bookmark",
       security: [%{"oAuth" => ["write:bookmarks"]}],
       description: "Privately bookmark a status",
@@ -218,7 +218,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def unbookmark_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Undo bookmark",
       security: [%{"oAuth" => ["write:bookmarks"]}],
       description: "Remove a status from your private bookmarks",
@@ -232,7 +232,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def mute_conversation_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Mute conversation",
       security: [%{"oAuth" => ["write:mutes"]}],
       description: "Do not receive notifications for the thread that this status is part of.",
@@ -267,7 +267,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def unmute_conversation_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Status actions"],
       summary: "Unmute conversation",
       security: [%{"oAuth" => ["write:mutes"]}],
       description:
@@ -283,7 +283,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def card_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Retrieve status information"],
       deprecated: true,
       summary: "Preview card",
       description: "Deprecated in favor of card property inlined on Status entity",
@@ -311,7 +311,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def favourited_by_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Retrieve status information"],
       summary: "Favourited by",
       description: "View who favourited a given status",
       operationId: "StatusController.favourited_by",
@@ -331,9 +331,9 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def reblogged_by_operation do
     %Operation{
-      tags: ["Statuses"],
-      summary: "Boosted by",
-      description: "View who boosted a given status",
+      tags: ["Retrieve status information"],
+      summary: "Reblogged by",
+      description: "View who reblogged a given status",
       operationId: "StatusController.reblogged_by",
       security: [%{"oAuth" => ["read:accounts"]}],
       parameters: [id_param()],
@@ -351,7 +351,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def context_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Retrieve status information"],
       summary: "Parent and child statuses",
       description: "View statuses above and below this status in the thread",
       operationId: "StatusController.context",
@@ -365,7 +365,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def favourites_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Timelines"],
       summary: "Favourited statuses",
       description:
         "Statuses the user has favourited. Please note that you have to use the link headers to paginate this. You can not build the query parameters yourself.",
@@ -380,7 +380,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
 
   def bookmarks_operation do
     %Operation{
-      tags: ["Statuses"],
+      tags: ["Timelines"],
       summary: "Bookmarked statuses",
       description: "Statuses the user has bookmarked",
       operationId: "StatusController.bookmarks",
@@ -413,34 +413,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
           items: %Schema{type: :string},
           description: "Array of Attachment ids to be attached as media."
         },
-        poll: %Schema{
-          nullable: true,
-          type: :object,
-          required: [:options],
-          properties: %{
-            options: %Schema{
-              type: :array,
-              items: %Schema{type: :string},
-              description: "Array of possible answers. Must be provided with `poll[expires_in]`."
-            },
-            expires_in: %Schema{
-              type: :integer,
-              nullable: true,
-              description:
-                "Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
-            },
-            multiple: %Schema{
-              allOf: [BooleanLike],
-              nullable: true,
-              description: "Allow multiple choices?"
-            },
-            hide_totals: %Schema{
-              allOf: [BooleanLike],
-              nullable: true,
-              description: "Hide vote counts until the poll ends?"
-            }
-          }
-        },
+        poll: poll_params(),
         in_reply_to_id: %Schema{
           nullable: true,
           allOf: [FlakeID],
@@ -522,6 +495,37 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
     }
   end
 
+  def poll_params do
+    %Schema{
+      nullable: true,
+      type: :object,
+      required: [:options, :expires_in],
+      properties: %{
+        options: %Schema{
+          type: :array,
+          items: %Schema{type: :string},
+          description: "Array of possible answers. Must be provided with `poll[expires_in]`."
+        },
+        expires_in: %Schema{
+          type: :integer,
+          nullable: true,
+          description:
+            "Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
+        },
+        multiple: %Schema{
+          allOf: [BooleanLike],
+          nullable: true,
+          description: "Allow multiple choices?"
+        },
+        hide_totals: %Schema{
+          allOf: [BooleanLike],
+          nullable: true,
+          description: "Hide vote counts until the poll ends?"
+        }
+      }
+    }
+  end
+
   def id_param do
     Operation.parameter(:id, :path, FlakeID, "Status ID",
       example: "9umDrYheeY451cQnEe",
index 1374a6ff4cbe67ca66490af62ee480998fb78c28..60a7fb3b023c11bbd9c8ab8b27fd1008586a85c2 100644 (file)
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Push Subscriptions"],
+      tags: ["Push subscriptions"],
       summary: "Subscribe to push notifications",
       description:
         "Add a Web Push API subscription to receive notifications. Each access token can have one push subscription. If you create a new subscription, the old subscription is deleted.",
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do
       security: [%{"oAuth" => ["push"]}],
       requestBody: Helpers.request_body("Parameters", create_request(), required: true),
       responses: %{
-        200 => Operation.response("Push Subscription", "application/json", PushSubscription),
+        200 => Operation.response("Push subscription", "application/json", PushSubscription),
         400 => Operation.response("Error", "application/json", ApiError),
         403 => Operation.response("Error", "application/json", ApiError)
       }
@@ -34,13 +34,13 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do
 
   def show_operation do
     %Operation{
-      tags: ["Push Subscriptions"],
+      tags: ["Push subscriptions"],
       summary: "Get current subscription",
       description: "View the PushSubscription currently associated with this access token.",
       operationId: "SubscriptionController.show",
       security: [%{"oAuth" => ["push"]}],
       responses: %{
-        200 => Operation.response("Push Subscription", "application/json", PushSubscription),
+        200 => Operation.response("Push subscription", "application/json", PushSubscription),
         403 => Operation.response("Error", "application/json", ApiError),
         404 => Operation.response("Error", "application/json", ApiError)
       }
@@ -49,7 +49,7 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Push Subscriptions"],
+      tags: ["Push subscriptions"],
       summary: "Change types of notifications",
       description:
         "Updates the current push subscription. Only the data part can be updated. To change fundamentals, a new subscription must be created instead.",
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do
       security: [%{"oAuth" => ["push"]}],
       requestBody: Helpers.request_body("Parameters", update_request(), required: true),
       responses: %{
-        200 => Operation.response("Push Subscription", "application/json", PushSubscription),
+        200 => Operation.response("Push subscription", "application/json", PushSubscription),
         403 => Operation.response("Error", "application/json", ApiError)
       }
     }
@@ -65,7 +65,7 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Push Subscriptions"],
+      tags: ["Push subscriptions"],
       summary: "Remove current subscription",
       description: "Removes the current Web Push API subscription.",
       operationId: "SubscriptionController.delete",
index 01396642c6776d60ac1c2db5d3d5feabcc457471..cae18c75813c39841bee8107ab64f46f18f8b2c5 100644 (file)
@@ -43,8 +43,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
       tags: ["Timelines"],
       summary: "Direct timeline",
       description:
-        "View statuses with a “direct” privacy, from your account or in your notifications",
-      deprecated: true,
+        "View statuses with a “direct” scope addressed to the account. Using this endpoint is discouraged, please use [conversations](#tag/Conversations) or [chats](#tag/Chats).",
       parameters: [with_muted_param() | pagination_params()],
       security: [%{"oAuth" => ["read:statuses"]}],
       operationId: "TimelineController.direct",
index 859404deda688934cf8d9ce78fef5a85a94b5724..6292e20043773cc1ccc0f918ba2c9dd74b525675 100644 (file)
@@ -17,8 +17,8 @@ defmodule Pleroma.Web.ApiSpec.UserImportOperation do
 
   def follow_operation do
     %Operation{
-      tags: ["follow_import"],
-      summary: "Imports your follows.",
+      tags: ["Data import"],
+      summary: "Import follows",
       operationId: "UserImportController.follow",
       requestBody: request_body("Parameters", import_request(), required: true),
       responses: %{
@@ -31,8 +31,8 @@ defmodule Pleroma.Web.ApiSpec.UserImportOperation do
 
   def blocks_operation do
     %Operation{
-      tags: ["blocks_import"],
-      summary: "Imports your blocks.",
+      tags: ["Data import"],
+      summary: "Import blocks",
       operationId: "UserImportController.blocks",
       requestBody: request_body("Parameters", import_request(), required: true),
       responses: %{
@@ -45,8 +45,8 @@ defmodule Pleroma.Web.ApiSpec.UserImportOperation do
 
   def mutes_operation do
     %Operation{
-      tags: ["mutes_import"],
-      summary: "Imports your mutes.",
+      tags: ["Data import"],
+      summary: "Import mutes",
       operationId: "UserImportController.mutes",
       requestBody: request_body("Parameters", import_request(), required: true),
       responses: %{
index 4f9b564d1e9e885f81919952bb1e22db25e00295..bd7143ab959420bb00e9b2ab2264cf3777f27fa1 100644 (file)
@@ -96,7 +96,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
               hide_notification_contents: %Schema{type: :boolean}
             }
           },
-          relationship: AccountRelationship,
+          relationship: %Schema{allOf: [AccountRelationship], nullable: true},
           settings_store: %Schema{
             type: :object,
             description:
index 2cda196318abd2cee305b2f01ac8c091d6313aeb..16b73ebb4191e02d32be50bcbc8e34b7ba13a6ee 100644 (file)
@@ -10,7 +10,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.AccountRelationship do
 
   OpenApiSpex.schema(%{
     title: "AccountRelationship",
-    description: "Response schema for relationship",
+    description: "Relationship between current account and requested account",
     type: :object,
     properties: %{
       blocked_by: %Schema{type: :boolean},
index dd0d9aa8fea257036e7b51d1be6be67f7598eb1e..cc051046a9906e52a79b6237c072e32c5d9135fb 100644 (file)
@@ -5,8 +5,8 @@
 defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do
   alias OpenApiSpex.Schema
   alias Pleroma.Web.ApiSpec.Schemas.Attachment
-  alias Pleroma.Web.ApiSpec.Schemas.Poll
   alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
+  alias Pleroma.Web.ApiSpec.StatusOperation
 
   require OpenApiSpex
 
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do
           spoiler_text: %Schema{type: :string, nullable: true},
           visibility: %Schema{allOf: [VisibilityScope], nullable: true},
           scheduled_at: %Schema{type: :string, format: :"date-time", nullable: true},
-          poll: %Schema{allOf: [Poll], nullable: true},
+          poll: StatusOperation.poll_params(),
           in_reply_to_id: %Schema{type: :string, nullable: true}
         }
       }
index c8b4a309553c894f27e7dab00d504980d149f850..9b1ae809d33184e1204a969aef027f5c8d574231 100644 (file)
@@ -20,6 +20,8 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do
 
   defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.FilterOperation
 
+  action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+
   @doc "GET /api/v1/filters"
   def index(%{assigns: %{user: user}} = conn, _) do
     filters = Filter.get_filters(user)
@@ -29,25 +31,23 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do
 
   @doc "POST /api/v1/filters"
   def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
-    query = %Filter{
-      user_id: user.id,
-      phrase: params.phrase,
-      context: params.context,
-      hide: params.irreversible,
-      whole_word: params.whole_word
-      # TODO: support `expires_in` parameter (as in Mastodon API)
-    }
-
-    {:ok, response} = Filter.create(query)
-
-    render(conn, "show.json", filter: response)
+    with {:ok, response} <-
+           params
+           |> Map.put(:user_id, user.id)
+           |> Map.put(:hide, params[:irreversible])
+           |> Map.delete(:irreversible)
+           |> Filter.create() do
+      render(conn, "show.json", filter: response)
+    end
   end
 
   @doc "GET /api/v1/filters/:id"
   def show(%{assigns: %{user: user}} = conn, %{id: filter_id}) do
-    filter = Filter.get(filter_id, user)
-
-    render(conn, "show.json", filter: filter)
+    with %Filter{} = filter <- Filter.get(filter_id, user) do
+      render(conn, "show.json", filter: filter)
+    else
+      nil -> {:error, :not_found}
+    end
   end
 
   @doc "PUT /api/v1/filters/:id"
@@ -56,28 +56,31 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do
         %{id: filter_id}
       ) do
     params =
-      params
-      |> Map.delete(:irreversible)
-      |> Map.put(:hide, params[:irreversible])
-      |> Enum.reject(fn {_key, value} -> is_nil(value) end)
-      |> Map.new()
-
-    # TODO: support `expires_in` parameter (as in Mastodon API)
+      if is_boolean(params[:irreversible]) do
+        params
+        |> Map.put(:hide, params[:irreversible])
+        |> Map.delete(:irreversible)
+      else
+        params
+      end
 
     with %Filter{} = filter <- Filter.get(filter_id, user),
          {:ok, %Filter{} = filter} <- Filter.update(filter, params) do
       render(conn, "show.json", filter: filter)
+    else
+      nil -> {:error, :not_found}
+      error -> error
     end
   end
 
   @doc "DELETE /api/v1/filters/:id"
   def delete(%{assigns: %{user: user}} = conn, %{id: filter_id}) do
-    query = %Filter{
-      user_id: user.id,
-      filter_id: filter_id
-    }
-
-    {:ok, _} = Filter.delete(query)
-    json(conn, %{})
+    with %Filter{} = filter <- Filter.get(filter_id, user),
+         {:ok, _} <- Filter.delete(filter) do
+      json(conn, %{})
+    else
+      nil -> {:error, :not_found}
+      error -> error
+    end
   end
 end
diff --git a/lib/pleroma/workers/purge_expired_filter.ex b/lib/pleroma/workers/purge_expired_filter.ex
new file mode 100644 (file)
index 0000000..4740d52
--- /dev/null
@@ -0,0 +1,43 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Workers.PurgeExpiredFilter do
+  @moduledoc """
+  Worker which purges expired filters
+  """
+
+  use Oban.Worker, queue: :filter_expiration, max_attempts: 1, unique: [period: :infinity]
+
+  import Ecto.Query
+
+  alias Oban.Job
+  alias Pleroma.Repo
+
+  @spec enqueue(%{filter_id: integer(), expires_at: DateTime.t()}) ::
+          {:ok, Job.t()} | {:error, Ecto.Changeset.t()}
+  def enqueue(args) do
+    {scheduled_at, args} = Map.pop(args, :expires_at)
+
+    args
+    |> new(scheduled_at: scheduled_at)
+    |> Oban.insert()
+  end
+
+  @impl true
+  def perform(%Job{args: %{"filter_id" => id}}) do
+    Pleroma.Filter
+    |> Repo.get(id)
+    |> Repo.delete()
+  end
+
+  @spec get_expiration(pos_integer()) :: Job.t() | nil
+  def get_expiration(id) do
+    from(j in Job,
+      where: j.state == "scheduled",
+      where: j.queue == "filter_expiration",
+      where: fragment("?->'filter_id' = ?", j.args, ^id)
+    )
+    |> Repo.one()
+  end
+end
index cf965999cd19311435f2bafe0b4f1ae51719b3c5..a4ab9928de7e360c80091e591807c4e8a6c550b4 100644 (file)
@@ -9,38 +9,50 @@ defmodule Pleroma.Workers.ScheduledActivityWorker do
 
   use Pleroma.Workers.WorkerHelper, queue: "scheduled_activities"
 
-  alias Pleroma.Config
+  alias Pleroma.Repo
   alias Pleroma.ScheduledActivity
   alias Pleroma.User
-  alias Pleroma.Web.CommonAPI
 
   require Logger
 
   @impl Oban.Worker
   def perform(%Job{args: %{"activity_id" => activity_id}}) do
-    if Config.get([ScheduledActivity, :enabled]) do
-      case Pleroma.Repo.get(ScheduledActivity, activity_id) do
-        %ScheduledActivity{} = scheduled_activity ->
-          post_activity(scheduled_activity)
-
-        _ ->
-          Logger.error("#{__MODULE__} Couldn't find scheduled activity: #{activity_id}")
-      end
+    with %ScheduledActivity{} = scheduled_activity <- find_scheduled_activity(activity_id),
+         %User{} = user <- find_user(scheduled_activity.user_id) do
+      params = atomize_keys(scheduled_activity.params)
+
+      Repo.transaction(fn ->
+        {:ok, activity} = Pleroma.Web.CommonAPI.post(user, params)
+        {:ok, _} = ScheduledActivity.delete(scheduled_activity)
+        activity
+      end)
+    else
+      {:error, :scheduled_activity_not_found} = error ->
+        Logger.error("#{__MODULE__} Couldn't find scheduled activity: #{activity_id}")
+        error
+
+      {:error, :user_not_found} = error ->
+        Logger.error("#{__MODULE__} Couldn't find user for scheduled activity: #{activity_id}")
+        error
     end
   end
 
-  defp post_activity(%ScheduledActivity{user_id: user_id, params: params} = scheduled_activity) do
-    params = Map.new(params, fn {key, value} -> {String.to_existing_atom(key), value} end)
+  defp find_scheduled_activity(id) do
+    with nil <- Repo.get(ScheduledActivity, id) do
+      {:error, :scheduled_activity_not_found}
+    end
+  end
 
-    with {:delete, {:ok, _}} <- {:delete, ScheduledActivity.delete(scheduled_activity)},
-         {:user, %User{} = user} <- {:user, User.get_cached_by_id(user_id)},
-         {:post, {:ok, _}} <- {:post, CommonAPI.post(user, params)} do
-      :ok
-    else
-      error ->
-        Logger.error(
-          "#{__MODULE__} Couldn't create a status from the scheduled activity: #{inspect(error)}"
-        )
+  defp find_user(id) do
+    with nil <- User.get_cached_by_id(id) do
+      {:error, :user_not_found}
     end
   end
+
+  defp atomize_keys(map) do
+    Map.new(map, fn
+      {key, value} when is_map(value) -> {String.to_existing_atom(key), atomize_keys(value)}
+      {key, value} -> {String.to_existing_atom(key), value}
+    end)
+  end
 end
diff --git a/test/config/emoji.txt b/test/config/emoji.txt
new file mode 100644 (file)
index 0000000..14dd0c3
--- /dev/null
@@ -0,0 +1 @@
+external_emoji, https://example.com/emoji.png
index 37e02fae20eb340c3ba46d83242c1de8908b7493..15f4982ea6dc04f873c5179ddbd3dda498fd0fc9 100644 (file)
@@ -87,7 +87,7 @@ defmodule Pleroma.Config.DeprecationWarningsTest do
   end
 
   test "check_activity_expiration_config/0" do
-    clear_config(Pleroma.ActivityExpiration, enabled: true)
+    clear_config([Pleroma.ActivityExpiration], enabled: true)
 
     assert capture_log(fn ->
              DeprecationWarnings.check_activity_expiration_config()
@@ -95,7 +95,7 @@ defmodule Pleroma.Config.DeprecationWarningsTest do
   end
 
   test "check_uploders_s3_public_endpoint/0" do
-    clear_config(Pleroma.Uploaders.S3, public_endpoint: "https://fake.amazonaws.com/bucket/")
+    clear_config([Pleroma.Uploaders.S3], public_endpoint: "https://fake.amazonaws.com/bucket/")
 
     assert capture_log(fn ->
              DeprecationWarnings.check_uploders_s3_public_endpoint()
index a9e256e8c7b67cd7e5fd821502df052f740db33e..19ad6b8c0f4c9b984cb603ae4229dc70d137d264 100644 (file)
@@ -7,81 +7,120 @@ defmodule Pleroma.FilterTest do
 
   import Pleroma.Factory
 
+  alias Oban.Job
   alias Pleroma.Filter
-  alias Pleroma.Repo
+
+  setup do
+    [user: insert(:user)]
+  end
 
   describe "creating filters" do
-    test "creating one filter" do
-      user = insert(:user)
+    test "creation validation error", %{user: user} do
+      attrs = %{
+        user_id: user.id,
+        expires_in: 60
+      }
+
+      {:error, _} = Filter.create(attrs)
+
+      assert Repo.all(Job) == []
+    end
 
-      query = %Filter{
+    test "use passed expires_at instead expires_in", %{user: user} do
+      now = NaiveDateTime.utc_now()
+
+      attrs = %{
         user_id: user.id,
-        filter_id: 42,
+        expires_at: now,
         phrase: "knights",
-        context: ["home"]
+        context: ["home"],
+        expires_in: 600
       }
 
-      {:ok, %Filter{} = filter} = Filter.create(query)
+      {:ok, %Filter{} = filter} = Filter.create(attrs)
+
       result = Filter.get(filter.filter_id, user)
-      assert query.phrase == result.phrase
-    end
+      assert result.expires_at == NaiveDateTime.truncate(now, :second)
 
-    test "creating one filter without a pre-defined filter_id" do
-      user = insert(:user)
+      [job] = Repo.all(Job)
 
-      query = %Filter{
+      assert DateTime.truncate(job.scheduled_at, :second) ==
+               now |> NaiveDateTime.truncate(:second) |> DateTime.from_naive!("Etc/UTC")
+    end
+
+    test "creating one filter", %{user: user} do
+      attrs = %{
         user_id: user.id,
+        filter_id: 42,
         phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Filter{} = filter} = Filter.create(query)
-      # Should start at 1
-      assert filter.filter_id == 1
+      {:ok, %Filter{} = filter} = Filter.create(attrs)
+      result = Filter.get(filter.filter_id, user)
+      assert attrs.phrase == result.phrase
     end
 
-    test "creating additional filters uses previous highest filter_id + 1" do
-      user = insert(:user)
-
-      query_one = %Filter{
+    test "creating with expired_at", %{user: user} do
+      attrs = %{
         user_id: user.id,
         filter_id: 42,
         phrase: "knights",
+        context: ["home"],
+        expires_in: 60
+      }
+
+      {:ok, %Filter{} = filter} = Filter.create(attrs)
+      result = Filter.get(filter.filter_id, user)
+      assert attrs.phrase == result.phrase
+
+      assert [_] = Repo.all(Job)
+    end
+
+    test "creating one filter without a pre-defined filter_id", %{user: user} do
+      attrs = %{
+        user_id: user.id,
+        phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Filter{} = filter_one} = Filter.create(query_one)
+      {:ok, %Filter{} = filter} = Filter.create(attrs)
+      # Should start at 1
+      assert filter.filter_id == 1
+    end
+
+    test "creating additional filters uses previous highest filter_id + 1", %{user: user} do
+      filter1 = insert(:filter, user: user)
 
-      query_two = %Filter{
+      attrs = %{
         user_id: user.id,
         # No filter_id
         phrase: "who",
         context: ["home"]
       }
 
-      {:ok, %Filter{} = filter_two} = Filter.create(query_two)
-      assert filter_two.filter_id == filter_one.filter_id + 1
+      {:ok, %Filter{} = filter2} = Filter.create(attrs)
+      assert filter2.filter_id == filter1.filter_id + 1
     end
 
-    test "filter_id is unique per user" do
-      user_one = insert(:user)
+    test "filter_id is unique per user", %{user: user_one} do
       user_two = insert(:user)
 
-      query_one = %Filter{
+      attrs1 = %{
         user_id: user_one.id,
         phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Filter{} = filter_one} = Filter.create(query_one)
+      {:ok, %Filter{} = filter_one} = Filter.create(attrs1)
 
-      query_two = %Filter{
+      attrs2 = %{
         user_id: user_two.id,
         phrase: "who",
         context: ["home"]
       }
 
-      {:ok, %Filter{} = filter_two} = Filter.create(query_two)
+      {:ok, %Filter{} = filter_two} = Filter.create(attrs2)
 
       assert filter_one.filter_id == 1
       assert filter_two.filter_id == 1
@@ -94,65 +133,61 @@ defmodule Pleroma.FilterTest do
     end
   end
 
-  test "deleting a filter" do
-    user = insert(:user)
+  test "deleting a filter", %{user: user} do
+    filter = insert(:filter, user: user)
 
-    query = %Filter{
-      user_id: user.id,
-      filter_id: 0,
-      phrase: "knights",
-      context: ["home"]
-    }
-
-    {:ok, _filter} = Filter.create(query)
-    {:ok, filter} = Filter.delete(query)
-    assert is_nil(Repo.get(Filter, filter.filter_id))
+    assert Repo.get(Filter, filter.id)
+    {:ok, filter} = Filter.delete(filter)
+    refute Repo.get(Filter, filter.id)
   end
 
-  test "getting all filters by an user" do
-    user = insert(:user)
-
-    query_one = %Filter{
+  test "deleting a filter with expires_at is removing Oban job too", %{user: user} do
+    attrs = %{
       user_id: user.id,
-      filter_id: 1,
-      phrase: "knights",
-      context: ["home"]
+      phrase: "cofe",
+      context: ["home"],
+      expires_in: 600
     }
 
-    query_two = %Filter{
-      user_id: user.id,
-      filter_id: 2,
-      phrase: "who",
-      context: ["home"]
-    }
+    {:ok, filter} = Filter.create(attrs)
+    assert %Job{id: job_id} = Pleroma.Workers.PurgeExpiredFilter.get_expiration(filter.id)
+    {:ok, _} = Filter.delete(filter)
 
-    {:ok, filter_one} = Filter.create(query_one)
-    {:ok, filter_two} = Filter.create(query_two)
-    filters = Filter.get_filters(user)
-    assert filter_one in filters
-    assert filter_two in filters
+    assert Repo.get(Job, job_id) == nil
   end
 
-  test "updating a filter" do
-    user = insert(:user)
+  test "getting all filters by an user", %{user: user} do
+    filter1 = insert(:filter, user: user)
+    filter2 = insert(:filter, user: user)
 
-    query_one = %Filter{
-      user_id: user.id,
-      filter_id: 1,
-      phrase: "knights",
-      context: ["home"]
-    }
+    filter_ids = user |> Filter.get_filters() |> collect_ids()
+
+    assert filter1.id in filter_ids
+    assert filter2.id in filter_ids
+  end
+
+  test "updating a filter", %{user: user} do
+    filter = insert(:filter, user: user)
 
     changes = %{
       phrase: "who",
       context: ["home", "timeline"]
     }
 
-    {:ok, filter_one} = Filter.create(query_one)
-    {:ok, filter_two} = Filter.update(filter_one, changes)
+    {:ok, updated_filter} = Filter.update(filter, changes)
+
+    assert filter != updated_filter
+    assert updated_filter.phrase == changes.phrase
+    assert updated_filter.context == changes.context
+  end
+
+  test "updating with error", %{user: user} do
+    filter = insert(:filter, user: user)
+
+    changes = %{
+      phrase: nil
+    }
 
-    assert filter_one != filter_two
-    assert filter_two.phrase == changes.phrase
-    assert filter_two.context == changes.context
+    {:error, _} = Filter.update(filter, changes)
   end
 end
index 23e4bc3af585ea12076ba0254e71d9a84f717bf0..e7688c7287c894011a9b6e48663c0dd00e3639a4 100644 (file)
@@ -405,13 +405,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     setup do
       user = insert(:user)
 
-      date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
-      date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
-      date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
-
-      insert(:note_activity, user: user, published: date1)
-      insert(:note_activity, user: user, published: date2)
-      insert(:note_activity, user: user, published: date3)
+      insert(:note_activity, user: user)
+      insert(:note_activity, user: user)
+      insert(:note_activity, user: user)
 
       %{user: user}
     end
@@ -419,23 +415,22 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     test "renders user's statuses", %{conn: conn, user: user} do
       conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
 
-      assert json_response(conn, 200) |> length() == 3
+      assert %{"total" => 3, "activities" => activities} = json_response(conn, 200)
+      assert length(activities) == 3
     end
 
     test "renders user's statuses with pagination", %{conn: conn, user: user} do
-      conn1 = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1")
-
-      response1 = json_response(conn1, 200)
-
-      assert response1 |> length() == 1
-
-      conn2 = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2")
-
-      response2 = json_response(conn2, 200)
+      %{"total" => 3, "activities" => [activity1]} =
+        conn
+        |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1")
+        |> json_response(200)
 
-      assert response2 |> length() == 1
+      %{"total" => 3, "activities" => [activity2]} =
+        conn
+        |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2")
+        |> json_response(200)
 
-      refute response1 == response2
+      refute activity1 == activity2
     end
 
     test "doesn't return private statuses by default", %{conn: conn, user: user} do
@@ -443,9 +438,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
       {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
 
-      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
+      %{"total" => 4, "activities" => activities} =
+        conn
+        |> get("/api/pleroma/admin/users/#{user.nickname}/statuses")
+        |> json_response(200)
 
-      assert json_response(conn, 200) |> length() == 4
+      assert length(activities) == 4
     end
 
     test "returns private statuses with godmode on", %{conn: conn, user: user} do
@@ -453,9 +451,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
       {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
 
-      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
+      %{"total" => 5, "activities" => activities} =
+        conn
+        |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
+        |> json_response(200)
 
-      assert json_response(conn, 200) |> length() == 5
+      assert length(activities) == 5
     end
 
     test "excludes reblogs by default", %{conn: conn, user: user} do
@@ -463,13 +464,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       {:ok, activity} = CommonAPI.post(user, %{status: "."})
       {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
 
-      conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
-      assert json_response(conn_res, 200) |> length() == 0
-
-      conn_res =
-        get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
+      assert %{"total" => 0, "activities" => []} ==
+               conn
+               |> get("/api/pleroma/admin/users/#{other_user.nickname}/statuses")
+               |> json_response(200)
 
-      assert json_response(conn_res, 200) |> length() == 1
+      assert %{"total" => 1, "activities" => [_]} =
+               conn
+               |> get(
+                 "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true"
+               )
+               |> json_response(200)
     end
   end
 
@@ -859,33 +864,30 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       insert_pair(:note_activity, user: user)
       activity = insert(:note_activity, user: user2)
 
-      ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
+      %{"total" => 2, "activities" => activities} =
+        conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
 
-      response = json_response(ret_conn, 200)
+      assert length(activities) == 2
 
-      assert length(response) == 2
+      %{"total" => 1, "activities" => [_]} =
+        conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200)
 
-      ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
+      %{"total" => 0, "activities" => []} =
+        conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200)
 
-      response = json_response(ret_conn, 200)
-
-      assert length(response) == 1
-
-      ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
+      CommonAPI.repeat(activity.id, user)
 
-      response = json_response(ret_conn, 200)
+      %{"total" => 2, "activities" => activities} =
+        conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
 
-      assert Enum.empty?(response)
+      assert length(activities) == 2
 
-      CommonAPI.repeat(activity.id, user)
-
-      ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
-      response = json_response(ret_conn, 200)
-      assert length(response) == 2
+      %{"total" => 3, "activities" => activities} =
+        conn
+        |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
+        |> json_response(200)
 
-      ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
-      response = json_response(ret_conn, 200)
-      assert length(response) == 3
+      assert length(activities) == 3
     end
   end
 
index dc6739178fa92a01ad801c421fd566635ff66667..98ab9e71768d658166ef44b1b84f656a52923437 100644 (file)
 
 defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
   use Pleroma.Web.ConnCase, async: true
+  use Oban.Testing, repo: Pleroma.Repo
 
-  alias Pleroma.Web.MastodonAPI.FilterView
+  import Pleroma.Factory
 
-  test "creating a filter" do
-    %{conn: conn} = oauth_access(["write:filters"])
+  alias Pleroma.Filter
+  alias Pleroma.Repo
+  alias Pleroma.Workers.PurgeExpiredFilter
 
-    filter = %Pleroma.Filter{
-      phrase: "knights",
-      context: ["home"]
-    }
-
-    conn =
+  test "non authenticated creation request", %{conn: conn} do
+    response =
       conn
       |> put_req_header("content-type", "application/json")
-      |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
-
-    assert response = json_response_and_validate_schema(conn, 200)
-    assert response["phrase"] == filter.phrase
-    assert response["context"] == filter.context
-    assert response["irreversible"] == false
-    assert response["id"] != nil
-    assert response["id"] != ""
+      |> post("/api/v1/filters", %{"phrase" => "knights", context: ["home"]})
+      |> json_response(403)
+
+    assert response["error"] == "Invalid credentials."
+  end
+
+  describe "creating" do
+    setup do: oauth_access(["write:filters"])
+
+    test "a common filter", %{conn: conn, user: user} do
+      params = %{
+        phrase: "knights",
+        context: ["home"],
+        irreversible: true
+      }
+
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/filters", params)
+        |> json_response_and_validate_schema(200)
+
+      assert response["phrase"] == params.phrase
+      assert response["context"] == params.context
+      assert response["irreversible"] == true
+      assert response["id"] != nil
+      assert response["id"] != ""
+      assert response["expires_at"] == nil
+
+      filter = Filter.get(response["id"], user)
+      assert filter.hide == true
+    end
+
+    test "a filter with expires_in", %{conn: conn, user: user} do
+      in_seconds = 600
+
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/filters", %{
+          "phrase" => "knights",
+          context: ["home"],
+          expires_in: in_seconds
+        })
+        |> json_response_and_validate_schema(200)
+
+      assert response["irreversible"] == false
+
+      expires_at =
+        NaiveDateTime.utc_now()
+        |> NaiveDateTime.add(in_seconds)
+        |> Pleroma.Web.CommonAPI.Utils.to_masto_date()
+
+      assert response["expires_at"] == expires_at
+
+      filter = Filter.get(response["id"], user)
+
+      id = filter.id
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      assert {:ok, %{id: ^id}} =
+               perform_job(PurgeExpiredFilter, %{
+                 filter_id: filter.id
+               })
+
+      assert Repo.aggregate(Filter, :count, :id) == 0
+    end
   end
 
   test "fetching a list of filters" do
     %{user: user, conn: conn} = oauth_access(["read:filters"])
 
-    query_one = %Pleroma.Filter{
-      user_id: user.id,
-      filter_id: 1,
-      phrase: "knights",
-      context: ["home"]
-    }
+    %{filter_id: id1} = insert(:filter, user: user)
+    %{filter_id: id2} = insert(:filter, user: user)
 
-    query_two = %Pleroma.Filter{
-      user_id: user.id,
-      filter_id: 2,
-      phrase: "who",
-      context: ["home"]
-    }
+    id1 = to_string(id1)
+    id2 = to_string(id2)
 
-    {:ok, filter_one} = Pleroma.Filter.create(query_one)
-    {:ok, filter_two} = Pleroma.Filter.create(query_two)
+    assert [%{"id" => ^id2}, %{"id" => ^id1}] =
+             conn
+             |> get("/api/v1/filters")
+             |> json_response_and_validate_schema(200)
+  end
+
+  test "fetching a list of filters without token", %{conn: conn} do
+    insert(:filter)
 
     response =
       conn
       |> get("/api/v1/filters")
-      |> json_response_and_validate_schema(200)
-
-    assert response ==
-             render_json(
-               FilterView,
-               "index.json",
-               filters: [filter_two, filter_one]
-             )
+      |> json_response(403)
+
+    assert response["error"] == "Invalid credentials."
   end
 
   test "get a filter" do
     %{user: user, conn: conn} = oauth_access(["read:filters"])
 
     # check whole_word false
-    query = %Pleroma.Filter{
-      user_id: user.id,
-      filter_id: 2,
-      phrase: "knight",
-      context: ["home"],
-      whole_word: false
-    }
-
-    {:ok, filter} = Pleroma.Filter.create(query)
+    filter = insert(:filter, user: user, whole_word: false)
 
-    conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
+    resp1 =
+      conn |> get("/api/v1/filters/#{filter.filter_id}") |> json_response_and_validate_schema(200)
 
-    assert response = json_response_and_validate_schema(conn, 200)
-    assert response["whole_word"] == false
+    assert resp1["whole_word"] == false
 
     # check whole_word true
-    %{user: user, conn: conn} = oauth_access(["read:filters"])
-
-    query = %Pleroma.Filter{
-      user_id: user.id,
-      filter_id: 3,
-      phrase: "knight",
-      context: ["home"],
-      whole_word: true
-    }
+    filter = insert(:filter, user: user, whole_word: true)
 
-    {:ok, filter} = Pleroma.Filter.create(query)
+    resp2 =
+      conn |> get("/api/v1/filters/#{filter.filter_id}") |> json_response_and_validate_schema(200)
 
-    conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
-
-    assert response = json_response_and_validate_schema(conn, 200)
-    assert response["whole_word"] == true
+    assert resp2["whole_word"] == true
   end
 
-  test "update a filter" do
-    %{user: user, conn: conn} = oauth_access(["write:filters"])
+  test "get a filter not_found error" do
+    filter = insert(:filter)
+    %{conn: conn} = oauth_access(["read:filters"])
 
-    query = %Pleroma.Filter{
-      user_id: user.id,
-      filter_id: 2,
-      phrase: "knight",
-      context: ["home"],
-      hide: true,
-      whole_word: true
-    }
+    response =
+      conn |> get("/api/v1/filters/#{filter.filter_id}") |> json_response_and_validate_schema(404)
 
-    {:ok, _filter} = Pleroma.Filter.create(query)
+    assert response["error"] == "Record not found"
+  end
+
+  describe "updating a filter" do
+    setup do: oauth_access(["write:filters"])
+
+    test "common" do
+      %{conn: conn, user: user} = oauth_access(["write:filters"])
+
+      filter =
+        insert(:filter,
+          user: user,
+          hide: true,
+          whole_word: true
+        )
+
+      params = %{
+        phrase: "nii",
+        context: ["public"],
+        irreversible: false
+      }
+
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> put("/api/v1/filters/#{filter.filter_id}", params)
+        |> json_response_and_validate_schema(200)
+
+      assert response["phrase"] == params.phrase
+      assert response["context"] == params.context
+      assert response["irreversible"] == false
+      assert response["whole_word"] == true
+    end
+
+    test "with adding expires_at", %{conn: conn, user: user} do
+      filter = insert(:filter, user: user)
+      in_seconds = 600
+
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> put("/api/v1/filters/#{filter.filter_id}", %{
+          phrase: "nii",
+          context: ["public"],
+          expires_in: in_seconds,
+          irreversible: true
+        })
+        |> json_response_and_validate_schema(200)
+
+      assert response["irreversible"] == true
+
+      assert response["expires_at"] ==
+               NaiveDateTime.utc_now()
+               |> NaiveDateTime.add(in_seconds)
+               |> Pleroma.Web.CommonAPI.Utils.to_masto_date()
+
+      filter = Filter.get(response["id"], user)
+
+      id = filter.id
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: id}
+      )
+
+      assert {:ok, %{id: ^id}} =
+               perform_job(PurgeExpiredFilter, %{
+                 filter_id: id
+               })
+
+      assert Repo.aggregate(Filter, :count, :id) == 0
+    end
+
+    test "with removing expires_at", %{conn: conn, user: user} do
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/filters", %{
+          phrase: "cofe",
+          context: ["home"],
+          expires_in: 600
+        })
+        |> json_response_and_validate_schema(200)
+
+      filter = Filter.get(response["id"], user)
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> put("/api/v1/filters/#{filter.filter_id}", %{
+          phrase: "nii",
+          context: ["public"],
+          expires_in: nil,
+          whole_word: true
+        })
+        |> json_response_and_validate_schema(200)
+
+      refute_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      assert response["irreversible"] == false
+      assert response["whole_word"] == true
+      assert response["expires_at"] == nil
+    end
+
+    test "expires_at is the same in create and update so job is in db", %{conn: conn, user: user} do
+      resp1 =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/filters", %{
+          phrase: "cofe",
+          context: ["home"],
+          expires_in: 600
+        })
+        |> json_response_and_validate_schema(200)
+
+      filter = Filter.get(resp1["id"], user)
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      job = PurgeExpiredFilter.get_expiration(filter.id)
+
+      resp2 =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> put("/api/v1/filters/#{filter.filter_id}", %{
+          phrase: "nii",
+          context: ["public"]
+        })
+        |> json_response_and_validate_schema(200)
+
+      updated_filter = Filter.get(resp2["id"], user)
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: updated_filter.id}
+      )
+
+      after_update = PurgeExpiredFilter.get_expiration(updated_filter.id)
+
+      assert resp1["expires_at"] == resp2["expires_at"]
+
+      assert job.scheduled_at == after_update.scheduled_at
+    end
+
+    test "updating expires_at updates oban job too", %{conn: conn, user: user} do
+      resp1 =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/filters", %{
+          phrase: "cofe",
+          context: ["home"],
+          expires_in: 600
+        })
+        |> json_response_and_validate_schema(200)
+
+      filter = Filter.get(resp1["id"], user)
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      job = PurgeExpiredFilter.get_expiration(filter.id)
+
+      resp2 =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> put("/api/v1/filters/#{filter.filter_id}", %{
+          phrase: "nii",
+          context: ["public"],
+          expires_in: 300
+        })
+        |> json_response_and_validate_schema(200)
+
+      updated_filter = Filter.get(resp2["id"], user)
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: updated_filter.id}
+      )
+
+      after_update = PurgeExpiredFilter.get_expiration(updated_filter.id)
+
+      refute resp1["expires_at"] == resp2["expires_at"]
+
+      refute job.scheduled_at == after_update.scheduled_at
+    end
+  end
 
-    new = %Pleroma.Filter{
-      phrase: "nii",
-      context: ["home"]
-    }
+  test "update filter without token", %{conn: conn} do
+    filter = insert(:filter)
 
-    conn =
+    response =
       conn
       |> put_req_header("content-type", "application/json")
-      |> put("/api/v1/filters/#{query.filter_id}", %{
-        phrase: new.phrase,
-        context: new.context
+      |> put("/api/v1/filters/#{filter.filter_id}", %{
+        phrase: "nii",
+        context: ["public"]
       })
+      |> json_response(403)
 
-    assert response = json_response_and_validate_schema(conn, 200)
-    assert response["phrase"] == new.phrase
-    assert response["context"] == new.context
-    assert response["irreversible"] == true
-    assert response["whole_word"] == true
+    assert response["error"] == "Invalid credentials."
   end
 
-  test "delete a filter" do
-    %{user: user, conn: conn} = oauth_access(["write:filters"])
-
-    query = %Pleroma.Filter{
-      user_id: user.id,
-      filter_id: 2,
-      phrase: "knight",
-      context: ["home"]
-    }
+  describe "delete a filter" do
+    setup do: oauth_access(["write:filters"])
+
+    test "common", %{conn: conn, user: user} do
+      filter = insert(:filter, user: user)
+
+      assert conn
+             |> delete("/api/v1/filters/#{filter.filter_id}")
+             |> json_response_and_validate_schema(200) == %{}
+
+      assert Repo.all(Filter) == []
+    end
+
+    test "with expires_at", %{conn: conn, user: user} do
+      response =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/filters", %{
+          phrase: "cofe",
+          context: ["home"],
+          expires_in: 600
+        })
+        |> json_response_and_validate_schema(200)
+
+      filter = Filter.get(response["id"], user)
+
+      assert_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      assert conn
+             |> delete("/api/v1/filters/#{filter.filter_id}")
+             |> json_response_and_validate_schema(200) == %{}
+
+      refute_enqueued(
+        worker: PurgeExpiredFilter,
+        args: %{filter_id: filter.id}
+      )
+
+      assert Repo.all(Filter) == []
+      assert Repo.all(Oban.Job) == []
+    end
+  end
 
-    {:ok, filter} = Pleroma.Filter.create(query)
+  test "delete a filter without token", %{conn: conn} do
+    filter = insert(:filter)
 
-    conn = delete(conn, "/api/v1/filters/#{filter.filter_id}")
+    response =
+      conn
+      |> delete("/api/v1/filters/#{filter.filter_id}")
+      |> json_response(403)
 
-    assert json_response_and_validate_schema(conn, 200) == %{}
+    assert response["error"] == "Invalid credentials."
   end
 end
index 3c73eb514597637625adab4d36d5dbedfd64bf00..dcd1e6d5b8bfa78fd1b12dc8e58168fa559dec25 100644 (file)
@@ -516,7 +516,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
              end)
 
       assert NaiveDateTime.diff(NaiveDateTime.from_iso8601!(response["poll"]["expires_at"]), time) in 420..430
-      refute response["poll"]["expred"]
+      assert response["poll"]["expired"] == false
 
       question = Object.get_by_id(response["poll"]["id"])
 
@@ -592,6 +592,44 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       %{"error" => error} = json_response_and_validate_schema(conn, 422)
       assert error == "Expiration date is too far in the future"
     end
+
+    test "scheduled poll", %{conn: conn} do
+      clear_config([ScheduledActivity, :enabled], true)
+
+      scheduled_at =
+        NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(6), :millisecond)
+        |> NaiveDateTime.to_iso8601()
+        |> Kernel.<>("Z")
+
+      %{"id" => scheduled_id} =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/statuses", %{
+          "status" => "very cool poll",
+          "poll" => %{
+            "options" => ~w(a b c),
+            "expires_in" => 420
+          },
+          "scheduled_at" => scheduled_at
+        })
+        |> json_response_and_validate_schema(200)
+
+      assert {:ok, %{id: activity_id}} =
+               perform_job(Pleroma.Workers.ScheduledActivityWorker, %{
+                 activity_id: scheduled_id
+               })
+
+      assert Repo.all(Oban.Job) == []
+
+      object =
+        Activity
+        |> Repo.get(activity_id)
+        |> Object.normalize()
+
+      assert object.data["content"] == "very cool poll"
+      assert object.data["type"] == "Question"
+      assert length(object.data["oneOf"]) == 3
+    end
   end
 
   test "get a status" do
diff --git a/test/pleroma/workers/purge_expired_filter_test.exs b/test/pleroma/workers/purge_expired_filter_test.exs
new file mode 100644 (file)
index 0000000..d10586b
--- /dev/null
@@ -0,0 +1,30 @@
+defmodule Pleroma.Workers.PurgeExpiredFilterTest do
+  use Pleroma.DataCase, async: true
+  use Oban.Testing, repo: Repo
+
+  import Pleroma.Factory
+
+  test "purges expired filter" do
+    %{id: user_id} = insert(:user)
+
+    {:ok, %{id: id}} =
+      Pleroma.Filter.create(%{
+        user_id: user_id,
+        phrase: "cofe",
+        context: ["home"],
+        expires_in: 600
+      })
+
+    assert_enqueued(
+      worker: Pleroma.Workers.PurgeExpiredFilter,
+      args: %{filter_id: id}
+    )
+
+    assert {:ok, %{id: ^id}} =
+             perform_job(Pleroma.Workers.PurgeExpiredFilter, %{
+               filter_id: id
+             })
+
+    assert Repo.aggregate(Pleroma.Filter, :count, :id) == 0
+  end
+end
index 6e11642d53647166c0b568e986c1a5cce8ed11d8..5558d5b5f9a789d14e1cf0557b09952bfe62d243 100644 (file)
@@ -11,10 +11,9 @@ defmodule Pleroma.Workers.ScheduledActivityWorkerTest do
   import Pleroma.Factory
   import ExUnit.CaptureLog
 
-  setup do: clear_config([ScheduledActivity, :enabled])
+  setup do: clear_config([ScheduledActivity, :enabled], true)
 
   test "creates a status from the scheduled activity" do
-    clear_config([ScheduledActivity, :enabled], true)
     user = insert(:user)
 
     naive_datetime =
@@ -32,18 +31,22 @@ defmodule Pleroma.Workers.ScheduledActivityWorkerTest do
         params: %{status: "hi"}
       )
 
-    ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => scheduled_activity.id}})
+    {:ok, %{id: activity_id}} =
+      ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => scheduled_activity.id}})
 
     refute Repo.get(ScheduledActivity, scheduled_activity.id)
-    activity = Repo.all(Pleroma.Activity) |> Enum.find(&(&1.actor == user.ap_id))
-    assert Pleroma.Object.normalize(activity, fetch: false).data["content"] == "hi"
-  end
 
-  test "adds log message if ScheduledActivity isn't find" do
-    clear_config([ScheduledActivity, :enabled], true)
+    object =
+      Pleroma.Activity
+      |> Repo.get(activity_id)
+      |> Pleroma.Object.normalize()
+
+    assert object.data["content"] == "hi"
+  end
 
+  test "error message for non-existent scheduled activity" do
     assert capture_log([level: :error], fn ->
              ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => 42}})
-           end) =~ "Couldn't find scheduled activity"
+           end) =~ "Couldn't find scheduled activity: 42"
   end
 end
index 436e19409c5ab0f4701bea5aa4dd1f4e32ca4ecb..af4fff45b947c771e5d622b1ff7af73cf9108388 100644 (file)
@@ -486,7 +486,8 @@ defmodule Pleroma.Factory do
     %Pleroma.Filter{
       user: build(:user),
       filter_id: sequence(:filter_id, & &1),
-      phrase: "cofe"
+      phrase: "cofe",
+      context: ["home"]
     }
   end
 end