aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorlain <lain@soykaf.club>2020-04-29 13:19:04 +0200
committerlain <lain@soykaf.club>2020-04-29 13:19:04 +0200
commit0c491b904d126725866087ad9a51fb6346e2a358 (patch)
tree652f0d122a25f28681ed28445b5087fb56681067 /lib
parent30ea6bb1674482ef6ddbfd8744f9bd878eae91e9 (diff)
parent58fded9858edbeb318dc011cb313e82a86fbafcb (diff)
downloadpleroma-0c491b904d126725866087ad9a51fb6346e2a358.tar.gz
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/plugs/auth_expected_plug.ex17
-rw-r--r--lib/pleroma/plugs/ensure_authenticated_plug.ex8
-rw-r--r--lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex6
-rw-r--r--lib/pleroma/plugs/expect_authenticated_check_plug.ex20
-rw-r--r--lib/pleroma/plugs/expect_public_or_authenticated_check_plug.ex21
-rw-r--r--lib/pleroma/plugs/oauth_scopes_plug.ex27
-rw-r--r--lib/pleroma/tests/auth_test_controller.ex93
-rw-r--r--lib/pleroma/tests/oauth_test_controller.ex31
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex36
-rw-r--r--lib/pleroma/web/api_spec/operations/account_operation.ex8
-rw-r--r--lib/pleroma/web/fallback_redirect_controller.ex2
-rw-r--r--lib/pleroma/web/masto_fe_controller.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/account_controller.ex25
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/app_controller.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/auth_controller.ex4
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/filter_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/instance_controller.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/list_controller.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/marker_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/media_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/notification_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/poll_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/report_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/search_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/status_controller.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex17
-rw-r--r--lib/pleroma/web/media_proxy/media_proxy_controller.ex1
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex5
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/account_controller.ex14
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex16
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex2
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex22
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex8
-rw-r--r--lib/pleroma/web/router.ex202
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex7
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex24
-rw-r--r--lib/pleroma/web/web.ex97
44 files changed, 518 insertions, 275 deletions
diff --git a/lib/pleroma/plugs/auth_expected_plug.ex b/lib/pleroma/plugs/auth_expected_plug.ex
deleted file mode 100644
index f79597dc3..000000000
--- a/lib/pleroma/plugs/auth_expected_plug.ex
+++ /dev/null
@@ -1,17 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Plugs.AuthExpectedPlug do
- import Plug.Conn
-
- def init(options), do: options
-
- def call(conn, _) do
- put_private(conn, :auth_expected, true)
- end
-
- def auth_expected?(conn) do
- conn.private[:auth_expected]
- end
-end
diff --git a/lib/pleroma/plugs/ensure_authenticated_plug.ex b/lib/pleroma/plugs/ensure_authenticated_plug.ex
index 054d2297f..9c8f5597f 100644
--- a/lib/pleroma/plugs/ensure_authenticated_plug.ex
+++ b/lib/pleroma/plugs/ensure_authenticated_plug.ex
@@ -5,17 +5,21 @@
defmodule Pleroma.Plugs.EnsureAuthenticatedPlug do
import Plug.Conn
import Pleroma.Web.TranslationHelpers
+
alias Pleroma.User
+ use Pleroma.Web, :plug
+
def init(options) do
options
end
- def call(%{assigns: %{user: %User{}}} = conn, _) do
+ @impl true
+ def perform(%{assigns: %{user: %User{}}} = conn, _) do
conn
end
- def call(conn, options) do
+ def perform(conn, options) do
perform =
cond do
options[:if_func] -> options[:if_func].()
diff --git a/lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex b/lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex
index d980ff13d..7265bb87a 100644
--- a/lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex
+++ b/lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex
@@ -5,14 +5,18 @@
defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug do
import Pleroma.Web.TranslationHelpers
import Plug.Conn
+
alias Pleroma.Config
alias Pleroma.User
+ use Pleroma.Web, :plug
+
def init(options) do
options
end
- def call(conn, _) do
+ @impl true
+ def perform(conn, _) do
public? = Config.get!([:instance, :public])
case {public?, conn} do
diff --git a/lib/pleroma/plugs/expect_authenticated_check_plug.ex b/lib/pleroma/plugs/expect_authenticated_check_plug.ex
new file mode 100644
index 000000000..66b8d5de5
--- /dev/null
+++ b/lib/pleroma/plugs/expect_authenticated_check_plug.ex
@@ -0,0 +1,20 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Plugs.ExpectAuthenticatedCheckPlug do
+ @moduledoc """
+ Marks `Pleroma.Plugs.EnsureAuthenticatedPlug` as expected to be executed later in plug chain.
+
+ No-op plug which affects `Pleroma.Web` operation (is checked with `PlugHelper.plug_called?/2`).
+ """
+
+ use Pleroma.Web, :plug
+
+ def init(options), do: options
+
+ @impl true
+ def perform(conn, _) do
+ conn
+ end
+end
diff --git a/lib/pleroma/plugs/expect_public_or_authenticated_check_plug.ex b/lib/pleroma/plugs/expect_public_or_authenticated_check_plug.ex
new file mode 100644
index 000000000..ba0ef76bd
--- /dev/null
+++ b/lib/pleroma/plugs/expect_public_or_authenticated_check_plug.ex
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug do
+ @moduledoc """
+ Marks `Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug` as expected to be executed later in plug
+ chain.
+
+ No-op plug which affects `Pleroma.Web` operation (is checked with `PlugHelper.plug_called?/2`).
+ """
+
+ use Pleroma.Web, :plug
+
+ def init(options), do: options
+
+ @impl true
+ def perform(conn, _) do
+ conn
+ end
+end
diff --git a/lib/pleroma/plugs/oauth_scopes_plug.ex b/lib/pleroma/plugs/oauth_scopes_plug.ex
index 66f48c28c..efc25b79f 100644
--- a/lib/pleroma/plugs/oauth_scopes_plug.ex
+++ b/lib/pleroma/plugs/oauth_scopes_plug.ex
@@ -7,15 +7,12 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do
import Pleroma.Web.Gettext
alias Pleroma.Config
- alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
- alias Pleroma.Plugs.PlugHelper
use Pleroma.Web, :plug
- @behaviour Plug
-
def init(%{scopes: _} = options), do: options
+ @impl true
def perform(%Plug.Conn{assigns: assigns} = conn, %{scopes: scopes} = options) do
op = options[:op] || :|
token = assigns[:token]
@@ -31,10 +28,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do
conn
options[:fallback] == :proceed_unauthenticated ->
- conn
- |> assign(:user, nil)
- |> assign(:token, nil)
- |> maybe_perform_instance_privacy_check(options)
+ drop_auth_info(conn)
true ->
missing_scopes = scopes -- matched_scopes
@@ -50,6 +44,15 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do
end
end
+ @doc "Drops authentication info from connection"
+ def drop_auth_info(conn) do
+ # To simplify debugging, setting a private variable on `conn` if auth info is dropped
+ conn
+ |> put_private(:authentication_ignored, true)
+ |> assign(:user, nil)
+ |> assign(:token, nil)
+ end
+
@doc "Filters descendants of supported scopes"
def filter_descendants(scopes, supported_scopes) do
Enum.filter(
@@ -71,12 +74,4 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do
scopes
end
end
-
- defp maybe_perform_instance_privacy_check(%Plug.Conn{} = conn, options) do
- if options[:skip_instance_privacy_check] do
- conn
- else
- EnsurePublicOrAuthenticatedPlug.call(conn, [])
- end
- end
end
diff --git a/lib/pleroma/tests/auth_test_controller.ex b/lib/pleroma/tests/auth_test_controller.ex
new file mode 100644
index 000000000..fb04411d9
--- /dev/null
+++ b/lib/pleroma/tests/auth_test_controller.ex
@@ -0,0 +1,93 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+# A test controller reachable only in :test env.
+defmodule Pleroma.Tests.AuthTestController do
+ @moduledoc false
+
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.User
+
+ # Serves only with proper OAuth token (:api and :authenticated_api)
+ # Skipping EnsurePublicOrAuthenticatedPlug has no effect in this case
+ #
+ # Suggested use case: all :authenticated_api endpoints (makes no sense for :api endpoints)
+ plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :do_oauth_check)
+
+ # Via :api, keeps :user if token has requested scopes (if :user is dropped, serves if public)
+ # Via :authenticated_api, serves if token is present and has requested scopes
+ #
+ # Suggested use case: vast majority of :api endpoints (no sense for :authenticated_api ones)
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["read"], fallback: :proceed_unauthenticated}
+ when action == :fallback_oauth_check
+ )
+
+ # Keeps :user if present, executes regardless of token / token scopes
+ # Fails with no :user for :authenticated_api / no user for :api on private instance
+ # Note: EnsurePublicOrAuthenticatedPlug is not skipped (private instance fails on no :user)
+ # Note: Basic Auth processing results in :skip_plug call for OAuthScopesPlug
+ #
+ # Suggested use: suppressing OAuth checks for other auth mechanisms (like Basic Auth)
+ # For controller-level use, see :skip_oauth_skip_publicity_check instead
+ plug(
+ :skip_plug,
+ OAuthScopesPlug when action == :skip_oauth_check
+ )
+
+ # (Shouldn't be executed since the plug is skipped)
+ plug(OAuthScopesPlug, %{scopes: ["admin"]} when action == :skip_oauth_check)
+
+ # Via :api, keeps :user if token has requested scopes, and continues with nil :user otherwise
+ # Via :authenticated_api, serves if token is present and has requested scopes
+ #
+ # Suggested use: as :fallback_oauth_check but open with nil :user for :api on private instances
+ plug(
+ :skip_plug,
+ EnsurePublicOrAuthenticatedPlug when action == :fallback_oauth_skip_publicity_check
+ )
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["read"], fallback: :proceed_unauthenticated}
+ when action == :fallback_oauth_skip_publicity_check
+ )
+
+ # Via :api, keeps :user if present, serves regardless of token presence / scopes / :user presence
+ # Via :authenticated_api, serves if :user is set (regardless of token presence and its scopes)
+ #
+ # Suggested use: making an :api endpoint always accessible (e.g. email confirmation endpoint)
+ plug(
+ :skip_plug,
+ [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug]
+ when action == :skip_oauth_skip_publicity_check
+ )
+
+ # Via :authenticated_api, always fails with 403 (endpoint is insecure)
+ # Via :api, drops :user if present and serves if public (private instance rejects on no user)
+ #
+ # Suggested use: none; please define OAuth rules for all :api / :authenticated_api endpoints
+ plug(:skip_plug, [] when action == :missing_oauth_check_definition)
+
+ def do_oauth_check(conn, _params), do: conn_state(conn)
+
+ def fallback_oauth_check(conn, _params), do: conn_state(conn)
+
+ def skip_oauth_check(conn, _params), do: conn_state(conn)
+
+ def fallback_oauth_skip_publicity_check(conn, _params), do: conn_state(conn)
+
+ def skip_oauth_skip_publicity_check(conn, _params), do: conn_state(conn)
+
+ def missing_oauth_check_definition(conn, _params), do: conn_state(conn)
+
+ defp conn_state(%{assigns: %{user: %User{} = user}} = conn),
+ do: json(conn, %{user_id: user.id})
+
+ defp conn_state(conn), do: json(conn, %{user_id: nil})
+end
diff --git a/lib/pleroma/tests/oauth_test_controller.ex b/lib/pleroma/tests/oauth_test_controller.ex
deleted file mode 100644
index 58d517f78..000000000
--- a/lib/pleroma/tests/oauth_test_controller.ex
+++ /dev/null
@@ -1,31 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-# A test controller reachable only in :test env.
-# Serves to test OAuth scopes check skipping / enforcement.
-defmodule Pleroma.Tests.OAuthTestController do
- @moduledoc false
-
- use Pleroma.Web, :controller
-
- alias Pleroma.Plugs.OAuthScopesPlug
-
- plug(:skip_plug, OAuthScopesPlug when action == :skipped_oauth)
-
- plug(OAuthScopesPlug, %{scopes: ["read"]} when action != :missed_oauth)
-
- def skipped_oauth(conn, _params) do
- noop(conn)
- end
-
- def performed_oauth(conn, _params) do
- noop(conn)
- end
-
- def missed_oauth(conn, _params) do
- noop(conn)
- end
-
- defp noop(conn), do: json(conn, %{})
-end
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 9c79310c0..816c11e01 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -48,6 +48,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
%{scopes: ["write:accounts"], admin: true}
when action in [
:get_password_reset,
+ :force_password_reset,
:user_delete,
:users_create,
:user_toggle_activation,
@@ -56,7 +57,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
:tag_users,
:untag_users,
:right_add,
+ :right_add_multiple,
:right_delete,
+ :right_delete_multiple,
:update_user_credentials
]
)
@@ -84,13 +87,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
plug(
OAuthScopesPlug,
%{scopes: ["write:reports"], admin: true}
- when action in [:reports_update]
+ when action in [:reports_update, :report_notes_create, :report_notes_delete]
)
plug(
OAuthScopesPlug,
%{scopes: ["read:statuses"], admin: true}
- when action == :list_user_statuses
+ when action in [:list_statuses, :list_user_statuses, :list_instance_statuses]
)
plug(
@@ -102,13 +105,30 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
plug(
OAuthScopesPlug,
%{scopes: ["read"], admin: true}
- when action in [:config_show, :list_log, :stats]
+ when action in [
+ :config_show,
+ :list_log,
+ :stats,
+ :relay_list,
+ :config_descriptions,
+ :need_reboot
+ ]
)
plug(
OAuthScopesPlug,
%{scopes: ["write"], admin: true}
- when action == :config_update
+ when action in [
+ :restart,
+ :config_update,
+ :resend_confirmation_email,
+ :confirm_email,
+ :oauth_app_create,
+ :oauth_app_list,
+ :oauth_app_update,
+ :oauth_app_delete,
+ :reload_emoji
+ ]
)
action_fallback(:errors)
@@ -1103,25 +1123,25 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|> json(%{"status_visibility" => count})
end
- def errors(conn, {:error, :not_found}) do
+ defp errors(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
|> json(dgettext("errors", "Not found"))
end
- def errors(conn, {:error, reason}) do
+ defp errors(conn, {:error, reason}) do
conn
|> put_status(:bad_request)
|> json(reason)
end
- def errors(conn, {:param_cast, _}) do
+ defp errors(conn, {:param_cast, _}) do
conn
|> put_status(:bad_request)
|> json(dgettext("errors", "Invalid parameters"))
end
- def errors(conn, _) do
+ defp errors(conn, _) do
conn
|> put_status(:internal_server_error)
|> json(dgettext("errors", "Something went wrong"))
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 2efe6e901..64e2e43c4 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -294,13 +294,13 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
- def follows_operation do
+ def follow_by_uri_operation do
%Operation{
tags: ["accounts"],
- summary: "Follows",
+ summary: "Follow by URI",
operationId: "AccountController.follows",
security: [%{"oAuth" => ["follow", "write:follows"]}],
- requestBody: request_body("Parameters", follows_request(), required: true),
+ requestBody: request_body("Parameters", follow_by_uri_request(), required: true),
responses: %{
200 => Operation.response("Account", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
@@ -615,7 +615,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
- defp follows_request do
+ defp follow_by_uri_request do
%Schema{
title: "AccountFollowsRequest",
description: "POST body for muting an account",
diff --git a/lib/pleroma/web/fallback_redirect_controller.ex b/lib/pleroma/web/fallback_redirect_controller.ex
index c13518030..0d9d578fc 100644
--- a/lib/pleroma/web/fallback_redirect_controller.ex
+++ b/lib/pleroma/web/fallback_redirect_controller.ex
@@ -4,7 +4,9 @@
defmodule Fallback.RedirectController do
use Pleroma.Web, :controller
+
require Logger
+
alias Pleroma.User
alias Pleroma.Web.Metadata
diff --git a/lib/pleroma/web/masto_fe_controller.ex b/lib/pleroma/web/masto_fe_controller.ex
index 557cde328..d0d8bc8eb 100644
--- a/lib/pleroma/web/masto_fe_controller.ex
+++ b/lib/pleroma/web/masto_fe_controller.ex
@@ -5,19 +5,25 @@
defmodule Pleroma.Web.MastoFEController do
use Pleroma.Web, :controller
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.User
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :put_settings)
# Note: :index action handles attempt of unauthenticated access to private instance with redirect
+ plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action == :index)
+
plug(
OAuthScopesPlug,
- %{scopes: ["read"], fallback: :proceed_unauthenticated, skip_instance_privacy_check: true}
+ %{scopes: ["read"], fallback: :proceed_unauthenticated}
when action == :index
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action not in [:index, :manifest])
+ plug(
+ :skip_plug,
+ [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :manifest
+ )
@doc "GET /web/*path"
def index(%{assigns: %{user: user, token: token}} = conn, _params)
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index 37adeec5f..1eedf02d6 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
skip_relationships?: 1
]
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Plugs.RateLimiter
alias Pleroma.User
@@ -28,18 +29,26 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
- plug(:skip_plug, OAuthScopesPlug when action == :identity_proofs)
+ plug(:skip_plug, [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :create)
+
+ plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:show, :statuses])
plug(
OAuthScopesPlug,
%{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]}
- when action == :show
+ when action in [:show, :followers, :following]
+ )
+
+ plug(
+ OAuthScopesPlug,
+ %{fallback: :proceed_unauthenticated, scopes: ["read:statuses"]}
+ when action == :statuses
)
plug(
OAuthScopesPlug,
%{scopes: ["read:accounts"]}
- when action in [:endorsements, :verify_credentials, :followers, :following]
+ when action in [:verify_credentials, :endorsements, :identity_proofs]
)
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :update_credentials)
@@ -58,21 +67,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug(OAuthScopesPlug, %{scopes: ["read:follows"]} when action == :relationships)
- # Note: :follows (POST /api/v1/follows) is the same as :follow, consider removing :follows
plug(
OAuthScopesPlug,
- %{scopes: ["follow", "write:follows"]} when action in [:follows, :follow, :unfollow]
+ %{scopes: ["follow", "write:follows"]} when action in [:follow_by_uri, :follow, :unfollow]
)
plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes)
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute])
- plug(
- Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
- when action not in [:create, :show, :statuses]
- )
-
@relationship_actions [:follow, :unfollow]
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
@@ -378,7 +381,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "POST /api/v1/follows"
- def follows(%{body_params: %{uri: uri}} = conn, _) do
+ def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do
case User.get_cached_by_nickname(uri) do
%User{} = user ->
conn
diff --git a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
index 005c60444..408e11474 100644
--- a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.MastodonAPI.AppController do
use Pleroma.Web, :controller
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Repo
alias Pleroma.Web.OAuth.App
@@ -13,7 +14,14 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+ plug(
+ :skip_plug,
+ [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug]
+ when action == :create
+ )
+
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
+
plug(OpenApiSpex.Plug.CastAndValidate)
@local_mastodon_name "Mastodon-Local"
diff --git a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
index 37b389382..753b3db3e 100644
--- a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
@@ -13,10 +13,10 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
- @local_mastodon_name "Mastodon-Local"
-
plug(Pleroma.Plugs.RateLimiter, [name: :password_reset] when action == :password_reset)
+ @local_mastodon_name "Mastodon-Local"
+
@doc "GET /web/login"
def login(%{assigns: %{user: %User{}}} = conn, _params) do
redirect(conn, to: local_mastodon_root_path(conn))
diff --git a/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex b/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
index 7c9b11bf1..c44641526 100644
--- a/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
@@ -14,9 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action == :index)
- plug(OAuthScopesPlug, %{scopes: ["write:conversations"]} when action == :read)
-
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(OAuthScopesPlug, %{scopes: ["write:conversations"]} when action != :index)
@doc "GET /api/v1/conversations"
def index(%{assigns: %{user: user}} = conn, params) do
@@ -28,7 +26,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do
end
@doc "POST /api/v1/conversations/:id/read"
- def read(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
+ def mark_as_read(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
with %Participation{} = participation <-
Repo.get_by(Participation, id: participation_id, user_id: user.id),
{:ok, participation} <- Participation.mark_as_read(participation) do
diff --git a/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex b/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex
index 3bfebef8b..000ad743f 100644
--- a/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex
@@ -7,6 +7,12 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiController do
plug(OpenApiSpex.Plug.CastAndValidate)
+ plug(
+ :skip_plug,
+ [Pleroma.Plugs.OAuthScopesPlug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug]
+ when action == :index
+ )
+
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.CustomEmojiOperation
def index(conn, _params) do
diff --git a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
index 84de79413..c4fa383f2 100644
--- a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
@@ -21,8 +21,6 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
%{scopes: ["follow", "write:blocks"]} when action != :index
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "GET /api/v1/domain_blocks"
def index(%{assigns: %{user: user}} = conn, _) do
json(conn, Map.get(user, :domain_blocks, []))
diff --git a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
index 7b0b937a2..7fd0562c9 100644
--- a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
@@ -17,8 +17,6 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do
%{scopes: ["write:filters"]} when action not in @oauth_read_actions
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "GET /api/v1/filters"
def index(%{assigns: %{user: user}} = conn, _) do
filters = Filter.get_filters(user)
diff --git a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex
index 1ca86f63f..25f2269b9 100644
--- a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex
@@ -21,8 +21,6 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
%{scopes: ["follow", "write:follows"]} when action != :index
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "GET /api/v1/follow_requests"
def index(%{assigns: %{user: followed}} = conn, _params) do
follow_requests = User.get_follow_requests(followed)
diff --git a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex
index 27b5b1a52..237f85677 100644
--- a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex
@@ -5,6 +5,12 @@
defmodule Pleroma.Web.MastodonAPI.InstanceController do
use Pleroma.Web, :controller
+ plug(
+ :skip_plug,
+ [Pleroma.Plugs.OAuthScopesPlug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug]
+ when action in [:show, :peers]
+ )
+
@doc "GET /api/v1/instance"
def show(conn, _params) do
render(conn, "show.json")
diff --git a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex
index dac4daa7b..bfe856025 100644
--- a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex
@@ -11,16 +11,16 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
plug(:list_by_id_and_user when action not in [:index, :create])
- plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in [:index, :show, :list_accounts])
+ @oauth_read_actions [:index, :show, :list_accounts]
+
+ plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in @oauth_read_actions)
plug(
OAuthScopesPlug,
%{scopes: ["write:lists"]}
- when action in [:create, :update, :delete, :add_to_list, :remove_from_list]
+ when action not in @oauth_read_actions
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
# GET /api/v1/lists
diff --git a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
index 58e8a30c2..9f9d4574e 100644
--- a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerController do
)
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :upsert)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
# GET /api/v1/markers
diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
index ac8c18f24..e7767de4e 100644
--- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
@@ -15,9 +15,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
require Logger
- plug(:skip_plug, Pleroma.Plugs.OAuthScopesPlug when action in [:empty_array, :empty_object])
-
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(
+ :skip_plug,
+ [Pleroma.Plugs.OAuthScopesPlug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug]
+ when action in [:empty_array, :empty_object]
+ )
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
diff --git a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
index 2b6f00952..e36751220 100644
--- a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
@@ -15,8 +15,6 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
plug(OAuthScopesPlug, %{scopes: ["write:media"]})
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "POST /api/v1/media"
def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
with {:ok, object} <-
diff --git a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
index 7fb536b09..311405277 100644
--- a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
@@ -20,8 +20,6 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action not in @oauth_read_actions)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
# GET /api/v1/notifications
def index(conn, %{"account_id" => account_id} = params) do
case Pleroma.User.get_cached_by_id(account_id) do
diff --git a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
index d9f894118..af9b66eff 100644
--- a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
@@ -22,8 +22,6 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :vote)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "GET /api/v1/polls/:id"
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
diff --git a/lib/pleroma/web/mastodon_api/controllers/report_controller.ex b/lib/pleroma/web/mastodon_api/controllers/report_controller.ex
index f5782be13..9fbaa7bd1 100644
--- a/lib/pleroma/web/mastodon_api/controllers/report_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/report_controller.ex
@@ -11,8 +11,6 @@ defmodule Pleroma.Web.MastodonAPI.ReportController do
plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "POST /api/v1/reports"
def create(%{assigns: %{user: user}} = conn, params) do
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
diff --git a/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex b/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex
index e1e6bd89b..899b78873 100644
--- a/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex
@@ -18,8 +18,6 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in @oauth_read_actions)
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action not in @oauth_read_actions)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
@doc "GET /api/v1/scheduled_statuses"
diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
index c258742dd..cd49da6ad 100644
--- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated})
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ # Note: on private instances auth is required (EnsurePublicOrAuthenticatedPlug is not skipped)
plug(RateLimiter, [name: :search] when action in [:search, :search2, :account_search])
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index f6e4f7d66..9eea2e9eb 100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -24,6 +24,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
+ plug(:skip_plug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action in [:index, :show])
+
@unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []}
plug(
@@ -77,8 +79,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
%{scopes: ["write:bookmarks"]} when action in [:bookmark, :unbookmark]
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action not in [:index, :show])
-
@rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a
plug(
@@ -358,7 +358,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/favourites"
- def favourites(%{assigns: %{user: user}} = conn, params) do
+ def favourites(%{assigns: %{user: %User{} = user}} = conn, params) do
activities =
ActivityPub.fetch_favourites(
user,
diff --git a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex
index 4647c1f96..d184ea1d0 100644
--- a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex
@@ -12,7 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionController do
action_fallback(:errors)
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]})
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+
plug(:restrict_push_enabled)
# Creates PushSubscription
diff --git a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
index 403d500e0..2d67e19da 100644
--- a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
@@ -9,11 +9,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
only: [add_link_headers: 2, add_link_headers: 3, truthy_param?: 1, skip_relationships?: 1]
alias Pleroma.Pagination
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Plugs.RateLimiter
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
+ plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:public, :hashtag])
+
# TODO: Replace with a macro when there is a Phoenix release with the following commit in it:
# https://github.com/phoenixframework/phoenix/commit/2e8c63c01fec4dde5467dbbbf9705ff9e780735e
@@ -26,7 +29,11 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:home, :direct])
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :list)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action != :public)
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated}
+ when action in [:public, :hashtag]
+ )
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
@@ -94,7 +101,9 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
restrict? = Pleroma.Config.get([:restrict_unauthenticated, :timelines, cfg_key])
- if not (restrict? and is_nil(user)) do
+ if restrict? and is_nil(user) do
+ render_error(conn, :unauthorized, "authorization required for timeline view")
+ else
activities =
params
|> Map.put("type", ["Create", "Announce"])
@@ -112,12 +121,10 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
as: :activity,
skip_relationships: skip_relationships?(params)
)
- else
- render_error(conn, :unauthorized, "authorization required for timeline view")
end
end
- def hashtag_fetching(params, user, local_only) do
+ defp hashtag_fetching(params, user, local_only) do
tags =
[params["tag"], params["any"]]
|> List.flatten()
diff --git a/lib/pleroma/web/media_proxy/media_proxy_controller.ex b/lib/pleroma/web/media_proxy/media_proxy_controller.ex
index 1a09ac62a..4657a4383 100644
--- a/lib/pleroma/web/media_proxy/media_proxy_controller.ex
+++ b/lib/pleroma/web/media_proxy/media_proxy_controller.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.MediaProxy.MediaProxyController do
use Pleroma.Web, :controller
+
alias Pleroma.ReverseProxy
alias Pleroma.Web.MediaProxy
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index 0121cd661..685269877 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -25,9 +25,10 @@ defmodule Pleroma.Web.OAuth.OAuthController do
plug(:fetch_session)
plug(:fetch_flash)
- plug(RateLimiter, [name: :authentication] when action == :create_authorization)
- plug(:skip_plug, Pleroma.Plugs.OAuthScopesPlug)
+ plug(:skip_plug, [Pleroma.Plugs.OAuthScopesPlug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug])
+
+ plug(RateLimiter, [name: :authentication] when action == :create_authorization)
action_fallback(Pleroma.Web.OAuth.FallbackController)
diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
index 60405fbff..be7477867 100644
--- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2, skip_relationships?: 1]
alias Ecto.Changeset
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Plugs.RateLimiter
alias Pleroma.User
@@ -18,6 +19,11 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
require Pleroma.Constants
plug(
+ :skip_plug,
+ [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirmation_resend
+ )
+
+ plug(
OAuthScopesPlug,
%{scopes: ["follow", "write:follows"]} when action in [:subscribe, :unsubscribe]
)
@@ -33,15 +39,13 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
]
)
- plug(OAuthScopesPlug, %{scopes: ["read:favourites"]} when action == :favourites)
-
- # An extra safety measure for possible actions not guarded by OAuth permissions specification
plug(
- Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
- when action != :confirmation_resend
+ OAuthScopesPlug,
+ %{scopes: ["read:favourites"], fallback: :proceed_unauthenticated} when action == :favourites
)
plug(RateLimiter, [name: :account_confirmation_resend] when action == :confirmation_resend)
+
plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
index 03e95e020..e01825b48 100644
--- a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
@@ -1,6 +1,7 @@
defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
use Pleroma.Web, :controller
+ alias Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug
alias Pleroma.Plugs.OAuthScopesPlug
require Logger
@@ -11,17 +12,20 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
when action in [
:create,
:delete,
- :download_from,
- :list_from,
+ :save_from,
:import_from_fs,
:update_file,
:update_metadata
]
)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(
+ :skip_plug,
+ [OAuthScopesPlug, ExpectPublicOrAuthenticatedCheckPlug]
+ when action in [:download_shared, :list_packs, :list_from]
+ )
- def emoji_dir_path do
+ defp emoji_dir_path do
Path.join(
Pleroma.Config.get!([:instance, :static_dir]),
"emoji"
@@ -212,13 +216,13 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
end
@doc """
- An admin endpoint to request downloading a pack named `pack_name` from the instance
+ An admin endpoint to request downloading and storing a pack named `pack_name` from the instance
`instance_address`.
If the requested instance's admin chose to share the pack, it will be downloaded
from that instance, otherwise it will be downloaded from the fallback source, if there is one.
"""
- def download_from(conn, %{"instance_address" => address, "pack_name" => name} = data) do
+ def save_from(conn, %{"instance_address" => address, "pack_name" => name} = data) do
address = String.trim(address)
if shareable_packs_available(address) do
diff --git a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex
index d9c1c8636..d4e0d8b7c 100644
--- a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex
@@ -12,8 +12,6 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show)
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
-
@doc "GET /api/v1/pleroma/mascot"
def show(%{assigns: %{user: user}} = conn, _params) do
json(conn, User.get_mascot(user))
diff --git a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
index fe1b97a20..2c1874051 100644
--- a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
@@ -28,18 +28,26 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
plug(
OAuthScopesPlug,
+ %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated}
+ when action == :emoji_reactions_by
+ )
+
+ plug(
+ OAuthScopesPlug,
%{scopes: ["write:statuses"]}
when action in [:react_with_emoji, :unreact_with_emoji]
)
plug(
OAuthScopesPlug,
- %{scopes: ["write:conversations"]} when action in [:update_conversation, :read_conversations]
+ %{scopes: ["write:conversations"]}
+ when action in [:update_conversation, :mark_conversations_as_read]
)
- plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :read_notification)
-
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["write:notifications"]} when action == :mark_notifications_as_read
+ )
def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id} = params) do
with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
@@ -167,7 +175,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
end
end
- def read_conversations(%{assigns: %{user: user}} = conn, _params) do
+ def mark_conversations_as_read(%{assigns: %{user: user}} = conn, _params) do
with {:ok, _, participations} <- Participation.mark_all_as_read(user) do
conn
|> add_link_headers(participations)
@@ -176,7 +184,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
end
end
- def read_notification(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
+ def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
with {:ok, notification} <- Notification.read_one(user, notification_id) do
conn
|> put_view(NotificationView)
@@ -189,7 +197,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
end
end
- def read_notification(%{assigns: %{user: user}} = conn, %{"max_id" => max_id} = params) do
+ def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => max_id} = params) do
with notifications <- Notification.set_read_up_to(user, max_id) do
notifications = Enum.take(notifications, 80)
diff --git a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
index 4463ec477..22da6c0ad 100644
--- a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
@@ -13,10 +13,12 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.StatusView
- plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :user_scrobbles)
- plug(OAuthScopesPlug, %{scopes: ["write"]} when action != :user_scrobbles)
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["read"], fallback: :proceed_unauthenticated} when action == :user_scrobbles
+ )
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(OAuthScopesPlug, %{scopes: ["write"]} when action != :user_scrobbles)
def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do
params =
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index aad2e3b98..e826bff6f 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -16,6 +16,14 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Plugs.UserEnabledPlug)
end
+ pipeline :expect_authentication do
+ plug(Pleroma.Plugs.ExpectAuthenticatedCheckPlug)
+ end
+
+ pipeline :expect_public_instance_or_authentication do
+ plug(Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug)
+ end
+
pipeline :authenticate do
plug(Pleroma.Plugs.OAuthPlug)
plug(Pleroma.Plugs.BasicAuthDecoderPlug)
@@ -39,20 +47,22 @@ defmodule Pleroma.Web.Router do
end
pipeline :api do
+ plug(:expect_public_instance_or_authentication)
plug(:base_api)
plug(:after_auth)
plug(Pleroma.Plugs.IdempotencyPlug)
end
pipeline :authenticated_api do
+ plug(:expect_authentication)
plug(:base_api)
- plug(Pleroma.Plugs.AuthExpectedPlug)
plug(:after_auth)
plug(Pleroma.Plugs.EnsureAuthenticatedPlug)
plug(Pleroma.Plugs.IdempotencyPlug)
end
pipeline :admin_api do
+ plug(:expect_authentication)
plug(:base_api)
plug(Pleroma.Plugs.AdminSecretAuthenticationPlug)
plug(:after_auth)
@@ -200,24 +210,28 @@ defmodule Pleroma.Web.Router do
end
scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do
+ # Modifying packs
scope "/packs" do
- # Modifying packs
pipe_through(:admin_api)
post("/import_from_fs", EmojiAPIController, :import_from_fs)
-
post("/:pack_name/update_file", EmojiAPIController, :update_file)
post("/:pack_name/update_metadata", EmojiAPIController, :update_metadata)
put("/:name", EmojiAPIController, :create)
delete("/:name", EmojiAPIController, :delete)
- post("/download_from", EmojiAPIController, :download_from)
- post("/list_from", EmojiAPIController, :list_from)
+
+ # Note: /download_from downloads and saves to instance, not to requester
+ post("/download_from", EmojiAPIController, :save_from)
end
+ # Pack info / downloading
scope "/packs" do
- # Pack info / downloading
get("/", EmojiAPIController, :list_packs)
get("/:name/download_shared/", EmojiAPIController, :download_shared)
+ get("/list_from", EmojiAPIController, :list_from)
+
+ # Deprecated: POST /api/pleroma/emoji/packs/list_from (use GET instead)
+ post("/list_from", EmojiAPIController, :list_from)
end
end
@@ -286,7 +300,7 @@ defmodule Pleroma.Web.Router do
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
get("/conversations/:id", PleromaAPIController, :conversation)
- post("/conversations/read", PleromaAPIController, :read_conversations)
+ post("/conversations/read", PleromaAPIController, :mark_conversations_as_read)
end
scope [] do
@@ -295,7 +309,7 @@ defmodule Pleroma.Web.Router do
patch("/conversations/:id", PleromaAPIController, :update_conversation)
put("/statuses/:id/reactions/:emoji", PleromaAPIController, :react_with_emoji)
delete("/statuses/:id/reactions/:emoji", PleromaAPIController, :unreact_with_emoji)
- post("/notifications/read", PleromaAPIController, :read_notification)
+ post("/notifications/read", PleromaAPIController, :mark_notifications_as_read)
patch("/accounts/update_avatar", AccountController, :update_avatar)
patch("/accounts/update_banner", AccountController, :update_banner)
@@ -331,53 +345,84 @@ defmodule Pleroma.Web.Router do
pipe_through(:authenticated_api)
get("/accounts/verify_credentials", AccountController, :verify_credentials)
+ patch("/accounts/update_credentials", AccountController, :update_credentials)
get("/accounts/relationships", AccountController, :relationships)
-
get("/accounts/:id/lists", AccountController, :lists)
get("/accounts/:id/identity_proofs", AccountController, :identity_proofs)
-
- get("/follow_requests", FollowRequestController, :index)
+ get("/endorsements", AccountController, :endorsements)
get("/blocks", AccountController, :blocks)
get("/mutes", AccountController, :mutes)
- get("/timelines/home", TimelineController, :home)
- get("/timelines/direct", TimelineController, :direct)
+ post("/follows", AccountController, :follow_by_uri)
+ post("/accounts/:id/follow", AccountController, :follow)
+ post("/accounts/:id/unfollow", AccountController, :unfollow)
+ post("/accounts/:id/block", AccountController, :block)
+ post("/accounts/:id/unblock", AccountController, :unblock)
+ post("/accounts/:id/mute", AccountController, :mute)
+ post("/accounts/:id/unmute", AccountController, :unmute)
- get("/favourites", StatusController, :favourites)
- get("/bookmarks", StatusController, :bookmarks)
+ get("/apps/verify_credentials", AppController, :verify_credentials)
+
+ get("/conversations", ConversationController, :index)
+ post("/conversations/:id/read", ConversationController, :mark_as_read)
+
+ get("/domain_blocks", DomainBlockController, :index)
+ post("/domain_blocks", DomainBlockController, :create)
+ delete("/domain_blocks", DomainBlockController, :delete)
+
+ get("/filters", FilterController, :index)
+
+ post("/filters", FilterController, :create)
+ get("/filters/:id", FilterController, :show)
+ put("/filters/:id", FilterController, :update)
+ delete("/filters/:id", FilterController, :delete)
+
+ get("/follow_requests", FollowRequestController, :index)
+ post("/follow_requests/:id/authorize", FollowRequestController, :authorize)
+ post("/follow_requests/:id/reject", FollowRequestController, :reject)
+
+ get("/lists", ListController, :index)
+ get("/lists/:id", ListController, :show)
+ get("/lists/:id/accounts", ListController, :list_accounts)
+
+ delete("/lists/:id", ListController, :delete)
+ post("/lists", ListController, :create)
+ put("/lists/:id", ListController, :update)
+ post("/lists/:id/accounts", ListController, :add_to_list)
+ delete("/lists/:id/accounts", ListController, :remove_from_list)
+
+ get("/markers", MarkerController, :index)
+ post("/markers", MarkerController, :upsert)
+
+ post("/media", MediaController, :create)
+ put("/media/:id", MediaController, :update)
get("/notifications", NotificationController, :index)
get("/notifications/:id", NotificationController, :show)
+
post("/notifications/:id/dismiss", NotificationController, :dismiss)
post("/notifications/clear", NotificationController, :clear)
delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple)
# Deprecated: was removed in Mastodon v3, use `/notifications/:id/dismiss` instead
post("/notifications/dismiss", NotificationController, :dismiss)
- get("/scheduled_statuses", ScheduledActivityController, :index)
- get("/scheduled_statuses/:id", ScheduledActivityController, :show)
-
- get("/lists", ListController, :index)
- get("/lists/:id", ListController, :show)
- get("/lists/:id/accounts", ListController, :list_accounts)
-
- get("/domain_blocks", DomainBlockController, :index)
-
- get("/filters", FilterController, :index)
+ post("/polls/:id/votes", PollController, :vote)
- get("/suggestions", SuggestionController, :index)
+ post("/reports", ReportController, :create)
- get("/conversations", ConversationController, :index)
- post("/conversations/:id/read", ConversationController, :read)
+ get("/scheduled_statuses", ScheduledActivityController, :index)
+ get("/scheduled_statuses/:id", ScheduledActivityController, :show)
- get("/endorsements", AccountController, :endorsements)
+ put("/scheduled_statuses/:id", ScheduledActivityController, :update)
+ delete("/scheduled_statuses/:id", ScheduledActivityController, :delete)
- patch("/accounts/update_credentials", AccountController, :update_credentials)
+ # Unlike `GET /api/v1/accounts/:id/favourites`, demands authentication
+ get("/favourites", StatusController, :favourites)
+ get("/bookmarks", StatusController, :bookmarks)
post("/statuses", StatusController, :create)
delete("/statuses/:id", StatusController, :delete)
-
post("/statuses/:id/reblog", StatusController, :reblog)
post("/statuses/:id/unreblog", StatusController, :unreblog)
post("/statuses/:id/favourite", StatusController, :favourite)
@@ -389,49 +434,16 @@ defmodule Pleroma.Web.Router do
post("/statuses/:id/mute", StatusController, :mute_conversation)
post("/statuses/:id/unmute", StatusController, :unmute_conversation)
- put("/scheduled_statuses/:id", ScheduledActivityController, :update)
- delete("/scheduled_statuses/:id", ScheduledActivityController, :delete)
-
- post("/polls/:id/votes", PollController, :vote)
-
- post("/media", MediaController, :create)
- put("/media/:id", MediaController, :update)
-
- delete("/lists/:id", ListController, :delete)
- post("/lists", ListController, :create)
- put("/lists/:id", ListController, :update)
-
- post("/lists/:id/accounts", ListController, :add_to_list)
- delete("/lists/:id/accounts", ListController, :remove_from_list)
-
- post("/filters", FilterController, :create)
- get("/filters/:id", FilterController, :show)
- put("/filters/:id", FilterController, :update)
- delete("/filters/:id", FilterController, :delete)
-
- post("/reports", ReportController, :create)
-
- post("/follows", AccountController, :follows)
- post("/accounts/:id/follow", AccountController, :follow)
- post("/accounts/:id/unfollow", AccountController, :unfollow)
- post("/accounts/:id/block", AccountController, :block)
- post("/accounts/:id/unblock", AccountController, :unblock)
- post("/accounts/:id/mute", AccountController, :mute)
- post("/accounts/:id/unmute", AccountController, :unmute)
-
- post("/follow_requests/:id/authorize", FollowRequestController, :authorize)
- post("/follow_requests/:id/reject", FollowRequestController, :reject)
-
- post("/domain_blocks", DomainBlockController, :create)
- delete("/domain_blocks", DomainBlockController, :delete)
-
post("/push/subscription", SubscriptionController, :create)
get("/push/subscription", SubscriptionController, :get)
put("/push/subscription", SubscriptionController, :update)
delete("/push/subscription", SubscriptionController, :delete)
- get("/markers", MarkerController, :index)
- post("/markers", MarkerController, :upsert)
+ get("/suggestions", SuggestionController, :index)
+
+ get("/timelines/home", TimelineController, :home)
+ get("/timelines/direct", TimelineController, :direct)
+ get("/timelines/list/:list_id", TimelineController, :list)
end
scope "/api/web", Pleroma.Web do
@@ -443,15 +455,24 @@ defmodule Pleroma.Web.Router do
scope "/api/v1", Pleroma.Web.MastodonAPI do
pipe_through(:api)
- post("/accounts", AccountController, :create)
get("/accounts/search", SearchController, :account_search)
+ get("/search", SearchController, :search)
+
+ get("/accounts/:id/statuses", AccountController, :statuses)
+ get("/accounts/:id/followers", AccountController, :followers)
+ get("/accounts/:id/following", AccountController, :following)
+ get("/accounts/:id", AccountController, :show)
+
+ post("/accounts", AccountController, :create)
get("/instance", InstanceController, :show)
get("/instance/peers", InstanceController, :peers)
post("/apps", AppController, :create)
- get("/apps/verify_credentials", AppController, :verify_credentials)
+ get("/statuses", StatusController, :index)
+ get("/statuses/:id", StatusController, :show)
+ get("/statuses/:id/context", StatusController, :context)
get("/statuses/:id/card", StatusController, :card)
get("/statuses/:id/favourited_by", StatusController, :favourited_by)
get("/statuses/:id/reblogged_by", StatusController, :reblogged_by)
@@ -462,20 +483,8 @@ defmodule Pleroma.Web.Router do
get("/timelines/public", TimelineController, :public)
get("/timelines/tag/:tag", TimelineController, :hashtag)
- get("/timelines/list/:list_id", TimelineController, :list)
-
- get("/statuses", StatusController, :index)
- get("/statuses/:id", StatusController, :show)
- get("/statuses/:id/context", StatusController, :context)
get("/polls/:id", PollController, :show)
-
- get("/accounts/:id/statuses", AccountController, :statuses)
- get("/accounts/:id/followers", AccountController, :followers)
- get("/accounts/:id/following", AccountController, :following)
- get("/accounts/:id", AccountController, :show)
-
- get("/search", SearchController, :search)
end
scope "/api/v2", Pleroma.Web.MastodonAPI do
@@ -516,7 +525,11 @@ defmodule Pleroma.Web.Router do
get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens)
delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token)
- post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read)
+ post(
+ "/qvitter/statuses/notifications/read",
+ TwitterAPI.Controller,
+ :mark_notifications_as_read
+ )
end
pipeline :ostatus do
@@ -656,11 +669,28 @@ defmodule Pleroma.Web.Router do
# Test-only routes needed to test action dispatching and plug chain execution
if Pleroma.Config.get(:env) == :test do
+ @test_actions [
+ :do_oauth_check,
+ :fallback_oauth_check,
+ :skip_oauth_check,
+ :fallback_oauth_skip_publicity_check,
+ :skip_oauth_skip_publicity_check,
+ :missing_oauth_check_definition
+ ]
+
+ scope "/test/api", Pleroma.Tests do
+ pipe_through(:api)
+
+ for action <- @test_actions do
+ get("/#{action}", AuthTestController, action)
+ end
+ end
+
scope "/test/authenticated_api", Pleroma.Tests do
pipe_through(:authenticated_api)
- for action <- [:skipped_oauth, :performed_oauth, :missed_oauth] do
- get("/#{action}", OAuthTestController, action)
+ for action <- @test_actions do
+ get("/#{action}", AuthTestController, action)
end
end
end
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index d5d5ce08f..fd2aee175 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -25,13 +25,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
when action == :follow_import
)
- # Note: follower can submit the form (with password auth) not being signed in (having no token)
- plug(
- OAuthScopesPlug,
- %{fallback: :proceed_unauthenticated, scopes: ["follow", "write:follows"]}
- when action == :do_remote_follow
- )
-
plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import)
plug(
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index 31adc2817..c2de26b0b 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
use Pleroma.Web, :controller
alias Pleroma.Notification
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.User
alias Pleroma.Web.OAuth.Token
@@ -13,11 +14,17 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
require Logger
- plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read)
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["write:notifications"]} when action == :mark_notifications_as_read
+ )
- plug(:skip_plug, OAuthScopesPlug when action in [:oauth_tokens, :revoke_token])
+ plug(
+ :skip_plug,
+ [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirm_email
+ )
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(:skip_plug, OAuthScopesPlug when action in [:oauth_tokens, :revoke_token])
action_fallback(:errors)
@@ -46,13 +53,13 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
json_reply(conn, 201, "")
end
- def errors(conn, {:param_cast, _}) do
+ defp errors(conn, {:param_cast, _}) do
conn
|> put_status(400)
|> json("Invalid parameters")
end
- def errors(conn, _) do
+ defp errors(conn, _) do
conn
|> put_status(500)
|> json("Something went wrong")
@@ -64,7 +71,10 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|> send_resp(status, json)
end
- def notifications_read(%{assigns: %{user: user}} = conn, %{"latest_id" => latest_id} = params) do
+ def mark_notifications_as_read(
+ %{assigns: %{user: user}} = conn,
+ %{"latest_id" => latest_id} = params
+ ) do
Notification.set_read_up_to(user, latest_id)
notifications = Notification.for_user(user, params)
@@ -75,7 +85,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|> render("index.json", %{notifications: notifications, for: user})
end
- def notifications_read(%{assigns: %{user: _user}} = conn, _) do
+ def mark_notifications_as_read(%{assigns: %{user: _user}} = conn, _) do
bad_request_reply(conn, "You need to specify latest_id")
end
diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex
index bf48ce26c..08e42a7e5 100644
--- a/lib/pleroma/web/web.ex
+++ b/lib/pleroma/web/web.ex
@@ -2,6 +2,11 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
+defmodule Pleroma.Web.Plug do
+ # Substitute for `call/2` which is defined with `use Pleroma.Web, :plug`
+ @callback perform(Plug.Conn.t(), Plug.opts()) :: Plug.Conn.t()
+end
+
defmodule Pleroma.Web do
@moduledoc """
A module that keeps using definitions for controllers,
@@ -20,44 +25,91 @@ defmodule Pleroma.Web do
below.
"""
+ alias Pleroma.Plugs.EnsureAuthenticatedPlug
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
+ alias Pleroma.Plugs.ExpectAuthenticatedCheckPlug
+ alias Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Plugs.PlugHelper
+
def controller do
quote do
use Phoenix.Controller, namespace: Pleroma.Web
import Plug.Conn
+
import Pleroma.Web.Gettext
import Pleroma.Web.Router.Helpers
import Pleroma.Web.TranslationHelpers
- alias Pleroma.Plugs.PlugHelper
-
plug(:set_put_layout)
defp set_put_layout(conn, _) do
put_layout(conn, Pleroma.Config.get(:app_layout, "app.html"))
end
- # Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain
- defp skip_plug(conn, plug_module) do
- try do
- plug_module.skip_plug(conn)
- rescue
- UndefinedFunctionError ->
- raise "#{plug_module} is not skippable. Append `use Pleroma.Web, :plug` to its code."
- end
+ # Marks plugs intentionally skipped and blocks their execution if present in plugs chain
+ defp skip_plug(conn, plug_modules) do
+ plug_modules
+ |> List.wrap()
+ |> Enum.reduce(
+ conn,
+ fn plug_module, conn ->
+ try do
+ plug_module.skip_plug(conn)
+ rescue
+ UndefinedFunctionError ->
+ raise "`#{plug_module}` is not skippable. Append `use Pleroma.Web, :plug` to its code."
+ end
+ end
+ )
end
# Executed just before actual controller action, invokes before-action hooks (callbacks)
defp action(conn, params) do
- with %Plug.Conn{halted: false} <- maybe_halt_on_missing_oauth_scopes_check(conn) do
+ 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
super(conn, params)
end
end
+ # For non-authenticated API actions, drops auth info if OAuth scopes check was ignored
+ # (neither performed nor explicitly skipped)
+ defp maybe_drop_authentication_if_oauth_check_ignored(conn) do
+ if PlugHelper.plug_called?(conn, ExpectPublicOrAuthenticatedCheckPlug) and
+ not PlugHelper.plug_called_or_skipped?(conn, OAuthScopesPlug) do
+ OAuthScopesPlug.drop_auth_info(conn)
+ else
+ conn
+ end
+ end
+
+ # Ensures instance is public -or- user is authenticated if such check was scheduled
+ defp maybe_perform_public_or_authenticated_check(conn) do
+ if PlugHelper.plug_called?(conn, ExpectPublicOrAuthenticatedCheckPlug) do
+ EnsurePublicOrAuthenticatedPlug.call(conn, %{})
+ else
+ conn
+ end
+ end
+
+ # Ensures user is authenticated if such check was scheduled
+ # Note: runs prior to action even if it was already executed earlier in plug chain
+ # (since OAuthScopesPlug has option of proceeding unauthenticated)
+ defp maybe_perform_authenticated_check(conn) do
+ if PlugHelper.plug_called?(conn, ExpectAuthenticatedCheckPlug) do
+ EnsureAuthenticatedPlug.call(conn, %{})
+ else
+ conn
+ end
+ end
+
# Halts if authenticated API action neither performs nor explicitly skips OAuth scopes check
defp maybe_halt_on_missing_oauth_scopes_check(conn) do
- if Pleroma.Plugs.AuthExpectedPlug.auth_expected?(conn) &&
- not PlugHelper.plug_called_or_skipped?(conn, Pleroma.Plugs.OAuthScopesPlug) do
+ if PlugHelper.plug_called?(conn, ExpectAuthenticatedCheckPlug) and
+ not PlugHelper.plug_called_or_skipped?(conn, OAuthScopesPlug) do
conn
|> render_error(
:forbidden,
@@ -132,7 +184,8 @@ defmodule Pleroma.Web do
def plug do
quote do
- alias Pleroma.Plugs.PlugHelper
+ @behaviour Pleroma.Web.Plug
+ @behaviour Plug
@doc """
Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain.
@@ -146,14 +199,22 @@ defmodule Pleroma.Web do
end
@impl Plug
- @doc "If marked as skipped, returns `conn`, and calls `perform/2` otherwise."
+ @doc """
+ If marked as skipped, returns `conn`, otherwise calls `perform/2`.
+ Note: multiple invocations of the same plug (with different or same options) are allowed.
+ """
def call(%Plug.Conn{} = conn, options) do
if PlugHelper.plug_skipped?(conn, __MODULE__) do
conn
else
- conn
- |> PlugHelper.append_to_private_list(PlugHelper.called_plugs_list_id(), __MODULE__)
- |> perform(options)
+ conn =
+ PlugHelper.append_to_private_list(
+ conn,
+ PlugHelper.called_plugs_list_id(),
+ __MODULE__
+ )
+
+ apply(__MODULE__, :perform, [conn, options])
end
end
end