Merge branch 'feat/client_app_details' into 'develop'
authorlain <lain@soykaf.club>
Sun, 28 Feb 2021 16:17:34 +0000 (16:17 +0000)
committerlain <lain@soykaf.club>
Sun, 28 Feb 2021 16:17:34 +0000 (16:17 +0000)
Support application field

See merge request pleroma/pleroma!3311

88 files changed:
.gitignore
.gitlab-ci.yml
.mailmap
CHANGELOG.md
COPYING
config/config.exs
config/test.exs
docs/clients.md
docs/development/API/admin_api.md
docs/development/API/differences_in_mastoapi_responses.md
docs/installation/otp_en.md
lib/mix/tasks/pleroma/ecto/rollback.ex
lib/mix/tasks/pleroma/openapi_spec.ex
lib/pleroma/application.ex
lib/pleroma/config.ex
lib/pleroma/conversation.ex
lib/pleroma/conversation/participation.ex
lib/pleroma/notification.ex
lib/pleroma/stats.ex
lib/pleroma/upload/filter/exiftool.ex
lib/pleroma/upload/filter/mogrifun.ex
lib/pleroma/upload/filter/mogrify.ex
lib/pleroma/web.ex
lib/pleroma/web/activity_pub/activity_pub_controller.ex
lib/pleroma/web/activity_pub/visibility.ex
lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
lib/pleroma/web/admin_api/controllers/chat_controller.ex
lib/pleroma/web/admin_api/controllers/config_controller.ex
lib/pleroma/web/admin_api/controllers/frontend_controller.ex
lib/pleroma/web/admin_api/controllers/instance_document_controller.ex
lib/pleroma/web/admin_api/controllers/invite_controller.ex
lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex
lib/pleroma/web/admin_api/controllers/relay_controller.ex
lib/pleroma/web/admin_api/controllers/report_controller.ex
lib/pleroma/web/admin_api/controllers/status_controller.ex
lib/pleroma/web/admin_api/controllers/user_controller.ex
lib/pleroma/web/api_spec.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/chat_operation.ex
lib/pleroma/web/api_spec/operations/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/schemas/chat_message.ex
lib/pleroma/web/api_spec/schemas/scheduled_status.ex
lib/pleroma/web/mastodon_api/controllers/app_controller.ex
lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
lib/pleroma/web/mastodon_api/views/app_view.ex
lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex
lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex
lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex
lib/pleroma/web/plugs/ensure_authenticated_plug.ex
lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex
lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
lib/pleroma/web/plugs/frontend_static.ex
lib/pleroma/web/plugs/o_auth_scopes_plug.ex
lib/pleroma/web/router.ex
priv/static/images/avi.png
test/fixtures/users_mock/localhost.json [deleted file]
test/mix/tasks/pleroma/ecto/rollback_test.exs
test/pleroma/conversation/participation_test.exs
test/pleroma/notification_test.exs
test/pleroma/web/activity_pub/activity_pub_controller_test.exs
test/pleroma/web/activity_pub/visibility_test.exs
test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs
test/pleroma/web/admin_api/controllers/user_controller_test.exs
test/pleroma/web/mastodon_api/controllers/app_controller_test.exs
test/pleroma/web/mastodon_api/controllers/conversation_controller_test.exs
test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs
test/pleroma/web/mastodon_api/controllers/status_controller_test.exs
test/pleroma/web/mastodon_api/views/notification_view_test.exs
test/pleroma/web/mastodon_api/views/scheduled_activity_view_test.exs
test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs
test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs
test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs
test/pleroma/web/plugs/frontend_static_plug_test.exs
test/pleroma/web/plugs/o_auth_scopes_plug_test.exs
test/pleroma/web/streamer_test.exs

index 4dea75e9333aa49659c5676174e64a4ea4949962..f30f4cf5fb2fe583d8726b35e513dd67d5f4afb0 100644 (file)
@@ -53,3 +53,7 @@ pleroma.iml
 
 # asdf
 .tool-versions
