Refactor checking permissions when managing events and tests

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-07-26 17:23:42 +02:00
parent 52fe274c5a
commit acd921432f
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
3 changed files with 539 additions and 343 deletions

View file

@ -255,11 +255,19 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
# See https://github.com/absinthe-graphql/absinthe/issues/490 # See https://github.com/absinthe-graphql/absinthe/issues/490
with {:is_owned, %Actor{} = organizer_actor} <- User.owns_actor(user, organizer_actor_id), with {:is_owned, %Actor{} = organizer_actor} <- User.owns_actor(user, organizer_actor_id),
args <- Map.put(args, :options, args[:options] || %{}), args <- Map.put(args, :options, args[:options] || %{}),
{:group_check, true} <- {:group_check, is_organizer_group_member?(args)},
args_with_organizer <- Map.put(args, :organizer_actor, organizer_actor), args_with_organizer <- Map.put(args, :organizer_actor, organizer_actor),
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <- {:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
API.Events.create_event(args_with_organizer) do API.Events.create_event(args_with_organizer) do
{:ok, event} {:ok, event}
else else
{:group_check, false} ->
{:error,
dgettext(
"errors",
"Organizer profile doesn't have permission to create an event on behalf of this group"
)}
{:is_owned, nil} -> {:is_owned, nil} ->
{:error, dgettext("errors", "Organizer profile is not owned by the user")} {:error, dgettext("errors", "Organizer profile is not owned by the user")}
@ -286,16 +294,21 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
# See https://github.com/absinthe-graphql/absinthe/issues/490 # See https://github.com/absinthe-graphql/absinthe/issues/490
with args <- Map.put(args, :options, args[:options] || %{}), with args <- Map.put(args, :options, args[:options] || %{}),
{:ok, %Event{} = event} <- Events.get_event_with_preload(event_id), {:ok, %Event{} = event} <- Events.get_event_with_preload(event_id),
{:old_actor, {:is_owned, %Actor{}}} <- %Actor{} = actor <- Users.get_actor_for_user(user),
{:old_actor, User.owns_actor(user, event.organizer_actor_id)}, {:ok, args} <- verify_profile_change(args, event, user, actor),
new_organizer_actor_id <- args |> Map.get(:organizer_actor_id, event.organizer_actor_id), {:event_can_be_managed, true} <-
{:new_actor, {:is_owned, %Actor{} = organizer_actor}} <- {:event_can_be_managed, can_event_be_updated_by?(event, actor)},
{:new_actor, User.owns_actor(user, new_organizer_actor_id)},
args <- Map.put(args, :organizer_actor, organizer_actor),
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <- {:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
API.Events.update_event(args, event) do API.Events.update_event(args, event) do
{:ok, event} {:ok, event}
else else
{:event_can_be_managed, false} ->
{:error,
dgettext(
"errors",
"This profile doesn't have permission to update an event on behalf of this group"
)}
{:error, :event_not_found} -> {:error, :event_not_found} ->
{:error, dgettext("errors", "Event not found")} {:error, dgettext("errors", "Event not found")}
@ -325,7 +338,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
with {:ok, %Event{local: is_local} = event} <- Events.get_event_with_preload(event_id), with {:ok, %Event{local: is_local} = event} <- Events.get_event_with_preload(event_id),
%Actor{id: actor_id} = actor <- Users.get_actor_for_user(user) do %Actor{id: actor_id} = actor <- Users.get_actor_for_user(user) do
cond do cond do
{:event_can_be_managed, true} == Event.can_be_managed_by(event, actor_id) -> {:event_can_be_managed, true} ==
{:event_can_be_managed, can_event_be_deleted_by?(event, actor)} ->
do_delete_event(event, actor) do_delete_event(event, actor)
role in [:moderator, :administrator] -> role in [:moderator, :administrator] ->
@ -355,4 +369,67 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
{:ok, %{id: event.id}} {:ok, %{id: event.id}}
end end
end end
defp is_organizer_group_member?(%{
attributed_to_id: attributed_to_id,
organizer_actor_id: organizer_actor_id
})
when not is_nil(attributed_to_id) do
Actors.is_member?(organizer_actor_id, attributed_to_id) &&
Permission.can_create_group_object?(organizer_actor_id, attributed_to_id, %Event{})
end
defp is_organizer_group_member?(_), do: true
defp verify_profile_change(
args,
%Event{attributed_to: %Actor{}},
%User{} = _user,
%Actor{} = current_profile
) do
# The organizer_actor has to be the current profile, because otherwise we're left with a possible remote organizer
args = Map.put(args, :organizer_actor, current_profile)
{:ok, args}
end
defp verify_profile_change(
args,
%Event{organizer_actor: %Actor{id: organizer_actor_id}},
%User{} = user,
%Actor{} = _actor
) do
with {:old_actor, {:is_owned, %Actor{}}} <-
{:old_actor, User.owns_actor(user, organizer_actor_id)},
new_organizer_actor_id <- args |> Map.get(:organizer_actor_id, organizer_actor_id),
{:new_actor, {:is_owned, %Actor{} = organizer_actor}} <-
{:new_actor, User.owns_actor(user, new_organizer_actor_id)},
args <- Map.put(args, :organizer_actor, organizer_actor) do
{:ok, args}
end
end
defp can_event_be_updated_by?(
%Event{attributed_to: %Actor{type: :Group}} = event,
%Actor{} = actor_member
) do
Permission.can_update_group_object?(actor_member, event)
end
defp can_event_be_updated_by?(
%Event{} = event,
%Actor{id: actor_member_id}
) do
Event.can_be_managed_by?(event, actor_member_id)
end
defp can_event_be_deleted_by?(
%Event{attributed_to: %Actor{type: :Group}} = event,
%Actor{} = actor_member
) do
Permission.can_delete_group_object?(actor_member, event)
end
defp can_event_be_deleted_by?(%Event{} = event, %Actor{id: actor_member_id}) do
Event.can_be_managed_by?(event, actor_member_id)
end
end end

View file

@ -153,6 +153,7 @@ defmodule Mobilizon.Events do
def get_event_by_url!(url) do def get_event_by_url!(url) do
url url
|> event_by_url_query() |> event_by_url_query()
|> preload_for_event()
|> Repo.one!() |> Repo.one!()
end end

View file

@ -5,8 +5,11 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Events alias Mobilizon.Actors.Actor
alias Mobilizon.{Events, Users}
alias Mobilizon.Events.Event
alias Mobilizon.Service.Workers alias Mobilizon.Service.Workers
alias Mobilizon.Users.User
alias Mobilizon.GraphQL.AbsintheHelpers alias Mobilizon.GraphQL.AbsintheHelpers
@ -21,14 +24,6 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
category: "meeting" category: "meeting"
} }
setup %{conn: conn} do
user = insert(:user)
actor = insert(:actor, user: user, preferred_username: "test")
{:ok, conn: conn, actor: actor, user: user}
end
describe "Event Resolver" do
@find_event_query """ @find_event_query """
query Event($uuid: UUID!) { query Event($uuid: UUID!) {
event(uuid: $uuid) { event(uuid: $uuid) {
@ -38,6 +33,14 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
} }
""" """
setup %{conn: conn} do
user = insert(:user)
actor = insert(:actor, user: user, preferred_username: "test")
{:ok, conn: conn, actor: actor, user: user}
end
describe "Find an event" do
test "find_event/3 returns an event", context do test "find_event/3 returns an event", context do
event = event =
@event @event
@ -66,7 +69,9 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
assert [%{"message" => "Event not found"}] = res["errors"] assert [%{"message" => "Event not found"}] = res["errors"]
end end
end
describe "create_event/3 for a regular profile" do
@create_event_mutation """ @create_event_mutation """
mutation CreateEvent( mutation CreateEvent(
$title: String!, $title: String!,
@ -76,6 +81,7 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
$status: EventStatus, $status: EventStatus,
$visibility: EventVisibility, $visibility: EventVisibility,
$organizer_actor_id: ID!, $organizer_actor_id: ID!,
$attributed_to_id: ID,
$online_address: String, $online_address: String,
$options: EventOptionsInput, $options: EventOptionsInput,
$draft: Boolean $draft: Boolean
@ -88,6 +94,7 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
status: $status, status: $status,
visibility: $visibility, visibility: $visibility,
organizer_actor_id: $organizer_actor_id, organizer_actor_id: $organizer_actor_id,
attributed_to_id: $attributed_to_id,
online_address: $online_address, online_address: $online_address,
options: $options, options: $options,
draft: $draft draft: $draft
@ -629,30 +636,171 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
assert json_response(res, 200)["data"]["createEvent"]["picture"]["url"] assert json_response(res, 200)["data"]["createEvent"]["picture"]["url"]
end end
end
test "update_event/3 should check the event exists", %{conn: conn, actor: _actor, user: user} do describe "create_event/3 on behalf of a group" do
mutation = """ @variables %{
mutation { title: "come to my event",
updateEvent( description: "it will be fine",
event_id: 45, begins_on: "2021-07-26T09:00:00Z"
title: "my event updated" }
test "create_event/3 should check the member has permission to create a group event", %{
conn: conn
} do
%User{} = user = insert(:user)
%Actor{id: group_id} = group = insert(:group)
%Actor{id: member_not_approved_actor_id} =
member_not_approved_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: member_not_approved_actor)
%Actor{id: member_actor_id} = member_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: member_actor, role: :member)
%Actor{id: moderator_actor_id} = moderator_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: moderator_actor, role: :moderator)
%Actor{id: not_member_actor_id} = insert(:actor, user: user)
variables = Map.put(@variables, :attributed_to_id, "#{group_id}")
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{member_not_approved_actor_id}")
)
assert res["data"]["createEvent"] == nil
assert hd(res["errors"])["message"] ==
"Organizer profile doesn't have permission to create an event on behalf of this group"
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{not_member_actor_id}")
)
assert res["data"]["createEvent"] == nil
assert hd(res["errors"])["message"] ==
"Organizer profile doesn't have permission to create an event on behalf of this group"
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{member_actor_id}")
)
assert res["data"]["createEvent"] == nil
assert hd(res["errors"])["message"] ==
"Organizer profile doesn't have permission to create an event on behalf of this group"
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{moderator_actor_id}")
)
assert res["errors"] == nil
assert res["data"]["createEvent"] != nil
end
end
@update_event_mutation """
mutation updateEvent(
$eventId: ID!
$title: String
$description: String
$beginsOn: DateTime
$endsOn: DateTime
$status: EventStatus
$visibility: EventVisibility
$joinOptions: EventJoinOptions
$draft: Boolean
$tags: [String]
$picture: MediaInput
$onlineAddress: String
$phoneAddress: String
$organizerActorId: ID
$attributedToId: ID
$category: String
$physicalAddress: AddressInput
$options: EventOptionsInput
$contacts: [Contact]
) { ) {
title, updateEvent(
eventId: $eventId
title: $title
description: $description
beginsOn: $beginsOn
endsOn: $endsOn
status: $status
visibility: $visibility
joinOptions: $joinOptions
draft: $draft
tags: $tags
picture: $picture
onlineAddress: $onlineAddress
phoneAddress: $phoneAddress
organizerActorId: $organizerActorId
attributedToId: $attributedToId
category: $category
physicalAddress: $physicalAddress
options: $options
contacts: $contacts
) {
id,
uuid, uuid,
url,
title
draft
description
beginsOn
endsOn
status
tags { tags {
title, title,
slug slug
},
online_address,
phone_address,
category,
options {
maximumAttendeeCapacity,
showRemainingAttendeeCapacity
},
physicalAddress {
url,
geom,
street
}
picture {
name
} }
} }
} }
""" """
describe "update_event/3" do
test "update_event/3 should check the event exists", %{conn: conn, actor: _actor, user: user} do
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{eventId: 45, title: "my event updated"}
)
assert hd(json_response(res, 200)["errors"])["message"] == "Event not found" assert hd(res["errors"])["message"] == "Event not found"
end end
test "update_event/3 should check the user can change the organizer", %{ test "update_event/3 should check the user can change the organizer", %{
@ -663,29 +811,15 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
event = insert(:event, organizer_actor: actor) event = insert(:event, organizer_actor: actor)
actor2 = insert(:actor) actor2 = insert(:actor)
mutation = """
mutation {
updateEvent(
title: "my event updated",
event_id: #{event.id}
organizer_actor_id: #{actor2.id}
) {
title,
uuid,
tags {
title,
slug
}
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{eventId: event.id, title: "my event updated", organizerActorId: actor2.id}
)
assert hd(json_response(res, 200)["errors"])["message"] == assert hd(res["errors"])["message"] ==
"You can't attribute this event to this profile." "You can't attribute this event to this profile."
end end
@ -696,28 +830,15 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
} do } do
event = insert(:event) event = insert(:event)
mutation = """
mutation {
updateEvent(
title: "my event updated",
event_id: #{event.id}
) {
title,
uuid,
tags {
title,
slug
}
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{eventId: event.id, title: "my event updated"}
)
assert hd(json_response(res, 200)["errors"])["message"] == "You can't edit this event." assert hd(res["errors"])["message"] == "You can't edit this event."
end end
test "update_event/3 should check the user is the organizer also when it's changed", %{ test "update_event/3 should check the user is the organizer also when it's changed", %{
@ -727,29 +848,15 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
} do } do
event = insert(:event) event = insert(:event)
mutation = """
mutation {
updateEvent(
title: "my event updated",
event_id: #{event.id},
organizer_actor_id: #{actor.id}
) {
title,
uuid,
tags {
title,
slug
}
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{eventId: event.id, title: "my event updated", organizerActorId: actor.id}
)
assert hd(json_response(res, 200)["errors"])["message"] == "You can't edit this event." assert hd(res["errors"])["message"] == "You can't edit this event."
end end
test "update_event/3 should check end time is after the beginning time", %{ test "update_event/3 should check end time is after the beginning time", %{
@ -759,29 +866,19 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
} do } do
event = insert(:event, organizer_actor: actor) event = insert(:event, organizer_actor: actor)
mutation = """
mutation {
updateEvent(
title: "my event updated",
ends_on: "#{Timex.shift(event.begins_on, hours: -2)}",
event_id: #{event.id}
) {
title,
uuid,
tags {
title,
slug
}
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{
eventId: event.id,
title: "my event updated",
endsOn: event.begins_on |> DateTime.add(3600 * -2) |> DateTime.to_iso8601()
}
)
assert hd(json_response(res, 200)["errors"])["message"] == assert hd(res["errors"])["message"] ==
["ends_on cannot be set before begins_on"] ["ends_on cannot be set before begins_on"]
end end
@ -799,69 +896,41 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
begins_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601() begins_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()
ends_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601() ends_on = DateTime.utc_now() |> DateTime.truncate(:second) |> DateTime.to_iso8601()
mutation = """
mutation {
updateEvent(
event_id: #{event.id},
title: "my event updated",
description: "description updated",
begins_on: "#{begins_on}",
ends_on: "#{ends_on}",
status: TENTATIVE,
tags: ["tag1_updated", "tag2_updated"],
online_address: "toto@example.com",
phone_address: "0000000000",
category: "birthday",
options: {
maximumAttendeeCapacity: 30,
showRemainingAttendeeCapacity: true
},
physical_address: {
street: "#{address.street}",
locality: "#{address.locality}"
}
) {
id,
uuid,
url,
title,
description,
begins_on,
ends_on,
status,
tags {
title,
slug
},
online_address,
phone_address,
category,
options {
maximumAttendeeCapacity,
showRemainingAttendeeCapacity
},
physicalAddress {
url,
geom,
street
}
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{
eventId: event.id,
title: "my event updated",
description: "description updated",
beginsOn: "#{begins_on}",
endsOn: "#{ends_on}",
status: "TENTATIVE",
tags: ["tag1_updated", "tag2_updated"],
onlineAddress: "toto@example.com",
phoneAddress: "0000000000",
category: "birthday",
options: %{
maximumAttendeeCapacity: 30,
showRemainingAttendeeCapacity: true
},
physicalAddress: %{
street: "#{address.street}",
locality: "#{address.locality}"
}
}
)
assert json_response(res, 200)["errors"] == nil assert res["errors"] == nil
event_res = json_response(res, 200)["data"]["updateEvent"] event_res = res["data"]["updateEvent"]
assert event_res["title"] == "my event updated" assert event_res["title"] == "my event updated"
assert event_res["description"] == "description updated" assert event_res["description"] == "description updated"
assert event_res["begins_on"] == "#{begins_on}" assert event_res["beginsOn"] == "#{begins_on}"
assert event_res["ends_on"] == "#{ends_on}" assert event_res["endsOn"] == "#{ends_on}"
assert event_res["status"] == "TENTATIVE" assert event_res["status"] == "TENTATIVE"
assert event_res["online_address"] == "toto@example.com" assert event_res["online_address"] == "toto@example.com"
assert event_res["phone_address"] == "0000000000" assert event_res["phone_address"] == "0000000000"
@ -920,212 +989,166 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
begins_on = begins_on =
event.begins_on event.begins_on
|> Timex.shift(hours: 3) |> DateTime.add(3 * 3600)
|> DateTime.truncate(:second) |> DateTime.truncate(:second)
|> DateTime.to_iso8601() |> DateTime.to_iso8601()
mutation = """
mutation {
updateEvent(
title: "my event updated",
description: "description updated",
begins_on: "#{begins_on}",
event_id: #{event.id},
category: "birthday",
picture: {
media: {
name: "picture for my event",
alt: "A very sunny landscape",
file: "event.jpg",
actor_id: "#{actor.id}"
}
}
) {
title,
uuid,
url,
beginsOn,
picture {
name,
url
}
}
}
"""
map = %{
"query" => mutation,
"event.jpg" => %Plug.Upload{
path: "test/fixtures/picture.png",
filename: "event.jpg"
}
}
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> put_req_header("content-type", "multipart/form-data") |> put_req_header("content-type", "multipart/form-data")
|> post("/api", map) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: %{
eventId: event.id,
title: "my event updated",
description: "description updated",
beginsOn: "#{begins_on}",
category: "birthday",
picture: %{
media: %{
name: "picture for my event",
alt: "A very sunny landscape",
file: "event.jpg",
actorId: "#{actor.id}"
}
}
},
uploads: %{
"event.jpg" => %Plug.Upload{
path: "test/fixtures/picture.png",
filename: "event.jpg"
}
}
)
assert json_response(res, 200)["errors"] == nil assert res["errors"] == nil
assert json_response(res, 200)["data"]["updateEvent"]["title"] == "my event updated" assert res["data"]["updateEvent"]["title"] == "my event updated"
assert json_response(res, 200)["data"]["updateEvent"]["uuid"] == event.uuid assert res["data"]["updateEvent"]["uuid"] == event.uuid
assert json_response(res, 200)["data"]["updateEvent"]["url"] == event.url assert res["data"]["updateEvent"]["url"] == event.url
assert json_response(res, 200)["data"]["updateEvent"]["beginsOn"] == assert res["data"]["updateEvent"]["beginsOn"] ==
DateTime.to_iso8601(event.begins_on |> Timex.shift(hours: 3)) event.begins_on |> DateTime.add(3 * 3600) |> DateTime.to_iso8601()
assert json_response(res, 200)["data"]["updateEvent"]["picture"]["name"] == assert res["data"]["updateEvent"]["picture"]["name"] ==
"picture for my event" "picture for my event"
end end
test "update_event/3 respects the draft status", %{conn: conn, actor: actor, user: user} do @person_participations_query """
query EventPersonParticipation($actorId: ID!, $eventId: ID!) {
person(id: $actorId) {
id
participations(eventId: $eventId) {
total
elements {
role
actor {
id
}
event {
id
}
}
}
}
}
"""
test "respects the draft status", %{conn: conn, actor: actor, user: user} do
event = insert(:event, organizer_actor: actor, draft: true) event = insert(:event, organizer_actor: actor, draft: true)
mutation = """ res =
mutation { conn
updateEvent( |> auth_conn(user)
event_id: #{event.id}, |> AbsintheHelpers.graphql_query(
title: "my event updated but still draft" query: @update_event_mutation,
) { variables: %{
draft, eventId: event.id,
title, title: "my event updated but still draft",
uuid draft: true
} }
)
assert res["data"]["updateEvent"]["draft"] == true
res =
conn
|> AbsintheHelpers.graphql_query(
query: @find_event_query,
variables: %{
uuid: event.uuid
} }
""" )
assert hd(res["errors"])["message"] =~ "not found"
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @find_event_query,
assert json_response(res, 200)["data"]["updateEvent"]["draft"] == true variables: %{
uuid: event.uuid
query = """
{
event(uuid: "#{event.uuid}") {
uuid,
draft
} }
} )
"""
res = assert res["errors"] == nil
conn assert res["data"]["event"]["draft"] == true
|> get("/api", AbsintheHelpers.query_skeleton(query, "event"))
assert hd(json_response(res, 200)["errors"])["message"] =~ "not found"
query = """
{
event(uuid: "#{event.uuid}") {
uuid,
draft
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> get("/api", AbsintheHelpers.query_skeleton(query, "event")) |> AbsintheHelpers.graphql_query(
query: @person_participations_query,
variables: %{
eventId: event.id,
actorId: actor.id
}
)
assert json_response(res, 200)["errors"] == nil assert res["errors"] == nil
assert json_response(res, 200)["data"]["event"]["draft"] == true assert res["data"]["person"]["participations"]["elements"] == []
query = """
{
person(id: "#{actor.id}") {
id,
participations(eventId: #{event.id}) {
elements {
id,
role,
actor {
id
},
event {
id
}
}
}
}
}
"""
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> get("/api", AbsintheHelpers.query_skeleton(query, "person")) |> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
assert json_response(res, 200)["errors"] == nil variables: %{
assert json_response(res, 200)["data"]["person"]["participations"]["elements"] == [] eventId: event.id,
mutation = """
mutation {
updateEvent(
event_id: #{event.id},
title: "my event updated and no longer draft", title: "my event updated and no longer draft",
draft: false draft: false
) {
draft,
title,
uuid
} }
)
assert res["data"]["updateEvent"]["draft"] == false
res =
conn
|> AbsintheHelpers.graphql_query(
query: @find_event_query,
variables: %{
uuid: event.uuid
} }
""" )
assert res["errors"] == nil
assert res["data"]["event"]["draft"] == false
res = res =
conn conn
|> auth_conn(user) |> auth_conn(user)
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) |> AbsintheHelpers.graphql_query(
query: @person_participations_query,
assert json_response(res, 200)["data"]["updateEvent"]["draft"] == false variables: %{
eventId: event.id,
query = """ actorId: actor.id
{
event(uuid: "#{event.uuid}") {
uuid,
draft
} }
} )
"""
res = assert res["errors"] == nil
conn
|> get("/api", AbsintheHelpers.query_skeleton(query, "event"))
assert json_response(res, 200)["errors"] == nil assert res["data"]["person"]["participations"]["elements"] == [
assert json_response(res, 200)["data"]["event"]["draft"] == false
query = """
{
person(id: "#{actor.id}") {
id,
participations(eventId: #{event.id}) {
elements {
role,
actor {
id
},
event {
id
}
}
}
}
}
"""
res =
conn
|> auth_conn(user)
|> get("/api", AbsintheHelpers.query_skeleton(query, "person"))
assert json_response(res, 200)["errors"] == nil
assert json_response(res, 200)["data"]["person"]["participations"]["elements"] == [
%{ %{
"actor" => %{"id" => to_string(actor.id)}, "actor" => %{"id" => to_string(actor.id)},
"event" => %{"id" => to_string(event.id)}, "event" => %{"id" => to_string(event.id)},
@ -1133,7 +1156,98 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
} }
] ]
end end
end
describe "update_event/3 on behalf of a group" do
test "should check the member has permission to update a group event", %{
conn: conn
} do
%User{} = user = insert(:user)
%Actor{id: group_id} = group = insert(:group)
%Actor{id: member_not_approved_actor_id} =
member_not_approved_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: member_not_approved_actor)
%Actor{id: member_actor_id} = member_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: member_actor, role: :member)
%Actor{id: moderator_actor_id} = moderator_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: moderator_actor, role: :moderator)
%Actor{} = administrator_actor = insert(:actor, user: user)
insert(:member, parent: group, actor: administrator_actor, role: :administrator)
%Actor{id: not_member_actor_id} = insert(:actor, user: user)
%Event{} =
event = insert(:event, attributed_to: group, organizer_actor: administrator_actor)
variables =
@variables
|> Map.put(:attributed_to_id, "#{group_id}")
|> Map.put(:eventId, to_string(event.id))
Users.update_user_default_actor(user.id, member_not_approved_actor_id)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{member_not_approved_actor_id}")
)
assert res["data"]["updateEvent"] == nil
assert hd(res["errors"])["message"] ==
"This profile doesn't have permission to update an event on behalf of this group"
Users.update_user_default_actor(user.id, not_member_actor_id)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{not_member_actor_id}")
)
assert res["data"]["updateEvent"] == nil
assert hd(res["errors"])["message"] ==
"This profile doesn't have permission to update an event on behalf of this group"
Users.update_user_default_actor(user.id, member_actor_id)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{member_actor_id}")
)
assert res["data"]["updateEvent"] == nil
assert hd(res["errors"])["message"] ==
"This profile doesn't have permission to update an event on behalf of this group"
Users.update_user_default_actor(user.id, moderator_actor_id)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_event_mutation,
variables: Map.put(variables, :organizer_actor_id, "#{moderator_actor_id}")
)
assert res["errors"] == nil
assert res["data"]["updateEvent"] != nil
end
end
describe "list_events/3" do
@fetch_events_query """ @fetch_events_query """
query Events($page: Int, $limit: Int) { query Events($page: Int, $limit: Int) {
events(page: $page, limit: $limit) { events(page: $page, limit: $limit) {
@ -1250,7 +1364,9 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
# assert json_response(res, 200)["errors"] |> hd |> Map.get("message") == # assert json_response(res, 200)["errors"] |> hd |> Map.get("message") ==
# "Event with UUID #{event.uuid} not found" # "Event with UUID #{event.uuid} not found"
# end # end
end
describe "delete_event/3" do
test "delete_event/3 deletes an event", %{conn: conn, user: user, actor: actor} do test "delete_event/3 deletes an event", %{conn: conn, user: user, actor: actor} do
event = insert(:event, organizer_actor: actor) event = insert(:event, organizer_actor: actor)
@ -1393,7 +1509,9 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
"object" => %{"title" => event.title, "id" => to_string(event.id)} "object" => %{"title" => event.title, "id" => to_string(event.id)}
} }
end end
end
describe "list_related_events/3" do
test "list_related_events/3 should give related events", %{ test "list_related_events/3 should give related events", %{
conn: conn, conn: conn,
actor: actor actor: actor