diff --git a/lib/federation/node_info.ex b/lib/federation/node_info.ex index b37bd3e96..bf17b788c 100644 --- a/lib/federation/node_info.ex +++ b/lib/federation/node_info.ex @@ -5,6 +5,7 @@ defmodule Mobilizon.Federation.NodeInfo do alias Mobilizon.Service.HTTP.WebfingerClient require Logger + import Mobilizon.Service.HTTP.Utils, only: [is_content_type?: 2] @application_uri "https://www.w3.org/ns/activitystreams#Application" @nodeinfo_rel_2_0 "http://nodeinfo.diaspora.software/ns/schema/2.0" @@ -31,7 +32,9 @@ defmodule Mobilizon.Federation.NodeInfo do with {:ok, endpoint} when is_binary(endpoint) <- fetch_nodeinfo_details(host), :ok <- Logger.debug("Going to get NodeInfo information from URL #{endpoint}"), - {:ok, %{body: body, status: code}} when code in 200..299 <- WebfingerClient.get(endpoint) do + {:ok, %{body: body, status: code, headers: headers}} when code in 200..299 <- + WebfingerClient.get(endpoint), + {:ok, body} <- validate_json_response(body, headers) do Logger.debug("Found nodeinfo information for domain #{host}") {:ok, body} else @@ -58,8 +61,8 @@ defmodule Mobilizon.Federation.NodeInfo do prefix = if @env !== :dev, do: "https", else: "http" case WebfingerClient.get("#{prefix}://#{host}/.well-known/nodeinfo") do - {:ok, %{body: body, status: code}} when code in 200..299 -> - {:ok, body} + {:ok, %{body: body, status: code, headers: headers}} when code in 200..299 -> + validate_json_response(body, headers) err -> Logger.debug("Failed to fetch NodeInfo data #{inspect(err)}") @@ -102,4 +105,19 @@ defmodule Mobilizon.Federation.NodeInfo do rel == relation and is_binary(href) end) end + + @spec validate_json_response(map() | String.t(), list()) :: + {:ok, String.t()} | {:error, :bad_content_type | :body_not_json} + defp validate_json_response(body, headers) do + cond do + !is_content_type?(headers, "application/json") -> + {:error, :bad_content_type} + + !is_map(body) -> + {:error, :body_not_json} + + true -> + {:ok, body} + end + end end diff --git a/test/federation/node_info_test.exs b/test/federation/node_info_test.exs index d4f34d6c7..203040bc9 100644 --- a/test/federation/node_info_test.exs +++ b/test/federation/node_info_test.exs @@ -24,7 +24,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://event-federation.eu/.well-known/nodeinfo" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_data, + headers: [{"content-type", "application/json"}] + }} end) assert "https://event-federation.eu/actor-relay" == @@ -76,7 +81,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://mobilizon.fr/.well-known/nodeinfo" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_end_point_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_end_point_data, + headers: [{"content-type", "application/json"}] + }} end) WebfingerClientMock @@ -86,7 +96,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://mobilizon.fr/.well-known/nodeinfo/2.1" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_data, + headers: [{"content-type", "application/json"}] + }} end) assert {:ok, data} = NodeInfo.nodeinfo("mobilizon.fr") @@ -107,7 +122,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://event-federation.eu/.well-known/nodeinfo" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_end_point_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_end_point_data, + headers: [{"content-type", "application/json"}] + }} end) WebfingerClientMock @@ -117,7 +137,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://event-federation.eu/wp-json/activitypub/1.0/nodeinfo" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_wp_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_wp_data, + headers: [{"content-type", "application/json"}] + }} end) assert {:ok, data} = NodeInfo.nodeinfo("event-federation.eu") @@ -138,7 +163,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://somewhere.tld/.well-known/nodeinfo" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_end_point_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_end_point_data, + headers: [{"content-type", "application/json"}] + }} end) assert {:error, :no_node_info_endpoint_found} = NodeInfo.nodeinfo("somewhere.tld") @@ -169,7 +199,12 @@ defmodule Mobilizon.Federation.NodeInfoTest do url: "https://mobilizon.fr/.well-known/nodeinfo" }, _opts -> - {:ok, %Tesla.Env{status: 200, body: nodeinfo_end_point_data}} + {:ok, + %Tesla.Env{ + status: 200, + body: nodeinfo_end_point_data, + headers: [{"content-type", "application/json"}] + }} end) WebfingerClientMock diff --git a/test/service/workers/refresh_instances_test.exs b/test/service/workers/refresh_instances_test.exs index 0a5181238..0948b4740 100644 --- a/test/service/workers/refresh_instances_test.exs +++ b/test/service/workers/refresh_instances_test.exs @@ -5,7 +5,6 @@ defmodule Mobilizon.Service.Workers.RefreshInstancesTest do alias Mobilizon.Actors.Actor alias Mobilizon.Federation.ActivityPub.Relay - alias Mobilizon.Instances.Instance alias Mobilizon.Service.Workers.RefreshInstances use Mobilizon.DataCase @@ -14,7 +13,7 @@ defmodule Mobilizon.Service.Workers.RefreshInstancesTest do test "unless if local actor" do # relay = Mobilizon.Web.Relay.get_actor() assert {:error, :not_remote_instance} == - RefreshInstances.refresh_instance_actor(%Instance{domain: nil}) + RefreshInstances.refresh_instance_actor(nil) end test "unless if local relay actor" do @@ -22,7 +21,7 @@ defmodule Mobilizon.Service.Workers.RefreshInstancesTest do %URI{host: domain} = URI.new!(url) assert {:error, :not_remote_instance} == - RefreshInstances.refresh_instance_actor(%Instance{domain: domain}) + RefreshInstances.refresh_instance_actor(domain) end end end