+
+# Editor temp files
+/*~
+/*#
\ No newline at end of file
index 0fec893684a316ad4ecf15db972b2381a458ca17..c7e8291d8161005471895583e3736aed095e517d 100644 (file)
@@ -371,3 +371,26 @@ docker-release:
     - dind
   only:
     - /^release/.*$/@pleroma/pleroma
+
+docker-adhoc:
+  stage: docker
+  image: docker:latest
+  cache: {}
+  dependencies: []
+  variables: *docker-variables
+  before_script: *before-docker
+  allow_failure: true
+  script:
+  script:
+    - mkdir -p /root/.docker/cli-plugins
+    - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+    - echo "${DOCKER_BUILDX_HASH}  /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+    - chmod +x ~/.docker/cli-plugins/docker-buildx
+    - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+    - docker buildx create --name mbuilder --driver docker-container --use
+    - docker buildx inspect --bootstrap
+    - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
+  tags:
+    - dind
+  only:
+    - /^build-docker/.*$/@pleroma/pleroma
\ No newline at end of file
index e4ca5f9b589d8b6a1aeb815b9a146f7222e250ad..84fffaee78f6b3535a362562c1a4fd059c508742 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -1,2 +1,3 @@
 Ariadne Conill <ariadne@dereferenced.org> <nenolod@dereferenced.org>
 Ariadne Conill <ariadne@dereferenced.org> <nenolod@gmail.com>
+rinpatch <rin@patch.cx> <rinpatch@sdf.org>
index 69b9e2c5299e78f020d1297128e1c6bd1582cc58..c4837c9553b763cbaa458ae710e8a003e7e00f4b 100644 (file)
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 ## Unreleased
 
+### Removed
+
+- `:auth, :enforce_oauth_admin_scope_usage` configuration option.
+
 ### Changed
 
 - **Breaking**: Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm`
@@ -21,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Provide redirect of external posts from `/notice/:id` to their original URL
 - Admins no longer receive notifications for reports if they are the actor making the report.
 - Improved Mailer configuration setting descriptions for AdminFE.
+- Updated default avatar to look nicer.
 
 <details>
   <summary>API Changes</summary>
@@ -31,6 +36,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - **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
+- Pleroma API: `GET /api/v1/pleroma/chats` is deprecated in favor of `GET /api/v2/pleroma/chats`.
 
 </details>
 
@@ -58,6 +64,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 <details>
   <summary>API Changes</summary>
 - Admin API: (`GET /api/pleroma/admin/users`) filter users by `unconfirmed` status and `actor_type`.
+- Pleroma API: `GET /api/v2/pleroma/chats` added. It is exactly like `GET /api/v1/pleroma/chats` except supports pagination.
 - Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
 - Pleroma API: (`GET /api/v1/pleroma/federation_status`) Add a way to get a list of unreachable instances.
 - Mastodon API: User and conversation mutes can now auto-expire if `expires_in` parameter was given while adding the mute.
@@ -67,6 +74,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mastodon API: Add monthly active users to `/api/v1/instance` (`pleroma.stats.mau`).
 - Mastodon API: Home, public, hashtag & list timelines accept `only_media`, `remote` & `local` parameters for filtration.
 - Mastodon API: `/api/v1/accounts/:id` & `/api/v1/mutes` endpoints accept `with_relationships` parameter and return filled `pleroma.relationship` field.
+- Mastodon API: Endpoint to remove a conversation (`DELETE /api/v1/conversations/:id`).
+- Mastodon API: `expires_in` in the scheduled post `params` field on `/api/v1/statuses` and `/api/v1/scheduled_statuses/:id` endpoints.
 </details>
 
 ### Fixed
diff --git a/COPYING b/COPYING
index eb60dbd5668338ffe1cd69c884b06c8a14af63dd..dd25f1d81ddc95abf1453abe421ba5fe1a9b341a 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -5,6 +5,13 @@ copy of the license file as AGPL-3.
 
 ---
 
+Files inside docs directory are copyright Â© 2021 Pleroma Authors
+<https://pleroma.social/>, and are distributed under the Creative Commons
+Attribution 4.0 International license, you should have received
+a copy of the license file as CC-BY-4.0.
+
+---
+
 The following files are copyright Â© 2019 shitposter.club, and are distributed
 under the Creative Commons Attribution-ShareAlike 4.0 International license,
 you should have received a copy of the license file as CC-BY-SA-4.0.
index 0fbca06f3f8f8d2cd35c0cdef8a39c0fb378efea..66aee3264a0fa0a305a6748ceba77d1b846d1369 100644 (file)
@@ -611,10 +611,7 @@ config :ueberauth,
        base_path: "/oauth",
        providers: ueberauth_providers
 
-config :pleroma,
-       :auth,
-       enforce_oauth_admin_scope_usage: true,
-       oauth_consumer_strategies: oauth_consumer_strategies
+config :pleroma, :auth, oauth_consumer_strategies: oauth_consumer_strategies
 
 config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail, enabled: false
 
index 690c98e40e909b6b3ff4aaa8f85f655f9727c5df..87396a88dbfe98e0764db7817c54476eb9c48ddb 100644 (file)
@@ -38,7 +38,7 @@ config :pleroma, :instance,
   external_user_synchronization: false,
   static_dir: "test/instance_static/"
 
-config :pleroma, :activitypub, sign_object_fetches: false
+config :pleroma, :activitypub, sign_object_fetches: false, follow_handshake_timeout: 0
 
 # Configure your database
 config :pleroma, Pleroma.Repo,
index 3d81763e1ab029dfb346c4906f00f667377b0d47..5650ea236542c0e69820e81d7422c3009adb6b8b 100644 (file)
@@ -17,7 +17,7 @@ Feel free to contact us to be added to this list!
 - Features: MastoAPI
 
 ### Whalebird
-- Homepage: <https://whalebird.org/>
+- Homepage: <https://whalebird.social/>
 - Source Code: <https://github.com/h3poteto/whalebird-desktop>
 - Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)
 - Platforms: Windows, Mac, Linux
index 04a1814016cf86c03b85bbc2c16064242a82297f..f6519830bf2915746603d3b59f0261962691bade 100644 (file)
@@ -2,13 +2,6 @@
 
 Authentication is required and the user must be an admin.
 
-Configuration options:
-
-* `[:auth, :enforce_oauth_admin_scope_usage]` â€” OAuth admin scope requirement toggle.
-    If `true`, admin actions explicitly demand admin OAuth scope(s) presence in OAuth token (client app must support admin scopes).
-    If `false` and token doesn't have admin scope(s), `is_admin` user flag grants access to admin-specific actions.
-    Note that client app needs to explicitly support admin scopes and request them when obtaining auth token.
-
 ## `GET /api/pleroma/admin/users`
 
 ### List users
index 38d70fa78e188757590423639a73f38165cf9478..5f694602277c285d0f15e0fbcdff3961a178232b 100644 (file)
@@ -39,6 +39,12 @@ Has these additional fields under the `pleroma` object:
 - `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
 - `parent_visible`: If the parent of this post is visible to the user or not.
 
+## Scheduled statuses
+
+Has these additional fields in `params`:
+
+- `expires_in`: the number of seconds the posted activity should expire in.
+
 ## Media Attachments
 
 Has these additional fields under the `pleroma` object:
@@ -92,7 +98,7 @@ Has these additional fields under the `pleroma` object:
 - `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
 - `hide_follows_count`: boolean, true when the user has follow stat hiding enabled
 - `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `/api/v1/accounts/verify_credentials` and `/api/v1/accounts/update_credentials`
-- `chat_token`: The token needed for Pleroma chat. Only returned in `/api/v1/accounts/verify_credentials`
+- `chat_token`: The token needed for Pleroma shoutbox. Only returned in `/api/v1/accounts/verify_credentials`
 - `deactivated`: boolean, true when the user is deactivated
 - `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
 - `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
index f36b33c32ecd8431bad550d6d8997d16e1cc5955..42e264e657c7a11182a7c76a54c0cdf9a3b6f2ae 100644 (file)
@@ -150,7 +150,7 @@ su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate"
 # su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
 
 # Start the instance to verify that everything is working as expected
-su pleroma -s $SHELL -lc "export $(cat /opt/pleroma/config/pleroma.env); ./bin/pleroma daemon"
+su pleroma -s $SHELL -lc "./bin/pleroma daemon"
 
 # Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly
 sleep 20 && curl http://localhost:4000/api/v1/instance
index 2b1d48048de83735b935712eaa7f90e281e49fcd..025ebaf19b8e885f19d0f753ebd8db02ef530e7a 100644 (file)
@@ -20,7 +20,8 @@ defmodule Mix.Tasks.Pleroma.Ecto.Rollback do
     start: :boolean,
     quiet: :boolean,
     log_sql: :boolean,
-    migrations_path: :string
+    migrations_path: :string,
+    env: :string
   ]
 
   @moduledoc """
@@ -59,7 +60,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.Rollback do
     level = Logger.level()
     Logger.configure(level: :info)
 
-    if Pleroma.Config.get(:env) == :test do
+    if opts[:env] == "test" do
       Logger.info("Rollback succesfully")
     else
       {:ok, _, _} =
index 524bf514427633fe78cc8b150940070d8286c0bf..8f719c58b71b069a14314f48fa1b568d9ebafe89 100644 (file)
@@ -1,5 +1,7 @@
 defmodule Mix.Tasks.Pleroma.OpenapiSpec do
   def run([path]) do
+    # Load Pleroma application to get version info
+    Application.load(:pleroma)
     spec = Pleroma.Web.ApiSpec.spec(server_specific: false) |> Jason.encode!()
     File.write(path, spec)
   end
index 375507de16570c3b58ac10d40df1cdfeb1faf47b..c853a2bb4564409c22bae36d5fdc1a622913a35a 100644 (file)
@@ -97,13 +97,13 @@ defmodule Pleroma.Application do
           Pleroma.Stats,
           Pleroma.JobQueueMonitor,
           {Majic.Pool, [name: Pleroma.MajicPool, pool_size: Config.get([:majic_pool, :size], 2)]},
-          {Oban, Config.get(Oban)}
+          {Oban, Config.get(Oban)},
+          Pleroma.Web.Endpoint
         ] ++
         task_children(@mix_env) ++
         dont_run_in_test(@mix_env) ++
         chat_child(chat_enabled?()) ++
         [
-          Pleroma.Web.Endpoint,
           Pleroma.Gopher.Server
         ]
 
index f17e141282883d7c29e876a253003556a66a7747..2e15a37193ada875eeb73746d30b2bc37e464a68 100644 (file)
@@ -99,16 +99,4 @@ defmodule Pleroma.Config do
   def oauth_consumer_strategies, do: get([:auth, :oauth_consumer_strategies], [])
 
   def oauth_consumer_enabled?, do: oauth_consumer_strategies() != []
-
-  def enforce_oauth_admin_scope_usage?, do: !!get([:auth, :enforce_oauth_admin_scope_usage])
-
-  def oauth_admin_scopes(scopes) when is_list(scopes) do
-    Enum.flat_map(
-      scopes,
-      fn scope ->
-        ["admin:#{scope}"] ++
-          if enforce_oauth_admin_scope_usage?(), do: [], else: [scope]
-      end
-    )
-  end
 end
index 8812b456ddd54a2eb7f7b899bf122f91fb0cfc2e..828e274504a2d6b394a520ece4bff61e6cc06b9b 100644 (file)
@@ -61,9 +61,8 @@ defmodule Pleroma.Conversation do
          "Create" <- activity.data["type"],
          %Object{} = object <- Object.normalize(activity, fetch: false),
          true <- object.data["type"] in ["Note", "Question"],
-         ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"] do
-      {:ok, conversation} = create_for_ap_id(ap_id)
-
+         ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"],
+         {:ok, conversation} <- create_for_ap_id(ap_id) do
       users = User.get_users_from_set(activity.recipients, local_only: false)
 
       participations =
index da5e57714d60e6758d515326fa15f32c2537a73e..e0a3af28b9b62fdeaa2b0a31bf2ac663578b3eb0 100644 (file)
@@ -220,4 +220,8 @@ defmodule Pleroma.Conversation.Participation do
       select: %{count: count(p.id)}
     )
   end
+
+  def delete(%__MODULE__{} = participation) do
+    Repo.delete(participation)
+  end
 end
index 1970fbf65d1611ac907fdeaa78aa6f660404e5d2..7efbdc49afe1811a145a78cc548ad0dd54935849 100644 (file)
@@ -112,13 +112,6 @@ defmodule Pleroma.Notification do
 
     Notification
     |> where(user_id: ^user.id)
-    |> where(
-      [n, a],
-      fragment(
-        "? not in (SELECT ap_id FROM users WHERE is_active = 'false')",
-        a.actor
-      )
-    )
     |> join(:inner, [n], activity in assoc(n, :activity))
     |> join(:left, [n, a], object in Object,
       on:
@@ -129,7 +122,9 @@ defmodule Pleroma.Notification do
           a.data
         )
     )
+    |> join(:inner, [_n, a], u in User, on: u.ap_id == a.actor, as: :user_actor)
     |> preload([n, a, o], activity: {a, object: o})
+    |> where([user_actor: user_actor], user_actor.is_active)
     |> exclude_notification_muted(user, exclude_notification_muted_opts)
     |> exclude_blocked(user, exclude_blocked_opts)
     |> exclude_filtered(user)
@@ -156,9 +151,10 @@ defmodule Pleroma.Notification do
     query
     |> where([n, a], a.actor not in ^notification_muted_ap_ids)
     |> join(:left, [n, a], tm in ThreadMute,
-      on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
+      on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data),
+      as: :thread_mute
     )
-    |> where([n, a, o, tm], is_nil(tm.user_id))
+    |> where([thread_mute: thread_mute], is_nil(thread_mute.user_id))
   end
 
   defp exclude_filtered(query, user) do
index b096a9b1e8ea43a0a3fa958eafcaf2a9262829eb..3e3f24c2c21cae836bd7831c5c4b59d04c7dff51 100644 (file)
@@ -23,7 +23,11 @@ defmodule Pleroma.Stats do
 
   @impl true
   def init(_args) do
-    {:ok, nil, {:continue, :calculate_stats}}
+    if Pleroma.Config.get(:env) != :test do
+      {:ok, nil, {:continue, :calculate_stats}}
+    else
+      {:ok, calculate_stat_data()}
+    end
   end
 
   @doc "Performs update stats"
index 2dbde540d975dc804df7571ac20a4f16a189f1f3..a2bfbbf612c92b590e70558db3329c9a2abeadf3 100644 (file)
@@ -11,7 +11,8 @@ defmodule Pleroma.Upload.Filter.Exiftool do
 
   @spec filter(Pleroma.Upload.t()) :: {:ok, any()} | {:error, String.t()}
 
-  # webp is not compatible with exiftool at this time
+  # Formats not compatible with exiftool at this time
+  def filter(%Pleroma.Upload{content_type: "image/heic"}), do: {:ok, :noop}
   def filter(%Pleroma.Upload{content_type: "image/webp"}), do: {:ok, :noop}
 
   def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do
@@ -21,8 +22,8 @@ defmodule Pleroma.Upload.Filter.Exiftool do
         {error, 1} -> {:error, error}
       end
     rescue
-      _e in ErlangError ->
-        {:error, "exiftool command not found"}
+      e in ErlangError ->
+        {:error, "#{__MODULE__}: #{inspect(e)}"}
     end
   end
 
index 9abdd2d516bf6986b80d70c96db2837230e6a53e..01126aaeb6c6908e2960ab766c4e7876860a3f4b 100644 (file)
@@ -44,8 +44,8 @@ defmodule Pleroma.Upload.Filter.Mogrifun do
       Filter.Mogrify.do_filter(file, [Enum.random(@filters)])
       {:ok, :filtered}
     rescue
-      _e in ErlangError ->
-        {:error, "mogrify command not found"}
+      e in ErlangError ->
+        {:error, "#{__MODULE__}: #{inspect(e)}"}
     end
   end
 
index 4bca4f5cac4149703c97604c92b43cebfb146108..f27aefc2252d283451006cc987d45cb541d86b92 100644 (file)
@@ -14,8 +14,8 @@ defmodule Pleroma.Upload.Filter.Mogrify do
       do_filter(file, Pleroma.Config.get!([__MODULE__, :args]))
       {:ok, :filtered}
     rescue
-      _e in ErlangError ->
-        {:error, "mogrify command not found"}
+      e in ErlangError ->
+        {:error, "#{__MODULE__}: #{inspect(e)}"}
     end
   end
 
index c3aa3949274d279ed1fd94962cbe3c555038aa6d..8630f244b8505dc5bba489fa88f72061f1b65396 100644 (file)
@@ -63,7 +63,8 @@ defmodule Pleroma.Web do
 
       # Executed just before actual controller action, invokes before-action hooks (callbacks)
       defp action(conn, params) do
-        with %{halted: false} = conn <- maybe_drop_authentication_if_oauth_check_ignored(conn),
+        with %{halted: false} = conn <-
+               maybe_drop_authentication_if_oauth_check_ignored(conn),
              %{halted: false} = conn <- maybe_perform_public_or_authenticated_check(conn),
              %{halted: false} = conn <- maybe_perform_authenticated_check(conn),
              %{halted: false} = conn <- maybe_halt_on_missing_oauth_scopes_check(conn) do
@@ -232,4 +233,16 @@ defmodule Pleroma.Web do
   def base_url do
     Pleroma.Web.Endpoint.url()
   end
+
+  # TODO: Change to Phoenix.Router.routes/1 for Phoenix 1.6.0+
+  def get_api_routes do
+    Pleroma.Web.Router.__routes__()
+    |> Enum.reject(fn r -> r.plug == Pleroma.Web.Fallback.RedirectController end)
+    |> Enum.map(fn r ->
+      r.path
+      |> String.split("/", trim: true)
+      |> List.first()
+    end)
+    |> Enum.uniq()
+  end
 end
index eb9e119f7d685a108e0cbce2b45f18c8eadbdfe9..9d3dcc7f976122b2bc84dbb2589119bfb332cdb7 100644 (file)
@@ -79,11 +79,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     end
   end
 
-  def object(conn, _) do
+  def object(%{assigns: assigns} = conn, _) do
     with ap_id <- Endpoint.url() <> conn.request_path,
          %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
-         {_, true} <- {:public?, Visibility.is_public?(object)},
-         {_, false} <- {:local?, Visibility.is_local_public?(object)} do
+         user <- Map.get(assigns, :user, nil),
+         {_, true} <- {:visible?, Visibility.visible_for_user?(object, user)} do
       conn
       |> assign(:tracking_fun_data, object.id)
       |> set_cache_ttl_for(object)
@@ -91,11 +91,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
       |> put_view(ObjectView)
       |> render("object.json", object: object)
     else
-      {:public?, false} ->
-        {:error, :not_found}
-
-      {:local?, true} ->
-        {:error, :not_found}
+      {:visible?, false} -> {:error, :not_found}
+      nil -> {:error, :not_found}
     end
   end
 
@@ -109,11 +106,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     conn
   end
 
-  def activity(conn, _params) do
+  def activity(%{assigns: assigns} = conn, _) do
     with ap_id <- Endpoint.url() <> conn.request_path,
          %Activity{} = activity <- Activity.normalize(ap_id),
-         {_, true} <- {:public?, Visibility.is_public?(activity)},
-         {_, false} <- {:local?, Visibility.is_local_public?(activity)} do
+         {_, true} <- {:local?, activity.local},
+         user <- Map.get(assigns, :user, nil),
+         {_, true} <- {:visible?, Visibility.visible_for_user?(activity, user)} do
       conn
       |> maybe_set_tracking_data(activity)
       |> set_cache_ttl_for(activity)
@@ -121,8 +119,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
       |> put_view(ObjectView)
       |> render("object.json", object: activity)
     else
-      {:public?, false} -> {:error, :not_found}
-      {:local?, true} -> {:error, :not_found}
+      {:visible?, false} -> {:error, :not_found}
+      {:local?, false} -> {:error, :not_found}
       nil -> {:error, :not_found}
     end
   end
index 6ef59e93fc62b29a7262762a3a1d58e089bb2957..00234c0b05c7eddf9d0cac3b86f4f8b4e516d73a 100644 (file)
@@ -56,11 +56,10 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
   def is_list?(%{data: %{"listMessage" => _}}), do: true
   def is_list?(_), do: false
 
-  @spec visible_for_user?(Activity.t() | nil, User.t() | nil) :: boolean()
+  @spec visible_for_user?(Object.t() | Activity.t() | nil, User.t() | nil) :: boolean()
   def visible_for_user?(%Activity{actor: ap_id}, %User{ap_id: ap_id}), do: true
-
+  def visible_for_user?(%Object{data: %{"actor" => ap_id}}, %User{ap_id: ap_id}), do: true
   def visible_for_user?(nil, _), do: false
-
   def visible_for_user?(%Activity{data: %{"listMessage" => _}}, nil), do: false
 
   def visible_for_user?(
@@ -73,16 +72,18 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
       |> Pleroma.List.member?(user)
   end
 
-  def visible_for_user?(%Activity{} = activity, nil) do
-    if restrict_unauthenticated_access?(activity),
+  def visible_for_user?(%{__struct__: module} = message, nil)
+      when module in [Activity, Object] do
+    if restrict_unauthenticated_access?(message),
       do: false,
-      else: is_public?(activity)
+      else: is_public?(message) and not is_local_public?(message)
   end
 
-  def visible_for_user?(%Activity{} = activity, user) do
+  def visible_for_user?(%{__struct__: module} = message, user)
+      when module in [Activity, Object] do
     x = [user.ap_id | User.following(user)]
-    y = [activity.actor] ++ activity.data["to"] ++ (activity.data["cc"] || [])
-    is_public?(activity) || Enum.any?(x, &(&1 in y))
+    y = [message.data["actor"]] ++ message.data["to"] ++ (message.data["cc"] || [])
+    is_public?(message) || Enum.any?(x, &(&1 in y))
   end
 
   def entire_thread_visible_for_user?(%Activity{} = activity, %User{} = user) do
index d581df4a282166ec84f980bc9e7fbf1ac38b5f83..839ac1a8d9185381f56cc84ff14122da63cfb899 100644 (file)
@@ -25,13 +25,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:accounts"], admin: true}
+    %{scopes: ["admin:read:accounts"]}
     when action in [:right_get, :show_user_credentials, :create_backup]
   )
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:accounts"], admin: true}
+    %{scopes: ["admin:write:accounts"]}
     when action in [
            :get_password_reset,
            :force_password_reset,
@@ -48,19 +48,19 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:statuses"], admin: true}
+    %{scopes: ["admin:read:statuses"]}
     when action in [:list_user_statuses, :list_instance_statuses]
   )
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:chats"], admin: true}
+    %{scopes: ["admin:read:chats"]}
     when action in [:list_user_chats]
   )
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read"], admin: true}
+    %{scopes: ["admin:read"]}
     when action in [
            :list_log,
            :stats,
@@ -70,7 +70,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write"], admin: true}
+    %{scopes: ["admin:write"]}
     when action in [
            :restart,
            :resend_confirmation_email,
index 3761a588a98c96024e72570cb59dca8dcd5bcd6f..ff20c8604360d2a33044df8e019da7b73958e6e3 100644 (file)
@@ -21,12 +21,12 @@ defmodule Pleroma.Web.AdminAPI.ChatController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:chats"], admin: true} when action in [:show, :messages]
+    %{scopes: ["admin:read:chats"]} when action in [:show, :messages]
   )
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:chats"], admin: true} when action in [:delete_message]
+    %{scopes: ["admin:write:chats"]} when action in [:delete_message]
   )
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
index 4ebf2a305c58c7ab142cb7133f67b5c213ba43e2..a718d7b8d7a1f32f1d502e3bc0f72c9fcd5d1be0 100644 (file)
@@ -10,11 +10,11 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
   alias Pleroma.Web.Plugs.OAuthScopesPlug
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
-  plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :update)
+  plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update)
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read"], admin: true}
+    %{scopes: ["admin:read"]}
     when action in [:show, :descriptions]
   )
 
index 20472a55ef371755300b92c856df8aec5f5f5505..722f51bd2e119183527ba053775db91ffd13b4fd 100644 (file)
@@ -9,8 +9,8 @@ defmodule Pleroma.Web.AdminAPI.FrontendController do
   alias Pleroma.Web.Plugs.OAuthScopesPlug
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
-  plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :install)
-  plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :index)
+  plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :install)
+  plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :index)
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
 
   defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.FrontendOperation
index ef00d341792b3e82c28aa21f1f9bd637e5bfed2d..a55857a0ed21a1c1d65e3217f6e01b8830ba5c6d 100644 (file)
@@ -15,8 +15,8 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
 
   defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation
 
-  plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :show)
-  plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action in [:update, :delete])
+  plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :show)
+  plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:update, :delete])
 
   def show(conn, %{name: document_name}) do
     with {:ok, url} <- InstanceDocument.get(document_name),
index 3f233a0c48a8e0fd2bb896bc499da070a6709996..727ebd846f52acb2028a75b6828e8c08e1a4cd66 100644 (file)
@@ -14,11 +14,11 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
   require Logger
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
-  plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index)
+  plug(OAuthScopesPlug, %{scopes: ["admin:read:invites"]} when action == :index)
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:invites"], admin: true} when action in [:create, :revoke, :email]
+    %{scopes: ["admin:write:invites"]} when action in [:create, :revoke, :email]
   )
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
index 3564738afdca14fe6cf3b6f3672396975704aad3..a6d7aaf54a49e28568ed9c69e7fbd1bb196dee45 100644 (file)
@@ -15,12 +15,12 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:media_proxy_caches"], admin: true} when action in [:index]
+    %{scopes: ["admin:read:media_proxy_caches"]} when action in [:index]
   )
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:media_proxy_caches"], admin: true} when action in [:purge, :delete]
+    %{scopes: ["admin:write:media_proxy_caches"]} when action in [:purge, :delete]
   )
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
index 2bd2b3644ad78fabf040ec13642802f8067884f4..005fe67e2883a218127f5404a7b77f153c79ae5d 100644 (file)
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.AdminAPI.OAuthAppController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write"], admin: true}
+    %{scopes: ["admin:write"]}
     when action in [:create, :index, :update, :delete]
   )
 
index 18443e74eaca45a66dfaf838ca5abe01a05a8384..c6bd43feafa5e30391fc23c9644b92571b5b7ab7 100644 (file)
@@ -15,11 +15,11 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:follows"], admin: true}
+    %{scopes: ["admin:write:follows"]}
     when action in [:follow, :unfollow]
   )
 
-  plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :index)
+  plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :index)
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
 
index abc068a3fb445b3b5af570a30aca876ce5d6e462..d4a4935eec829bdb57fce6536ee720cef2ad7493 100644 (file)
@@ -19,11 +19,11 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
   require Logger
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
-  plug(OAuthScopesPlug, %{scopes: ["read:reports"], admin: true} when action in [:index, :show])
+  plug(OAuthScopesPlug, %{scopes: ["admin:read:reports"]} when action in [:index, :show])
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:reports"], admin: true}
+    %{scopes: ["admin:write:reports"]}
     when action in [:update, :notes_create, :notes_delete]
   )
 
index 903badec0431aad5f5dc28bc645383a1a2413095..7058def82b8ab1f4397ef242746b1a980946e951 100644 (file)
@@ -15,11 +15,11 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
   require Logger
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
-  plug(OAuthScopesPlug, %{scopes: ["read:statuses"], admin: true} when action in [:index, :show])
+  plug(OAuthScopesPlug, %{scopes: ["admin:read:statuses"]} when action in [:index, :show])
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:statuses"], admin: true} when action in [:update, :delete]
+    %{scopes: ["admin:write:statuses"]} when action in [:update, :delete]
   )
 
   action_fallback(Pleroma.Web.AdminAPI.FallbackController)
index a18b9f8d54c16d178dffacaa73817308408af284..65bc63cb9e66bb224e8390d6908d5f7d570c8592 100644 (file)
@@ -21,13 +21,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:accounts"], admin: true}
+    %{scopes: ["admin:read:accounts"]}
     when action in [:list, :show]
   )
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:accounts"], admin: true}
+    %{scopes: ["admin:write:accounts"]}
     when action in [
            :delete,
            :create,
@@ -40,7 +40,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["write:follows"], admin: true}
+    %{scopes: ["admin:write:follows"]}
     when action in [:follow, :unfollow]
   )
 
index 81b7bc9e843049b66f8979b4f8142cf8089ec8a6..adc8762dc573e25682a6c412046f4112cdbbeddb 100644 (file)
@@ -37,7 +37,8 @@ defmodule Pleroma.Web.ApiSpec do
 
         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(),
+        # Strip environment from the version
+        version: Application.spec(:pleroma, :vsn) |> to_string() |> String.replace(~r/\+.*$/, ""),
         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"}
@@ -84,7 +85,7 @@ defmodule Pleroma.Web.ApiSpec do
             "name" => "Administration",
             "tags" => [
               "Chat administration",
-              "Emoji packs",
+              "Emoji pack administration",
               "Frontend managment",
               "Instance configuration",
               "Instance documents",
@@ -126,7 +127,7 @@ defmodule Pleroma.Web.ApiSpec do
               "Status actions"
             ]
           },
-          %{"name" => "Miscellaneous", "tags" => ["Reports", "Suggestions"]}
+          %{"name" => "Miscellaneous", "tags" => ["Emoji packs", "Reports", "Suggestions"]}
         ]
       }
     }
index cbe4b89720ff664ddb5591bd550426033855dc7d..57906445e7227a952effc46cbbfafffb5cb7ce75 100644 (file)
@@ -33,7 +33,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do
       },
       security: [
         %{
-          "oAuth" => ["write:chats"]
+          "oAuth" => ["admin:write:chats"]
         }
       ]
     }
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do
       },
       security: [
         %{
-          "oAuth" => ["read:chats"]
+          "oAuth" => ["admin:read:chats"]
         }
       ]
     }
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do
       },
       security: [
         %{
-          "oAuth" => ["read"]
+          "oAuth" => ["admin:read"]
         }
       ]
     }
index b8ccc1d00fe425cdf72c70d613204315830c5db7..30c3433b7999aed78af0f0d2909f1a3a4b7c0ece 100644 (file)
@@ -28,7 +28,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ConfigOperation do
         )
         | admin_api_params()
       ],
-      security: [%{"oAuth" => ["read"]}],
+      security: [%{"oAuth" => ["admin:read"]}],
       responses: %{
         200 => Operation.response("Config", "application/json", config_response()),
         400 => Operation.response("Bad Request", "application/json", ApiError)
@@ -41,7 +41,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ConfigOperation do
       tags: ["Instance configuration"],
       summary: "Update instance configuration",
       operationId: "AdminAPI.ConfigController.update",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: admin_api_params(),
       requestBody:
         request_body("Parameters", %Schema{
@@ -74,7 +74,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ConfigOperation do
       tags: ["Instance configuration"],
       summary: "Retrieve config description",
       operationId: "AdminAPI.ConfigController.descriptions",
-      security: [%{"oAuth" => ["read"]}],
+      security: [%{"oAuth" => ["admin:read"]}],
       parameters: admin_api_params(),
       responses: %{
         200 =>
index b149becf9bcee480c2e5e2f13a9a03e29c14daae..566f1eeb1b0927670add4b80089fe1e4b20264ef 100644 (file)
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
       tags: ["Frontend managment"],
       summary: "Retrieve a list of available frontends",
       operationId: "AdminAPI.FrontendController.index",
-      security: [%{"oAuth" => ["read"]}],
+      security: [%{"oAuth" => ["admin:read"]}],
       responses: %{
         200 => Operation.response("Response", "application/json", list_of_frontends()),
         403 => Operation.response("Forbidden", "application/json", ApiError)
@@ -32,7 +32,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
       tags: ["Frontend managment"],
       summary: "Install a frontend",
       operationId: "AdminAPI.FrontendController.install",
-      security: [%{"oAuth" => ["read"]}],
+      security: [%{"oAuth" => ["admin:read"]}],
       requestBody: request_body("Parameters", install_request(), required: true),
       responses: %{
         200 => Operation.response("Response", "application/json", list_of_frontends()),
index 3e89abfb587ee136a4fae9abeaaaa1a2a51520bd..79ceae9703f9f1609b2a4594aa27a67c43039781 100644 (file)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do
       tags: ["Instance documents"],
       summary: "Retrieve an instance document",
       operationId: "AdminAPI.InstanceDocumentController.show",
-      security: [%{"oAuth" => ["read"]}],
+      security: [%{"oAuth" => ["admin:read"]}],
       parameters: [
         Operation.parameter(:name, :path, %Schema{type: :string}, "The document name",
           required: true
@@ -39,7 +39,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do
       tags: ["Instance documents"],
       summary: "Update an instance document",
       operationId: "AdminAPI.InstanceDocumentController.update",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       requestBody: Helpers.request_body("Parameters", update_request()),
       parameters: [
         Operation.parameter(:name, :path, %Schema{type: :string}, "The document name",
@@ -77,7 +77,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do
       tags: ["Instance documents"],
       summary: "Delete an instance document",
       operationId: "AdminAPI.InstanceDocumentController.delete",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: [
         Operation.parameter(:name, :path, %Schema{type: :string}, "The document name",
           required: true
index 60d69c7673e16dc889ac50cb7d27715c7c949740..704f082bafa0dba71f5c37028d8058e77593abb8 100644 (file)
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
       tags: ["Invites"],
       summary: "Get a list of generated invites",
       operationId: "AdminAPI.InviteController.index",
-      security: [%{"oAuth" => ["read:invites"]}],
+      security: [%{"oAuth" => ["admin:read:invites"]}],
       parameters: admin_api_params(),
       responses: %{
         200 =>
@@ -51,7 +51,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
       tags: ["Invites"],
       summary: "Create an account registration invite token",
       operationId: "AdminAPI.InviteController.create",
-      security: [%{"oAuth" => ["write:invites"]}],
+      security: [%{"oAuth" => ["admin:write:invites"]}],
       parameters: admin_api_params(),
       requestBody:
         request_body("Parameters", %Schema{
@@ -72,7 +72,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
       tags: ["Invites"],
       summary: "Revoke invite by token",
       operationId: "AdminAPI.InviteController.revoke",
-      security: [%{"oAuth" => ["write:invites"]}],
+      security: [%{"oAuth" => ["admin:write:invites"]}],
       parameters: admin_api_params(),
       requestBody:
         request_body(
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.InviteOperation do
       tags: ["Invites"],
       summary: "Sends registration invite via email",
       operationId: "AdminAPI.InviteController.email",
-      security: [%{"oAuth" => ["write:invites"]}],
+      security: [%{"oAuth" => ["admin:write:invites"]}],
       parameters: admin_api_params(),
       requestBody:
         request_body(
index 675504ee08f3293d8756a16af52745fda1efaa74..8f85ebf2debd5fc3cbc5f3e2e5774191b301f9f2 100644 (file)
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
       tags: ["MediaProxy cache"],
       summary: "Retrieve a list of banned MediaProxy URLs",
       operationId: "AdminAPI.MediaProxyCacheController.index",
-      security: [%{"oAuth" => ["read:media_proxy_caches"]}],
+      security: [%{"oAuth" => ["admin:read:media_proxy_caches"]}],
       parameters: [
         Operation.parameter(
           :query,
@@ -71,7 +71,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
       tags: ["MediaProxy cache"],
       summary: "Remove a banned MediaProxy URL",
       operationId: "AdminAPI.MediaProxyCacheController.delete",
-      security: [%{"oAuth" => ["write:media_proxy_caches"]}],
+      security: [%{"oAuth" => ["admin:write:media_proxy_caches"]}],
       parameters: admin_api_params(),
       requestBody:
         request_body(
@@ -97,7 +97,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.MediaProxyCacheOperation do
       tags: ["MediaProxy cache"],
       summary: "Purge a URL from MediaProxy cache and optionally ban it",
       operationId: "AdminAPI.MediaProxyCacheController.purge",
-      security: [%{"oAuth" => ["write:media_proxy_caches"]}],
+      security: [%{"oAuth" => ["admin:write:media_proxy_caches"]}],
       parameters: admin_api_params(),
       requestBody:
         request_body(
index 2f3bee4f0b6b9a3374b47443e7f7418e5c8404b5..35b029b19d6e4d7ca62f61ffa257cb0e49aea002 100644 (file)
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
       summary: "Retrieve a list of OAuth applications",
       tags: ["OAuth application managment"],
       operationId: "AdminAPI.OAuthAppController.index",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: [
         Operation.parameter(:name, :query, %Schema{type: :string}, "App name"),
         Operation.parameter(:client_id, :query, %Schema{type: :string}, "Client ID"),
@@ -74,7 +74,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
       operationId: "AdminAPI.OAuthAppController.create",
       requestBody: request_body("Parameters", create_request()),
       parameters: admin_api_params(),
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       responses: %{
         200 => Operation.response("App", "application/json", oauth_app()),
         400 => Operation.response("Bad Request", "application/json", ApiError)
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
       summary: "Update OAuth application",
       operationId: "AdminAPI.OAuthAppController.update",
       parameters: [id_param() | admin_api_params()],
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       requestBody: request_body("Parameters", update_request()),
       responses: %{
         200 => Operation.response("App", "application/json", oauth_app()),
@@ -106,7 +106,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
       summary: "Delete OAuth application",
       operationId: "AdminAPI.OAuthAppController.delete",
       parameters: [id_param() | admin_api_params()],
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       responses: %{
         204 => no_content_response(),
         400 => no_content_response()
index c47f18f0cee6caa4b439135ef974db5516686fec..c55c84fee8c9509b0a557869d32cb910e2523fc2 100644 (file)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
       tags: ["Relays"],
       summary: "Retrieve a list of relays",
       operationId: "AdminAPI.RelayController.index",
-      security: [%{"oAuth" => ["read"]}],
+      security: [%{"oAuth" => ["admin:read"]}],
       parameters: admin_api_params(),
       responses: %{
         200 =>
@@ -40,7 +40,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
       tags: ["Relays"],
       summary: "Follow a relay",
       operationId: "AdminAPI.RelayController.follow",
-      security: [%{"oAuth" => ["write:follows"]}],
+      security: [%{"oAuth" => ["admin:write:follows"]}],
       parameters: admin_api_params(),
       requestBody: request_body("Parameters", relay_url()),
       responses: %{
@@ -54,7 +54,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
       tags: ["Relays"],
       summary: "Unfollow a relay",
       operationId: "AdminAPI.RelayController.unfollow",
-      security: [%{"oAuth" => ["write:follows"]}],
+      security: [%{"oAuth" => ["admin:write:follows"]}],
       parameters: admin_api_params(),
       requestBody: request_body("Parameters", relay_unfollow()),
       responses: %{
index cfa892d296abba21076839d4b95630e6835d1811..3ea4af1e4a6d4ea302fd7227585a9ccb276c13c4 100644 (file)
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
       tags: ["Report managment"],
       summary: "Retrieve a list of reports",
       operationId: "AdminAPI.ReportController.index",
-      security: [%{"oAuth" => ["read:reports"]}],
+      security: [%{"oAuth" => ["admin:read:reports"]}],
       parameters: [
         Operation.parameter(
           :state,
@@ -73,7 +73,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
       summary: "Retrieve a report",
       operationId: "AdminAPI.ReportController.show",
       parameters: [id_param() | admin_api_params()],
-      security: [%{"oAuth" => ["read:reports"]}],
+      security: [%{"oAuth" => ["admin:read:reports"]}],
       responses: %{
         200 => Operation.response("Report", "application/json", report()),
         404 => Operation.response("Not Found", "application/json", ApiError)
@@ -86,7 +86,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
       tags: ["Report managment"],
       summary: "Change state of specified reports",
       operationId: "AdminAPI.ReportController.update",
-      security: [%{"oAuth" => ["write:reports"]}],
+      security: [%{"oAuth" => ["admin:write:reports"]}],
       parameters: admin_api_params(),
       requestBody: request_body("Parameters", update_request(), required: true),
       responses: %{
@@ -110,7 +110,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
             content: %Schema{type: :string, description: "The message"}
           }
         }),
-      security: [%{"oAuth" => ["write:reports"]}],
+      security: [%{"oAuth" => ["admin:write:reports"]}],
       responses: %{
         204 => no_content_response(),
         404 => Operation.response("Not Found", "application/json", ApiError)
@@ -128,7 +128,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
         Operation.parameter(:id, :path, :string, "Note ID")
         | admin_api_params()
       ],
-      security: [%{"oAuth" => ["write:reports"]}],
+      security: [%{"oAuth" => ["admin:write:reports"]}],
       responses: %{
         204 => no_content_response(),
         404 => Operation.response("Not Found", "application/json", ApiError)
index bbfbd8f930bcb69a6f9efb4bd0742d49c7230bc4..d25ab52471fbbdd797f2cad5edb5fbcd2a83fce3 100644 (file)
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
       tags: ["Status administration"],
       operationId: "AdminAPI.StatusController.index",
       summary: "Get all statuses",
-      security: [%{"oAuth" => ["read:statuses"]}],
+      security: [%{"oAuth" => ["admin:read:statuses"]}],
       parameters: [
         Operation.parameter(
           :godmode,
@@ -74,7 +74,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
       summary: "Get status",
       operationId: "AdminAPI.StatusController.show",
       parameters: [id_param() | admin_api_params()],
-      security: [%{"oAuth" => ["read:statuses"]}],
+      security: [%{"oAuth" => ["admin:read:statuses"]}],
       responses: %{
         200 => Operation.response("Status", "application/json", status()),
         404 => Operation.response("Not Found", "application/json", ApiError)
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
       summary: "Change the scope of a status",
       operationId: "AdminAPI.StatusController.update",
       parameters: [id_param() | admin_api_params()],
-      security: [%{"oAuth" => ["write:statuses"]}],
+      security: [%{"oAuth" => ["admin:write:statuses"]}],
       requestBody: request_body("Parameters", update_request(), required: true),
       responses: %{
         200 => Operation.response("Status", "application/json", Status),
@@ -103,7 +103,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
       summary: "Delete status",
       operationId: "AdminAPI.StatusController.delete",
       parameters: [id_param() | admin_api_params()],
-      security: [%{"oAuth" => ["write:statuses"]}],
+      security: [%{"oAuth" => ["admin:write:statuses"]}],
       responses: %{
         200 => empty_object_response(),
         404 => Operation.response("Not Found", "application/json", ApiError)
index b4970017256ea9e5211655a6b5c75add5c77a216..23cb66392b0cb32fc9981a1641ac78c7ea2fdd20 100644 (file)
@@ -131,8 +131,30 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
   def index_operation do
     %Operation{
       tags: ["Chats"],
-      summary: "Retrieve list of chats",
+      summary: "Retrieve list of chats (unpaginated)",
+      deprecated: true,
+      description:
+        "Deprecated due to no support for pagination. Using [/api/v2/pleroma/chats](#operation/ChatController.index2) instead is recommended.",
       operationId: "ChatController.index",
+      parameters: [
+        Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
+      ],
+      responses: %{
+        200 => Operation.response("The chats of the user", "application/json", chats_response())
+      },
+      security: [
+        %{
+          "oAuth" => ["read:chats"]
+        }
+      ]
+    }
+  end
+
+  def index2_operation do
+    %Operation{
+      tags: ["Chats"],
+      summary: "Retrieve list of chats",
+      operationId: "ChatController.index2",
       parameters: [
         Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
         | pagination_params()
index 367f4125a4a3f72c3f76becdcc726bbe72d6f352..17ed1af5e5ca861329e74d1624b4297a9b3e519a 100644 (file)
@@ -46,16 +46,31 @@ defmodule Pleroma.Web.ApiSpec.ConversationOperation do
       tags: ["Conversations"],
       summary: "Mark conversation as read",
       operationId: "ConversationController.mark_as_read",
-      parameters: [
-        Operation.parameter(:id, :path, :string, "Conversation ID",
-          example: "123",
-          required: true
-        )
-      ],
+      parameters: [id_param()],
       security: [%{"oAuth" => ["write:conversations"]}],
       responses: %{
         200 => Operation.response("Conversation", "application/json", Conversation)
       }
     }
   end
+
+  def delete_operation do
+    %Operation{
+      tags: ["Conversations"],
+      summary: "Remove conversation",
+      operationId: "ConversationController.delete",
+      parameters: [id_param()],
+      security: [%{"oAuth" => ["write:conversations"]}],
+      responses: %{
+        200 => empty_object_response()
+      }
+    }
+  end
+
+  def id_param do
+    Operation.parameter(:id, :path, :string, "Conversation ID",
+      example: "123",
+      required: true
+    )
+  end
 end
index bed9511ef578f259bbf1e48ffda0add0cbb428dd..8c76096b5cbc37121d04038a1822c9c08ab9ab4d 100644 (file)
@@ -16,10 +16,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Add new file to the pack",
       operationId: "PleromaAPI.EmojiPackController.add_file",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       requestBody: request_body("Parameters", create_request(), required: true),
       parameters: [name_param()],
       responses: %{
@@ -62,10 +62,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Add new file to the pack",
       operationId: "PleromaAPI.EmojiPackController.update_file",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       requestBody: request_body("Parameters", update_request(), required: true),
       parameters: [name_param()],
       responses: %{
@@ -106,10 +106,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Delete emoji file from pack",
       operationId: "PleromaAPI.EmojiPackController.delete_file",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: [
         name_param(),
         Operation.parameter(:shortcode, :query, :string, "File shortcode",
index 48dafa5f2c33de03f1ce8d28dddbad58613eacfc..49247d9b66f97c35497299fe9c5cb7fe227e08ef 100644 (file)
@@ -16,9 +16,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def remote_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Make request to another instance for emoji packs list",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: [
         url_param(),
         Operation.parameter(
@@ -115,10 +115,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def download_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Download pack from another instance",
       operationId: "PleromaAPI.EmojiPackController.download",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       requestBody: request_body("Parameters", download_request(), required: true),
       responses: %{
         200 => ok_response(),
@@ -145,10 +145,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def create_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Create an empty pack",
       operationId: "PleromaAPI.EmojiPackController.create",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: [name_param()],
       responses: %{
         200 => ok_response(),
@@ -161,10 +161,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def delete_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Delete a custom emoji pack",
       operationId: "PleromaAPI.EmojiPackController.delete",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       parameters: [name_param()],
       responses: %{
         200 => ok_response(),
@@ -177,10 +177,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def update_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Updates (replaces) pack metadata",
       operationId: "PleromaAPI.EmojiPackController.update",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       requestBody: request_body("Parameters", update_request(), required: true),
       parameters: [name_param()],
       responses: %{
@@ -193,10 +193,10 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
 
   def import_from_filesystem_operation do
     %Operation{
-      tags: ["Emoji packs"],
+      tags: ["Emoji pack administration"],
       summary: "Imports packs from filesystem",
       operationId: "PleromaAPI.EmojiPackController.import",
-      security: [%{"oAuth" => ["write"]}],
+      security: [%{"oAuth" => ["admin:write"]}],
       responses: %{
         200 =>
           Operation.response("Array of imported pack names", "application/json", %Schema{
index 6986b9c17b722a7cd7b7cab327dd1a0887ca1042..348fe95f88101ba855061dda4e4d2a6203cdefe7 100644 (file)
@@ -52,7 +52,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
           title: %Schema{type: :string, description: "Title of linked resource"},
           description: %Schema{type: :string, description: "Description of preview"}
         }
-      }
+      },
+      unread: %Schema{type: :boolean, description: "Whether a message has been marked as read."}
     },
     example: %{
       "account_id" => "someflakeid",
@@ -69,7 +70,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
         }
       ],
       "id" => "14",
-      "attachment" => nil
+      "attachment" => nil,
+      "unread" => false
     }
   })
 end
index cc051046a9906e52a79b6237c072e32c5d9135fb..607586e32600ac88fc2d751bf9da4de118145013 100644 (file)
@@ -30,7 +30,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do
           visibility: %Schema{allOf: [VisibilityScope], nullable: true},
           scheduled_at: %Schema{type: :string, format: :"date-time", nullable: true},
           poll: StatusOperation.poll_params(),
-          in_reply_to_id: %Schema{type: :string, nullable: true}
+          in_reply_to_id: %Schema{type: :string, nullable: true},
+          expires_in: %Schema{type: :integer, nullable: true}
         }
       }
     },
@@ -46,7 +47,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do
         scheduled_at: nil,
         poll: nil,
         idempotency: nil,
-        in_reply_to_id: nil
+        in_reply_to_id: nil,
+        expires_in: nil
       },
       media_attachments: [Attachment.schema().example]
     }
index a7e4d93f5a3127e974278fafda64172e49e23387..dd3b39c7789db7bc8fb3be29f046568edb4ad7a9 100644 (file)
@@ -3,6 +3,11 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.MastodonAPI.AppController do
+  @moduledoc """
+  Controller for supporting app-related actions.
+  If authentication is an option, app tokens (user-unbound) must be supported.
+  """
+
   use Pleroma.Web, :controller
 
   alias Pleroma.Repo
@@ -17,11 +22,9 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
   plug(
     :skip_plug,
     [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug]
-    when action == :create
+    when action in [:create, :verify_credentials]
   )
 
-  plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
-
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
 
   @local_mastodon_name "Mastodon-Local"
@@ -44,10 +47,13 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
     end
   end
 
-  @doc "GET /api/v1/apps/verify_credentials"
-  def verify_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do
-    with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
-      render(conn, "short.json", app: app)
+  @doc """
+  GET /api/v1/apps/verify_credentials
+  Gets compact non-secret representation of the app. Supports app tokens and user tokens.
+  """
+  def verify_credentials(%{assigns: %{token: %Token{} = token}} = conn, _) do
+    with %{app: %App{} = app} <- Repo.preload(token, :app) do
+      render(conn, "compact_non_secret.json", app: app)
     end
   end
 end
index 4526d3c7acbaa10dd32e3927f372acbed3ef10aa..f2a0949e853c62475af264f8300a1702a2d5ab20 100644 (file)
@@ -36,4 +36,13 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do
       render(conn, "participation.json", participation: participation, for: user)
     end
   end
+
+  @doc "DELETE /api/v1/conversations/:id"
+  def delete(%{assigns: %{user: user}} = conn, %{id: participation_id}) do
+    with %Participation{} = participation <-
+           Repo.get_by(Participation, id: participation_id, user_id: user.id),
+         {:ok, _} <- Participation.delete(participation) do
+      json(conn, %{})
+    end
+  end
 end
index 3d7131e09ac3f055f38e4278d3de81824bba5f8b..c406b5a27f939a32d1a877182ed38f86a6d2d66e 100644 (file)
@@ -34,10 +34,10 @@ defmodule Pleroma.Web.MastodonAPI.AppView do
     |> with_vapid_key()
   end
 
-  def render("short.json", %{app: %App{website: webiste, client_name: name}}) do
+  def render("compact_non_secret.json", %{app: %App{website: website, client_name: name}}) do
     %{
       name: name,
-      website: webiste
+      website: website
     }
     |> with_vapid_key()
   end
index 13774d23709705b19bba1f93d5b13ba9f54a6670..453221f4123b5ae83c08221f6a74160cd7c1655b 100644 (file)
@@ -37,7 +37,8 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityView do
       visibility: params["visibility"],
       scheduled_at: params["scheduled_at"],
       poll: params["poll"],
-      in_reply_to_id: params["in_reply_to_id"]
+      in_reply_to_id: params["in_reply_to_id"],
+      expires_in: params["expires_in"]
     }
     |> Pleroma.Maps.put_if_present(:media_ids, params["media_ids"])
   end
index f3cd1fbf6f590792e0bb936028b9c9df0c9d65bb..4adc685fe9eb60591e6d6538848c9f867ca495df 100644 (file)
@@ -35,7 +35,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:chats"]} when action in [:messages, :index, :show]
+    %{scopes: ["read:chats"]} when action in [:messages, :index, :index2, :show]
   )
 
   plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
@@ -138,20 +138,32 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
     end
   end
 
-  def index(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do
-    exclude_users =
-      User.cached_blocked_users_ap_ids(user) ++
-        if params[:with_muted], do: [], else: User.cached_muted_users_ap_ids(user)
-
+  def index(%{assigns: %{user: user}} = conn, params) do
     chats =
-      user_id
-      |> Chat.for_user_query()
-      |> where([c], c.recipient not in ^exclude_users)
+      index_query(user, params)
       |> Repo.all()
 
     render(conn, "index.json", chats: chats)
   end
 
+  def index2(%{assigns: %{user: user}} = conn, params) do
+    chats =
+      index_query(user, params)
+      |> Pagination.fetch_paginated(params)
+
+    render(conn, "index.json", chats: chats)
+  end
+
+  defp index_query(%{id: user_id} = user, params) do
+    exclude_users =
+      User.cached_blocked_users_ap_ids(user) ++
+        if params[:with_muted], do: [], else: User.cached_muted_users_ap_ids(user)
+
+    user_id
+    |> Chat.for_user_query()
+    |> where([c], c.recipient not in ^exclude_users)
+  end
+
   def create(%{assigns: %{user: user}} = conn, %{id: id}) do
     with %User{ap_id: recipient} <- User.get_cached_by_id(id),
          {:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
index 6a41bbab4bfe563b6f77402e9b63174b799c1b4b..204e81311f7adfc88f2edf2e9611780b85fdf85d 100644 (file)
@@ -12,7 +12,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
 
   plug(
     Pleroma.Web.Plugs.OAuthScopesPlug,
-    %{scopes: ["write"], admin: true}
+    %{scopes: ["admin:write"]}
     when action in [
            :create,
            :update,
index c696241f0343529d4f73002d39afeb377f2717f4..d0f677d3c5cfc1dfba99e3ffc719456639ce9ae4 100644 (file)
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
 
   plug(
     Pleroma.Web.Plugs.OAuthScopesPlug,
-    %{scopes: ["write"], admin: true}
+    %{scopes: ["admin:write"]}
     when action in [
            :import_from_filesystem,
            :remote,
index a4b5dc257039193d9e9dfb4a42d9b9eccd896ea4..31e7410d627b9fe5b0b2231ab85be2ba81a881e6 100644 (file)
@@ -3,6 +3,10 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.Plugs.EnsureAuthenticatedPlug do
+  @moduledoc """
+  Ensures _user_ authentication (app-bound user-unbound tokens are not accepted).
+  """
+
   import Plug.Conn
   import Pleroma.Web.TranslationHelpers
 
index b6dfc4f3ca8cb7a0e1a597743aeb91f14f8a2ad2..8a8532f4156f31d33f8e72a282c7ea4bb8305315 100644 (file)
@@ -3,6 +3,11 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.Plugs.EnsurePublicOrAuthenticatedPlug do
+  @moduledoc """
+  Ensures instance publicity or _user_ authentication
+  (app-bound user-unbound tokens are accepted only if the instance is public).
+  """
+
   import Pleroma.Web.TranslationHelpers
   import Plug.Conn
 
index 3a2b5dda866708a39a179e9182e49e30cb0b5105..534b0cff188b4bd620bbbafdc57014db235f16ac 100644 (file)
@@ -28,6 +28,11 @@ defmodule Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug do
     end
   end
 
+  # App-bound token case (obtained with client_id and client_secret)
+  def call(%{assigns: %{token: %Token{user_id: nil}}} = conn, _) do
+    assign(conn, :user, nil)
+  end
+
   def call(conn, _) do
     conn
     |> assign(:user, nil)
index eecf1626493243e873de35a672115e8b45abe9e8..eb385e94dfc97020acd05ba0b3d988fa9e1007a9 100644 (file)
@@ -10,6 +10,8 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do
   """
   @behaviour Plug
 
+  @api_routes Pleroma.Web.get_api_routes()
+
   def file_path(path, frontend_type \\ :primary) do
     if configuration = Pleroma.Config.get([:frontends, frontend_type]) do
       instance_static_path = Pleroma.Config.get([:instance, :static_dir], "instance/static")
@@ -34,7 +36,8 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do
   end
 
   def call(conn, opts) do
-    with false <- invalid_path?(conn.path_info),
+    with false <- api_route?(conn.path_info),
+         false <- invalid_path?(conn.path_info),
          frontend_type <- Map.get(opts, :frontend_type, :primary),
          path when not is_nil(path) <- file_path("", frontend_type) do
       call_static(conn, opts, path)
@@ -52,6 +55,10 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do
   defp invalid_path?([h | t], match), do: String.contains?(h, match) or invalid_path?(t)
   defp invalid_path?([], _match), do: false
 
+  defp api_route?([h | _]) when h in @api_routes, do: true
+  defp api_route?([_ | t]), do: api_route?(t)
+  defp api_route?([]), do: false
+
   defp call_static(conn, opts, from) do
     opts = Map.put(opts, :from, from)
     Plug.Static.call(conn, opts)
index 0f32f70a6e7a52d799e3eceeecf9e0d3c80fea7a..f017c8bc7abd627bcb61a2042eedd1b13dc8b551 100644 (file)
@@ -6,7 +6,6 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
   import Plug.Conn
   import Pleroma.Web.Gettext
 
-  alias Pleroma.Config
   alias Pleroma.Helpers.AuthHelper
 
   use Pleroma.Web, :plug
@@ -18,7 +17,6 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
     op = options[:op] || :|
     token = assigns[:token]
 
-    scopes = transform_scopes(scopes, options)
     matched_scopes = (token && filter_descendants(scopes, token.scopes)) || []
 
     cond do
@@ -57,13 +55,4 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
       end
     )
   end
-
-  @doc "Transforms scopes by applying supported options (e.g. :admin)"
-  def transform_scopes(scopes, options) do
-    if options[:admin] do
-      Config.oauth_admin_scopes(scopes)
-    else
-      scopes
-    end
-  end
 end
index 2105d7e9ed2bbf842a97032d4a81e693c0ae2921..d71011033cbf8b6e0f6616fc12d4d2c571f1cc47 100644 (file)
@@ -37,11 +37,13 @@ defmodule Pleroma.Web.Router do
     plug(Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug)
   end
 
-  pipeline :expect_authentication do
+  # Note: expects _user_ authentication (user-unbound app-bound tokens don't qualify)
+  pipeline :expect_user_authentication do
     plug(Pleroma.Web.Plugs.ExpectAuthenticatedCheckPlug)
   end
 
-  pipeline :expect_public_instance_or_authentication do
+  # Note: expects public instance or _user_ authentication (user-unbound tokens don't qualify)
+  pipeline :expect_public_instance_or_user_authentication do
     plug(Pleroma.Web.Plugs.ExpectPublicOrAuthenticatedCheckPlug)
   end
 
@@ -66,23 +68,30 @@ defmodule Pleroma.Web.Router do
     plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
   end
 
-  pipeline :api do
-    plug(:expect_public_instance_or_authentication)
+  pipeline :no_auth_or_privacy_expectations_api do
     plug(:base_api)
     plug(:after_auth)
     plug(Pleroma.Web.Plugs.IdempotencyPlug)
   end
 
+  # Pipeline for app-related endpoints (no user auth checks â€” app-bound tokens must be supported)
+  pipeline :app_api do
+    plug(:no_auth_or_privacy_expectations_api)
+  end
+
+  pipeline :api do
+    plug(:expect_public_instance_or_user_authentication)
+    plug(:no_auth_or_privacy_expectations_api)
+  end
+
   pipeline :authenticated_api do
-    plug(:expect_authentication)
-    plug(:base_api)
-    plug(:after_auth)
+    plug(:expect_user_authentication)
+    plug(:no_auth_or_privacy_expectations_api)
     plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug)
-    plug(Pleroma.Web.Plugs.IdempotencyPlug)
   end
 
   pipeline :admin_api do
-    plug(:expect_authentication)
+    plug(:expect_user_authentication)
     plug(:base_api)
     plug(Pleroma.Web.Plugs.AdminSecretAuthenticationPlug)
     plug(:after_auth)
@@ -411,6 +420,13 @@ defmodule Pleroma.Web.Router do
     get("/federation_status", InstancesController, :show)
   end
 
+  scope "/api/v2/pleroma", Pleroma.Web.PleromaAPI do
+    scope [] do
+      pipe_through(:authenticated_api)
+      get("/chats", ChatController, :index2)
+    end
+  end
+
   scope "/api/v1", Pleroma.Web.MastodonAPI do
     pipe_through(:authenticated_api)
 
@@ -432,10 +448,9 @@ defmodule Pleroma.Web.Router do
     post("/accounts/:id/mute", AccountController, :mute)
     post("/accounts/:id/unmute", AccountController, :unmute)
 
-    get("/apps/verify_credentials", AppController, :verify_credentials)
-
     get("/conversations", ConversationController, :index)
     post("/conversations/:id/read", ConversationController, :mark_as_read)
+    delete("/conversations/:id", ConversationController, :delete)
 
     get("/domain_blocks", DomainBlockController, :index)
     post("/domain_blocks", DomainBlockController, :create)
@@ -524,6 +539,13 @@ defmodule Pleroma.Web.Router do
     put("/settings", MastoFEController, :put_settings)
   end
 
+  scope "/api/v1", Pleroma.Web.MastodonAPI do
+    pipe_through(:app_api)
+
+    post("/apps", AppController, :create)
+    get("/apps/verify_credentials", AppController, :verify_credentials)
+  end
+
   scope "/api/v1", Pleroma.Web.MastodonAPI do
     pipe_through(:api)
 
@@ -540,8 +562,6 @@ defmodule Pleroma.Web.Router do
     get("/instance", InstanceController, :show)
     get("/instance/peers", InstanceController, :peers)
 
-    post("/apps", AppController, :create)
-
     get("/statuses", StatusController, :index)
     get("/statuses/:id", StatusController, :show)
     get("/statuses/:id/context", StatusController, :context)
index c6595adadd982f9a2c003a085a5de794c1074dba..df4e2d23364c8923ffb5ac1f17d108cc36a54c45 100644 (file)
Binary files a/priv/static/images/avi.png and b/priv/static/images/avi.png differ
diff --git a/test/fixtures/users_mock/localhost.json b/test/fixtures/users_mock/localhost.json
deleted file mode 100644 (file)
index a49935d..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "@context": [
-    "https://www.w3.org/ns/activitystreams",
-    "http://localhost:4001/schemas/litepub-0.1.jsonld",
-    {
-      "@language": "und"
-    }
-  ],
-  "attachment": [],
-  "endpoints": {
-    "oauthAuthorizationEndpoint": "http://localhost:4001/oauth/authorize",
-    "oauthRegistrationEndpoint": "http://localhost:4001/api/v1/apps",
-    "oauthTokenEndpoint": "http://localhost:4001/oauth/token",
-    "sharedInbox": "http://localhost:4001/inbox"
-  },
-  "followers": "http://localhost:4001/users/{{nickname}}/followers",
-  "following": "http://localhost:4001/users/{{nickname}}/following",
-  "icon": {
-    "type": "Image",
-    "url": "http://localhost:4001/media/4e914f5b84e4a259a3f6c2d2edc9ab642f2ab05f3e3d9c52c81fc2d984b3d51e.jpg"
-  },
-  "id": "http://localhost:4001/users/{{nickname}}",
-  "image": {
-    "type": "Image",
-    "url": "http://localhost:4001/media/f739efddefeee49c6e67e947c4811fdc911785c16ae43da4c3684051fbf8da6a.jpg?name=f739efddefeee49c6e67e947c4811fdc911785c16ae43da4c3684051fbf8da6a.jpg"
-  },
-  "inbox": "http://localhost:4001/users/{{nickname}}/inbox",
-  "manuallyApprovesFollowers": false,
-  "name": "{{nickname}}",
-  "outbox": "http://localhost:4001/users/{{nickname}}/outbox",
-  "preferredUsername": "{{nickname}}",
-  "publicKey": {
-    "id": "http://localhost:4001/users/{{nickname}}#main-key",
-    "owner": "http://localhost:4001/users/{{nickname}}",
-    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5DLtwGXNZElJyxFGfcVc\nXANhaMadj/iYYQwZjOJTV9QsbtiNBeIK54PJrYuU0/0YIdrvS1iqheX5IwXRhcwa\nhm3ZyLz7XeN9st7FBni4BmZMBtMpxAuYuu5p/jbWy13qAiYOhPreCx0wrWgm/lBD\n9mkgaxIxPooBE0S4ZWEJIDIV1Vft3AWcRUyWW1vIBK0uZzs6GYshbQZB952S0yo4\nFzI1hABGHncH8UvuFauh4EZ8tY7/X5I0pGRnDOcRN1dAht5w5yTA+6r5kebiFQjP\nIzN/eCO/a9Flrj9YGW7HDNtjSOH0A31PLRGlJtJO3yK57dnf5ppyCZGfL4emShQo\ncQIDAQAB\n-----END PUBLIC KEY-----\n\n"
-  },
-  "summary": "your friendly neighborhood pleroma developer<br>I like cute things and distributed systems, and really hate delete and redrafts",
-  "tag": [],
-  "type": "Person",
-  "url": "http://localhost:4001/users/{{nickname}}"
-}
\ No newline at end of file
index a0751acb12d715011a99cb2dd954afd8a88f34f3..f8a37bd49ccc9fe8aa023717b860261fefd78184 100644 (file)
@@ -12,7 +12,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.RollbackTest do
     Logger.configure(level: :warn)
 
     assert capture_log(fn ->
-             Mix.Tasks.Pleroma.Ecto.Rollback.run()
+             Mix.Tasks.Pleroma.Ecto.Rollback.run(["--env", "test"])
            end) =~ "[info] Rollback succesfully"
 
     Logger.configure(level: level)
index 8b039cd78de8cb7d30376491e6711006c8bf93a7..a25e17c957f1206b8b510cc75e67184d0b14535d 100644 (file)
@@ -359,4 +359,16 @@ defmodule Pleroma.Conversation.ParticipationTest do
       assert Participation.unread_count(blocked) == 1
     end
   end
+
+  test "deletes a conversation" do
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, _activity} =
+      CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
+
+    assert [participation] = Participation.for_user(other_user)
+    assert {:ok, _} = Participation.delete(participation)
+    assert [] == Participation.for_user(other_user)
+  end
 end
index 948587292af35746b5978bf4b30b30224e481607..abf1b04109255ba42a70031cdb6a9167e93f61c8 100644 (file)
@@ -990,7 +990,6 @@ defmodule Pleroma.NotificationTest do
       assert Enum.empty?(Notification.for_user(local_user))
     end
 
-    @tag capture_log: true
     test "move activity generates a notification" do
       %{ap_id: old_ap_id} = old_user = insert(:user)
       %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
@@ -1000,18 +999,6 @@ defmodule Pleroma.NotificationTest do
       User.follow(follower, old_user)
       User.follow(other_follower, old_user)
 
-      old_user_url = old_user.ap_id
-
-      body =
-        File.read!("test/fixtures/users_mock/localhost.json")
-        |> String.replace("{{nickname}}", old_user.nickname)
-        |> Jason.encode!()
-
-      Tesla.Mock.mock(fn
-        %{method: :get, url: ^old_user_url} ->
-          %Tesla.Env{status: 200, body: body}
-      end)
-
       Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
       ObanHelpers.perform_all()
 
index 91a3109bbb948f3514ed629d6ad5c48047348b9a..19e04d4726d5574edce20b226884912f66fab5b1 100644 (file)
@@ -229,6 +229,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       assert json_response(conn, 404)
     end
 
+    test "returns local-only objects when authenticated", %{conn: conn} do
+      user = insert(:user)
+      {:ok, post} = CommonAPI.post(user, %{status: "test", visibility: "local"})
+
+      assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post)
+
+      object = Object.normalize(post, fetch: false)
+      uuid = String.split(object.data["id"], "/") |> List.last()
+
+      assert response =
+               conn
+               |> assign(:user, user)
+               |> put_req_header("accept", "application/activity+json")
+               |> get("/objects/#{uuid}")
+
+      assert json_response(response, 200) == ObjectView.render("object.json", %{object: object})
+    end
+
     test "it returns a json representation of the object with accept application/json", %{
       conn: conn
     } do
@@ -285,6 +303,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       assert json_response(conn, 404)
     end
 
+    test "returns visible non-public messages when authenticated", %{conn: conn} do
+      note = insert(:direct_note)
+      uuid = String.split(note.data["id"], "/") |> List.last()
+      user = User.get_by_ap_id(note.data["actor"])
+      marisa = insert(:user)
+
+      assert conn
+             |> assign(:user, marisa)
+             |> put_req_header("accept", "application/activity+json")
+             |> get("/objects/#{uuid}")
+             |> json_response(404)
+
+      assert response =
+               conn
+               |> assign(:user, user)
+               |> put_req_header("accept", "application/activity+json")
+               |> get("/objects/#{uuid}")
+               |> json_response(200)
+
+      assert response == ObjectView.render("object.json", %{object: note})
+    end
+
     test "it returns 404 for tombstone objects", %{conn: conn} do
       tombstone = insert(:tombstone)
       uuid = String.split(tombstone.data["id"], "/") |> List.last()
@@ -358,6 +398,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       assert json_response(conn, 404)
     end
 
+    test "returns local-only activities when authenticated", %{conn: conn} do
+      user = insert(:user)
+      {:ok, post} = CommonAPI.post(user, %{status: "test", visibility: "local"})
+
+      assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post)
+
+      uuid = String.split(post.data["id"], "/") |> List.last()
+
+      assert response =
+               conn
+               |> assign(:user, user)
+               |> put_req_header("accept", "application/activity+json")
+               |> get("/activities/#{uuid}")
+
+      assert json_response(response, 200) == ObjectView.render("object.json", %{object: post})
+    end
+
     test "it returns a json representation of the activity", %{conn: conn} do
       activity = insert(:note_activity)
       uuid = String.split(activity.data["id"], "/") |> List.last()
@@ -382,6 +439,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       assert json_response(conn, 404)
     end
 
+    test "returns visible non-public messages when authenticated", %{conn: conn} do
+      note = insert(:direct_note_activity)
+      uuid = String.split(note.data["id"], "/") |> List.last()
+      user = User.get_by_ap_id(note.data["actor"])
+      marisa = insert(:user)
+
+      assert conn
+             |> assign(:user, marisa)
+             |> put_req_header("accept", "application/activity+json")
+             |> get("/activities/#{uuid}")
+             |> json_response(404)
+
+      assert response =
+               conn
+               |> assign(:user, user)
+               |> put_req_header("accept", "application/activity+json")
+               |> get("/activities/#{uuid}")
+               |> json_response(200)
+
+      assert response == ObjectView.render("object.json", %{object: note})
+    end
+
     test "it caches a response", %{conn: conn} do
       activity = insert(:note_activity)
       uuid = String.split(activity.data["id"], "/") |> List.last()
@@ -1022,6 +1101,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
 
       assert response(conn, 200) =~ announce_activity.data["object"]
     end
+
+    test "It returns poll Answers when authenticated", %{conn: conn} do
+      poller = insert(:user)
+      voter = insert(:user)
+
+      {:ok, activity} =
+        CommonAPI.post(poller, %{
+          status: "suya...",
+          poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
+        })
+
+      assert question = Object.normalize(activity, fetch: false)
+
+      {:ok, [activity], _object} = CommonAPI.vote(voter, question, [1])
+
+      assert outbox_get =
+               conn
+               |> assign(:user, voter)
+               |> put_req_header("accept", "application/activity+json")
+               |> get(voter.ap_id <> "/outbox?page=true")
+               |> json_response(200)
+
+      assert [answer_outbox] = outbox_get["orderedItems"]
+      assert answer_outbox["id"] == activity.data["id"]
+    end
   end
 
   describe "POST /users/:nickname/outbox (C2S)" do
index d8544279a3fd4ab18ec2e3abd49cdf9c9d4a6b26..23485225d0b60404c117778518ad237afc8c7ec1 100644 (file)
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
   use Pleroma.DataCase, async: true
 
   alias Pleroma.Activity
+  alias Pleroma.Object
   alias Pleroma.Web.ActivityPub.Visibility
   alias Pleroma.Web.CommonAPI
   import Pleroma.Factory
@@ -107,7 +108,7 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
     assert Visibility.is_list?(list)
   end
 
-  test "visible_for_user?", %{
+  test "visible_for_user? Activity", %{
     public: public,
     private: private,
     direct: direct,
@@ -149,10 +150,76 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
     refute Visibility.visible_for_user?(private, unrelated)
     refute Visibility.visible_for_user?(direct, unrelated)
 
+    # Public and unlisted visible for unauthenticated
+
+    assert Visibility.visible_for_user?(public, nil)
+    assert Visibility.visible_for_user?(unlisted, nil)
+    refute Visibility.visible_for_user?(private, nil)
+    refute Visibility.visible_for_user?(direct, nil)
+
     # Visible for a list member
     assert Visibility.visible_for_user?(list, unrelated)
   end
 
+  test "visible_for_user? Object", %{
+    public: public,
+    private: private,
+    direct: direct,
+    unlisted: unlisted,
+    user: user,
+    mentioned: mentioned,
+    following: following,
+    unrelated: unrelated,
+    list: list
+  } do
+    public = Object.normalize(public)
+    private = Object.normalize(private)
+    unlisted = Object.normalize(unlisted)
+    direct = Object.normalize(direct)
+    list = Object.normalize(list)
+
+    # All visible to author
+
+    assert Visibility.visible_for_user?(public, user)
+    assert Visibility.visible_for_user?(private, user)
+    assert Visibility.visible_for_user?(unlisted, user)
+    assert Visibility.visible_for_user?(direct, user)
+    assert Visibility.visible_for_user?(list, user)
+
+    # All visible to a mentioned user
+
+    assert Visibility.visible_for_user?(public, mentioned)
+    assert Visibility.visible_for_user?(private, mentioned)
+    assert Visibility.visible_for_user?(unlisted, mentioned)
+    assert Visibility.visible_for_user?(direct, mentioned)
+    assert Visibility.visible_for_user?(list, mentioned)
+
+    # DM not visible for just follower
+
+    assert Visibility.visible_for_user?(public, following)
+    assert Visibility.visible_for_user?(private, following)
+    assert Visibility.visible_for_user?(unlisted, following)
+    refute Visibility.visible_for_user?(direct, following)
+    refute Visibility.visible_for_user?(list, following)
+
+    # Public and unlisted visible for unrelated user
+
+    assert Visibility.visible_for_user?(public, unrelated)
+    assert Visibility.visible_for_user?(unlisted, unrelated)
+    refute Visibility.visible_for_user?(private, unrelated)
+    refute Visibility.visible_for_user?(direct, unrelated)
+
+    # Public and unlisted visible for unauthenticated
+
+    assert Visibility.visible_for_user?(public, nil)
+    assert Visibility.visible_for_user?(unlisted, nil)
+    refute Visibility.visible_for_user?(private, nil)
+    refute Visibility.visible_for_user?(direct, nil)
+
+    # Visible for a list member
+    # assert Visibility.visible_for_user?(list, unrelated)
+  end
+
   test "doesn't die when the user doesn't exist",
        %{
          direct: direct,
index e7688c7287c894011a9b6e48663c0dd00e3639a4..8cd9f939b20312ca64553e47a1b39c78b9ba63c3 100644 (file)
@@ -46,104 +46,47 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     assert json_response(conn, 200)
   end
 
-  describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
-    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
+  test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
+       %{admin: admin} do
+    user = insert(:user)
+    url = "/api/pleroma/admin/users/#{user.nickname}"
 
-    test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
-         %{admin: admin} do
-      user = insert(:user)
-      url = "/api/pleroma/admin/users/#{user.nickname}"
-
-      good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
-      good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
-      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
-
-      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
-      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
-      bad_token3 = nil
-
-      for good_token <- [good_token1, good_token2, good_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, good_token)
-          |> get(url)
-
-        assert json_response(conn, 200)
-      end
-
-      for good_token <- [good_token1, good_token2, good_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, nil)
-          |> assign(:token, good_token)
-          |> get(url)
-
-        assert json_response(conn, :forbidden)
-      end
-
-      for bad_token <- [bad_token1, bad_token2, bad_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, bad_token)
-          |> get(url)
-
-        assert json_response(conn, :forbidden)
-      end
+    good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
+    good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
+    good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
+
+    bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
+    bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
+    bad_token3 = nil
+
+    for good_token <- [good_token1, good_token2, good_token3] do
+      conn =
+        build_conn()
+        |> assign(:user, admin)
+        |> assign(:token, good_token)
+        |> get(url)
+
+      assert json_response(conn, 200)
     end
-  end
 
-  describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
-    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
+    for good_token <- [good_token1, good_token2, good_token3] do
+      conn =
+        build_conn()
+        |> assign(:user, nil)
+        |> assign(:token, good_token)
+        |> get(url)
+
+      assert json_response(conn, :forbidden)
+    end
 
-    test "GET /api/pleroma/admin/users/:nickname requires " <>
-           "read:accounts or admin:read:accounts or broader scope",
-         %{admin: admin} do
-      user = insert(:user)
-      url = "/api/pleroma/admin/users/#{user.nickname}"
-
-      good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
-      good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
-      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
-      good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
-      good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
-
-      good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
-
-      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
-      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
-      bad_token3 = nil
-
-      for good_token <- good_tokens do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, good_token)
-          |> get(url)
-
-        assert json_response(conn, 200)
-      end
-
-      for good_token <- good_tokens do
-        conn =
-          build_conn()
-          |> assign(:user, nil)
-          |> assign(:token, good_token)
-          |> get(url)
-
-        assert json_response(conn, :forbidden)
-      end
-
-      for bad_token <- [bad_token1, bad_token2, bad_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, bad_token)
-          |> get(url)
-
-        assert json_response(conn, :forbidden)
-      end
+    for bad_token <- [bad_token1, bad_token2, bad_token3] do
+      conn =
+        build_conn()
+        |> assign(:user, admin)
+        |> assign(:token, bad_token)
+        |> get(url)
+
+      assert json_response(conn, :forbidden)
     end
   end
 
index ef16dede3aa06035a95d476f83289cb3d2bc1863..beb8a5d58c454b02af963fd9ea4657afe7557b47 100644 (file)
@@ -47,104 +47,47 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
     assert json_response(conn, 200)
   end
 
-  describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
-    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
-
-    test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
-         %{admin: admin} do
-      user = insert(:user)
-      url = "/api/pleroma/admin/users/#{user.nickname}"
-
-      good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
-      good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
-      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
-
-      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
-      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
-      bad_token3 = nil
-
-      for good_token <- [good_token1, good_token2, good_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, good_token)
-          |> get(url)
+  test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
+       %{admin: admin} do
+    user = insert(:user)
+    url = "/api/pleroma/admin/users/#{user.nickname}"
 
-        assert json_response(conn, 200)
-      end
+    good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
+    good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
+    good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
 
-      for good_token <- [good_token1, good_token2, good_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, nil)
-          |> assign(:token, good_token)
-          |> get(url)
+    bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
+    bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
+    bad_token3 = nil
 
-        assert json_response(conn, :forbidden)
-      end
-
-      for bad_token <- [bad_token1, bad_token2, bad_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, bad_token)
-          |> get(url)
+    for good_token <- [good_token1, good_token2, good_token3] do
+      conn =
+        build_conn()
+        |> assign(:user, admin)
+        |> assign(:token, good_token)
+        |> get(url)
 
-        assert json_response(conn, :forbidden)
-      end
+      assert json_response(conn, 200)
     end
-  end
 
-  describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
-    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
-
-    test "GET /api/pleroma/admin/users/:nickname requires " <>
-           "read:accounts or admin:read:accounts or broader scope",
-         %{admin: admin} do
-      user = insert(:user)
-      url = "/api/pleroma/admin/users/#{user.nickname}"
-
-      good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
-      good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
-      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
-      good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
-      good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
-
-      good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
-
-      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
-      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
-      bad_token3 = nil
-
-      for good_token <- good_tokens do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, good_token)
-          |> get(url)
-
-        assert json_response(conn, 200)
-      end
-
-      for good_token <- good_tokens do
-        conn =
-          build_conn()
-          |> assign(:user, nil)
-          |> assign(:token, good_token)
-          |> get(url)
+    for good_token <- [good_token1, good_token2, good_token3] do
+      conn =
+        build_conn()
+        |> assign(:user, nil)
+        |> assign(:token, good_token)
+        |> get(url)
 
-        assert json_response(conn, :forbidden)
-      end
+      assert json_response(conn, :forbidden)
+    end
 
-      for bad_token <- [bad_token1, bad_token2, bad_token3] do
-        conn =
-          build_conn()
-          |> assign(:user, admin)
-          |> assign(:token, bad_token)
-          |> get(url)
+    for bad_token <- [bad_token1, bad_token2, bad_token3] do
+      conn =
+        build_conn()
+        |> assign(:user, admin)
+        |> assign(:token, bad_token)
+        |> get(url)
 
-        assert json_response(conn, :forbidden)
-      end
+      assert json_response(conn, :forbidden)
     end
   end
 
index 238fd265b974a777747e9662ad7271a695aa77ff..76d81b942333274ae69d3c279375fa82c52aff88 100644 (file)
@@ -12,22 +12,26 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do
   import Pleroma.Factory
 
   test "apps/verify_credentials", %{conn: conn} do
-    token = insert(:oauth_token)
+    user_bound_token = insert(:oauth_token)
+    app_bound_token = insert(:oauth_token, user: nil)
+    refute app_bound_token.user
 
-    conn =
-      conn
-      |> put_req_header("authorization", "Bearer #{token.token}")
-      |> get("/api/v1/apps/verify_credentials")
+    for token <- [app_bound_token, user_bound_token] do
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer #{token.token}")
+        |> get("/api/v1/apps/verify_credentials")
 
-    app = Repo.preload(token, :app).app
+      app = Repo.preload(token, :app).app
 
-    expected = %{
-      "name" => app.client_name,
-      "website" => app.website,
-      "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
-    }
+      expected = %{
+        "name" => app.client_name,
+        "website" => app.website,
+        "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
+      }
 
-    assert expected == json_response_and_validate_schema(conn, 200)
+      assert expected == json_response_and_validate_schema(conn, 200)
+    end
   end
 
   test "creates an oauth app", %{conn: conn} do
index 29bc4fd1784c5979078153b72940e52426fecd38..3176f12968069aac77bbdb8d15e321589dbabc52 100644 (file)
@@ -217,6 +217,32 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
     assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
   end
 
+  test "Removes a conversation", %{user: user_one, conn: conn} do
+    user_two = insert(:user)
+    token = insert(:oauth_token, user: user_one, scopes: ["read:statuses", "write:conversations"])
+
+    {:ok, _direct} = create_direct_message(user_one, [user_two])
+    {:ok, _direct} = create_direct_message(user_one, [user_two])
+
+    assert [%{"id" => conv1_id}, %{"id" => conv2_id}] =
+             conn
+             |> assign(:token, token)
+             |> get("/api/v1/conversations")
+             |> json_response_and_validate_schema(200)
+
+    assert %{} =
+             conn
+             |> assign(:token, token)
+             |> delete("/api/v1/conversations/#{conv1_id}")
+             |> json_response_and_validate_schema(200)
+
+    assert [%{"id" => ^conv2_id}] =
+             conn
+             |> assign(:token, token)
+             |> get("/api/v1/conversations")
+             |> json_response_and_validate_schema(200)
+  end
+
   defp create_direct_message(sender, recips) do
     hellos =
       recips
index 631e5c4fc34a993b84b8edbf348e59e5eac71e36..2615912a8dac5fe06ca50ea0cbd1d4e19a78a7f0 100644 (file)
@@ -555,24 +555,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     assert length(json_response_and_validate_schema(conn, 200)) == 1
   end
 
-  @tag capture_log: true
   test "see move notifications" do
     old_user = insert(:user)
     new_user = insert(:user, also_known_as: [old_user.ap_id])
     %{user: follower, conn: conn} = oauth_access(["read:notifications"])
 
-    old_user_url = old_user.ap_id
-
-    body =
-      File.read!("test/fixtures/users_mock/localhost.json")
-      |> String.replace("{{nickname}}", old_user.nickname)
-      |> Jason.encode!()
-
-    Tesla.Mock.mock(fn
-      %{method: :get, url: ^old_user_url} ->
-        %Tesla.Env{status: 200, body: body}
-    end)
-
     User.follow(follower, old_user)
     Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
     Pleroma.Tests.ObanHelpers.perform_all()
index bae2ad4bfad19f242cf4f63b957919f8a4ab9039..dd2f306b793e2d5a5af936464fbb6e00b671d897 100644 (file)
@@ -427,6 +427,31 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       assert [] == Repo.all(Activity)
     end
 
+    test "with expiration" do
+      %{conn: conn} = oauth_access(["write:statuses", "read:statuses"])
+
+      scheduled_at =
+        NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(6), :millisecond)
+        |> NaiveDateTime.to_iso8601()
+        |> Kernel.<>("Z")
+
+      assert %{"id" => status_id, "params" => %{"expires_in" => 300}} =
+               conn
+               |> put_req_header("content-type", "application/json")
+               |> post("/api/v1/statuses", %{
+                 "status" => "scheduled",
+                 "scheduled_at" => scheduled_at,
+                 "expires_in" => 300
+               })
+               |> json_response_and_validate_schema(200)
+
+      assert %{"id" => ^status_id, "params" => %{"expires_in" => 300}} =
+               conn
+               |> put_req_header("content-type", "application/json")
+               |> get("/api/v1/scheduled_statuses/#{status_id}")
+               |> json_response_and_validate_schema(200)
+    end
+
     test "ignores nil values", %{conn: conn} do
       conn =
         conn
index 965044fd3783f6a25f401f5f828852612ad396e8..496a688d1f79c6908bb5d8e1ac4dfb9a210c3814 100644 (file)
@@ -144,24 +144,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
     refute Repo.one(Notification)
   end
 
-  @tag capture_log: true
   test "Move notification" do
     old_user = insert(:user)
     new_user = insert(:user, also_known_as: [old_user.ap_id])
     follower = insert(:user)
 
-    old_user_url = old_user.ap_id
-
-    body =
-      File.read!("test/fixtures/users_mock/localhost.json")
-      |> String.replace("{{nickname}}", old_user.nickname)
-      |> Jason.encode!()
-
-    Tesla.Mock.mock(fn
-      %{method: :get, url: ^old_user_url} ->
-        %Tesla.Env{status: 200, body: body}
-    end)
-
     User.follow(follower, old_user)
     Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
     Pleroma.Tests.ObanHelpers.perform_all()
index c3b7f0f41f9d2e6df3bea1fbeefbcd7aa0abda99..e323f3a1f0fc35c69cb5fc30b33b7ad3c78b06ae 100644 (file)
@@ -58,7 +58,8 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityViewTest do
         sensitive: true,
         spoiler_text: "spoiler",
         text: "hi",
-        visibility: "unlisted"
+        visibility: "unlisted",
+        expires_in: nil
       },
       scheduled_at: Utils.to_masto_date(scheduled_activity.scheduled_at)
     }
index 372613b8bdeb1e9b8d160f4aab37fcf012c9c96c..99b0d43a7e5d2f60b7dab3804653e9724389c334 100644 (file)
@@ -304,139 +304,165 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
     end
   end
 
-  describe "GET /api/v1/pleroma/chats" do
-    setup do: oauth_access(["read:chats"])
-
-    test "it does not return chats with deleted users", %{conn: conn, user: user} do
-      recipient = insert(:user)
-      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-
-      Pleroma.Repo.delete(recipient)
-      User.invalidate_cache(recipient)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 0
-    end
-
-    test "it does not return chats with users you blocked", %{conn: conn, user: user} do
-      recipient = insert(:user)
-
-      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 1
-
-      User.block(user, recipient)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 0
-    end
-
-    test "it does not return chats with users you muted", %{conn: conn, user: user} do
-      recipient = insert(:user)
-
-      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 1
+  for tested_endpoint <- ["/api/v1/pleroma/chats", "/api/v2/pleroma/chats"] do
+    describe "GET #{tested_endpoint}" do
+      setup do: oauth_access(["read:chats"])
 
-      User.mute(user, recipient)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 0
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats?with_muted=true")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 1
-    end
-
-    test "it returns all chats", %{conn: conn, user: user} do
-      Enum.each(1..30, fn _ ->
+      test "it does not return chats with deleted users", %{conn: conn, user: user} do
         recipient = insert(:user)
         {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-      end)
 
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
+        Pleroma.Repo.delete(recipient)
+        User.invalidate_cache(recipient)
 
-      assert length(result) == 30
-    end
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
 
-    test "it return a list of chats the current user is participating in, in descending order of updates",
-         %{conn: conn, user: user} do
-      har = insert(:user)
-      jafnhar = insert(:user)
-      tridi = insert(:user)
+        assert length(result) == 0
+      end
 
-      {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id)
-      {:ok, chat_1} = time_travel(chat_1, -3)
-      {:ok, chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id)
-      {:ok, _chat_2} = time_travel(chat_2, -2)
-      {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id)
-      {:ok, chat_3} = time_travel(chat_3, -1)
+      test "it does not return chats with users you blocked", %{conn: conn, user: user} do
+        recipient = insert(:user)
 
-      # bump the second one
-      {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id)
+        {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
 
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
 
-      ids = Enum.map(result, & &1["id"])
+        assert length(result) == 1
 
-      assert ids == [
-               chat_2.id |> to_string(),
-               chat_3.id |> to_string(),
-               chat_1.id |> to_string()
-             ]
-    end
+        User.block(user, recipient)
 
-    test "it is not affected by :restrict_unauthenticated setting (issue #1973)", %{
-      conn: conn,
-      user: user
-    } do
-      clear_config([:restrict_unauthenticated, :profiles, :local], true)
-      clear_config([:restrict_unauthenticated, :profiles, :remote], true)
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
 
-      user2 = insert(:user)
-      user3 = insert(:user, local: false)
+        assert length(result) == 0
+      end
 
-      {:ok, _chat_12} = Chat.get_or_create(user.id, user2.ap_id)
-      {:ok, _chat_13} = Chat.get_or_create(user.id, user3.ap_id)
+      test "it does not return chats with users you muted", %{conn: conn, user: user} do
+        recipient = insert(:user)
 
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
+        {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
 
-      account_ids = Enum.map(result, &get_in(&1, ["account", "id"]))
-      assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id])
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        assert length(result) == 1
+
+        User.mute(user, recipient)
+
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        assert length(result) == 0
+
+        result =
+          conn
+          |> get("#{unquote(tested_endpoint)}?with_muted=true")
+          |> json_response_and_validate_schema(200)
+
+        assert length(result) == 1
+      end
+
+      if tested_endpoint == "/api/v1/pleroma/chats" do
+        test "it returns all chats", %{conn: conn, user: user} do
+          Enum.each(1..30, fn _ ->
+            recipient = insert(:user)
+            {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+          end)
+
+          result =
+            conn
+            |> get(unquote(tested_endpoint))
+            |> json_response_and_validate_schema(200)
+
+          assert length(result) == 30
+        end
+      else
+        test "it paginates chats", %{conn: conn, user: user} do
+          Enum.each(1..30, fn _ ->
+            recipient = insert(:user)
+            {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+          end)
+
+          result =
+            conn
+            |> get(unquote(tested_endpoint))
+            |> json_response_and_validate_schema(200)
+
+          assert length(result) == 20
+          last_id = List.last(result)["id"]
+
+          result =
+            conn
+            |> get(unquote(tested_endpoint) <> "?max_id=#{last_id}")
+            |> json_response_and_validate_schema(200)
+
+          assert length(result) == 10
+        end
+      end
+
+      test "it return a list of chats the current user is participating in, in descending order of updates",
+           %{conn: conn, user: user} do
+        har = insert(:user)
+        jafnhar = insert(:user)
+        tridi = insert(:user)
+
+        {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id)
+        {:ok, chat_1} = time_travel(chat_1, -3)
+        {:ok, chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id)
+        {:ok, _chat_2} = time_travel(chat_2, -2)
+        {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id)
+        {:ok, chat_3} = time_travel(chat_3, -1)
+
+        # bump the second one
+        {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id)
+
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        ids = Enum.map(result, & &1["id"])
+
+        assert ids == [
+                 chat_2.id |> to_string(),
+                 chat_3.id |> to_string(),
+                 chat_1.id |> to_string()
+               ]
+      end
+
+      test "it is not affected by :restrict_unauthenticated setting (issue #1973)", %{
+        conn: conn,
+        user: user
+      } do
+        clear_config([:restrict_unauthenticated, :profiles, :local], true)
+        clear_config([:restrict_unauthenticated, :profiles, :remote], true)
+
+        user2 = insert(:user)
+        user3 = insert(:user, local: false)
+
+        {:ok, _chat_12} = Chat.get_or_create(user.id, user2.ap_id)
+        {:ok, _chat_13} = Chat.get_or_create(user.id, user3.ap_id)
+
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        account_ids = Enum.map(result, &get_in(&1, ["account", "id"]))
+        assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id])
+      end
     end
   end
 end
index 8f0da00c016fc38495f43b56fe0801f767575323..54739124953e7d5332643b4163a66a748187c15e 100644 (file)
@@ -13,8 +13,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileControllerTest do
                 Pleroma.Config.get!([:instance, :static_dir]),
                 "emoji"
               )
-  setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
-
   setup do: clear_config([:instance, :public], true)
 
   setup do
index cd9fc391d54660518ca4c9057251422ed7d0657d..d1ba067b8eebb9d69485118db402b77277fb1966 100644 (file)
@@ -13,7 +13,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
                 Pleroma.Config.get!([:instance, :static_dir]),
                 "emoji"
               )
-  setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
 
   setup do: clear_config([:instance, :public], true)
 
index c8cfc967c1db2344022ee8679b8e83b2e32fbb0f..100b83d6a30a69e759772330a59e6fe4af1ac2bd 100644 (file)
@@ -74,4 +74,35 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
       assert %Plug.Conn{status: :success} = get(conn, url)
     end
   end
+
+  test "api routes are detected correctly" do
+    # If this test fails we have probably added something
+    # new that should be in /api/ instead
+    expected_routes = [
+      "api",
+      "main",
+      "ostatus_subscribe",
+      "oauth",
+      "objects",
+      "activities",
+      "notice",
+      "users",
+      "tags",
+      "mailer",
+      "inbox",
+      "relay",
+      "internal",
+      ".well-known",
+      "nodeinfo",
+      "web",
+      "auth",
+      "embed",
+      "proxy",
+      "test",
+      "user_exists",
+      "check_password"
+    ]
+
+    assert expected_routes == Pleroma.Web.get_api_routes()
+  end
 end
index 7241b0afd5b6a4734f13f96eea91a3a221a18d0c..9f6d3dc71b87d6e6c97528d1c7463b912f4551dc 100644 (file)
@@ -169,42 +169,4 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlugTest do
       assert f.(["admin:read"], ["write", "admin"]) == ["admin:read"]
     end
   end
-
-  describe "transform_scopes/2" do
-    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage])
-
-    setup do
-      {:ok, %{f: &OAuthScopesPlug.transform_scopes/2}}
-    end
-
-    test "with :admin option, prefixes all requested scopes with `admin:` " <>
-           "and [optionally] keeps only prefixed scopes, " <>
-           "depending on `[:auth, :enforce_oauth_admin_scope_usage]` setting",
-         %{f: f} do
-      clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
-
-      assert f.(["read"], %{admin: true}) == ["admin:read", "read"]
-
-      assert f.(["read", "write"], %{admin: true}) == [
-               "admin:read",
-               "read",
-               "admin:write",
-               "write"
-             ]
-
-      clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
-
-      assert f.(["read:accounts"], %{admin: true}) == ["admin:read:accounts"]
-
-      assert f.(["read", "write:reports"], %{admin: true}) == [
-               "admin:read",
-               "admin:write:reports"
-             ]
-    end
-
-    test "with no supported options, returns unmodified scopes", %{f: f} do
-      assert f.(["read"], %{}) == ["read"]
-      assert f.(["read", "write"], %{}) == ["read", "write"]
-    end
-  end
 end
index cef2b7629bf9ec8a7d8c369ef188861cb12ede37..b788a913861b56cceac3d10604b4f8cf9ed557f3 100644 (file)
@@ -383,19 +383,8 @@ defmodule Pleroma.Web.StreamerTest do
       user: user,
       token: oauth_token
     } do
-      user_url = user.ap_id
       user2 = insert(:user)
 
-      body =
-        File.read!("test/fixtures/users_mock/localhost.json")
-        |> String.replace("{{nickname}}", user.nickname)
-        |> Jason.encode!()
-
-      Tesla.Mock.mock_global(fn
-        %{method: :get, url: ^user_url} ->
-          %Tesla.Env{status: 200, body: body}
-      end)
-
       Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)
       {:ok, _follower, _followed, follow_activity} = CommonAPI.follow(user2, user)
 
@@ -409,20 +398,9 @@ defmodule Pleroma.Web.StreamerTest do
       token: oauth_token
     } do
       user_id = user.id
-      user_url = user.ap_id
       other_user = insert(:user)
       other_user_id = other_user.id
 
-      body =
-        File.read!("test/fixtures/users_mock/localhost.json")
-        |> String.replace("{{nickname}}", user.nickname)
-        |> Jason.encode!()
-
-      Tesla.Mock.mock_global(fn
-        %{method: :get, url: ^user_url} ->
-          %Tesla.Env{status: 200, body: body}
-      end)
-
       Streamer.get_topic_and_add_socket("user", user, oauth_token)
       {:ok, _follower, _followed, _follow_activity} = CommonAPI.follow(user, other_user)