Refactor Core things, including Ecto handling, ActivityPub & Transmogrifier modules
* Data doesn't need anymore to be converted to ActivityStream format to be saved (this was taken from Pleroma and not at all a good idea here) * Everything saved when creating an event is inserted into PostgreSQL in a single transaction
This commit is contained in:
@@ -2,55 +2,18 @@ defmodule MobilizonWeb.API.Comments do
|
||||
@moduledoc """
|
||||
API for Comments.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Comment
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
|
||||
|
||||
alias MobilizonWeb.API.Utils
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
|
||||
@doc """
|
||||
Create a comment
|
||||
|
||||
Creates a comment from an actor and a status
|
||||
"""
|
||||
@spec create_comment(String.t(), String.t(), String.t()) ::
|
||||
@spec create_comment(map()) ::
|
||||
{:ok, Activity.t(), Comment.t()} | any()
|
||||
def create_comment(
|
||||
from_username,
|
||||
status,
|
||||
visibility \\ :public,
|
||||
in_reply_to_comment_URL \\ nil
|
||||
) do
|
||||
with {:local_actor, %Actor{url: url} = actor} <-
|
||||
{:local_actor, Actors.get_local_actor_by_name(from_username)},
|
||||
in_reply_to_comment <- get_in_reply_to_comment(in_reply_to_comment_URL),
|
||||
{content_html, tags, to, cc} <-
|
||||
Utils.prepare_content(actor, status, visibility, [], in_reply_to_comment),
|
||||
comment <-
|
||||
ActivityPubUtils.make_comment_data(
|
||||
url,
|
||||
to,
|
||||
content_html,
|
||||
in_reply_to_comment,
|
||||
tags,
|
||||
cc
|
||||
) do
|
||||
ActivityPub.create(%{
|
||||
to: to,
|
||||
actor: actor,
|
||||
object: comment,
|
||||
local: true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_in_reply_to_comment(nil) :: nil
|
||||
defp get_in_reply_to_comment(nil), do: nil
|
||||
@spec get_in_reply_to_comment(String.t()) :: Comment.t()
|
||||
defp get_in_reply_to_comment(in_reply_to_comment_url) do
|
||||
ActivityPub.fetch_object_from_url(in_reply_to_comment_url)
|
||||
def create_comment(args) do
|
||||
ActivityPub.create(:comment, args, true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,37 +3,24 @@ defmodule MobilizonWeb.API.Events do
|
||||
API for Events.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
|
||||
|
||||
alias MobilizonWeb.API.Utils
|
||||
alias Mobilizon.Service.ActivityPub.Utils
|
||||
|
||||
@doc """
|
||||
Create an event
|
||||
"""
|
||||
@spec create_event(map()) :: {:ok, Activity.t(), Event.t()} | any()
|
||||
def create_event(%{organizer_actor: organizer_actor} = args) do
|
||||
with args <- prepare_args(args),
|
||||
event <-
|
||||
ActivityPubUtils.make_event_data(
|
||||
args.organizer_actor.url,
|
||||
%{to: args.to, cc: args.cc},
|
||||
args.title,
|
||||
args.content_html,
|
||||
args.picture,
|
||||
args.tags,
|
||||
args.metadata
|
||||
) do
|
||||
ActivityPub.create(%{
|
||||
to: args.to,
|
||||
actor: organizer_actor,
|
||||
object: event,
|
||||
# For now we don't federate drafts but it will be needed if we want to edit them as groups
|
||||
local: args.metadata.draft == false
|
||||
})
|
||||
def create_event(args) do
|
||||
with organizer_actor <- Map.get(args, :organizer_actor),
|
||||
args <-
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
process_picture(picture, organizer_actor)
|
||||
end) do
|
||||
# For now we don't federate drafts but it will be needed if we want to edit them as groups
|
||||
ActivityPub.create(:event, args, args.draft == false)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,65 +28,13 @@ defmodule MobilizonWeb.API.Events do
|
||||
Update an event
|
||||
"""
|
||||
@spec update_event(map(), Event.t()) :: {:ok, Activity.t(), Event.t()} | any()
|
||||
def update_event(
|
||||
%{
|
||||
organizer_actor: organizer_actor
|
||||
} = args,
|
||||
%Event{} = event
|
||||
) do
|
||||
with args <- Map.put(args, :tags, Map.get(args, :tags, [])),
|
||||
args <- prepare_args(Map.merge(event, args)),
|
||||
event <-
|
||||
ActivityPubUtils.make_event_data(
|
||||
args.organizer_actor.url,
|
||||
%{to: args.to, cc: args.cc},
|
||||
args.title,
|
||||
args.content_html,
|
||||
args.picture,
|
||||
args.tags,
|
||||
args.metadata,
|
||||
event.uuid,
|
||||
event.url
|
||||
) do
|
||||
ActivityPub.update(%{
|
||||
to: args.to,
|
||||
actor: organizer_actor.url,
|
||||
cc: [],
|
||||
object: event,
|
||||
local: args.metadata.draft == false
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
defp prepare_args(args) do
|
||||
with %Actor{} = organizer_actor <- Map.get(args, :organizer_actor),
|
||||
title <- args |> Map.get(:title, "") |> HtmlSanitizeEx.strip_tags() |> String.trim(),
|
||||
visibility <- Map.get(args, :visibility, :public),
|
||||
description <- Map.get(args, :description),
|
||||
tags <- Map.get(args, :tags),
|
||||
{content_html, tags, to, cc} <-
|
||||
Utils.prepare_content(organizer_actor, description, visibility, tags, nil) do
|
||||
%{
|
||||
title: title,
|
||||
content_html: content_html,
|
||||
picture: Map.get(args, :picture),
|
||||
tags: tags,
|
||||
organizer_actor: organizer_actor,
|
||||
to: to,
|
||||
cc: cc,
|
||||
metadata: %{
|
||||
begins_on: Map.get(args, :begins_on),
|
||||
ends_on: Map.get(args, :ends_on),
|
||||
physical_address: Map.get(args, :physical_address),
|
||||
category: Map.get(args, :category),
|
||||
options: Map.get(args, :options),
|
||||
join_options: Map.get(args, :join_options),
|
||||
status: Map.get(args, :status),
|
||||
online_address: Map.get(args, :online_address),
|
||||
phone_address: Map.get(args, :phone_address),
|
||||
draft: Map.get(args, :draft)
|
||||
}
|
||||
}
|
||||
def update_event(args, %Event{} = event) do
|
||||
with organizer_actor <- Map.get(args, :organizer_actor),
|
||||
args <-
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
process_picture(picture, organizer_actor)
|
||||
end) do
|
||||
ActivityPub.update(:event, event, args, Map.get(args, :draft, false) == false)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -111,4 +46,15 @@ defmodule MobilizonWeb.API.Events do
|
||||
def delete_event(%Event{} = event, federate \\ true) do
|
||||
ActivityPub.delete(event, federate)
|
||||
end
|
||||
|
||||
defp process_picture(nil, _), do: nil
|
||||
defp process_picture(%{picture_id: _picture_id} = args, _), do: args
|
||||
|
||||
defp process_picture(%{picture: picture}, %Actor{id: actor_id}) do
|
||||
%{
|
||||
file:
|
||||
picture |> Map.get(:file) |> Utils.make_picture_data(description: Map.get(picture, :name)),
|
||||
actor_id: actor_id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,7 @@ defmodule MobilizonWeb.API.Follows do
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor, Follower}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
|
||||
require Logger
|
||||
|
||||
@@ -32,17 +33,14 @@ defmodule MobilizonWeb.API.Follows do
|
||||
end
|
||||
|
||||
def accept(%Actor{} = follower, %Actor{} = followed) do
|
||||
with %Follower{approved: false, id: follow_id, url: follow_url} = follow <-
|
||||
with %Follower{approved: false} = follow <-
|
||||
Actors.is_following(follower, followed),
|
||||
activity_follow_url <- "#{MobilizonWeb.Endpoint.url()}/accept/follow/#{follow_id}",
|
||||
data <-
|
||||
ActivityPub.Utils.make_follow_data(followed, follower, follow_url),
|
||||
{:ok, activity, _} <-
|
||||
{:ok, %Activity{} = activity, %Follower{approved: true}} <-
|
||||
ActivityPub.accept(
|
||||
%{to: [follower.url], actor: followed.url, object: data},
|
||||
activity_follow_url
|
||||
),
|
||||
{:ok, %Follower{approved: true}} <- Actors.update_follower(follow, %{"approved" => true}) do
|
||||
:follow,
|
||||
follow,
|
||||
%{approved: true}
|
||||
) do
|
||||
{:ok, activity}
|
||||
else
|
||||
%Follower{approved: true} ->
|
||||
|
||||
@@ -6,38 +6,19 @@ defmodule MobilizonWeb.API.Groups do
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias MobilizonWeb.API.Utils
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
|
||||
@doc """
|
||||
Create a group
|
||||
"""
|
||||
@spec create_group(User.t(), map()) :: {:ok, Activity.t(), Group.t()} | any()
|
||||
def create_group(
|
||||
user,
|
||||
%{
|
||||
preferred_username: title,
|
||||
summary: summary,
|
||||
creator_actor_id: creator_actor_id,
|
||||
avatar: _avatar,
|
||||
banner: _banner
|
||||
} = args
|
||||
) do
|
||||
with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, creator_actor_id),
|
||||
title <- String.trim(title),
|
||||
{:existing_group, nil} <- {:existing_group, Actors.get_group_by_title(title)},
|
||||
visibility <- Map.get(args, :visibility, :public),
|
||||
{content_html, tags, to, cc} <-
|
||||
Utils.prepare_content(actor, summary, visibility, [], nil),
|
||||
group <- ActivityPubUtils.make_group_data(actor.url, to, title, content_html, tags, cc) do
|
||||
ActivityPub.create(%{
|
||||
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
actor: actor,
|
||||
object: group,
|
||||
local: true
|
||||
})
|
||||
@spec create_group(map()) :: {:ok, Activity.t(), Actor.t()} | any()
|
||||
def create_group(args) do
|
||||
with preferred_username <-
|
||||
args |> Map.get(:preferred_username) |> HtmlSanitizeEx.strip_tags() |> String.trim(),
|
||||
{:existing_group, nil} <-
|
||||
{:existing_group, Actors.get_local_group_by_title(preferred_username)},
|
||||
{:ok, %Activity{} = activity, %Actor{} = group} <- ActivityPub.create(:group, args, true) do
|
||||
{:ok, activity, group}
|
||||
else
|
||||
{:existing_group, _} ->
|
||||
{:error, "A group with this name already exists"}
|
||||
|
||||
@@ -38,12 +38,11 @@ defmodule MobilizonWeb.API.Participations do
|
||||
) do
|
||||
with {:ok, activity, _} <-
|
||||
ActivityPub.accept(
|
||||
%{
|
||||
to: [participation.actor.url],
|
||||
actor: moderator.url,
|
||||
object: participation.url
|
||||
},
|
||||
"#{MobilizonWeb.Endpoint.url()}/accept/join/#{participation.id}"
|
||||
:join,
|
||||
participation,
|
||||
%{role: :participant},
|
||||
true,
|
||||
%{"to" => [moderator.url]}
|
||||
),
|
||||
{:ok, %Participant{role: :participant} = participation} <-
|
||||
Events.update_participant(participation, %{"role" => :participant}),
|
||||
|
||||
@@ -3,89 +3,9 @@ defmodule MobilizonWeb.API.Utils do
|
||||
Utils for API.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Service.Formatter
|
||||
|
||||
@ap_public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
@doc """
|
||||
Determines the full audience based on mentions for a public audience
|
||||
|
||||
Audience is:
|
||||
* `to` : the mentioned actors, the eventual actor we're replying to and the public
|
||||
* `cc` : the actor's followers
|
||||
"""
|
||||
@spec get_to_and_cc(Actor.t(), list(), map(), String.t()) :: {list(), list()}
|
||||
def get_to_and_cc(%Actor{} = actor, mentions, inReplyTo, :public) do
|
||||
to = [@ap_public | mentions]
|
||||
cc = [actor.followers_url]
|
||||
|
||||
if inReplyTo do
|
||||
{Enum.uniq([inReplyTo.actor | to]), cc}
|
||||
else
|
||||
{to, cc}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Determines the full audience based on mentions based on a unlisted audience
|
||||
|
||||
Audience is:
|
||||
* `to` : the mentionned actors, actor's followers and the eventual actor we're replying to
|
||||
* `cc` : public
|
||||
"""
|
||||
@spec get_to_and_cc(Actor.t(), list(), map(), String.t()) :: {list(), list()}
|
||||
def get_to_and_cc(%Actor{} = actor, mentions, inReplyTo, :unlisted) do
|
||||
to = [actor.followers_url | mentions]
|
||||
cc = [@ap_public]
|
||||
|
||||
if inReplyTo do
|
||||
{Enum.uniq([inReplyTo.actor | to]), cc}
|
||||
else
|
||||
{to, cc}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Determines the full audience based on mentions based on a private audience
|
||||
|
||||
Audience is:
|
||||
* `to` : the mentioned actors, actor's followers and the eventual actor we're replying to
|
||||
* `cc` : none
|
||||
"""
|
||||
@spec get_to_and_cc(Actor.t(), list(), map(), String.t()) :: {list(), list()}
|
||||
def get_to_and_cc(%Actor{} = actor, mentions, inReplyTo, :private) do
|
||||
{to, cc} = get_to_and_cc(actor, mentions, inReplyTo, :direct)
|
||||
{[actor.followers_url | to], cc}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Determines the full audience based on mentions based on a direct audience
|
||||
|
||||
Audience is:
|
||||
* `to` : the mentioned actors and the eventual actor we're replying to
|
||||
* `cc` : none
|
||||
"""
|
||||
@spec get_to_and_cc(Actor.t(), list(), map(), String.t()) :: {list(), list()}
|
||||
def get_to_and_cc(_actor, mentions, inReplyTo, :direct) do
|
||||
if inReplyTo do
|
||||
{Enum.uniq([inReplyTo.actor | mentions]), []}
|
||||
else
|
||||
{mentions, []}
|
||||
end
|
||||
end
|
||||
|
||||
def get_to_and_cc(_actor, mentions, _inReplyTo, {:list, _}) do
|
||||
{mentions, []}
|
||||
end
|
||||
|
||||
# def get_addressed_users(_, to) when is_list(to) do
|
||||
# Actors.get(to)
|
||||
# end
|
||||
|
||||
def get_addressed_users(mentioned_users, _), do: mentioned_users
|
||||
|
||||
@doc """
|
||||
Creates HTML content from text and mentions
|
||||
"""
|
||||
@@ -126,19 +46,4 @@ defmodule MobilizonWeb.API.Utils do
|
||||
{:error, "Comment must be up to #{max_size} characters"}
|
||||
end
|
||||
end
|
||||
|
||||
def prepare_content(actor, content, visibility, tags, in_reply_to) do
|
||||
with content <- String.trim(content || ""),
|
||||
{content_html, mentions, tags} <-
|
||||
make_content_html(
|
||||
content,
|
||||
tags,
|
||||
"text/html"
|
||||
),
|
||||
mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.url),
|
||||
addressed_users <- get_addressed_users(mentioned_users, nil),
|
||||
{to, cc} <- get_to_and_cc(actor, addressed_users, in_reply_to, visibility) do
|
||||
{content_html, tags, to, cc}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,19 +4,19 @@ defmodule MobilizonWeb.Resolvers.Comment do
|
||||
"""
|
||||
|
||||
alias Mobilizon.Events.Comment
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Actors.Actor
|
||||
|
||||
alias MobilizonWeb.API.Comments
|
||||
|
||||
require Logger
|
||||
|
||||
def create_comment(_parent, %{text: comment, actor_username: username}, %{
|
||||
context: %{current_user: %User{} = _user}
|
||||
def create_comment(_parent, %{text: text, actor_id: actor_id}, %{
|
||||
context: %{current_user: %User{} = user}
|
||||
}) do
|
||||
with {:ok, %Activity{data: %{"object" => %{"type" => "Note"} = _object}},
|
||||
%Comment{} = comment} <-
|
||||
Comments.create_comment(username, comment) do
|
||||
with {:is_owned, %Actor{} = _organizer_actor} <- User.owns_actor(user, actor_id),
|
||||
{:ok, _, %Comment{} = comment} <-
|
||||
Comments.create_comment(%{actor_id: actor_id, text: text}) do
|
||||
{:ok, comment}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,11 +7,8 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Addresses
|
||||
alias Mobilizon.Addresses.Address
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Media.Picture
|
||||
alias Mobilizon.Events.{Event, Participant, EventParticipantStats}
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@@ -96,14 +93,8 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
{:ok, []}
|
||||
end
|
||||
|
||||
def stats_participants_for_event(%Event{id: id}, _args, _resolution) do
|
||||
{:ok,
|
||||
%{
|
||||
approved: Mobilizon.Events.count_approved_participants(id),
|
||||
unapproved: Mobilizon.Events.count_unapproved_participants(id),
|
||||
rejected: Mobilizon.Events.count_rejected_participants(id),
|
||||
participants: Mobilizon.Events.count_participant_participants(id)
|
||||
}}
|
||||
def stats_participants_going(%EventParticipantStats{} = stats, _args, _resolution) do
|
||||
{:ok, stats.participant + stats.moderator + stats.administrator + stats.creator}
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -277,8 +268,6 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
with args <- Map.put(args, :options, args[:options] || %{}),
|
||||
{:is_owned, %Actor{} = organizer_actor} <- User.owns_actor(user, organizer_actor_id),
|
||||
args_with_organizer <- Map.put(args, :organizer_actor, organizer_actor),
|
||||
{:ok, args_with_organizer} <- save_attached_picture(args_with_organizer),
|
||||
{:ok, args_with_organizer} <- save_physical_address(args_with_organizer),
|
||||
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
|
||||
MobilizonWeb.API.Events.create_event(args_with_organizer) do
|
||||
{:ok, event}
|
||||
@@ -309,8 +298,6 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
{:is_owned, %Actor{} = organizer_actor} <-
|
||||
User.owns_actor(user, event.organizer_actor_id),
|
||||
args <- Map.put(args, :organizer_actor, organizer_actor),
|
||||
{:ok, args} <- save_attached_picture(args),
|
||||
{:ok, args} <- save_physical_address(args),
|
||||
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
|
||||
MobilizonWeb.API.Events.update_event(args, event) do
|
||||
{:ok, event}
|
||||
@@ -327,47 +314,6 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
{:error, "You need to be logged-in to update an event"}
|
||||
end
|
||||
|
||||
# If we have an attached picture, just transmit it. It will be handled by
|
||||
# Mobilizon.Service.ActivityPub.Utils.make_picture_data/1
|
||||
# However, we need to pass its actor ID
|
||||
@spec save_attached_picture(map()) :: {:ok, map()}
|
||||
defp save_attached_picture(
|
||||
%{picture: %{picture: %{file: %Plug.Upload{} = _picture} = all_pic}} = args
|
||||
) do
|
||||
{:ok, Map.put(args, :picture, Map.put(all_pic, :actor_id, args.organizer_actor.id))}
|
||||
end
|
||||
|
||||
# Otherwise if we use a previously uploaded picture we need to fetch it from database
|
||||
@spec save_attached_picture(map()) :: {:ok, map()}
|
||||
defp save_attached_picture(%{picture: %{picture_id: picture_id}} = args) do
|
||||
with %Picture{} = picture <- Mobilizon.Media.get_picture(picture_id) do
|
||||
{:ok, Map.put(args, :picture, picture)}
|
||||
end
|
||||
end
|
||||
|
||||
@spec save_attached_picture(map()) :: {:ok, map()}
|
||||
defp save_attached_picture(args), do: {:ok, args}
|
||||
|
||||
@spec save_physical_address(map()) :: {:ok, map()}
|
||||
defp save_physical_address(%{physical_address: %{url: physical_address_url}} = args)
|
||||
when not is_nil(physical_address_url) do
|
||||
with %Address{} = address <- Addresses.get_address_by_url(physical_address_url),
|
||||
args <- Map.put(args, :physical_address, address.url) do
|
||||
{:ok, args}
|
||||
end
|
||||
end
|
||||
|
||||
@spec save_physical_address(map()) :: {:ok, map()}
|
||||
defp save_physical_address(%{physical_address: address} = args) when address != nil do
|
||||
with {:ok, %Address{} = address} <- Addresses.create_address(address),
|
||||
args <- Map.put(args, :physical_address, address.url) do
|
||||
{:ok, args}
|
||||
end
|
||||
end
|
||||
|
||||
@spec save_physical_address(map()) :: {:ok, map()}
|
||||
defp save_physical_address(args), do: {:ok, args}
|
||||
|
||||
@doc """
|
||||
Delete an event
|
||||
"""
|
||||
|
||||
@@ -6,7 +6,6 @@ defmodule MobilizonWeb.Resolvers.Group do
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.Activity
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias MobilizonWeb.API
|
||||
@@ -47,23 +46,18 @@ defmodule MobilizonWeb.Resolvers.Group do
|
||||
args,
|
||||
%{context: %{current_user: user}}
|
||||
) do
|
||||
with {
|
||||
:ok,
|
||||
%Activity{data: %{"object" => %{"type" => "Group"} = _object}},
|
||||
%Actor{} = group
|
||||
} <-
|
||||
API.Groups.create_group(
|
||||
user,
|
||||
%{
|
||||
preferred_username: args.preferred_username,
|
||||
creator_actor_id: args.creator_actor_id,
|
||||
name: Map.get(args, "name", args.preferred_username),
|
||||
summary: args.summary,
|
||||
avatar: Map.get(args, "avatar"),
|
||||
banner: Map.get(args, "banner")
|
||||
}
|
||||
) do
|
||||
with creator_actor_id <- Map.get(args, :creator_actor_id),
|
||||
{:is_owned, %Actor{} = actor} <- User.owns_actor(user, creator_actor_id),
|
||||
args <- Map.put(args, :creator_actor, actor),
|
||||
{:ok, _activity, %Actor{type: :Group} = group} <-
|
||||
API.Groups.create_group(args) do
|
||||
{:ok, group}
|
||||
else
|
||||
{:error, err} when is_bitstring(err) ->
|
||||
{:error, err}
|
||||
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Creator actor id is not owned by the current user"}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ defmodule MobilizonWeb.Resolvers.Person do
|
||||
if Map.has_key?(args, key) && !is_nil(args[key][:picture]) do
|
||||
pic = args[key][:picture]
|
||||
|
||||
with {:ok, %{"name" => name, "url" => [%{"href" => url, "mediaType" => content_type}]}} <-
|
||||
with {:ok, %{name: name, url: url, content_type: content_type, size: _size}} <-
|
||||
MobilizonWeb.Upload.store(pic.file, type: key, description: pic.alt) do
|
||||
Map.put(args, key, %{"name" => name, "url" => url, "mediaType" => content_type})
|
||||
end
|
||||
|
||||
@@ -51,7 +51,7 @@ defmodule MobilizonWeb.Resolvers.Picture do
|
||||
%{context: %{current_user: user}}
|
||||
) do
|
||||
with {:is_owned, %Actor{}} <- User.owns_actor(user, actor_id),
|
||||
{:ok, %{"url" => [%{"href" => url, "mediaType" => content_type}], "size" => size}} <-
|
||||
{:ok, %{name: _name, url: url, content_type: content_type, size: size}} <-
|
||||
MobilizonWeb.Upload.store(file),
|
||||
args <-
|
||||
args
|
||||
|
||||
@@ -35,7 +35,7 @@ defmodule MobilizonWeb.Schema.CommentType do
|
||||
@desc "Create a comment"
|
||||
field :create_comment, type: :comment do
|
||||
arg(:text, non_null(:string))
|
||||
arg(:actor_username, non_null(:string))
|
||||
arg(:actor_id, non_null(:id))
|
||||
|
||||
resolve(&Comment.create_comment/3)
|
||||
end
|
||||
|
||||
@@ -63,7 +63,7 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||
|
||||
field(:draft, :boolean, description: "Whether or not the event is a draft")
|
||||
|
||||
field(:participant_stats, :participant_stats, resolve: &Event.stats_participants_for_event/3)
|
||||
field(:participant_stats, :participant_stats)
|
||||
|
||||
field(:participants, list_of(:participant), description: "The event's participants") do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
@@ -112,13 +112,21 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||
end
|
||||
|
||||
object :participant_stats do
|
||||
field(:approved, :integer, description: "The number of approved participants")
|
||||
field(:unapproved, :integer, description: "The number of unapproved participants")
|
||||
field(:going, :integer,
|
||||
description: "The number of approved participants",
|
||||
resolve: &Event.stats_participants_going/3
|
||||
)
|
||||
|
||||
field(:not_approved, :integer, description: "The number of not approved participants")
|
||||
field(:rejected, :integer, description: "The number of rejected participants")
|
||||
|
||||
field(:participants, :integer,
|
||||
field(:participant, :integer,
|
||||
description: "The number of simple participants (excluding creators)"
|
||||
)
|
||||
|
||||
field(:moderator, :integer, description: "The number of moderators")
|
||||
field(:administrator, :integer, description: "The number of administrators")
|
||||
field(:creator, :integer, description: "The number of creators")
|
||||
end
|
||||
|
||||
object :event_offer do
|
||||
|
||||
@@ -73,16 +73,10 @@ defmodule MobilizonWeb.Upload do
|
||||
{:ok, url_spec} <- Uploaders.Uploader.put_file(opts.uploader, upload) do
|
||||
{:ok,
|
||||
%{
|
||||
"type" => opts.activity_type || get_type(upload.content_type),
|
||||
"url" => [
|
||||
%{
|
||||
"type" => "Link",
|
||||
"mediaType" => upload.content_type,
|
||||
"href" => url_from_spec(upload, opts.base_url, url_spec)
|
||||
}
|
||||
],
|
||||
"size" => upload.size,
|
||||
"name" => Map.get(opts, :description) || upload.name
|
||||
name: Map.get(opts, :description) || upload.name,
|
||||
url: url_from_spec(upload, opts.base_url, url_spec),
|
||||
content_type: upload.content_type,
|
||||
size: upload.size
|
||||
}}
|
||||
else
|
||||
{:error, error} ->
|
||||
@@ -166,16 +160,6 @@ defmodule MobilizonWeb.Upload do
|
||||
|
||||
defp check_file_size(_, _), do: :ok
|
||||
|
||||
@picture_content_types ["image/gif", "image/png", "image/jpg", "image/jpeg", "image/webp"]
|
||||
# Return whether the upload is a picture or not
|
||||
defp get_type(content_type) do
|
||||
if content_type in @picture_content_types do
|
||||
"Image"
|
||||
else
|
||||
"Document"
|
||||
end
|
||||
end
|
||||
|
||||
defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
|
||||
path =
|
||||
URI.encode(path, &char_unescaped?/1) <>
|
||||
|
||||
Reference in New Issue
Block a user