From d3b0647b1142b9b8ff4ac0c24eeb9291dbfbeb8a Mon Sep 17 00:00:00 2001 From: Phongpanot Date: Tue, 19 Dec 2023 09:20:39 +0100 Subject: [PATCH 1/8] Added translation using Weblate (Thai) --- src/i18n/th.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/i18n/th.json diff --git a/src/i18n/th.json b/src/i18n/th.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/i18n/th.json @@ -0,0 +1 @@ +{} From dd775b6ae25f381cf76e00999fd7d37764870122 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 09:52:32 +0100 Subject: [PATCH 2/8] fix(nodeinfo): fix getting application actor information from NodeInfo response Signed-off-by: Thomas Citharel --- lib/federation/node_info.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/federation/node_info.ex b/lib/federation/node_info.ex index 688abdac8..66e1bc43a 100644 --- a/lib/federation/node_info.ex +++ b/lib/federation/node_info.ex @@ -25,9 +25,10 @@ defmodule Mobilizon.Federation.NodeInfo do defp extract_application_actor(body) do body - |> Enum.find(%{rel: @application_uri, href: nil}, fn %{rel: rel, href: href} -> + |> Map.get("links", []) + |> Enum.find(%{"rel" => @application_uri, "href" => nil}, fn %{"rel" => rel, "href" => href} -> rel == @application_uri and is_binary(href) end) - |> Map.get(:href) + |> Map.get("href") end end From 00250ff33a97d5b7ef94acf2281f5a6ee72f28dd Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 09:53:05 +0100 Subject: [PATCH 3/8] refactor(activitypub): cleanup unused imports and variables Signed-off-by: Thomas Citharel --- lib/federation/activity_pub/relay.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/federation/activity_pub/relay.ex b/lib/federation/activity_pub/relay.ex index 3bc9e9212..50fef4737 100644 --- a/lib/federation/activity_pub/relay.ex +++ b/lib/federation/activity_pub/relay.ex @@ -16,7 +16,6 @@ defmodule Mobilizon.Federation.ActivityPub.Relay do alias Mobilizon.Federation.{NodeInfo, WebFinger} alias Mobilizon.GraphQL.API.Follows alias Mobilizon.Service.Workers.Background - import Mobilizon.Federation.ActivityPub.Utils, only: [create_full_domain_string: 1] require Logger @@ -185,7 +184,7 @@ defmodule Mobilizon.Federation.ActivityPub.Relay do defp fetch_actor("http://" <> address), do: fetch_actor(address) defp fetch_actor(address) do - %URI{host: host} = uri = URI.parse("http://" <> address) + %URI{host: host} = URI.parse("http://" <> address) cond do String.contains?(address, "@") -> From 78d3e76e465202c4fc246d7295007f07b09ca746 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 09:53:41 +0100 Subject: [PATCH 4/8] test(nodeinfo): add tests for Mobilizon.Federation.NodeInfo Signed-off-by: Thomas Citharel --- test/federation/node_info_test.exs | 60 +++++++++++++++++++ test/fixtures/nodeinfo/regular.json | 8 +++ .../nodeinfo/wp-event-federation.json | 12 ++++ 3 files changed, 80 insertions(+) create mode 100644 test/federation/node_info_test.exs create mode 100644 test/fixtures/nodeinfo/regular.json create mode 100644 test/fixtures/nodeinfo/wp-event-federation.json diff --git a/test/federation/node_info_test.exs b/test/federation/node_info_test.exs new file mode 100644 index 000000000..10a5c4b38 --- /dev/null +++ b/test/federation/node_info_test.exs @@ -0,0 +1,60 @@ +defmodule Mobilizon.Federation.NodeInfoTest do + use Mobilizon.DataCase + import Mox + + alias Mobilizon.Federation.NodeInfo + alias Mobilizon.Service.HTTP.WebfingerClient.Mock, as: WebfingerClientMock + + @instance_domain "event-federation.eu" + @nodeinfo_fixture_path "test/fixtures/nodeinfo/wp-event-federation.json" + @nodeinfo_regular_fixture_path "test/fixtures/nodeinfo/regular.json" + + describe "getting application actor" do + test "from wordpress event federation" do + nodeinfo_data = @nodeinfo_fixture_path |> File.read!() |> Jason.decode!() + + WebfingerClientMock + |> expect(:call, fn + %{ + method: :get, + url: "https://event-federation.eu/.well-known/nodeinfo" + }, + _opts -> + {:ok, %Tesla.Env{status: 200, body: nodeinfo_data}} + end) + + assert "https://event-federation.eu/actor-relay" == + NodeInfo.application_actor(@instance_domain) + end + + test "with no FEP-2677 information" do + nodeinfo_data = @nodeinfo_regular_fixture_path |> File.read!() |> Jason.decode!() + + WebfingerClientMock + |> expect(:call, fn + %{ + method: :get, + url: "https://event-federation.eu/.well-known/nodeinfo" + }, + _opts -> + {:ok, %Tesla.Env{status: 200, body: nodeinfo_data}} + end) + + assert nil == NodeInfo.application_actor(@instance_domain) + end + + test "with no result" do + WebfingerClientMock + |> expect(:call, fn + %{ + method: :get, + url: "https://event-federation.eu/.well-known/nodeinfo" + }, + _opts -> + {:ok, %Tesla.Env{status: 404, body: ""}} + end) + + assert nil == NodeInfo.application_actor(@instance_domain) + end + end +end diff --git a/test/fixtures/nodeinfo/regular.json b/test/fixtures/nodeinfo/regular.json new file mode 100644 index 000000000..f18dfcfab --- /dev/null +++ b/test/fixtures/nodeinfo/regular.json @@ -0,0 +1,8 @@ +{ + "links": [ + { + "rel": "http:\/\/nodeinfo.diaspora.software\/ns\/schema\/2.0", + "href": "https:\/\/event-federation.eu\/wp-json\/activitypub\/1.0\/nodeinfo" + } + ] +} \ No newline at end of file diff --git a/test/fixtures/nodeinfo/wp-event-federation.json b/test/fixtures/nodeinfo/wp-event-federation.json new file mode 100644 index 000000000..be64bcb71 --- /dev/null +++ b/test/fixtures/nodeinfo/wp-event-federation.json @@ -0,0 +1,12 @@ +{ + "links": [ + { + "rel": "http:\/\/nodeinfo.diaspora.software\/ns\/schema\/2.0", + "href": "https:\/\/event-federation.eu\/wp-json\/activitypub\/1.0\/nodeinfo" + }, + { + "rel": "https://www.w3.org/ns/activitystreams#Application", + "href": "https://event-federation.eu/actor-relay" + } + ] +} \ No newline at end of file From 64237cfc2633794a48022a059c79155b1ece14d1 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 10:52:31 +0100 Subject: [PATCH 5/8] feat(activitypub): allow simple text for address field Closes #1387 Signed-off-by: Thomas Citharel --- .../activity_stream/converter/address.ex | 27 ++++--- .../activity_stream/converter/utils.ex | 4 +- .../converter/address_test.exs | 74 +++++++++++++++++++ 3 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 test/federation/activity_stream/converter/address_test.exs diff --git a/lib/federation/activity_stream/converter/address.ex b/lib/federation/activity_stream/converter/address.ex index 012747f3b..1dc4d0f4d 100644 --- a/lib/federation/activity_stream/converter/address.ex +++ b/lib/federation/activity_stream/converter/address.ex @@ -24,16 +24,23 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Address do } res = - if is_nil(object["address"]) or not is_map(object["address"]) do - res - else - Map.merge(res, %{ - "country" => object["address"]["addressCountry"], - "postal_code" => object["address"]["postalCode"], - "region" => object["address"]["addressRegion"], - "street" => object["address"]["streetAddress"], - "locality" => object["address"]["addressLocality"] - }) + cond do + is_binary(object["address"]) -> + Map.merge(res, %{ + "street" => object["address"] + }) + + is_map(object["address"]) -> + Map.merge(res, %{ + "country" => object["address"]["addressCountry"], + "postal_code" => object["address"]["postalCode"], + "region" => object["address"]["addressRegion"], + "street" => object["address"]["streetAddress"], + "locality" => object["address"]["addressLocality"] + }) + + is_nil(object["address"]) -> + res end latitude = Map.get(object, "latitude") diff --git a/lib/federation/activity_stream/converter/utils.ex b/lib/federation/activity_stream/converter/utils.ex index 9101fc117..c0b1100a5 100644 --- a/lib/federation/activity_stream/converter/utils.ex +++ b/lib/federation/activity_stream/converter/utils.ex @@ -278,8 +278,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do end @spec get_address(map | binary | nil) :: Address.t() | nil - def get_address(address_url) when is_binary(address_url) do - get_address(%{"id" => address_url}) + def get_address(text_address) when is_binary(text_address) do + get_address(%{"type" => "Place", "name" => text_address}) end def get_address(%{"id" => url} = map) when is_map(map) and is_binary(url) do diff --git a/test/federation/activity_stream/converter/address_test.exs b/test/federation/activity_stream/converter/address_test.exs new file mode 100644 index 000000000..2c8527c5e --- /dev/null +++ b/test/federation/activity_stream/converter/address_test.exs @@ -0,0 +1,74 @@ +defmodule Mobilizon.Federation.ActivityStream.Converter.AddressTest do + use Mobilizon.DataCase + + alias Mobilizon.Addresses.Address + + alias Mobilizon.Federation.ActivityStream.Converter.Address, as: AddressConverter + + describe "address to AS" do + test "valid address to as" do + data = + AddressConverter.model_to_as(%Address{ + country: "France", + locality: "Lyon", + description: "Locaux'Motiv", + postal_code: "69007", + street: "10Bis Rue Jangot" + }) + + assert is_map(data) + assert data["type"] == "Place" + assert data["name"] == "Locaux'Motiv" + assert data["address"]["type"] == "PostalAddress" + assert data["address"]["addressLocality"] == "Lyon" + assert data["address"]["postalCode"] == "69007" + assert data["address"]["addressCountry"] == "France" + assert data["address"]["streetAddress"] == "10Bis Rue Jangot" + end + end + + describe "AS to Address" do + test "basic AS data to model" do + address = + AddressConverter.as_to_model_data(%{ + "type" => "Place", + "name" => "Federazione Anarchica Torinese", + "address" => "corso Palermo 46", + "latitude" => nil, + "longitude" => nil + }) + + assert address["description"] == "Federazione Anarchica Torinese" + assert address["street"] == "corso Palermo 46" + assert address["locality"] == nil + assert address["geom"] == nil + end + + test "AS data with PostalAddress to model" do + address = + AddressConverter.as_to_model_data(%{ + "type" => "Place", + "name" => "Federazione Anarchica Torinese", + "address" => %{ + "streetAddress" => "Corso Palermo, 46", + "addressCountry" => "Italia", + "postalCode" => "10152", + "addressLocality" => "Torino" + }, + "latitude" => 45.08281, + "longitude" => 7.69311 + }) + + assert address["description"] == "Federazione Anarchica Torinese" + assert address["street"] == "Corso Palermo, 46" + assert address["locality"] == "Torino" + assert address["postal_code"] == "10152" + assert address["country"] == "Italia" + + assert address["geom"] == %Geo.Point{ + coordinates: {7.69311, 45.08281}, + srid: 4326 + } + end + end +end From 001a0ed1a50894ad1abe0f7fc9dc5b9666de5dae Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 10:53:12 +0100 Subject: [PATCH 6/8] fix(activitypub): do not try to calculate timezone from missing geo-coordinates Signed-off-by: Thomas Citharel --- lib/federation/activity_stream/converter/event.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/federation/activity_stream/converter/event.ex b/lib/federation/activity_stream/converter/event.ex index 2eca4e805..76e695383 100644 --- a/lib/federation/activity_stream/converter/event.ex +++ b/lib/federation/activity_stream/converter/event.ex @@ -198,6 +198,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do defp calculate_timezone(_object, nil), do: nil + defp calculate_timezone(_object, %Address{geom: nil}), do: nil + defp calculate_timezone(_object, %Address{geom: geom}) do TimezoneDetector.detect( nil, From 75d7816a6cd1fe6754a66c1bb81153068b9c13e3 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 12:04:22 +0100 Subject: [PATCH 7/8] fix(docker): remove openssl1.1-compat Closes #1390 Signed-off-by: Thomas Citharel --- docker/production/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 6b40facd2..090813130 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -50,7 +50,7 @@ LABEL org.opencontainers.image.title="mobilizon" \ org.opencontainers.image.revision=$VCS_REF \ org.opencontainers.image.created=$BUILD_DATE -RUN apk add --no-cache curl openssl ca-certificates ncurses-libs file postgresql-client libgcc libstdc++ imagemagick python3 py3-pip py3-pillow py3-cffi py3-brotli gcc g++ musl-dev python3-dev pango libxslt-dev ttf-cantarell openssl1.1-compat +RUN apk add --no-cache curl openssl ca-certificates ncurses-libs file postgresql-client libgcc libstdc++ imagemagick python3 py3-pip py3-pillow py3-cffi py3-brotli gcc g++ musl-dev python3-dev pango libxslt-dev ttf-cantarell RUN pip --no-cache-dir install weasyprint pyexcel-ods3 # Create every data directory From 889cb91f2649861a87eb7e959065cfb49b30f366 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 19 Dec 2023 12:05:22 +0100 Subject: [PATCH 8/8] fix(docker): add --break-system-packages to pip install to add weasyprint and pyexcel-ods3 That's the only use of Python so we should be fine Signed-off-by: Thomas Citharel --- docker/production/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 090813130..d79986bb3 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -51,7 +51,7 @@ LABEL org.opencontainers.image.title="mobilizon" \ org.opencontainers.image.created=$BUILD_DATE RUN apk add --no-cache curl openssl ca-certificates ncurses-libs file postgresql-client libgcc libstdc++ imagemagick python3 py3-pip py3-pillow py3-cffi py3-brotli gcc g++ musl-dev python3-dev pango libxslt-dev ttf-cantarell -RUN pip --no-cache-dir install weasyprint pyexcel-ods3 +RUN pip --no-cache-dir install --break-system-packages weasyprint pyexcel-ods3 # Create every data directory RUN mkdir -p /var/lib/mobilizon/uploads && chown nobody:nobody /var/lib/mobilizon/uploads