diff --git a/.sobelow-skips b/.sobelow-skips index 9604b0817..c75fab5e2 100644 --- a/.sobelow-skips +++ b/.sobelow-skips @@ -41,4 +41,5 @@ FE1EEB91EA633570F703B251AE2D4D4E E7967805C1EA5301F2722C7BDB2F25F3 BDFB0FB1AAF69C18212CBCFD42F8B717 40220A533CCACB3A1CE9DBF1A8A430A1 -EEB29D1DDA3A3015BC645A989B5BD38E \ No newline at end of file +EEB29D1DDA3A3015BC645A989B5BD38E +5AEE3C678C80E0389C3B0D9D11886EB6 \ No newline at end of file diff --git a/js/src/graphql/group.ts b/js/src/graphql/group.ts index 689288b65..0b1d60874 100644 --- a/js/src/graphql/group.ts +++ b/js/src/graphql/group.ts @@ -186,6 +186,9 @@ export const GROUP_BASIC_FIELDS_FRAGMENTS = gql` ...PostBasicFields } } + members { + total + } } ${ACTOR_FRAGMENT} ${ADDRESS_FRAGMENT} diff --git a/lib/federation/activity_pub/relay.ex b/lib/federation/activity_pub/relay.ex index acc5c6647..9091ce30f 100644 --- a/lib/federation/activity_pub/relay.ex +++ b/lib/federation/activity_pub/relay.ex @@ -26,7 +26,7 @@ defmodule Mobilizon.Federation.ActivityPub.Relay do relay = get_actor() unless Regex.match?(~r/BEGIN RSA PRIVATE KEY/, relay.keys) do - {:ok, relay} = Actors.actor_key_rotation(relay) + {:ok, _relay} = Actors.actor_key_rotation(relay) end relay diff --git a/lib/federation/activity_stream/converter/utils.ex b/lib/federation/activity_stream/converter/utils.ex index 3bba5f3dc..9101fc117 100644 --- a/lib/federation/activity_stream/converter/utils.ex +++ b/lib/federation/activity_stream/converter/utils.ex @@ -26,7 +26,11 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do Logger.debug("fetching tags") Logger.debug(inspect(tags)) - tags |> Enum.flat_map(&fetch_tag/1) |> Enum.uniq() |> Enum.map(&existing_tag_or_data/1) + tags + |> Enum.flat_map(&fetch_tag/1) + |> Enum.uniq() + |> Enum.filter(& &1) + |> Enum.map(&existing_tag_or_data/1) end def fetch_tags(_), do: [] @@ -122,6 +126,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do create_mention(mention, acc) end + defp create_mention(_, acc), do: acc + @spec maybe_fetch_actor_and_attributed_to_id(map()) :: {:ok, Actor.t(), Actor.t() | nil} | {:error, atom()} def maybe_fetch_actor_and_attributed_to_id(%{ @@ -179,8 +185,10 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do def maybe_fetch_actor_and_attributed_to_id(_), do: {:error, :no_actor_found} - @spec fetch_actor(String.t()) :: {:ok, Actor.t()} | {:error, atom()} - def fetch_actor(actor_url) do + @spec fetch_actor(String.t() | map()) :: {:ok, Actor.t()} | {:error, atom()} + def fetch_actor(%{"id" => actor_url}) when is_binary(actor_url), do: fetch_actor(actor_url) + + def fetch_actor(actor_url) when is_binary(actor_url) do case ActivityPubActor.get_or_fetch_actor_by_url(actor_url) do {:ok, %Actor{suspended: false} = actor} -> {:ok, actor} @@ -193,6 +201,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do end end + def fetch_actor(_), do: {:error, :no_actor_found} + @spec process_pictures(map(), integer()) :: Keyword.t() def process_pictures(object, actor_id) do attachements = Map.get(object, "attachment", []) diff --git a/lib/graphql/resolvers/discussion.ex b/lib/graphql/resolvers/discussion.ex index b7ca8e51a..ecb07c39e 100644 --- a/lib/graphql/resolvers/discussion.ex +++ b/lib/graphql/resolvers/discussion.ex @@ -195,6 +195,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do else {:member, false} -> {:error, :unauthorized} + + {:error, %Ecto.Changeset{} = err} -> + {:error, err} end end diff --git a/lib/graphql/resolvers/participant.ex b/lib/graphql/resolvers/participant.ex index e752c0a51..f488e88c8 100644 --- a/lib/graphql/resolvers/participant.ex +++ b/lib/graphql/resolvers/participant.ex @@ -282,6 +282,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Participant do {:error, dgettext("errors", "Participation is confirmed but not approved yet by an organizer")} + {:has_participant, %Participant{role: :participant}} -> + {:error, dgettext("errors", "Participation is already confirmed")} + {:has_participant, nil} -> {:error, dgettext("errors", "This token is invalid")} diff --git a/lib/mobilizon/actors/actor.ex b/lib/mobilizon/actors/actor.ex index 21ee6eaec..36ec653b8 100644 --- a/lib/mobilizon/actors/actor.ex +++ b/lib/mobilizon/actors/actor.ex @@ -341,7 +341,7 @@ defmodule Mobilizon.Actors.Actor do |> put_address(attrs) |> unique_constraint(:url, name: :actors_url_index) |> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_type_index) - |> validate_format(:preferred_username, ~r/[a-z0-9_]+/) + |> validate_format(:preferred_username, ~r/[A-z0-9_]+/) |> put_change(:last_refreshed_at, DateTime.utc_now() |> DateTime.truncate(:second)) end diff --git a/lib/service/formatter/formatter.ex b/lib/service/formatter/formatter.ex index d5ae67078..6cdda2318 100644 --- a/lib/service/formatter/formatter.ex +++ b/lib/service/formatter/formatter.ex @@ -62,8 +62,8 @@ defmodule Mobilizon.Service.Formatter do {link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, actor})}} - # Ignore groups mentions for now - {:ok, %Actor{type: :Group}} -> + # Ignore every other actor type mentions for now + {:ok, %Actor{}} -> {buffer, acc} {:error, _} -> diff --git a/lib/web/controllers/export_controller.ex b/lib/web/controllers/export_controller.ex index ce937b68d..dd660e2f2 100644 --- a/lib/web/controllers/export_controller.ex +++ b/lib/web/controllers/export_controller.ex @@ -26,10 +26,13 @@ defmodule Mobilizon.Web.ExportController do {:error, :not_found} end else - {:error, - dgettext("errors", "Export to format %{format} is not enabled on this instance", - format: format - )} + send_resp( + conn, + 404, + dgettext("errors", "Export to format %{format} is not enabled on this instance", + format: format + ) + ) end end end diff --git a/test/graphql/resolvers/participant_test.exs b/test/graphql/resolvers/participant_test.exs index bd431f14b..8c8201d8b 100644 --- a/test/graphql/resolvers/participant_test.exs +++ b/test/graphql/resolvers/participant_test.exs @@ -1136,6 +1136,15 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do assert %Participant{role: :participant} = event.id |> Events.list_participants_for_event() |> Map.get(:elements) |> hd() + res = + conn + |> AbsintheHelpers.graphql_query( + query: @confirmation_mutation, + variables: %{confirmationToken: confirmation_token} + ) + + assert hd(res["errors"])["message"] == "Participation is already confirmed" + assert_email_sent(to: @email) end diff --git a/test/web/controllers/activity_pub_controller_test.exs b/test/web/controllers/activity_pub_controller_test.exs index d44ddeefa..e9cf2101f 100644 --- a/test/web/controllers/activity_pub_controller_test.exs +++ b/test/web/controllers/activity_pub_controller_test.exs @@ -262,11 +262,16 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do conn |> get(Actor.build_url(actor.preferred_username, :outbox, page: 0)) |> json_response(200) + |> Map.get("orderedItems") + # Published time can be different while we reach the second page + |> Enum.map(&Map.drop(&1, ["published"])) page_1_result = conn |> get(Actor.build_url(actor.preferred_username, :outbox, page: 1)) |> json_response(200) + |> Map.get("orderedItems") + |> Enum.map(&Map.drop(&1, ["published"])) assert page_0_result == page_1_result end diff --git a/test/web/controllers/export_controller_test.exs b/test/web/controllers/export_controller_test.exs new file mode 100644 index 000000000..253a080d8 --- /dev/null +++ b/test/web/controllers/export_controller_test.exs @@ -0,0 +1,13 @@ +# Portions of this file are derived from Pleroma: +# Copyright © 2017-2018 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only +# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/web_finger/web_finger_test.exs + +defmodule Mobilizon.Web.ExportControllerTest do + use Mobilizon.Web.ConnCase + + test "GET /.well-known/webfinger with no query", %{conn: conn} do + conn = get(conn, "/exports/not_existing/whatever") + assert response(conn, 404) == "Export to format not_existing is not enabled on this instance" + end +end