diff --git a/changelog.d/disabling-chats.change b/changelog.d/disabling-chats.change new file mode 100644 index 000000000..579679a03 --- /dev/null +++ b/changelog.d/disabling-chats.change @@ -0,0 +1 @@ +Allow disabling Chats feature diff --git a/config/config.exs b/config/config.exs index e6a4eb3e6..f13c12fb9 100644 --- a/config/config.exs +++ b/config/config.exs @@ -979,6 +979,8 @@ config :pleroma, :database_config_whitelist, [ {:web_push_encryption, :vapid_details} ] +config :pleroma, Pleroma.Chat, enabled: true + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/config/description.exs b/config/description.exs index 7c377588c..1293179b9 100644 --- a/config/description.exs +++ b/config/description.exs @@ -2726,6 +2726,19 @@ config :pleroma, :config_description, [ } ] }, + %{ + group: :pleroma, + key: Pleroma.Chat, + type: :group, + description: "Pleroma Chat settings", + children: [ + %{ + key: :enabled, + type: :boolean, + description: "Enables the chats API." + } + ] + }, %{ group: :pleroma, key: :http, diff --git a/lib/pleroma/chat.ex b/lib/pleroma/chat.ex index 926176bfa..6ac1b24b8 100644 --- a/lib/pleroma/chat.ex +++ b/lib/pleroma/chat.ex @@ -108,4 +108,6 @@ defmodule Pleroma.Chat do |> cast(%{pinned: false}, [:pinned]) |> Repo.update() end + + def enabled?, do: Pleroma.Config.get([__MODULE__, :enabled], true) end diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 8847692c8..c273043e1 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do capabilities = if is_boolean(user.accepts_chat_messages) do %{ - "acceptsChatMessages" => user.accepts_chat_messages + "acceptsChatMessages" => Pleroma.Chat.enabled?() and user.accepts_chat_messages } else %{} diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index 76c2db57e..7bc39acc6 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -31,7 +31,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "The updated chat", "application/json", Chat - ) + ), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -56,7 +57,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "The read ChatMessage", "application/json", ChatMessage - ) + ), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -87,7 +89,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "The existing chat", "application/json", Chat - ) + ), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -118,7 +121,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "The created or existing chat", "application/json", Chat - ) + ), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -146,7 +150,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do Operation.parameter(:pinned, :query, BooleanLike.schema(), "Include only pinned chats") ], responses: %{ - 200 => Operation.response("The chats of the user", "application/json", chats_response()) + 200 => Operation.response("The chats of the user", "application/json", chats_response()), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -172,7 +177,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do | pagination_params() ], responses: %{ - 200 => Operation.response("The chats of the user", "application/json", chats_response()) + 200 => Operation.response("The chats of the user", "application/json", chats_response()), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -224,6 +230,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do ChatMessage ), 400 => Operation.response("Bad Request", "application/json", ApiError), + 404 => Operation.response("Not Found", "application/json", ApiError), 422 => Operation.response("MRF Rejection", "application/json", ApiError) }, security: [ @@ -249,7 +256,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "The deleted ChatMessage", "application/json", ChatMessage - ) + ), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -268,7 +276,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do Operation.parameter(:id, :path, :string, "The id of the chat", required: true) ], responses: %{ - 200 => Operation.response("The existing chat", "application/json", Chat) + 200 => Operation.response("The existing chat", "application/json", Chat), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ @@ -287,7 +296,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do Operation.parameter(:id, :path, :string, "The id of the chat", required: true) ], responses: %{ - 200 => Operation.response("The existing chat", "application/json", Chat) + 200 => Operation.response("The existing chat", "application/json", Chat), + 404 => Operation.response("Not Found", "application/json", ApiError) }, security: [ %{ diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex index d6f2dd3a3..a65326226 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex @@ -385,6 +385,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do |> cast_params() |> Map.update(:include_types, [], fn include_types -> include_types end) + if "pleroma:chat_mention" in options.include_types and not Pleroma.Chat.enabled?() do + options + |> Map.update(:include_types, [], fn include_types -> + List.delete(include_types, "pleroma:chat_mention") + end) + else + options + end + if ("pleroma:report" not in options.include_types and User.privileged?(user, :reports_manage_reports)) or User.privileged?(user, :reports_manage_reports) do diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 5386c5a6c..1e3882fc6 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -287,6 +287,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do user.last_status_at && user.last_status_at |> NaiveDateTime.to_date() |> Date.to_iso8601() + accepts_chat_messages = Pleroma.Chat.enabled?() and user.accepts_chat_messages + %{ id: to_string(user.id), username: username_from_nickname(user.nickname), @@ -336,7 +338,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do relationship: relationship, skip_thread_containment: user.skip_thread_containment, background_image: image_url(user.background) |> MediaProxy.url(), - accepts_chat_messages: user.accepts_chat_messages, + accepts_chat_messages: accepts_chat_messages, favicon: favicon, avatar_description: avatar_description, header_description: header_description @@ -391,6 +393,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do |> Kernel.put_in([:source, :pleroma, :show_role], user.show_role) |> Kernel.put_in([:source, :pleroma, :no_rich_text], user.no_rich_text) |> Kernel.put_in([:source, :pleroma, :show_birthday], user.show_birthday) + |> Kernel.put_in([:source, :pleroma, :accepts_chat_messages], user.accepts_chat_messages) end defp maybe_put_settings(data, _, _, _), do: data diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 1a0f63ffa..437e42580 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -202,8 +202,12 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do end, "pleroma_emoji_reactions", "pleroma_custom_emoji_reactions", - "pleroma_chat_messages", - "pleroma:pin_chats", + if Pleroma.Chat.enabled?() do + "pleroma_chat_messages" + end, + if Pleroma.Chat.enabled?() do + "pleroma:pin_chats" + end, if Config.get([:instance, :show_reactions]) do "exposable_reactions" end, diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex index ac9bb2779..9c9f17e86 100644 --- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -41,6 +41,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do ) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false) + plug(:ensure_chats_enabled) defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation @@ -244,4 +245,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do _ -> nil end end + + defp ensure_chats_enabled(conn, _opts) do + if Chat.enabled?() do + conn + else + conn + |> put_status(:not_found) + |> put_view(Pleroma.Web.ErrorView) + |> render("404.json") + |> halt() + end + end end diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 120e94751..14d942c9f 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -289,15 +289,17 @@ defmodule Pleroma.Web.Streamer do defp do_stream(topic, {user, %MessageReference{} = cm_ref}) when topic in ["user", "user:pleroma_chat"] do - topic = "#{topic}:#{user.id}" + if Pleroma.Chat.enabled?() do + topic = "#{topic}:#{user.id}" - text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}, topic) + text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}, topic) - Registry.dispatch(@registry, topic, fn list -> - Enum.each(list, fn {pid, _auth} -> - send(pid, {:text, text}) + Registry.dispatch(@registry, topic, fn list -> + Enum.each(list, fn {pid, _auth} -> + send(pid, {:text, text}) + end) end) - end) + end end defp do_stream("user", %Activity{} = item) do diff --git a/test/pleroma/web/activity_pub/views/user_view_test.exs b/test/pleroma/web/activity_pub/views/user_view_test.exs index a3f807ca9..1aed28d5b 100644 --- a/test/pleroma/web/activity_pub/views/user_view_test.exs +++ b/test/pleroma/web/activity_pub/views/user_view_test.exs @@ -220,5 +220,13 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do "acceptsChatMessages" ) end + + test "it returns false if chat is disabled" do + clear_config([Pleroma.Chat, :enabled], false) + user = insert(:user, accepts_chat_messages: true) + + assert %{"capabilities" => %{"acceptsChatMessages" => false}} = + UserView.render("user.json", user: user) + end end end diff --git a/test/pleroma/web/mastodon_api/views/instance_view_test.exs b/test/pleroma/web/mastodon_api/views/instance_view_test.exs index 66485be0e..5f1e21098 100644 --- a/test/pleroma/web/mastodon_api/views/instance_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/instance_view_test.exs @@ -114,8 +114,6 @@ defmodule Pleroma.Web.MastodonAPI.InstanceViewTest do "quote_posting", "pleroma_emoji_reactions", "pleroma_custom_emoji_reactions", - "pleroma_chat_messages", - "pleroma:pin_chats", "pleroma:get:main/ostatus", "pleroma:group_actors", "pleroma:bookmark_folders", @@ -128,6 +126,8 @@ defmodule Pleroma.Web.MastodonAPI.InstanceViewTest do "gopher", "chat", "shout", + "pleroma_chat_messages", + "pleroma:pin_chats", "relay", "safe_dm_mentions", "exposable_reactions", @@ -139,6 +139,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceViewTest do [:media_proxy, :enabled], [:gopher, :enabled], [:shout, :enabled], + [Pleroma.Chat, :enabled], [:instance, :allow_relay], [:instance, :safe_dm_mentions], [:instance, :show_reactions], @@ -443,6 +444,32 @@ defmodule Pleroma.Web.MastodonAPI.InstanceViewTest do end end + describe "chat features" do + test "advertises Shout without Chats" do + clear_config([:shout, :enabled], true) + clear_config([Pleroma.Chat, :enabled], false) + + features = InstanceView.features() + + assert "chat" in features + assert "shout" in features + refute "pleroma_chat_messages" in features + refute "pleroma:pin_chats" in features + end + + test "advertises Chats without Shout" do + clear_config([:shout, :enabled], false) + clear_config([Pleroma.Chat, :enabled], true) + + features = InstanceView.features() + + refute "chat" in features + refute "shout" in features + assert "pleroma_chat_messages" in features + assert "pleroma:pin_chats" in features + end + end + describe "federation/0" do setup do: clear_config([:mrf, :transparency], true) diff --git a/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs index 0dc0e7014..8244ba434 100644 --- a/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs @@ -546,6 +546,14 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do account_ids = Enum.map(result, &get_in(&1, ["account", "id"])) assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id]) end + + test "it returns 404 when chats are disabled", %{conn: conn} do + clear_config([Pleroma.Chat, :enabled], false) + + conn + |> get(unquote(tested_endpoint)) + |> json_response_and_validate_schema(404) + end end end end