Introduce group basic federation, event new page and notifications
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -3,7 +3,7 @@ defmodule Mobilizon.GraphQL.API.Comments do
|
||||
API for Comments.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Events.Comment
|
||||
alias Mobilizon.Conversations.Comment
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Activity
|
||||
@@ -18,6 +18,10 @@ defmodule Mobilizon.GraphQL.API.Comments do
|
||||
ActivityPub.create(:comment, args, true)
|
||||
end
|
||||
|
||||
def update_comment(%Comment{} = comment, args) do
|
||||
ActivityPub.update(:comment, comment, args, true)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a comment
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Admin.{ActionLog, Setting}
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Events.{Comment, Event}
|
||||
alias Mobilizon.Events.{Comment, Event}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Federation.ActivityPub.Relay
|
||||
alias Mobilizon.Reports.{Note, Report}
|
||||
alias Mobilizon.Service.Statistics
|
||||
|
||||
@@ -3,10 +3,10 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
|
||||
Handles the comment-related GraphQL calls.
|
||||
"""
|
||||
|
||||
alias Mobilizon.{Actors, Admin, Events}
|
||||
alias Mobilizon.{Actors, Admin, Conversations}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Comment, as: CommentModel
|
||||
alias Mobilizon.Conversations.Comment, as: CommentModel
|
||||
alias Mobilizon.Users
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias Mobilizon.GraphQL.API.Comments
|
||||
@@ -14,13 +14,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
|
||||
require Logger
|
||||
|
||||
def get_thread(_parent, %{id: thread_id}, _context) do
|
||||
{:ok, Events.get_thread_replies(thread_id)}
|
||||
{:ok, Conversations.get_thread_replies(thread_id)}
|
||||
end
|
||||
|
||||
def create_comment(
|
||||
_parent,
|
||||
%{actor_id: actor_id} = args,
|
||||
%{context: %{current_user: %User{} = user}}
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:is_owned, %Actor{} = _organizer_actor} <- User.owns_actor(user, actor_id),
|
||||
{:ok, _, %CommentModel{} = comment} <-
|
||||
@@ -36,14 +40,40 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
|
||||
{:error, "You are not allowed to create a comment if not connected"}
|
||||
end
|
||||
|
||||
def update_comment(
|
||||
_parent,
|
||||
%{text: text, comment_id: comment_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
%CommentModel{actor_id: comment_actor_id} = comment <-
|
||||
Mobilizon.Conversations.get_comment(comment_id),
|
||||
true <- actor_id === comment_actor_id,
|
||||
{:ok, _, %CommentModel{} = comment} <- Comments.update_comment(comment, %{text: text}) do
|
||||
{:ok, comment}
|
||||
end
|
||||
end
|
||||
|
||||
def edit_comment(_parent, _args, _context) do
|
||||
{:error, "You are not allowed to update a comment if not connected"}
|
||||
end
|
||||
|
||||
def delete_comment(
|
||||
_parent,
|
||||
%{actor_id: actor_id, comment_id: comment_id},
|
||||
%{context: %{current_user: %User{role: role} = user}}
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{role: role} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{:is_owned, %Actor{} = _organizer_actor} <- User.owns_actor(user, actor_id),
|
||||
%CommentModel{} = comment <- Events.get_comment_with_preload(comment_id) do
|
||||
%CommentModel{} = comment <- Conversations.get_comment_with_preload(comment_id) do
|
||||
cond do
|
||||
{:comment_can_be_managed, true} == CommentModel.can_be_managed_by(comment, actor_id) ->
|
||||
do_delete_comment(comment)
|
||||
|
||||
@@ -100,7 +100,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Config do
|
||||
endpoint: Config.instance_maps_tiles_endpoint(),
|
||||
attribution: Config.instance_maps_tiles_attribution()
|
||||
}
|
||||
}
|
||||
},
|
||||
resource_providers: Config.instance_resource_providers(),
|
||||
timezones: Tzdata.zone_list()
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
110
lib/graphql/resolvers/conversation.ex
Normal file
110
lib/graphql/resolvers/conversation.ex
Normal file
@@ -0,0 +1,110 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
||||
@moduledoc """
|
||||
Handles the group-related GraphQL calls.
|
||||
"""
|
||||
|
||||
alias Mobilizon.{Actors, Conversations, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations.Conversation, as: ConversationModel
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
def find_conversations_for_actor(
|
||||
%Actor{id: group_id},
|
||||
_args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:ok, Conversations.find_conversations_for_actor(group_id)}
|
||||
else
|
||||
{:member, false} ->
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
end
|
||||
end
|
||||
|
||||
def find_conversations_for_actor(%Actor{}, _args, _resolution) do
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
end
|
||||
|
||||
def get_conversation(_parent, %{id: id}, _resolution) do
|
||||
{:ok, Conversations.get_conversation(id)}
|
||||
end
|
||||
|
||||
def get_comments_for_conversation(
|
||||
%ConversationModel{id: conversation_id},
|
||||
%{page: page, limit: limit},
|
||||
_resolution
|
||||
) do
|
||||
{:ok, Conversations.get_comments_for_conversation(conversation_id, page, limit)}
|
||||
end
|
||||
|
||||
def create_conversation(
|
||||
_parent,
|
||||
%{title: title, text: text, actor_id: actor_id, creator_id: creator_id},
|
||||
_resolution
|
||||
) do
|
||||
with {:ok, %ConversationModel{} = conversation} <-
|
||||
Conversations.create_conversation(%{
|
||||
title: title,
|
||||
text: text,
|
||||
actor_id: actor_id,
|
||||
creator_id: creator_id
|
||||
}) do
|
||||
{:ok, conversation}
|
||||
end
|
||||
end
|
||||
|
||||
def reply_to_conversation(
|
||||
_parent,
|
||||
%{text: text, conversation_id: conversation_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:no_conversation, %ConversationModel{} = conversation} <-
|
||||
{:no_conversation, Conversations.get_conversation(conversation_id)},
|
||||
{:ok, %ConversationModel{} = conversation} <-
|
||||
Conversations.reply_to_conversation(
|
||||
conversation,
|
||||
%{
|
||||
text: text,
|
||||
actor_id: actor_id
|
||||
}
|
||||
) do
|
||||
{:ok, conversation}
|
||||
end
|
||||
end
|
||||
|
||||
@spec update_conversation(map(), map(), map()) :: {:ok, ConversationModel.t()}
|
||||
def update_conversation(
|
||||
_parent,
|
||||
%{title: title, conversation_id: conversation_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:no_conversation, %ConversationModel{creator_id: creator_id} = conversation} <-
|
||||
{:no_conversation, Conversations.get_conversation(conversation_id)},
|
||||
{:check_access, true} <- {:check_access, actor_id == creator_id},
|
||||
{:ok, %ConversationModel{} = conversation} <-
|
||||
Conversations.update_conversation(
|
||||
conversation,
|
||||
%{
|
||||
title: title
|
||||
}
|
||||
) do
|
||||
{:ok, conversation}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,23 +3,50 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
Handles the group-related GraphQL calls.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.{Actors, Events, Users}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.GraphQL.API
|
||||
alias Mobilizon.GraphQL.Resolvers.Person
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
require Logger
|
||||
|
||||
@doc """
|
||||
Find a group
|
||||
"""
|
||||
def find_group(
|
||||
parent,
|
||||
%{preferred_username: name} = args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:ok, %Actor{id: group_id} = group} <-
|
||||
ActivityPub.find_or_make_group_from_nickname(name),
|
||||
{:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
group <- Person.proxify_pictures(group) do
|
||||
{:ok, group}
|
||||
else
|
||||
{:member, false} ->
|
||||
find_group(parent, args, nil)
|
||||
|
||||
_ ->
|
||||
{:error, "Group with name #{name} not found"}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Find a group
|
||||
"""
|
||||
def find_group(_parent, %{preferred_username: name}, _resolution) do
|
||||
with {:ok, actor} <- ActivityPub.find_or_make_group_from_nickname(name),
|
||||
actor <- Person.proxify_pictures(actor) do
|
||||
%Actor{} = actor <- Person.proxify_pictures(actor),
|
||||
%Actor{} = actor <- restrict_fields_for_non_member_request(actor) do
|
||||
{:ok, actor}
|
||||
else
|
||||
_ ->
|
||||
@@ -31,18 +58,21 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
Lists all groups
|
||||
"""
|
||||
def list_groups(_parent, %{page: page, limit: limit}, _resolution) do
|
||||
{
|
||||
:ok,
|
||||
page
|
||||
|> Actors.list_groups(limit)
|
||||
|> Enum.map(fn actor -> Person.proxify_pictures(actor) end)
|
||||
}
|
||||
{:ok, Actors.list_groups(page, limit)}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Create a new group. The creator is automatically added as admin
|
||||
"""
|
||||
def create_group(_parent, args, %{context: %{current_user: user}}) do
|
||||
def create_group(
|
||||
_parent,
|
||||
args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with creator_actor_id <- Map.get(args, :creator_actor_id),
|
||||
{:is_owned, %Actor{} = creator_actor} <- User.owns_actor(user, creator_actor_id),
|
||||
args <- Map.put(args, :creator_actor, creator_actor),
|
||||
@@ -68,14 +98,18 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
def delete_group(
|
||||
_parent,
|
||||
%{group_id: group_id, actor_id: actor_id},
|
||||
%{context: %{current_user: user}}
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{group_id, ""} <- Integer.parse(group_id),
|
||||
{:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
|
||||
{:is_owned, %Actor{}} <- User.owns_actor(user, actor_id),
|
||||
{:ok, %Member{} = member} <- Actors.get_member(actor_id, group.id),
|
||||
{:is_admin, true} <- Member.is_administrator(member),
|
||||
{:is_admin, true} <- {:is_admin, Member.is_administrator(member)},
|
||||
group <- Actors.delete_group!(group) do
|
||||
{:ok, %{id: group.id}}
|
||||
else
|
||||
@@ -103,7 +137,11 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
def join_group(
|
||||
_parent,
|
||||
%{group_id: group_id, actor_id: actor_id},
|
||||
%{context: %{current_user: user}}
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{group_id, ""} <- Integer.parse(group_id),
|
||||
@@ -146,7 +184,11 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
def leave_group(
|
||||
_parent,
|
||||
%{group_id: group_id, actor_id: actor_id},
|
||||
%{context: %{current_user: user}}
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{group_id, ""} <- Integer.parse(group_id),
|
||||
@@ -156,7 +198,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
{:only_administrator, check_that_member_is_not_last_administrator(group_id, actor_id)},
|
||||
{:ok, _} <-
|
||||
Mobilizon.Actors.delete_member(member) do
|
||||
{:ok, %{parent: %{id: group_id}, actor: %{id: actor_id}}}
|
||||
{
|
||||
:ok,
|
||||
%{
|
||||
parent: %{
|
||||
id: group_id
|
||||
},
|
||||
actor: %{
|
||||
id: actor_id
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
@@ -173,17 +225,65 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
{:error, "You need to be logged-in to leave a group"}
|
||||
end
|
||||
|
||||
def find_events_for_group(
|
||||
%Actor{id: group_id} = group,
|
||||
_args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
# TODO : Handle public / restricted to group members events
|
||||
{:ok, Events.list_organized_events_for_group(group)}
|
||||
else
|
||||
{:member, false} ->
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
end
|
||||
end
|
||||
|
||||
def find_events_for_group(_parent, _args, _resolution) do
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
end
|
||||
|
||||
# We check that the actor asking to leave the group is not it's only administrator
|
||||
# We start by fetching the list of administrator or creators and if there's only one of them
|
||||
# and that it's the actor requesting leaving the group we return true
|
||||
@spec check_that_member_is_not_last_administrator(integer, integer) :: boolean
|
||||
defp check_that_member_is_not_last_administrator(group_id, actor_id) do
|
||||
case Actors.list_administrator_members_for_group(group_id) do
|
||||
[%Member{actor: %Actor{id: member_actor_id}}] ->
|
||||
%Page{total: total} when total > 1 ->
|
||||
true
|
||||
|
||||
%Page{
|
||||
total: 1,
|
||||
elements: [
|
||||
%Member{
|
||||
actor: %Actor{
|
||||
id: member_actor_id
|
||||
}
|
||||
}
|
||||
]
|
||||
} ->
|
||||
actor_id == member_actor_id
|
||||
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp restrict_fields_for_non_member_request(%Actor{} = group) do
|
||||
Map.merge(
|
||||
group,
|
||||
%{
|
||||
followers: [],
|
||||
followings: [],
|
||||
organized_events: [],
|
||||
comments: [],
|
||||
feed_tokens: []
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,14 +3,92 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
Handles the member-related GraphQL calls
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor}
|
||||
alias Mobilizon.{Actors, Users}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@doc """
|
||||
Find members for group
|
||||
Find members for group.
|
||||
|
||||
If actor requesting is not part of the group, we only return the number of members, not members
|
||||
"""
|
||||
def find_members_for_group(%Actor{} = actor, _args, _resolution) do
|
||||
members = Actors.list_members_for_group(actor)
|
||||
{:ok, members}
|
||||
def find_members_for_group(
|
||||
%Actor{id: group_id} = group,
|
||||
_args,
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
%Page{} = page <- Actors.list_members_for_group(group) do
|
||||
{:ok, page}
|
||||
else
|
||||
{:member, false} ->
|
||||
# Actor is not member of group, fallback to public
|
||||
with %Page{} = page <- Actors.list_members_for_group(group) do
|
||||
{:ok, %Page{page | elements: []}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_members_for_group(%Actor{} = group, _args, _resolution) do
|
||||
with %Page{} = page <- Actors.list_members_for_group(group) do
|
||||
{:ok, %Page{page | elements: []}}
|
||||
end
|
||||
end
|
||||
|
||||
def invite_member(
|
||||
_parent,
|
||||
%{group_id: group_id, target_actor_username: target_actor_username},
|
||||
%{context: %{current_user: %User{} = user}}
|
||||
) do
|
||||
with %Actor{id: actor_id} = actor <- Users.get_actor_for_user(user),
|
||||
{:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
|
||||
{:has_rights_to_invite, {:ok, %Member{role: role}}}
|
||||
when role in [:moderator, :administrator, :creator] <-
|
||||
{:has_rights_to_invite, Actors.get_member(actor_id, group_id)},
|
||||
{:target_actor_username, {:ok, %Actor{id: target_actor_id} = target_actor}} <-
|
||||
{:target_actor_username,
|
||||
ActivityPub.find_or_make_actor_from_nickname(target_actor_username)},
|
||||
{:error, :member_not_found} <- Actors.get_member(target_actor_id, group.id),
|
||||
{:ok, _activity, %Member{} = member} <- ActivityPub.invite(group, actor, target_actor) do
|
||||
{:ok, member}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
|
||||
{:error, :group_not_found} ->
|
||||
{:error, "Group id not found"}
|
||||
|
||||
{:target_actor_username, _} ->
|
||||
{:error, "Actor invited doesn't exist"}
|
||||
|
||||
{:has_rights_to_invite, {:error, :member_not_found}} ->
|
||||
{:error, "You are not a member of this group"}
|
||||
|
||||
{:has_rights_to_invite, _} ->
|
||||
{:error, "You cannot invite to this group"}
|
||||
|
||||
{:ok, %Member{}} ->
|
||||
{:error, "Actor is already a member of this group"}
|
||||
end
|
||||
end
|
||||
|
||||
def accept_invitation(_parent, %{id: member_id}, %{context: %{current_user: %User{} = user}}) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
%Member{actor: %Actor{id: member_actor_id}} = member <- Actors.get_member(member_id),
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id === actor_id},
|
||||
{:ok, _activity, %Member{} = member} <-
|
||||
ActivityPub.accept(
|
||||
:invite,
|
||||
member,
|
||||
true
|
||||
) do
|
||||
# Launch an async task to refresh the group profile, fetch resources, discussions, members
|
||||
{:ok, member}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -105,7 +105,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Participant do
|
||||
|
||||
@spec do_actor_join_event(Actor.t(), integer | String.t(), map()) ::
|
||||
{:ok, Participant.t()} | {:error, String.t()}
|
||||
defp do_actor_join_event(actor, event_id, args \\ %{}) do
|
||||
defp do_actor_join_event(actor, event_id, args) do
|
||||
with {:has_event, {:ok, %Event{} = event}} <-
|
||||
{:has_event, Events.get_event_with_preload(event_id)},
|
||||
{:ok, _activity, participant} <- Participations.join(event, actor, args),
|
||||
|
||||
@@ -224,6 +224,19 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of events this person is going to
|
||||
"""
|
||||
def person_memberships(%Actor{id: actor_id}, _args, %{context: %{current_user: user}}) do
|
||||
with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
participations <- Actors.list_members_for_actor(actor) do
|
||||
{:ok, participations}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
end
|
||||
end
|
||||
|
||||
def proxify_pictures(%Actor{} = actor) do
|
||||
actor
|
||||
|> proxify_avatar
|
||||
|
||||
230
lib/graphql/resolvers/resource.ex
Normal file
230
lib/graphql/resolvers/resource.ex
Normal file
@@ -0,0 +1,230 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
||||
@moduledoc """
|
||||
Handles the resources-related GraphQL calls
|
||||
"""
|
||||
|
||||
alias Mobilizon.{Actors, Resources, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Resources.Resource
|
||||
alias Mobilizon.Resources.Resource.Metadata
|
||||
alias Mobilizon.Service.RichMedia.Parser
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
require Logger
|
||||
|
||||
@doc """
|
||||
Find resources for group.
|
||||
|
||||
Returns only if actor requesting is a member of the group
|
||||
"""
|
||||
def find_resources_for_group(
|
||||
%Actor{id: group_id} = group,
|
||||
%{page: page, limit: limit},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
%Page{} = page <- Resources.get_resources_for_group(group, page, limit) do
|
||||
{:ok, page}
|
||||
else
|
||||
{:member, _} ->
|
||||
find_resources_for_group(nil, nil, nil)
|
||||
end
|
||||
end
|
||||
|
||||
def find_resources_for_group(
|
||||
_group,
|
||||
_args,
|
||||
_resolution
|
||||
) do
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
end
|
||||
|
||||
def find_resources_for_parent(
|
||||
%Resource{actor_id: group_id} = parent,
|
||||
_args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
%Page{} = page <- Resources.get_resources_for_folder(parent) do
|
||||
{:ok, page}
|
||||
end
|
||||
end
|
||||
|
||||
def find_resources_for_parent(_parent, _args, _resolution),
|
||||
do: {:ok, %Page{total: 0, elements: []}}
|
||||
|
||||
def get_resource(
|
||||
_parent,
|
||||
%{path: path, username: username},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:current_actor, %Actor{id: actor_id}} <-
|
||||
{:current_actor, Users.get_actor_for_user(user)},
|
||||
{:group, %Actor{id: group_id}} <- {:group, Actors.get_actor_by_name(username, :Group)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:resource, %Resource{} = resource} <-
|
||||
{:resource, Resources.get_resource_by_group_and_path_with_preloads(group_id, path)} do
|
||||
{:ok, resource}
|
||||
else
|
||||
{:member, false} -> {:error, "Actor is not member of group"}
|
||||
{:resource, _} -> {:error, "No such resource"}
|
||||
end
|
||||
end
|
||||
|
||||
def get_resource(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to access resources"}
|
||||
end
|
||||
|
||||
def create_resource(
|
||||
_parent,
|
||||
%{actor_id: group_id} = args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
parent <- get_eventual_parent(args),
|
||||
{:own_check, true} <- {:own_check, check_resource_owned_by_group(parent, group_id)},
|
||||
{:ok, _, %Resource{} = resource} <-
|
||||
ActivityPub.create(
|
||||
:resource,
|
||||
args
|
||||
|> Map.put(:actor_id, group_id)
|
||||
|> Map.put(:creator_id, actor_id),
|
||||
true,
|
||||
%{}
|
||||
) do
|
||||
{:ok, resource}
|
||||
else
|
||||
{:own_check, _} ->
|
||||
{:error, "Parent resource doesn't match this group"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def create_resource(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to create resources"}
|
||||
end
|
||||
|
||||
def update_resource(
|
||||
_parent,
|
||||
%{id: resource_id} = args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:resource, %Resource{actor_id: group_id} = resource} <-
|
||||
{:resource, Resources.get_resource_with_preloads(resource_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, _, %Resource{} = resource} <-
|
||||
ActivityPub.update(:resource, resource, args, true, %{}) do
|
||||
{:ok, resource}
|
||||
else
|
||||
{:resource, _} ->
|
||||
{:error, "Resource doesn't exist"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def update_resource(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to update resources"}
|
||||
end
|
||||
|
||||
def delete_resource(
|
||||
_parent,
|
||||
%{id: resource_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:resource, %Resource{parent_id: _parent_id, actor_id: group_id} = resource} <-
|
||||
{:resource, Resources.get_resource_with_preloads(resource_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, _, %Resource{} = resource} <-
|
||||
ActivityPub.delete(resource) do
|
||||
{:ok, resource}
|
||||
else
|
||||
{:resource, _} ->
|
||||
{:error, "Resource doesn't exist"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def delete_resource(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to delete resources"}
|
||||
end
|
||||
|
||||
def preview_resource_link(
|
||||
_parent,
|
||||
%{resource_url: resource_url},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = _user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:ok, data} when is_map(data) <- Parser.parse(resource_url) do
|
||||
{:ok, struct(Metadata, data)}
|
||||
end
|
||||
end
|
||||
|
||||
def preview_resource_link(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to view a resource preview"}
|
||||
end
|
||||
|
||||
@spec get_eventual_parent(map()) :: Resource.t() | nil
|
||||
defp get_eventual_parent(args) do
|
||||
parent = args |> Map.get(:parent_id) |> get_parent_resource()
|
||||
|
||||
case parent do
|
||||
%Resource{} -> parent
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_parent_resource(integer | nil) :: nil | Resource.t()
|
||||
defp get_parent_resource(nil), do: nil
|
||||
defp get_parent_resource(parent_id), do: Resources.get_resource(parent_id)
|
||||
|
||||
@spec check_resource_owned_by_group(Resource.t() | nil, integer) :: boolean
|
||||
defp check_resource_owned_by_group(nil, _group_id), do: true
|
||||
|
||||
defp check_resource_owned_by_group(%Resource{actor_id: actor_id}, group_id)
|
||||
when is_binary(group_id),
|
||||
do: actor_id == String.to_integer(group_id)
|
||||
|
||||
defp check_resource_owned_by_group(%Resource{actor_id: actor_id}, group_id)
|
||||
when is_number(group_id),
|
||||
do: actor_id == group_id
|
||||
end
|
||||
255
lib/graphql/resolvers/todos.ex
Normal file
255
lib/graphql/resolvers/todos.ex
Normal file
@@ -0,0 +1,255 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
||||
@moduledoc """
|
||||
Handles the todos related GraphQL calls
|
||||
"""
|
||||
|
||||
alias Mobilizon.{Actors, Todos, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Todos.{Todo, TodoList}
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
require Logger
|
||||
|
||||
@doc """
|
||||
Find todo lists for group.
|
||||
|
||||
Returns only if actor requesting is a member of the group
|
||||
"""
|
||||
def find_todo_lists_for_group(
|
||||
%Actor{id: group_id} = group,
|
||||
_args,
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
%Page{} = page <- Todos.get_todo_lists_for_group(group) do
|
||||
{:ok, page}
|
||||
else
|
||||
{:member, _} ->
|
||||
with %Page{} = page <- Todos.get_todo_lists_for_group(group) do
|
||||
{:ok, %Page{page | elements: []}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_todo_lists_for_group(_parent, _args, _resolution) do
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
end
|
||||
|
||||
def find_todos_for_todo_list(
|
||||
%TodoList{actor_id: group_id} = todo_list,
|
||||
_args,
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
%Page{} = page <- Todos.get_todos_for_todo_list(todo_list) do
|
||||
{:ok, page}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def get_todo_list(
|
||||
_parent,
|
||||
%{id: todo_list_id},
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id}} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:todo, %TodoList{actor_id: group_id} = todo} <-
|
||||
{:todo, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:todo, nil} ->
|
||||
{:error, "Todo list doesn't exist"}
|
||||
|
||||
{:actor, nil} ->
|
||||
{:error, "No actor found for user"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def create_todo_list(
|
||||
_parent,
|
||||
%{group_id: group_id} = args,
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, _, %TodoList{} = todo_list} <-
|
||||
ActivityPub.create(:todo_list, Map.put(args, :actor_id, group_id), true, %{}) do
|
||||
{:ok, todo_list}
|
||||
else
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
# def update_todo_list(
|
||||
# _parent,
|
||||
# %{id: todo_list_id, actor_id: actor_id},
|
||||
# %{
|
||||
# context: %{current_user: %User{} = user}
|
||||
# } = _resolution
|
||||
# ) do
|
||||
# with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
# {:todo_list, %TodoList{actor_id: group_id} = todo_list} <-
|
||||
# {:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
# {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
# {:ok, _, %TodoList{} = todo} <-
|
||||
# ActivityPub.update_todo_list(todo_list, actor, true, %{}) do
|
||||
# {:ok, todo}
|
||||
# else
|
||||
# {:todo_list, _} ->
|
||||
# {:error, "TodoList doesn't exist"}
|
||||
|
||||
# {:member, _} ->
|
||||
# {:error, "Actor id is not member of group"}
|
||||
# end
|
||||
# end
|
||||
|
||||
# def delete_todo_list(
|
||||
# _parent,
|
||||
# %{id: todo_list_id, actor_id: actor_id},
|
||||
# %{
|
||||
# context: %{current_user: %User{} = user}
|
||||
# } = _resolution
|
||||
# ) do
|
||||
# with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
# {:todo_list, %TodoList{actor_id: group_id} = todo_list} <-
|
||||
# {:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
# {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
# {:ok, _, %TodoList{} = todo} <-
|
||||
# ActivityPub.delete_todo_list(todo_list, actor, true, %{}) do
|
||||
# {:ok, todo}
|
||||
# else
|
||||
# {:todo_list, _} ->
|
||||
# {:error, "TodoList doesn't exist"}
|
||||
|
||||
# {:member, _} ->
|
||||
# {:error, "Actor id is not member of group"}
|
||||
# end
|
||||
# end
|
||||
|
||||
def get_todo(
|
||||
_parent,
|
||||
%{id: todo_id},
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id}} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:todo, %Todo{todo_list_id: todo_list_id} = todo} <-
|
||||
{:todo, Todos.get_todo(todo_id)},
|
||||
{:todo_list, %TodoList{actor_id: group_id}} <-
|
||||
{:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:todo, nil} ->
|
||||
{:error, "Todo doesn't exist"}
|
||||
|
||||
{:actor, nil} ->
|
||||
{:error, "No actor found for user"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def create_todo(
|
||||
_parent,
|
||||
%{todo_list_id: todo_list_id} = args,
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:todo_list, %TodoList{actor_id: group_id} = _todo_list} <-
|
||||
{:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, _, %Todo{} = todo} <-
|
||||
ActivityPub.create(:todo, Map.put(args, :creator_id, actor_id), true, %{}) do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:todo_list, _} ->
|
||||
{:error, "TodoList doesn't exist"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
def update_todo(
|
||||
_parent,
|
||||
%{id: todo_id} = args,
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:todo, %Todo{todo_list_id: todo_list_id} = todo} <-
|
||||
{:todo, Todos.get_todo(todo_id)},
|
||||
{:todo_list, %TodoList{actor_id: group_id}} <-
|
||||
{:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, _, %Todo{} = todo} <-
|
||||
ActivityPub.update(:todo, todo, args, true, %{}) do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:todo_list, _} ->
|
||||
{:error, "TodoList doesn't exist"}
|
||||
|
||||
{:todo, _} ->
|
||||
{:error, "Todo doesn't exist"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "Actor id is not member of group"}
|
||||
end
|
||||
end
|
||||
|
||||
# def delete_todo(
|
||||
# _parent,
|
||||
# %{id: todo_id, actor_id: actor_id},
|
||||
# %{
|
||||
# context: %{current_user: %User{} = user}
|
||||
# } = _resolution
|
||||
# ) do
|
||||
# with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
# {:todo, %Todo{todo_list_id: todo_list_id} = todo} <-
|
||||
# {:todo, Todos.get_todo(todo_id)},
|
||||
# {:todo_list, %TodoList{actor_id: group_id}} <-
|
||||
# {:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
# {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
# {:ok, _, %Todo{} = todo} <-
|
||||
# ActivityPub.delete_todo(todo, actor, true, %{}) do
|
||||
# {:ok, todo}
|
||||
# else
|
||||
# {:todo_list, _} ->
|
||||
# {:error, "TodoList doesn't exist"}
|
||||
|
||||
# {:todo, _} ->
|
||||
# {:error, "Todo doesn't exist"}
|
||||
|
||||
# {:member, _} ->
|
||||
# {:error, "Actor id is not member of group"}
|
||||
# end
|
||||
# end
|
||||
end
|
||||
@@ -8,8 +8,8 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
alias Mobilizon.{Actors, Config, Events, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Crypto
|
||||
alias Mobilizon.Storage.Repo
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Storage.{Page, Repo}
|
||||
alias Mobilizon.Users.{Setting, User}
|
||||
|
||||
alias Mobilizon.Web.{Auth, Email}
|
||||
|
||||
@@ -245,7 +245,7 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
%{context: %{current_user: %User{id: logged_user_id}}}
|
||||
) do
|
||||
with true <- user_id == logged_user_id,
|
||||
participations <-
|
||||
%Page{} = page <-
|
||||
Events.list_participations_for_user(
|
||||
user_id,
|
||||
Map.get(args, :after_datetime),
|
||||
@@ -253,7 +253,26 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
Map.get(args, :page),
|
||||
Map.get(args, :limit)
|
||||
) do
|
||||
{:ok, participations}
|
||||
{:ok, page}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of groups this user is a member is a member of
|
||||
"""
|
||||
def user_memberships(
|
||||
%User{id: user_id},
|
||||
%{page: page, limit: limit} = _args,
|
||||
%{context: %{current_user: %User{id: logged_user_id}}}
|
||||
) do
|
||||
with true <- user_id == logged_user_id,
|
||||
memberships <-
|
||||
Actors.list_memberships_for_user(
|
||||
user_id,
|
||||
page,
|
||||
limit
|
||||
) do
|
||||
{:ok, memberships}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -379,4 +398,42 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
def delete_account(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to delete your account"}
|
||||
end
|
||||
|
||||
@spec user_settings(User.t(), map(), map()) :: {:ok, list(Setting.t())} | {:error, String.t()}
|
||||
def user_settings(%User{id: user_id} = user, _args, %{
|
||||
context: %{current_user: %User{id: logged_user_id}}
|
||||
}) do
|
||||
with {:same_user, true} <- {:same_user, user_id == logged_user_id},
|
||||
{:setting, settings} <- {:setting, Users.get_setting(user)} do
|
||||
{:ok, settings}
|
||||
else
|
||||
{:same_user, _} ->
|
||||
{:error, "User requested is not logged-in"}
|
||||
end
|
||||
end
|
||||
|
||||
@spec set_user_setting(map(), map(), map()) :: {:ok, Setting.t()} | {:error, any()}
|
||||
def set_user_setting(_parent, attrs, %{
|
||||
context: %{current_user: %User{id: logged_user_id}}
|
||||
}) do
|
||||
attrs = Map.put(attrs, :user_id, logged_user_id)
|
||||
|
||||
res =
|
||||
case Users.get_setting(logged_user_id) do
|
||||
nil ->
|
||||
Users.create_setting(attrs)
|
||||
|
||||
%Setting{} = setting ->
|
||||
Users.update_setting(setting, attrs)
|
||||
end
|
||||
|
||||
case res do
|
||||
{:ok, %Setting{} = setting} ->
|
||||
{:ok, setting}
|
||||
|
||||
{:error, changeset} ->
|
||||
Logger.debug(inspect(changeset))
|
||||
{:error, "Error while saving user setting"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,9 +5,10 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
|
||||
use Absinthe.Schema
|
||||
|
||||
alias Mobilizon.{Actors, Addresses, Events, Media, Reports, Users}
|
||||
alias Mobilizon.{Actors, Addresses, Conversations, Events, Media, Reports, Todos, Users}
|
||||
alias Mobilizon.Actors.{Actor, Follower, Member}
|
||||
alias Mobilizon.Events.{Comment, Event, Participant}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
alias Mobilizon.Storage.Repo
|
||||
|
||||
@@ -22,8 +23,12 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
import_types(Schema.Actors.PersonType)
|
||||
import_types(Schema.Actors.GroupType)
|
||||
import_types(Schema.Actors.ApplicationType)
|
||||
import_types(Schema.CommentType)
|
||||
import_types(Schema.Conversations.CommentType)
|
||||
import_types(Schema.Conversations.ConversationType)
|
||||
import_types(Schema.SearchType)
|
||||
import_types(Schema.ResourceType)
|
||||
import_types(Schema.Todos.TodoListType)
|
||||
import_types(Schema.Todos.TodoType)
|
||||
import_types(Schema.ConfigType)
|
||||
import_types(Schema.ReportType)
|
||||
import_types(Schema.AdminType)
|
||||
@@ -98,10 +103,12 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
Dataloader.new()
|
||||
|> Dataloader.add_source(Actors, default_source)
|
||||
|> Dataloader.add_source(Users, default_source)
|
||||
|> Dataloader.add_source(Events, Events.data())
|
||||
|> Dataloader.add_source(Events, default_source)
|
||||
|> Dataloader.add_source(Conversations, Conversations.data())
|
||||
|> Dataloader.add_source(Addresses, default_source)
|
||||
|> Dataloader.add_source(Media, default_source)
|
||||
|> Dataloader.add_source(Reports, default_source)
|
||||
|> Dataloader.add_source(Todos, default_source)
|
||||
|
||||
Map.put(ctx, :loader, loader)
|
||||
end
|
||||
@@ -126,6 +133,10 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
import_fields(:picture_queries)
|
||||
import_fields(:report_queries)
|
||||
import_fields(:admin_queries)
|
||||
import_fields(:todo_list_queries)
|
||||
import_fields(:todo_queries)
|
||||
import_fields(:conversation_queries)
|
||||
import_fields(:resource_queries)
|
||||
end
|
||||
|
||||
@desc """
|
||||
@@ -143,6 +154,10 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
import_fields(:picture_mutations)
|
||||
import_fields(:report_mutations)
|
||||
import_fields(:admin_mutations)
|
||||
import_fields(:todo_list_mutations)
|
||||
import_fields(:todo_mutations)
|
||||
import_fields(:conversation_mutations)
|
||||
import_fields(:resource_mutations)
|
||||
end
|
||||
|
||||
@desc """
|
||||
|
||||
@@ -5,10 +5,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.GraphQL.Resolvers.{Group, Member}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Conversation, Group, Member, Resource, Todos}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
|
||||
import_types(Schema.Actors.MemberType)
|
||||
@@ -44,10 +41,15 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
field(:followingCount, :integer, description: "Number of actors following this actor")
|
||||
|
||||
# This one should have a privacy setting
|
||||
field(:organized_events, list_of(:event),
|
||||
resolve: dataloader(Events),
|
||||
description: "A list of the events this actor has organized"
|
||||
)
|
||||
field :organized_events, :paginated_event_list do
|
||||
resolve(&Group.find_events_for_group/3)
|
||||
description("A list of the events this actor has organized")
|
||||
end
|
||||
|
||||
field :conversations, :paginated_conversation_list do
|
||||
resolve(&Conversation.find_conversations_for_actor/3)
|
||||
description("A list of the conversations for this group")
|
||||
end
|
||||
|
||||
field(:types, :group_type, description: "The type of group : Group, Community,…")
|
||||
|
||||
@@ -55,10 +57,22 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description: "Whether the group is opened to all or has restricted access"
|
||||
)
|
||||
|
||||
field(:members, non_null(list_of(:member)),
|
||||
resolve: &Member.find_members_for_group/3,
|
||||
description: "List of group members"
|
||||
)
|
||||
field :members, :paginated_member_list do
|
||||
resolve(&Member.find_members_for_group/3)
|
||||
description("List of group members")
|
||||
end
|
||||
|
||||
field :resources, :paginated_resource_list do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
resolve(&Resource.find_resources_for_group/3)
|
||||
description("A paginated list of the resources this group has")
|
||||
end
|
||||
|
||||
field :todo_lists, :paginated_todo_list_list do
|
||||
resolve(&Todos.find_todo_lists_for_group/3)
|
||||
description("A paginated list of the todo lists this group has")
|
||||
end
|
||||
end
|
||||
|
||||
@desc """
|
||||
@@ -80,9 +94,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
value(:open, description: "The actor is open to followings")
|
||||
end
|
||||
|
||||
object :paginated_group_list do
|
||||
field(:elements, list_of(:group), description: "A list of groups")
|
||||
field(:total, :integer, description: "The total number of elements in the list")
|
||||
end
|
||||
|
||||
object :group_queries do
|
||||
@desc "Get all groups"
|
||||
field :groups, list_of(:group) do
|
||||
field :groups, :paginated_group_list do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
resolve(&Group.list_groups/3)
|
||||
|
||||
@@ -4,15 +4,27 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
alias Mobilizon.GraphQL.Resolvers.Group
|
||||
alias Mobilizon.GraphQL.Resolvers.{Group, Member}
|
||||
|
||||
@desc """
|
||||
Represents a member of a group
|
||||
"""
|
||||
object :member do
|
||||
field(:id, :id, description: "The member's ID")
|
||||
field(:parent, :group, description: "Of which the profile is member")
|
||||
field(:actor, :person, description: "Which profile is member of")
|
||||
field(:role, :integer, description: "The role of this membership")
|
||||
field(:role, :member_role_enum, description: "The role of this membership")
|
||||
field(:invited_by, :person, description: "Who invited this member")
|
||||
end
|
||||
|
||||
enum :member_role_enum do
|
||||
value(:not_approved)
|
||||
value(:invited)
|
||||
value(:member)
|
||||
value(:moderator)
|
||||
value(:administrator)
|
||||
value(:creator)
|
||||
value(:rejected)
|
||||
end
|
||||
|
||||
@desc "Represents a deleted member"
|
||||
@@ -21,6 +33,11 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
field(:actor, :deleted_object)
|
||||
end
|
||||
|
||||
object :paginated_member_list do
|
||||
field(:elements, list_of(:member), description: "A list of members")
|
||||
field(:total, :integer, description: "The total number of elements in the list")
|
||||
end
|
||||
|
||||
object :member_mutations do
|
||||
@desc "Join a group"
|
||||
field :join_group, :member do
|
||||
@@ -30,12 +47,27 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
resolve(&Group.join_group/3)
|
||||
end
|
||||
|
||||
@desc "Leave an event"
|
||||
@desc "Leave a group"
|
||||
field :leave_group, :deleted_member do
|
||||
arg(:group_id, non_null(:id))
|
||||
arg(:actor_id, non_null(:id))
|
||||
|
||||
resolve(&Group.leave_group/3)
|
||||
end
|
||||
|
||||
@desc "Invite an actor to join the group"
|
||||
field :invite_member, :member do
|
||||
arg(:group_id, non_null(:id))
|
||||
arg(:target_actor_username, non_null(:string))
|
||||
|
||||
resolve(&Member.invite_member/3)
|
||||
end
|
||||
|
||||
@desc "Accept an invitation to a group"
|
||||
field :accept_invitation, :member do
|
||||
arg(:id, non_null(:id))
|
||||
|
||||
resolve(&Member.accept_invitation/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,6 +64,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
arg(:event_id, :id)
|
||||
resolve(&Person.person_participations/3)
|
||||
end
|
||||
|
||||
@desc "The list of group this person is member of"
|
||||
field(:memberships, :paginated_member_list,
|
||||
description: "The list of group this person is member of"
|
||||
) do
|
||||
resolve(&Person.person_memberships/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :person_queries do
|
||||
|
||||
@@ -5,7 +5,8 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
alias Mobilizon.Events.{Comment, Event}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Reports.{Note, Report}
|
||||
|
||||
alias Mobilizon.GraphQL.Resolvers.Admin
|
||||
|
||||
@@ -20,6 +20,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
field(:geocoding, :geocoding)
|
||||
field(:maps, :maps)
|
||||
field(:anonymous, :anonymous)
|
||||
field(:resource_providers, list_of(:resource_provider))
|
||||
field(:timezones, list_of(:string))
|
||||
|
||||
field(:terms, :terms, description: "The instance's terms") do
|
||||
arg(:locale, :string, default_value: "en")
|
||||
@@ -97,6 +99,12 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
field(:enabled, :boolean)
|
||||
end
|
||||
|
||||
object :resource_provider do
|
||||
field(:type, :string)
|
||||
field(:endpoint, :string)
|
||||
field(:software, :string)
|
||||
end
|
||||
|
||||
object :config_queries do
|
||||
@desc "Get the instance config"
|
||||
field :config, :config do
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.CommentType do
|
||||
defmodule Mobilizon.GraphQL.Schema.Conversations.CommentType do
|
||||
@moduledoc """
|
||||
Schema representation for Comment
|
||||
"""
|
||||
@@ -48,6 +48,11 @@ defmodule Mobilizon.GraphQL.Schema.CommentType do
|
||||
value(:invite, description: "visible only to people invited")
|
||||
end
|
||||
|
||||
object :paginated_comment_list do
|
||||
field(:elements, list_of(:comment), description: "A list of comments")
|
||||
field(:total, :integer, description: "The total number of comments in the list")
|
||||
end
|
||||
|
||||
object :comment_queries do
|
||||
@desc "Get replies for thread"
|
||||
field :thread, type: list_of(:comment) do
|
||||
@@ -67,6 +72,14 @@ defmodule Mobilizon.GraphQL.Schema.CommentType do
|
||||
resolve(&Comment.create_comment/3)
|
||||
end
|
||||
|
||||
@desc "Update a comment"
|
||||
field :update_comment, type: :comment do
|
||||
arg(:text, non_null(:string))
|
||||
arg(:comment_id, non_null(:id))
|
||||
|
||||
resolve(&Comment.update_comment/3)
|
||||
end
|
||||
|
||||
field :delete_comment, type: :comment do
|
||||
arg(:comment_id, non_null(:id))
|
||||
arg(:actor_id, non_null(:id))
|
||||
74
lib/graphql/schema/conversations/conversation.ex
Normal file
74
lib/graphql/schema/conversations/conversation.ex
Normal file
@@ -0,0 +1,74 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.Conversations.ConversationType do
|
||||
@moduledoc """
|
||||
Schema representation for Conversation
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.GraphQL.Resolvers.Conversation
|
||||
|
||||
@desc "A conversation"
|
||||
object :conversation do
|
||||
field(:id, :id, description: "Internal ID for this conversation")
|
||||
field(:title, :string)
|
||||
field(:slug, :string)
|
||||
field(:last_comment, :comment)
|
||||
|
||||
field :comments, :paginated_comment_list do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
resolve(&Conversation.get_comments_for_conversation/3)
|
||||
description("The comments for the conversation")
|
||||
end
|
||||
|
||||
field(:creator, :person, resolve: dataloader(Actors))
|
||||
field(:actor, :actor, resolve: dataloader(Actors))
|
||||
field(:inserted_at, :datetime)
|
||||
field(:updated_at, :datetime)
|
||||
end
|
||||
|
||||
object :paginated_conversation_list do
|
||||
field(:elements, list_of(:conversation), description: "A list of conversation")
|
||||
field(:total, :integer, description: "The total number of comments in the list")
|
||||
end
|
||||
|
||||
object :conversation_queries do
|
||||
@desc "Get a conversation"
|
||||
field :conversation, type: :conversation do
|
||||
arg(:id, non_null(:id))
|
||||
resolve(&Conversation.get_conversation/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :conversation_mutations do
|
||||
@desc "Create a conversation"
|
||||
field :create_conversation, type: :conversation do
|
||||
arg(:title, non_null(:string))
|
||||
arg(:text, non_null(:string))
|
||||
arg(:actor_id, non_null(:id))
|
||||
arg(:creator_id, non_null(:id))
|
||||
|
||||
resolve(&Conversation.create_conversation/3)
|
||||
end
|
||||
|
||||
field :reply_to_conversation, type: :conversation do
|
||||
arg(:conversation_id, non_null(:id))
|
||||
arg(:text, non_null(:string))
|
||||
resolve(&Conversation.reply_to_conversation/3)
|
||||
end
|
||||
|
||||
field :update_conversation, type: :conversation do
|
||||
arg(:title, non_null(:string))
|
||||
arg(:conversation_id, non_null(:id))
|
||||
resolve(&Conversation.update_conversation/3)
|
||||
end
|
||||
|
||||
field :delete_conversation, type: :conversation do
|
||||
arg(:conversation_id, non_null(:id))
|
||||
|
||||
# resolve(&Conversation.delete_conversation/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -115,6 +115,11 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
value(:cancelled, description: "The event is cancelled")
|
||||
end
|
||||
|
||||
object :paginated_event_list do
|
||||
field(:elements, list_of(:event), description: "A list of events")
|
||||
field(:total, :integer, description: "The total number of events in the list")
|
||||
end
|
||||
|
||||
object :participant_stats do
|
||||
field(:going, :integer,
|
||||
description: "The number of approved participants",
|
||||
@@ -201,6 +206,11 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
|
||||
field(:show_start_time, :boolean, description: "Show event start time")
|
||||
field(:show_end_time, :boolean, description: "Show event end time")
|
||||
|
||||
field(:hide_organizer_when_group_event, :boolean,
|
||||
description:
|
||||
"Whether to show or hide the person organizer when event is organized by a group"
|
||||
)
|
||||
end
|
||||
|
||||
input_object :event_options_input do
|
||||
@@ -242,6 +252,11 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
|
||||
field(:show_start_time, :boolean, description: "Show event start time")
|
||||
field(:show_end_time, :boolean, description: "Show event end time")
|
||||
|
||||
field(:hide_organizer_when_group_event, :boolean,
|
||||
description:
|
||||
"Whether to show or hide the person organizer when event is organized by a group"
|
||||
)
|
||||
end
|
||||
|
||||
object :event_queries do
|
||||
@@ -284,6 +299,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
arg(:online_address, :string)
|
||||
arg(:phone_address, :string)
|
||||
arg(:organizer_actor_id, non_null(:id))
|
||||
arg(:attributed_to_id, :id)
|
||||
arg(:category, :string, default_value: "meeting")
|
||||
arg(:physical_address, :address_input)
|
||||
arg(:options, :event_options_input)
|
||||
@@ -314,6 +330,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
arg(:online_address, :string)
|
||||
arg(:phone_address, :string)
|
||||
arg(:organizer_actor_id, :id)
|
||||
arg(:attributed_to_id, :id)
|
||||
arg(:category, :string)
|
||||
arg(:physical_address, :address_input)
|
||||
arg(:options, :event_options_input)
|
||||
|
||||
95
lib/graphql/schema/resource.ex
Normal file
95
lib/graphql/schema/resource.ex
Normal file
@@ -0,0 +1,95 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
@moduledoc """
|
||||
Schema representation for Resources
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
alias Mobilizon.GraphQL.Resolvers.Resource
|
||||
|
||||
@desc "A resource"
|
||||
object :resource do
|
||||
field(:id, :id, description: "The resource's ID")
|
||||
field(:title, :string, description: "The resource's title")
|
||||
field(:summary, :string, description: "The resource's summary")
|
||||
field(:url, :string, description: "The resource's URL")
|
||||
field(:resource_url, :string, description: "The resource's URL")
|
||||
field(:metadata, :resource_metadata, description: "The resource's metadata")
|
||||
field(:creator, :actor, description: "The resource's creator")
|
||||
field(:actor, :actor, description: "The resource's owner")
|
||||
field(:inserted_at, :naive_datetime, description: "The resource's creation date")
|
||||
field(:updated_at, :naive_datetime, description: "The resource's last update date")
|
||||
field(:type, :string, description: "The resource's type (if it's a folder)")
|
||||
field(:path, :string, description: "The resource's path")
|
||||
field(:parent, :resource, description: "The resource's parent")
|
||||
|
||||
field :children, :paginated_resource_list do
|
||||
description("Children resources in folder")
|
||||
resolve(&Resource.find_resources_for_parent/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :paginated_resource_list do
|
||||
field(:elements, list_of(:resource), description: "A list of resources")
|
||||
field(:total, :integer, description: "The total number of resources in the list")
|
||||
end
|
||||
|
||||
object :resource_metadata do
|
||||
field(:type, :string, description: "The type of the resource")
|
||||
field(:title, :string, description: "The resource's metadata title")
|
||||
field(:description, :string, description: "The resource's metadata description")
|
||||
field(:image_remote_url, :string, description: "The resource's metadata image")
|
||||
field(:width, :integer)
|
||||
field(:height, :integer)
|
||||
field(:author_name, :string)
|
||||
field(:author_url, :string)
|
||||
field(:provider_name, :string)
|
||||
field(:provider_url, :string)
|
||||
field(:html, :string)
|
||||
field(:favicon_url, :string)
|
||||
end
|
||||
|
||||
object :resource_queries do
|
||||
@desc "Get a resource"
|
||||
field :resource, :resource do
|
||||
arg(:path, non_null(:string))
|
||||
arg(:username, non_null(:string))
|
||||
resolve(&Resource.get_resource/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :resource_mutations do
|
||||
@desc "Create a resource"
|
||||
field :create_resource, :resource do
|
||||
arg(:parent_id, :id)
|
||||
arg(:actor_id, non_null(:id))
|
||||
arg(:title, non_null(:string))
|
||||
arg(:summary, :string)
|
||||
arg(:resource_url, :string)
|
||||
arg(:type, :string, default_value: "link")
|
||||
|
||||
resolve(&Resource.create_resource/3)
|
||||
end
|
||||
|
||||
@desc "Update a resource"
|
||||
field :update_resource, :resource do
|
||||
arg(:id, non_null(:id))
|
||||
arg(:title, :string)
|
||||
arg(:summary, :string)
|
||||
arg(:parent_id, :id)
|
||||
arg(:resource_url, :string)
|
||||
|
||||
resolve(&Resource.update_resource/3)
|
||||
end
|
||||
|
||||
@desc "Delete a resource"
|
||||
field :delete_resource, :deleted_object do
|
||||
arg(:id, non_null(:id))
|
||||
resolve(&Resource.delete_resource/3)
|
||||
end
|
||||
|
||||
@desc "Get a preview for a resource link"
|
||||
field :preview_resource_link, :resource_metadata do
|
||||
arg(:resource_url, non_null(:string))
|
||||
resolve(&Resource.preview_resource_link/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
72
lib/graphql/schema/todos/todo.ex
Normal file
72
lib/graphql/schema/todos/todo.ex
Normal file
@@ -0,0 +1,72 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.Todos.TodoType do
|
||||
@moduledoc """
|
||||
Schema representation for Todos
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
alias Mobilizon.GraphQL.Resolvers.Todos, as: TodoResolver
|
||||
alias Mobilizon.{Actors, Todos}
|
||||
|
||||
@desc "A todo"
|
||||
object :todo do
|
||||
field(:id, :id, description: "The todo's ID")
|
||||
field(:title, :string, description: "The todo's title")
|
||||
field(:status, :boolean, description: "The todo's status")
|
||||
field(:due_date, :datetime, description: "The todo's due date")
|
||||
field(:creator, :actor, resolve: dataloader(Actors), description: "The todo's creator")
|
||||
|
||||
field(:todo_list, :todo_list,
|
||||
resolve: dataloader(Todos),
|
||||
description: "The todo list this todo is attached to"
|
||||
)
|
||||
|
||||
field(:assigned_to, :actor,
|
||||
resolve: dataloader(Actors),
|
||||
description: "The todos's assigned person"
|
||||
)
|
||||
end
|
||||
|
||||
object :paginated_todo_list do
|
||||
field(:elements, list_of(:todo), description: "A list of todos")
|
||||
field(:total, :integer, description: "The total number of todos in the list")
|
||||
end
|
||||
|
||||
object :todo_queries do
|
||||
@desc "Get a todo"
|
||||
field :todo, :todo do
|
||||
arg(:id, non_null(:id))
|
||||
resolve(&TodoResolver.get_todo/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :todo_mutations do
|
||||
@desc "Create a todo"
|
||||
field :create_todo, :todo do
|
||||
arg(:todo_list_id, non_null(:id))
|
||||
arg(:title, non_null(:string))
|
||||
arg(:status, :boolean)
|
||||
arg(:due_date, :datetime)
|
||||
arg(:assigned_to_id, :id)
|
||||
|
||||
resolve(&TodoResolver.create_todo/3)
|
||||
end
|
||||
|
||||
@desc "Update a todo"
|
||||
field :update_todo, :todo do
|
||||
arg(:id, non_null(:id))
|
||||
arg(:todo_list_id, :id)
|
||||
arg(:title, :string)
|
||||
arg(:status, :boolean)
|
||||
arg(:due_date, :datetime)
|
||||
arg(:assigned_to_id, :id)
|
||||
|
||||
resolve(&TodoResolver.update_todo/3)
|
||||
end
|
||||
|
||||
# @desc "Delete a todo"
|
||||
# field :delete_todo, :deleted_object do
|
||||
# arg(:id, non_null(:id))
|
||||
# resolve(&TodoResolver.delete_todo/3)
|
||||
# end
|
||||
end
|
||||
end
|
||||
47
lib/graphql/schema/todos/todo_list.ex
Normal file
47
lib/graphql/schema/todos/todo_list.ex
Normal file
@@ -0,0 +1,47 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.Todos.TodoListType do
|
||||
@moduledoc """
|
||||
Schema representation for Todo Lists
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.GraphQL.Resolvers.Todos
|
||||
|
||||
@desc "A todo list"
|
||||
object :todo_list do
|
||||
field(:id, :id, description: "The todo list's ID")
|
||||
field(:title, :string, description: "The todo list's title")
|
||||
|
||||
field(:actor, :actor,
|
||||
resolve: dataloader(Actors),
|
||||
description: "The actor that owns this todo list"
|
||||
)
|
||||
|
||||
field(:todos, :paginated_todo_list,
|
||||
resolve: &Todos.find_todos_for_todo_list/3,
|
||||
description: "The todo-list's todos"
|
||||
)
|
||||
end
|
||||
|
||||
object :paginated_todo_list_list do
|
||||
field(:elements, list_of(:todo_list), description: "A list of todo lists")
|
||||
field(:total, :integer, description: "The total number of todo lists in the list")
|
||||
end
|
||||
|
||||
object :todo_list_queries do
|
||||
@desc "Get a todo list"
|
||||
field :todo_list, :todo_list do
|
||||
arg(:id, non_null(:id))
|
||||
resolve(&Todos.get_todo_list/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :todo_list_mutations do
|
||||
@desc "Create a todo list"
|
||||
field :create_todo_list, :todo_list do
|
||||
arg(:title, non_null(:string))
|
||||
arg(:group_id, non_null(:id))
|
||||
resolve(&Todos.create_todo_list/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -51,7 +51,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
|
||||
field(:locale, :string, description: "The user's locale")
|
||||
|
||||
field(:participations, list_of(:participant),
|
||||
field(:participations, :paginated_participant_list,
|
||||
description: "The list of participations this user has"
|
||||
) do
|
||||
arg(:after_datetime, :datetime)
|
||||
@@ -61,11 +61,23 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
resolve(&User.user_participations/3)
|
||||
end
|
||||
|
||||
field(:memberships, :paginated_member_list,
|
||||
description: "The list of memberships for this user"
|
||||
) do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
resolve(&User.user_memberships/3)
|
||||
end
|
||||
|
||||
field(:drafts, list_of(:event), description: "The list of draft events this user has created") do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
resolve(&User.user_drafted_events/3)
|
||||
end
|
||||
|
||||
field(:settings, :user_settings, description: "The list of settings for this user") do
|
||||
resolve(&User.user_settings/3)
|
||||
end
|
||||
end
|
||||
|
||||
enum :user_role do
|
||||
@@ -91,6 +103,22 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
value(:id)
|
||||
end
|
||||
|
||||
object :user_settings do
|
||||
field(:timezone, :string, description: "The timezone for this user")
|
||||
|
||||
field(:notification_on_day, :boolean,
|
||||
description: "Whether this user will receive an email at the start of the day of an event."
|
||||
)
|
||||
|
||||
field(:notification_each_week, :boolean,
|
||||
description: "Whether this user will receive an weekly event recap"
|
||||
)
|
||||
|
||||
field(:notification_before_event, :boolean,
|
||||
description: "Whether this user will receive a notification right before event"
|
||||
)
|
||||
end
|
||||
|
||||
object :user_queries do
|
||||
@desc "Get an user"
|
||||
field :user, :user do
|
||||
@@ -179,20 +207,31 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
resolve(&User.change_password/3)
|
||||
end
|
||||
|
||||
@desc "Change an user email"
|
||||
field :change_email, :user do
|
||||
arg(:email, non_null(:string))
|
||||
arg(:password, non_null(:string))
|
||||
resolve(&User.change_email/3)
|
||||
end
|
||||
|
||||
@desc "Validate an user email"
|
||||
field :validate_email, :user do
|
||||
arg(:token, non_null(:string))
|
||||
resolve(&User.validate_email/3)
|
||||
end
|
||||
|
||||
@desc "Delete an account"
|
||||
field :delete_account, :deleted_object do
|
||||
arg(:password, non_null(:string))
|
||||
resolve(&User.delete_account/3)
|
||||
end
|
||||
|
||||
field :set_user_settings, :user_settings do
|
||||
arg(:timezone, :string)
|
||||
arg(:notification_on_day, :boolean)
|
||||
arg(:notification_each_week, :boolean)
|
||||
arg(:notification_before_event, :boolean)
|
||||
resolve(&User.set_user_setting/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user