diff --git a/js/src/graphql/actor.ts b/js/src/graphql/actor.ts index aa7f0d372..2b8771153 100644 --- a/js/src/graphql/actor.ts +++ b/js/src/graphql/actor.ts @@ -214,6 +214,9 @@ export const LOGGED_USER_DRAFTS = gql` } beginsOn visibility + attributedTo { + ...ActorFragment + } organizerActor { ...ActorFragment } diff --git a/lib/federation/activity_pub/transmogrifier.ex b/lib/federation/activity_pub/transmogrifier.ex index 34cd4e9f9..b41ab49e8 100644 --- a/lib/federation/activity_pub/transmogrifier.ex +++ b/lib/federation/activity_pub/transmogrifier.ex @@ -391,12 +391,15 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do } = params ) when object_type in ["Person", "Group", "Application", "Service", "Organization"] do - with {:ok, %Actor{suspended: false} = old_actor} <- + with author_url <- Utils.get_actor(params), + {:ok, %Actor{suspended: false} = author} <- + ActivityPubActor.get_or_fetch_actor_by_url(author_url), + {:ok, %Actor{suspended: false} = old_actor} <- ActivityPubActor.get_or_fetch_actor_by_url(object["id"]), object_data <- object |> Converter.Actor.as_to_model_data(), {:ok, %Activity{} = activity, %Actor{} = new_actor} <- - Actions.Update.update(old_actor, object_data, false) do + Actions.Update.update(old_actor, object_data, false, %{updater_actor: author}) do {:ok, activity, new_actor} else e -> diff --git a/lib/federation/activity_pub/types/actors.ex b/lib/federation/activity_pub/types/actors.ex index 081974dec..b08cccd47 100644 --- a/lib/federation/activity_pub/types/actors.ex +++ b/lib/federation/activity_pub/types/actors.ex @@ -43,18 +43,22 @@ defmodule Mobilizon.Federation.ActivityPub.Types.Actors do @spec update(Actor.t(), map, map) :: {:ok, Actor.t(), ActivityStream.t()} | {:error, Ecto.Changeset.t()} def update(%Actor{} = old_actor, args, additional) do + updater_actor = Map.get(args, :updater_actor) || Map.get(additional, :updater_actor) + case Actors.update_actor(old_actor, args) do {:ok, %Actor{} = new_actor} -> GroupActivity.insert_activity(new_actor, subject: "group_updated", old_group: old_actor, - updater_actor: Map.get(args, :updater_actor) + updater_actor: updater_actor ) actor_as_data = Convertible.model_to_as(new_actor) Cachex.del(:activity_pub, "actor_#{new_actor.preferred_username}") audience = Audience.get_audience(new_actor) - additional = Map.merge(additional, %{"actor" => old_actor.url}) + + additional = Map.merge(additional, %{"actor" => (updater_actor || old_actor).url}) + update_data = make_update_data(actor_as_data, Map.merge(audience, additional)) {:ok, new_actor, update_data} diff --git a/lib/federation/activity_pub/types/events.ex b/lib/federation/activity_pub/types/events.ex index ed817af80..52bf0c622 100644 --- a/lib/federation/activity_pub/types/events.ex +++ b/lib/federation/activity_pub/types/events.ex @@ -129,7 +129,7 @@ defmodule Mobilizon.Federation.ActivityPub.Types.Events do @spec permissions(Event.t()) :: Permission.t() def permissions(%Event{draft: draft, attributed_to_id: _attributed_to_id}) do %Permission{ - access: if(draft, do: nil, else: :member), + access: if(draft, do: :moderator, else: :member), create: :moderator, update: :moderator, delete: :moderator diff --git a/test/graphql/resolvers/event_test.exs b/test/graphql/resolvers/event_test.exs index e56b32ded..f1a771373 100644 --- a/test/graphql/resolvers/event_test.exs +++ b/test/graphql/resolvers/event_test.exs @@ -112,6 +112,9 @@ defmodule Mobilizon.Web.Resolvers.EventTest do organizer_actor { id }, + attributed_to { + id + }, online_address, phone_address, category, @@ -320,6 +323,56 @@ defmodule Mobilizon.Web.Resolvers.EventTest do assert res["data"]["person"]["participations"]["elements"] == [] end + test "create_event/3 creates an event as a draft for a group", %{ + conn: conn, + actor: actor, + user: user + } do + %Actor{id: group_id} = group = insert(:group) + insert(:member, parent: group, actor: actor, role: :moderator) + + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query( + query: @create_event_mutation, + variables: %{ + title: "come to my event", + description: "it will be fine", + begins_on: "#{DateTime.utc_now()}", + organizer_actor_id: "#{actor.id}", + attributed_to_id: group_id, + draft: true + } + ) + + assert res["data"]["createEvent"]["title"] == "come to my event" + assert res["data"]["createEvent"]["draft"] == true + assert res["data"]["createEvent"]["attributed_to"]["id"] == to_string(group_id) + + event_uuid = res["data"]["createEvent"]["uuid"] + event_id = res["data"]["createEvent"]["id"] + + refute_enqueued( + worker: Workers.BuildSearch, + args: %{event_id: String.to_integer(event_id), op: :insert_search_event} + ) + + res = + conn + |> AbsintheHelpers.graphql_query(query: @find_event_query, variables: %{uuid: event_uuid}) + + assert hd(res["errors"])["message"] =~ "not found" + + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query(query: @find_event_query, variables: %{uuid: event_uuid}) + + assert res["errors"] == nil + assert res["data"]["event"]["draft"] == true + end + test "create_event/3 creates an event with options", %{conn: conn, actor: actor, user: user} do begins_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601() ends_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()