Merge branch 'develop' into openapi/notifications
This commit is contained in:
commit
9c1adb35de
56 changed files with 842 additions and 408 deletions
|
|
@ -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
|
||||
|
|
@ -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].()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
20
lib/pleroma/plugs/expect_authenticated_check_plug.ex
Normal file
20
lib/pleroma/plugs/expect_authenticated_check_plug.ex
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
93
lib/pleroma/tests/auth_test_controller.ex
Normal file
93
lib/pleroma/tests/auth_test_controller.ex
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"))
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
"Include statuses from muted acccounts."
|
||||
),
|
||||
Operation.parameter(:exclude_reblogs, :query, BooleanLike, "Exclude reblogs"),
|
||||
Operation.parameter(:exclude_replies, :query, BooleanLike, "Exclude replies"),
|
||||
Operation.parameter(
|
||||
:exclude_visibilities,
|
||||
:query,
|
||||
|
|
@ -294,13 +295,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 +616,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",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
defmodule Fallback.RedirectController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
require Logger
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.Metadata
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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, []))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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} <-
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||
|
||||
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action not in @oauth_read_actions)
|
||||
|
||||
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.NotificationOperation
|
||||
|
||||
# GET /api/v1/notifications
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.MediaProxy.MediaProxyController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.ReverseProxy
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -17,6 +18,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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
|||
when action in [:conversation, :conversation_statuses]
|
||||
)
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["read:statuses"], fallback: :proceed_unauthenticated}
|
||||
when action == :emoji_reactions_by
|
||||
)
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["write:statuses"]}
|
||||
|
|
@ -34,12 +40,14 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
|||
|
||||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -277,7 +291,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
|
||||
|
|
@ -286,7 +300,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)
|
||||
|
|
@ -322,53 +336,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_via_body)
|
||||
|
||||
post("/polls/:id/votes", PollController, :vote)
|
||||
|
||||
post("/reports", ReportController, :create)
|
||||
|
||||
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)
|
||||
put("/scheduled_statuses/:id", ScheduledActivityController, :update)
|
||||
delete("/scheduled_statuses/:id", ScheduledActivityController, :delete)
|
||||
|
||||
get("/domain_blocks", DomainBlockController, :index)
|
||||
|
||||
get("/filters", FilterController, :index)
|
||||
|
||||
get("/suggestions", SuggestionController, :index)
|
||||
|
||||
get("/conversations", ConversationController, :index)
|
||||
post("/conversations/:id/read", ConversationController, :read)
|
||||
|
||||
get("/endorsements", AccountController, :endorsements)
|
||||
|
||||
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)
|
||||
|
|
@ -380,49 +425,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
|
||||
|
|
@ -434,15 +446,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)
|
||||
|
|
@ -453,20 +474,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
|
||||
|
|
@ -507,7 +516,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
|
||||
|
|
@ -647,11 +660,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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,12 +14,18 @@ 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, EnsurePublicOrAuthenticatedPlug] when action == :confirm_email
|
||||
)
|
||||
|
||||
plug(:skip_plug, OAuthScopesPlug when action in [:oauth_tokens, :revoke_token])
|
||||
|
||||
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||
|
||||
action_fallback(:errors)
|
||||
|
||||
def confirm_email(conn, %{"user_id" => uid, "token" => token}) do
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue