diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 4aee9326f3..d36e5de445 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -174,7 +174,7 @@ defp prepare_upload(%Plug.Upload{} = file, opts) do defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do parsed = Regex.named_captures(~r/(?jpeg|png|gif);base64,(?.*)/, image_data) data = Base.decode64!(parsed["data"], ignore: :whitespace) - hash = Base.encode16(:crypto.hash(:sha256, data), lower: true) + hash = Base.encode16(:crypto.hash(:sha256, data), case: :lower) with :ok <- check_binary_size(data, opts.size_limit), tmp_path <- tempfile_for_image(data), diff --git a/lib/pleroma/web/api_spec/operations/instance_operation.ex b/lib/pleroma/web/api_spec/operations/instance_operation.ex index 85a1cc7c6b..b26c5a7adc 100644 --- a/lib/pleroma/web/api_spec/operations/instance_operation.ex +++ b/lib/pleroma/web/api_spec/operations/instance_operation.ex @@ -57,6 +57,22 @@ def rules_operation do } end + def domain_blocks_operation do + %Operation{ + tags: ["Instance"], + summary: "Retrieve instance domain blocks", + operationId: "InstanceController.domain_blocks", + responses: %{ + 200 => + Operation.response( + "Array of domain blocks", + "application/json", + array_of_domain_blocks() + ) + } + } + end + defp instance do %Schema{ type: :object, @@ -425,4 +441,19 @@ defp array_of_rules do } } end + + defp array_of_domain_blocks do + %Schema{ + type: :array, + items: %Schema{ + type: :object, + properties: %{ + domain: %Schema{type: :string}, + digest: %Schema{type: :string}, + severity: %Schema{type: :string}, + comment: %Schema{type: :string} + } + } + } + end end diff --git a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex index 10293c990e..1e1e350c7a 100644 --- a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex @@ -30,4 +30,9 @@ def peers(conn, _params) do def rules(conn, _params) do render(conn, "rules.json") end + + @doc "GET /api/v1/instance/domain_blocks" + def domain_blocks(conn, _params) do + render(conn, "domain_blocks.json") + end end diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 3f8d82231e..a2b136a422 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -12,6 +12,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do @mastodon_api_level "2.7.2" + @block_severities %{ + federated_timeline_removal: "silence", + reject: "suspend" + } + def render("show.json", _) do instance = Config.get(:instance) @@ -100,6 +105,34 @@ def render("rule.json", %{rule: rule}) do } end + def render("domain_blocks.json", _) do + if Config.get([:mrf, :transparency]) do + exclusions = Config.get([:mrf, :transparency_exclusions]) |> MRF.instance_list_from_tuples() + + domain_blocks = + Config.get(:mrf_simple) + |> Enum.map(fn {rule, instances} -> + MRF.normalize_instance_list(instances) + |> Enum.reject(fn {host, _} -> + host in exclusions or not Map.has_key?(@block_severities, rule) + end) + |> Enum.map(fn {host, reason} -> + %{ + domain: host, + digest: :crypto.hash(:sha256, host) |> Base.encode16(case: :lower), + severity: Map.get(@block_severities, rule), + comment: reason + } + end) + end) + |> List.flatten() + + domain_blocks + else + [] + end + end + def features do [ "pleroma_api", @@ -172,7 +205,7 @@ def federation do |> Map.put(:enabled, Config.get([:instance, :federating])) end - def fields_limits do + defp fields_limits do %{ max_fields: Config.get([:instance, :max_account_fields]), max_remote_fields: Config.get([:instance, :max_remote_account_fields]), @@ -181,7 +214,7 @@ def fields_limits do } end - def configuration do + defp configuration do %{ statuses: %{ max_characters: Config.get([:instance, :limit]), @@ -200,7 +233,7 @@ def configuration do } end - def configuration2 do + defp configuration2 do configuration() |> Map.merge(%{ urls: %{streaming: Pleroma.Web.Endpoint.websocket_url()}, diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index ba6642d4b0..a07ba912f8 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -661,6 +661,7 @@ defmodule Pleroma.Web.Router do get("/instance", InstanceController, :show) get("/instance/peers", InstanceController, :peers) get("/instance/rules", InstanceController, :rules) + get("/instance/domain_blocks", InstanceController, :domain_blocks) get("/statuses", StatusController, :index) get("/statuses/:id", StatusController, :show) diff --git a/lib/pleroma/webhook.ex b/lib/pleroma/webhook.ex index 6cf47fd687..5579b24118 100644 --- a/lib/pleroma/webhook.ex +++ b/lib/pleroma/webhook.ex @@ -94,7 +94,6 @@ defp put_secret(changeset) do end defp generate_secret do - Base.encode16(:crypto.strong_rand_bytes(20)) - |> String.downcase() + Base.encode16(:crypto.strong_rand_bytes(20), case: :lower) end end diff --git a/lib/pleroma/webhook/notify.ex b/lib/pleroma/webhook/notify.ex index ec84b89ef5..e805dee8f7 100644 --- a/lib/pleroma/webhook/notify.ex +++ b/lib/pleroma/webhook/notify.ex @@ -67,6 +67,6 @@ defp deliver(%Webhook{url: url, secret: secret}, object, type) do end defp signature(body, secret) do - :crypto.mac(:hmac, :sha256, secret, body) |> Base.encode16() + :crypto.mac(:hmac, :sha256, secret, body) |> Base.encode16(case: :lower) end end diff --git a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs index 6abd021fee..0697820c3d 100644 --- a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs @@ -154,4 +154,31 @@ test "get instance information v2", %{conn: conn} do assert get(conn, "/api/v2/instance") |> json_response_and_validate_schema(200) end + + describe "instance domain blocks" do + setup do + clear_config([:mrf_simple, :reject], [{"fediverse.pl", "uses Soapbox"}]) + end + + test "get instance domain blocks", %{conn: conn} do + conn = get(conn, "/api/v1/instance/domain_blocks") + + assert [ + %{ + "comment" => "uses Soapbox", + "digest" => "55e3f44aefe7eb022d3b1daaf7396cabf7f181bf6093c8ea841e30c9fc7d8226", + "domain" => "fediverse.pl", + "severity" => "suspend" + } + ] == json_response_and_validate_schema(conn, 200) + end + + test "returns empty array if mrf transparency is disabled", %{conn: conn} do + clear_config([:mrf, :transparency], false) + + conn = get(conn, "/api/v1/instance/domain_blocks") + + assert [] == json_response_and_validate_schema(conn, 200) + end + end end