Track usage of media files and add a job to clean them
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -1,34 +1,59 @@
|
||||
defmodule Mobilizon.GraphQL.API.Comments do
|
||||
@moduledoc """
|
||||
API for Comments.
|
||||
API for discussions and comments.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Activity
|
||||
alias Mobilizon.GraphQL.API.Utils
|
||||
|
||||
@doc """
|
||||
Create a comment
|
||||
|
||||
Creates a comment from an actor
|
||||
"""
|
||||
@spec create_comment(map) :: {:ok, Activity.t(), Comment.t()} | any
|
||||
def create_comment(args) do
|
||||
args = extract_pictures_from_comment_body(args)
|
||||
ActivityPub.create(:comment, args, true)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a comment
|
||||
"""
|
||||
@spec update_comment(Comment.t(), map()) :: {:ok, Activity.t(), Comment.t()} | any
|
||||
def update_comment(%Comment{} = comment, args) do
|
||||
args = extract_pictures_from_comment_body(args)
|
||||
ActivityPub.update(comment, args, true)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a comment
|
||||
|
||||
Deletes a comment from an actor
|
||||
"""
|
||||
@spec delete_comment(Comment.t(), Actor.t()) :: {:ok, Activity.t(), Comment.t()} | any
|
||||
def delete_comment(%Comment{} = comment, %Actor{} = actor) do
|
||||
ActivityPub.delete(comment, actor, true)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a discussion (or reply to a discussion)
|
||||
"""
|
||||
@spec create_discussion(map()) :: map()
|
||||
def create_discussion(args) do
|
||||
args = extract_pictures_from_comment_body(args)
|
||||
|
||||
ActivityPub.create(
|
||||
:discussion,
|
||||
args,
|
||||
true
|
||||
)
|
||||
end
|
||||
|
||||
@spec extract_pictures_from_comment_body(map()) :: map()
|
||||
defp extract_pictures_from_comment_body(%{text: text, actor_id: actor_id} = args) do
|
||||
pictures = Utils.extract_pictures_from_body(text, actor_id)
|
||||
Map.put(args, :media, pictures)
|
||||
end
|
||||
|
||||
defp extract_pictures_from_comment_body(args), do: args
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule Mobilizon.GraphQL.API.Events do
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.{Activity, Utils}
|
||||
alias Mobilizon.GraphQL.API.Utils, as: APIUtils
|
||||
|
||||
@doc """
|
||||
Create an event
|
||||
@@ -15,6 +16,7 @@ defmodule Mobilizon.GraphQL.API.Events do
|
||||
@spec create_event(map) :: {:ok, Activity.t(), Event.t()} | any
|
||||
def create_event(args) do
|
||||
with organizer_actor <- Map.get(args, :organizer_actor),
|
||||
args <- extract_pictures_from_event_body(args, organizer_actor),
|
||||
args <-
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
process_picture(picture, organizer_actor)
|
||||
@@ -30,6 +32,7 @@ defmodule Mobilizon.GraphQL.API.Events do
|
||||
@spec update_event(map, Event.t()) :: {:ok, Activity.t(), Event.t()} | any
|
||||
def update_event(args, %Event{} = event) do
|
||||
with organizer_actor <- Map.get(args, :organizer_actor),
|
||||
args <- extract_pictures_from_event_body(args, organizer_actor),
|
||||
args <-
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
process_picture(picture, organizer_actor)
|
||||
@@ -40,23 +43,32 @@ defmodule Mobilizon.GraphQL.API.Events do
|
||||
|
||||
@doc """
|
||||
Trigger the deletion of an event
|
||||
|
||||
If the event is deleted by
|
||||
"""
|
||||
def delete_event(%Event{} = event, %Actor{} = actor, federate \\ true) do
|
||||
ActivityPub.delete(event, actor, federate)
|
||||
end
|
||||
|
||||
defp process_picture(nil, _), do: nil
|
||||
defp process_picture(%{picture_id: _picture_id} = args, _), do: args
|
||||
defp process_picture(%{media_id: _picture_id} = args, _), do: args
|
||||
|
||||
defp process_picture(%{picture: picture}, %Actor{id: actor_id}) do
|
||||
defp process_picture(%{media: media}, %Actor{id: actor_id}) do
|
||||
%{
|
||||
file:
|
||||
picture
|
||||
media
|
||||
|> Map.get(:file)
|
||||
|> Utils.make_picture_data(description: Map.get(picture, :name)),
|
||||
|> Utils.make_media_data(description: Map.get(media, :name)),
|
||||
actor_id: actor_id
|
||||
}
|
||||
end
|
||||
|
||||
@spec extract_pictures_from_event_body(map(), Actor.t()) :: map()
|
||||
defp extract_pictures_from_event_body(
|
||||
%{description: description} = args,
|
||||
%Actor{id: organizer_actor_id}
|
||||
) do
|
||||
pictures = APIUtils.extract_pictures_from_body(description, organizer_actor_id)
|
||||
Map.put(args, :media, pictures)
|
||||
end
|
||||
|
||||
defp extract_pictures_from_event_body(args, _), do: args
|
||||
end
|
||||
|
||||
@@ -3,7 +3,8 @@ defmodule Mobilizon.GraphQL.API.Utils do
|
||||
Utils for API.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.{Config, Medias}
|
||||
alias Mobilizon.Medias.Media
|
||||
alias Mobilizon.Service.Formatter
|
||||
|
||||
@doc """
|
||||
@@ -40,4 +41,41 @@ defmodule Mobilizon.GraphQL.API.Utils do
|
||||
{:error, "Comment must be up to #{max_size} characters"}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Use the data-media-id attributes to extract media from body text
|
||||
"""
|
||||
@spec extract_pictures_from_body(String.t(), integer() | String.t()) :: list(Media.t())
|
||||
def extract_pictures_from_body(body, actor_id) do
|
||||
body
|
||||
|> do_extract_pictures_from_body()
|
||||
|> Enum.map(&fetch_picture(&1, actor_id))
|
||||
|> Enum.filter(& &1)
|
||||
end
|
||||
|
||||
@spec do_extract_pictures_from_body(String.t()) :: list(String.t())
|
||||
defp do_extract_pictures_from_body(body) when is_nil(body) or body == "", do: []
|
||||
|
||||
defp do_extract_pictures_from_body(body) do
|
||||
{:ok, document} = Floki.parse_document(body)
|
||||
|
||||
document
|
||||
|> Floki.attribute("img", "data-media-id")
|
||||
end
|
||||
|
||||
@spec fetch_picture(String.t() | integer(), String.t() | integer()) :: Media.t() | nil
|
||||
defp fetch_picture(id, actor_id) do
|
||||
with %Media{actor_id: media_actor_id} = media <- Medias.get_media(id),
|
||||
{:owns_media, true} <-
|
||||
{:owns_media, check_actor_owns_media?(actor_id, media_actor_id)} do
|
||||
media
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
@spec check_actor_owns_media?(integer() | String.t(), integer() | String.t()) :: boolean()
|
||||
defp check_actor_owns_media?(actor_id, media_actor_id) do
|
||||
actor_id == media_actor_id || Mobilizon.Actors.is_member?(media_actor_id, actor_id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,6 +7,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions.{Comment, Discussion}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.GraphQL.API.Comments
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Users.User
|
||||
import Mobilizon.Web.Gettext
|
||||
@@ -94,17 +95,13 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
||||
with {:actor, %Actor{id: creator_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(creator_id, group_id)},
|
||||
{:ok, _activity, %Discussion{} = discussion} <-
|
||||
ActivityPub.create(
|
||||
:discussion,
|
||||
%{
|
||||
title: title,
|
||||
text: text,
|
||||
actor_id: group_id,
|
||||
creator_id: creator_id,
|
||||
attributed_to_id: group_id
|
||||
},
|
||||
true
|
||||
) do
|
||||
Comments.create_discussion(%{
|
||||
title: title,
|
||||
text: text,
|
||||
actor_id: group_id,
|
||||
creator_id: creator_id,
|
||||
attributed_to_id: group_id
|
||||
}) do
|
||||
{:ok, discussion}
|
||||
else
|
||||
{:member, false} ->
|
||||
@@ -134,19 +131,15 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
||||
{:no_discussion, Discussions.get_discussion(discussion_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
|
||||
{:ok, _activity, %Discussion{} = discussion} <-
|
||||
ActivityPub.create(
|
||||
:discussion,
|
||||
%{
|
||||
text: text,
|
||||
discussion_id: discussion_id,
|
||||
actor_id: creator_id,
|
||||
attributed_to_id: actor_id,
|
||||
in_reply_to_comment_id: last_comment_id,
|
||||
origin_comment_id:
|
||||
origin_comment_id || previous_in_reply_to_comment_id || last_comment_id
|
||||
},
|
||||
true
|
||||
) do
|
||||
Comments.create_discussion(%{
|
||||
text: text,
|
||||
discussion_id: discussion_id,
|
||||
actor_id: creator_id,
|
||||
attributed_to_id: actor_id,
|
||||
in_reply_to_comment_id: last_comment_id,
|
||||
origin_comment_id:
|
||||
origin_comment_id || previous_in_reply_to_comment_id || last_comment_id
|
||||
}) do
|
||||
{:ok, discussion}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,8 +96,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
# TODO Move me to somewhere cleaner
|
||||
defp save_attached_pictures(args) do
|
||||
Enum.reduce([:avatar, :banner], args, fn key, args ->
|
||||
if Map.has_key?(args, key) && !is_nil(args[key][:picture]) do
|
||||
pic = args[key][:picture]
|
||||
if Map.has_key?(args, key) && !is_nil(args[key][:media]) do
|
||||
pic = args[key][:media]
|
||||
|
||||
with {:ok, %{name: name, url: url, content_type: content_type, size: _size}} <-
|
||||
Upload.store(pic.file, type: key, description: pic.alt) do
|
||||
|
||||
@@ -1,50 +1,47 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.Picture do
|
||||
defmodule Mobilizon.GraphQL.Resolvers.Media do
|
||||
@moduledoc """
|
||||
Handles the picture-related GraphQL calls
|
||||
Handles the media-related GraphQL calls
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.{Media, Users}
|
||||
alias Mobilizon.Media.Picture
|
||||
alias Mobilizon.{Medias, Users}
|
||||
alias Mobilizon.Medias.Media
|
||||
alias Mobilizon.Users.User
|
||||
import Mobilizon.Web.Gettext
|
||||
|
||||
@doc """
|
||||
Get picture for an event
|
||||
Get media for an event
|
||||
|
||||
See Mobilizon.Web.Resolvers.Event.create_event/3
|
||||
"""
|
||||
def picture(%{picture_id: picture_id} = _parent, _args, _resolution) do
|
||||
with {:ok, picture} <- do_fetch_picture(picture_id), do: {:ok, picture}
|
||||
def media(%{picture_id: media_id} = _parent, _args, _resolution) do
|
||||
with {:ok, media} <- do_fetch_media(media_id), do: {:ok, media}
|
||||
end
|
||||
|
||||
def picture(%{picture: picture} = _parent, _args, _resolution), do: {:ok, picture}
|
||||
def picture(_parent, %{id: picture_id}, _resolution), do: do_fetch_picture(picture_id)
|
||||
def picture(_parent, _args, _resolution), do: {:ok, nil}
|
||||
def media(%{picture: media} = _parent, _args, _resolution), do: {:ok, media}
|
||||
def media(_parent, %{id: media_id}, _resolution), do: do_fetch_media(media_id)
|
||||
def media(_parent, _args, _resolution), do: {:ok, nil}
|
||||
|
||||
@spec do_fetch_picture(nil) :: {:error, nil}
|
||||
defp do_fetch_picture(nil), do: {:error, nil}
|
||||
def medias(%{media: medias}, _args, _resolution) do
|
||||
{:ok, Enum.map(medias, &transform_media/1)}
|
||||
end
|
||||
|
||||
@spec do_fetch_picture(String.t()) :: {:ok, Picture.t()} | {:error, :not_found}
|
||||
defp do_fetch_picture(picture_id) do
|
||||
case Media.get_picture(picture_id) do
|
||||
%Picture{id: id, file: file} ->
|
||||
{:ok,
|
||||
%{
|
||||
name: file.name,
|
||||
url: file.url,
|
||||
id: id,
|
||||
content_type: file.content_type,
|
||||
size: file.size
|
||||
}}
|
||||
@spec do_fetch_media(nil) :: {:error, nil}
|
||||
defp do_fetch_media(nil), do: {:error, nil}
|
||||
|
||||
@spec do_fetch_media(String.t()) :: {:ok, Media.t()} | {:error, :not_found}
|
||||
defp do_fetch_media(media_id) do
|
||||
case Medias.get_media(media_id) do
|
||||
%Media{} = media ->
|
||||
{:ok, transform_media(media)}
|
||||
|
||||
nil ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
@spec upload_picture(map, map, map) :: {:ok, Picture.t()} | {:error, any}
|
||||
def upload_picture(
|
||||
@spec upload_media(map, map, map) :: {:ok, Media.t()} | {:error, any}
|
||||
def upload_media(
|
||||
_parent,
|
||||
%{file: %Plug.Upload{} = file} = args,
|
||||
%{context: %{current_user: %User{} = user}}
|
||||
@@ -57,16 +54,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Picture do
|
||||
|> Map.put(:url, url)
|
||||
|> Map.put(:size, size)
|
||||
|> Map.put(:content_type, content_type),
|
||||
{:ok, picture = %Picture{}} <-
|
||||
Media.create_picture(%{"file" => args, "actor_id" => actor_id}) do
|
||||
{:ok,
|
||||
%{
|
||||
name: picture.file.name,
|
||||
url: picture.file.url,
|
||||
id: picture.id,
|
||||
content_type: picture.file.content_type,
|
||||
size: picture.file.size
|
||||
}}
|
||||
{:ok, media = %Media{}} <-
|
||||
Medias.create_media(%{"file" => args, "actor_id" => actor_id}) do
|
||||
{:ok, transform_media(media)}
|
||||
else
|
||||
{:error, :mime_type_not_allowed} ->
|
||||
{:error, dgettext("errors", "File doesn't have an allowed MIME type.")}
|
||||
@@ -76,28 +66,28 @@ defmodule Mobilizon.GraphQL.Resolvers.Picture do
|
||||
end
|
||||
end
|
||||
|
||||
def upload_picture(_parent, _args, _resolution), do: {:error, :unauthenticated}
|
||||
def upload_media(_parent, _args, _resolution), do: {:error, :unauthenticated}
|
||||
|
||||
@doc """
|
||||
Remove a picture that the user owns
|
||||
Remove a media that the user owns
|
||||
"""
|
||||
@spec remove_picture(map(), map(), map()) ::
|
||||
{:ok, Picture.t()}
|
||||
@spec remove_media(map(), map(), map()) ::
|
||||
{:ok, Media.t()}
|
||||
| {:error, :unauthorized}
|
||||
| {:error, :unauthenticated}
|
||||
| {:error, :not_found}
|
||||
def remove_picture(_parent, %{id: picture_id}, %{context: %{current_user: %User{} = user}}) do
|
||||
with {:picture, %Picture{actor_id: actor_id} = picture} <-
|
||||
{:picture, Media.get_picture(picture_id)},
|
||||
def remove_media(_parent, %{id: media_id}, %{context: %{current_user: %User{} = user}}) do
|
||||
with {:media, %Media{actor_id: actor_id} = media} <-
|
||||
{:media, Medias.get_media(media_id)},
|
||||
{:is_owned, %Actor{} = _actor} <- User.owns_actor(user, actor_id) do
|
||||
Media.delete_picture(picture)
|
||||
Medias.delete_media(media)
|
||||
else
|
||||
{:picture, nil} -> {:error, :not_found}
|
||||
{:media, nil} -> {:error, :not_found}
|
||||
{:is_owned, _} -> {:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
def remove_picture(_parent, _args, _resolution), do: {:error, :unauthenticated}
|
||||
def remove_media(_parent, _args, _resolution), do: {:error, :unauthenticated}
|
||||
|
||||
@doc """
|
||||
Return the total media size for an actor
|
||||
@@ -108,7 +98,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Picture do
|
||||
context: %{current_user: %User{} = user}
|
||||
}) do
|
||||
if can_get_actor_size?(user, actor_id) do
|
||||
{:ok, Media.media_size_for_actor(actor_id)}
|
||||
{:ok, Medias.media_size_for_actor(actor_id)}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
@@ -125,7 +115,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Picture do
|
||||
context: %{current_user: %User{} = logged_user}
|
||||
}) do
|
||||
if can_get_user_size?(logged_user, user_id) do
|
||||
{:ok, Media.media_size_for_user(user_id)}
|
||||
{:ok, Medias.media_size_for_user(user_id)}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
@@ -133,6 +123,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Picture do
|
||||
|
||||
def user_size(_parent, _args, _resolution), do: {:error, :unauthenticated}
|
||||
|
||||
@spec transform_media(Media.t()) :: map()
|
||||
defp transform_media(%Media{id: id, file: file}) do
|
||||
%{
|
||||
name: file.name,
|
||||
url: file.url,
|
||||
id: id,
|
||||
content_type: file.content_type,
|
||||
size: file.size
|
||||
}
|
||||
end
|
||||
|
||||
@spec can_get_user_size?(User.t(), integer()) :: boolean()
|
||||
defp can_get_actor_size?(%User{role: role} = user, actor_id) do
|
||||
role in [:moderator, :administrator] || owns_actor?(User.owns_actor(user, actor_id))
|
||||
@@ -13,6 +13,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
|
||||
import Mobilizon.Web.Gettext
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
require Logger
|
||||
|
||||
alias Mobilizon.Web.{MediaProxy, Upload}
|
||||
|
||||
@@ -137,6 +138,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
|
||||
%{id: id} = args,
|
||||
%{context: %{current_user: user}} = _resolution
|
||||
) do
|
||||
require Logger
|
||||
args = Map.put(args, :user_id, user.id)
|
||||
|
||||
with {:find_actor, %Actor{} = actor} <-
|
||||
@@ -198,11 +200,11 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
|
||||
|
||||
defp save_attached_pictures(args) do
|
||||
Enum.reduce([:avatar, :banner], args, fn key, args ->
|
||||
if Map.has_key?(args, key) && !is_nil(args[key][:picture]) do
|
||||
pic = args[key][:picture]
|
||||
if Map.has_key?(args, key) && !is_nil(args[key][:media]) do
|
||||
media = args[key][:media]
|
||||
|
||||
with {:ok, %{name: name, url: url, content_type: content_type, size: _size}} <-
|
||||
Upload.store(pic.file, type: key, description: pic.alt) do
|
||||
Upload.store(media.file, type: key, description: media.alt) do
|
||||
Map.put(args, key, %{"name" => name, "url" => url, "mediaType" => content_type})
|
||||
end
|
||||
else
|
||||
|
||||
@@ -116,6 +116,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
process_picture(picture, group)
|
||||
end),
|
||||
args <- extract_pictures_from_post_body(args, actor_id),
|
||||
{:ok, _, %Post{} = post} <-
|
||||
ActivityPub.create(
|
||||
:post,
|
||||
@@ -156,6 +157,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
process_picture(picture, group)
|
||||
end),
|
||||
args <- extract_pictures_from_post_body(args, actor_id),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, _, %Post{} = post} <-
|
||||
ActivityPub.update(post, args, true, %{"actor" => actor_url}) do
|
||||
@@ -210,15 +212,23 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
||||
end
|
||||
|
||||
defp process_picture(nil, _), do: nil
|
||||
defp process_picture(%{picture_id: _picture_id} = args, _), do: args
|
||||
defp process_picture(%{media_id: _picture_id} = args, _), do: args
|
||||
|
||||
defp process_picture(%{picture: picture}, %Actor{id: actor_id}) do
|
||||
defp process_picture(%{media: media}, %Actor{id: actor_id}) do
|
||||
%{
|
||||
file:
|
||||
picture
|
||||
media
|
||||
|> Map.get(:file)
|
||||
|> Utils.make_picture_data(description: Map.get(picture, :name)),
|
||||
|> Utils.make_media_data(description: Map.get(media, :name)),
|
||||
actor_id: actor_id
|
||||
}
|
||||
end
|
||||
|
||||
@spec extract_pictures_from_post_body(map(), String.t()) :: map()
|
||||
defp extract_pictures_from_post_body(%{body: body} = args, actor_id) do
|
||||
pictures = Mobilizon.GraphQL.API.Utils.extract_pictures_from_body(body, actor_id)
|
||||
Map.put(args, :media, pictures)
|
||||
end
|
||||
|
||||
defp extract_pictures_from_post_body(args, _actor_id), do: args
|
||||
end
|
||||
|
||||
@@ -529,7 +529,7 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
context: %{current_user: %User{id: logged_in_user_id}}
|
||||
})
|
||||
when user_id == logged_in_user_id do
|
||||
%{elements: elements, total: total} = Mobilizon.Media.pictures_for_user(user_id, page, limit)
|
||||
%{elements: elements, total: total} = Mobilizon.Medias.medias_for_user(user_id, page, limit)
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
|
||||
@@ -30,7 +30,7 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
import_types(Schema.Custom.Point)
|
||||
|
||||
import_types(Schema.UserType)
|
||||
import_types(Schema.PictureType)
|
||||
import_types(Schema.MediaType)
|
||||
import_types(Schema.ActorInterface)
|
||||
import_types(Schema.Actors.PersonType)
|
||||
import_types(Schema.Actors.GroupType)
|
||||
@@ -145,7 +145,7 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
import_fields(:tag_queries)
|
||||
import_fields(:address_queries)
|
||||
import_fields(:config_queries)
|
||||
import_fields(:picture_queries)
|
||||
import_fields(:media_queries)
|
||||
import_fields(:report_queries)
|
||||
import_fields(:admin_queries)
|
||||
import_fields(:todo_list_queries)
|
||||
@@ -168,7 +168,7 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
import_fields(:participant_mutations)
|
||||
import_fields(:member_mutations)
|
||||
import_fields(:feed_token_mutations)
|
||||
import_fields(:picture_mutations)
|
||||
import_fields(:media_mutations)
|
||||
import_fields(:report_mutations)
|
||||
import_fields(:admin_mutations)
|
||||
import_fields(:todo_list_mutations)
|
||||
|
||||
@@ -28,8 +28,8 @@ defmodule Mobilizon.GraphQL.Schema.ActorInterface do
|
||||
|
||||
field(:suspended, :boolean, description: "If the actor is suspended")
|
||||
|
||||
field(:avatar, :picture, description: "The actor's avatar picture")
|
||||
field(:banner, :picture, description: "The actor's banner picture")
|
||||
field(:avatar, :media, description: "The actor's avatar media")
|
||||
field(:banner, :media, description: "The actor's banner media")
|
||||
|
||||
# These one should have a privacy setting
|
||||
field(:following, list_of(:follower), description: "List of followings")
|
||||
|
||||
@@ -3,7 +3,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.ApplicationType do
|
||||
Schema representation for Group.
|
||||
"""
|
||||
|
||||
alias Mobilizon.GraphQL.Resolvers.Picture
|
||||
alias Mobilizon.GraphQL.Resolvers.Media
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
@desc """
|
||||
@@ -27,8 +27,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.ApplicationType do
|
||||
|
||||
field(:suspended, :boolean, description: "If the actor is suspended")
|
||||
|
||||
field(:avatar, :picture, description: "The actor's avatar picture")
|
||||
field(:banner, :picture, description: "The actor's banner picture")
|
||||
field(:avatar, :media, description: "The actor's avatar media")
|
||||
field(:banner, :media, description: "The actor's banner media")
|
||||
|
||||
# These one should have a privacy setting
|
||||
field(:following, list_of(:follower), description: "List of followings")
|
||||
@@ -37,7 +37,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.ApplicationType do
|
||||
field(:followingCount, :integer, description: "Number of actors following this actor")
|
||||
|
||||
field(:media_size, :integer,
|
||||
resolve: &Picture.actor_size/3,
|
||||
resolve: &Media.actor_size/3,
|
||||
description: "The total size of the media from this actor"
|
||||
)
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
|
||||
alias Mobilizon.Addresses
|
||||
alias Mobilizon.GraphQL.Resolvers.{Discussion, Group, Member, Picture, Post, Resource, Todos}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Discussion, Group, Media, Member, Post, Resource, Todos}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
|
||||
import_types(Schema.Actors.MemberType)
|
||||
@@ -38,8 +38,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
|
||||
field(:suspended, :boolean, description: "If the actor is suspended")
|
||||
|
||||
field(:avatar, :picture, description: "The actor's avatar picture")
|
||||
field(:banner, :picture, description: "The actor's banner picture")
|
||||
field(:avatar, :media, description: "The actor's avatar media")
|
||||
field(:banner, :media, description: "The actor's banner media")
|
||||
|
||||
field(:physical_address, :address,
|
||||
resolve: dataloader(Addresses),
|
||||
@@ -53,7 +53,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
field(:followingCount, :integer, description: "Number of actors following this actor")
|
||||
|
||||
field(:media_size, :integer,
|
||||
resolve: &Picture.actor_size/3,
|
||||
resolve: &Media.actor_size/3,
|
||||
description: "The total size of the media from this actor"
|
||||
)
|
||||
|
||||
@@ -198,14 +198,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
default_value: :public
|
||||
)
|
||||
|
||||
arg(:avatar, :picture_input,
|
||||
arg(:avatar, :media_input,
|
||||
description:
|
||||
"The avatar for the group, either as an object or directly the ID of an existing Picture"
|
||||
"The avatar for the group, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:banner, :picture_input,
|
||||
arg(:banner, :media_input,
|
||||
description:
|
||||
"The banner for the group, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the group, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:physical_address, :address_input, description: "The physical address for the group")
|
||||
@@ -226,14 +226,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description: "Whether the group can be join freely, with approval or is invite-only."
|
||||
)
|
||||
|
||||
arg(:avatar, :picture_input,
|
||||
arg(:avatar, :media_input,
|
||||
description:
|
||||
"The avatar for the group, either as an object or directly the ID of an existing Picture"
|
||||
"The avatar for the group, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:banner, :picture_input,
|
||||
arg(:banner, :media_input,
|
||||
description:
|
||||
"The banner for the group, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the group, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:physical_address, :address_input, description: "The physical address for the group")
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.GraphQL.Resolvers.{Person, Picture}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Media, Person}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
|
||||
import_types(Schema.Events.FeedTokenType)
|
||||
@@ -40,8 +40,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
field(:suspended, :boolean, description: "If the actor is suspended")
|
||||
|
||||
field(:avatar, :picture, description: "The actor's avatar picture")
|
||||
field(:banner, :picture, description: "The actor's banner picture")
|
||||
field(:avatar, :media, description: "The actor's avatar media")
|
||||
field(:banner, :media, description: "The actor's banner media")
|
||||
|
||||
# These one should have a privacy setting
|
||||
field(:following, list_of(:follower), description: "List of followings")
|
||||
@@ -50,7 +50,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
field(:followingCount, :integer, description: "Number of actors following this actor")
|
||||
|
||||
field(:media_size, :integer,
|
||||
resolve: &Picture.actor_size/3,
|
||||
resolve: &Media.actor_size/3,
|
||||
description: "The total size of the media from this actor"
|
||||
)
|
||||
|
||||
@@ -150,14 +150,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
arg(:summary, :string, description: "The summary for the new profile", default_value: "")
|
||||
|
||||
arg(:avatar, :picture_input,
|
||||
arg(:avatar, :media_input,
|
||||
description:
|
||||
"The avatar for the profile, either as an object or directly the ID of an existing Picture"
|
||||
"The avatar for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:banner, :picture_input,
|
||||
arg(:banner, :media_input,
|
||||
description:
|
||||
"The banner for the profile, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
resolve(&Person.create_person/3)
|
||||
@@ -171,14 +171,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
arg(:summary, :string, description: "The summary for this profile")
|
||||
|
||||
arg(:avatar, :picture_input,
|
||||
arg(:avatar, :media_input,
|
||||
description:
|
||||
"The avatar for the profile, either as an object or directly the ID of an existing Picture"
|
||||
"The avatar for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:banner, :picture_input,
|
||||
arg(:banner, :media_input,
|
||||
description:
|
||||
"The banner for the profile, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
resolve(&Person.update_person/3)
|
||||
@@ -200,14 +200,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
arg(:summary, :string, description: "The summary for the new profile", default_value: "")
|
||||
arg(:email, non_null(:string), description: "The email from the user previously created")
|
||||
|
||||
arg(:avatar, :picture_input,
|
||||
arg(:avatar, :media_input,
|
||||
description:
|
||||
"The avatar for the profile, either as an object or directly the ID of an existing Picture"
|
||||
"The avatar for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:banner, :picture_input,
|
||||
arg(:banner, :media_input,
|
||||
description:
|
||||
"The banner for the profile, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
resolve(&Person.register_person/3)
|
||||
|
||||
@@ -43,7 +43,6 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
An address input
|
||||
"""
|
||||
input_object :address_input do
|
||||
# Either a full picture object
|
||||
field(:geom, :point, description: "The geocoordinates for the point where this address is")
|
||||
field(:street, :string, description: "The address's street name (with number)")
|
||||
field(:locality, :string, description: "The address's locality")
|
||||
|
||||
@@ -8,7 +8,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
|
||||
alias Mobilizon.{Actors, Addresses, Discussions}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Event, Picture, Tag}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Event, Media, Tag}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
|
||||
import_types(Schema.AddressType)
|
||||
@@ -31,9 +31,14 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
field(:visibility, :event_visibility, description: "The event's visibility")
|
||||
field(:join_options, :event_join_options, description: "The event's visibility")
|
||||
|
||||
field(:picture, :picture,
|
||||
field(:picture, :media,
|
||||
description: "The event's picture",
|
||||
resolve: &Picture.picture/3
|
||||
resolve: &Media.media/3
|
||||
)
|
||||
|
||||
field(:media, list_of(:media),
|
||||
description: "The event's media",
|
||||
resolve: &Media.medias/3
|
||||
)
|
||||
|
||||
field(:publish_at, :datetime, description: "When the event was published")
|
||||
@@ -328,9 +333,9 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
description: "The list of tags associated to the event"
|
||||
)
|
||||
|
||||
arg(:picture, :picture_input,
|
||||
arg(:picture, :media_input,
|
||||
description:
|
||||
"The picture for the event, either as an object or directly the ID of an existing Picture"
|
||||
"The picture for the event, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:publish_at, :datetime, description: "Datetime when the event was published")
|
||||
@@ -379,9 +384,9 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
|
||||
arg(:tags, list_of(:string), description: "The list of tags associated to the event")
|
||||
|
||||
arg(:picture, :picture_input,
|
||||
arg(:picture, :media_input,
|
||||
description:
|
||||
"The picture for the event, either as an object or directly the ID of an existing Picture"
|
||||
"The picture for the event, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
arg(:online_address, :string, description: "Online address of the event")
|
||||
|
||||
68
lib/graphql/schema/media.ex
Normal file
68
lib/graphql/schema/media.ex
Normal file
@@ -0,0 +1,68 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
@moduledoc """
|
||||
Schema representation for Medias
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
alias Mobilizon.GraphQL.Resolvers.Media
|
||||
|
||||
@desc "A media"
|
||||
object :media do
|
||||
field(:id, :id, description: "The media's ID")
|
||||
field(:alt, :string, description: "The media's alternative text")
|
||||
field(:name, :string, description: "The media's name")
|
||||
field(:url, :string, description: "The media's full URL")
|
||||
field(:content_type, :string, description: "The media's detected content type")
|
||||
field(:size, :integer, description: "The media's size")
|
||||
end
|
||||
|
||||
@desc """
|
||||
A paginated list of medias
|
||||
"""
|
||||
object :paginated_media_list do
|
||||
field(:elements, list_of(:media), description: "The list of medias")
|
||||
field(:total, :integer, description: "The total number of medias in the list")
|
||||
end
|
||||
|
||||
@desc "An attached media or a link to a media"
|
||||
input_object :media_input do
|
||||
# Either a full media object
|
||||
field(:media, :media_input_object, description: "A full media attached")
|
||||
# Or directly the ID of an existing media
|
||||
field(:media_id, :id, description: "The ID of an existing media")
|
||||
end
|
||||
|
||||
@desc "An attached media"
|
||||
input_object :media_input_object do
|
||||
field(:name, non_null(:string), description: "The media's name")
|
||||
field(:alt, :string, description: "The media's alternative text")
|
||||
field(:file, non_null(:upload), description: "The media file")
|
||||
field(:actor_id, :id, description: "The media owner")
|
||||
end
|
||||
|
||||
object :media_queries do
|
||||
@desc "Get a media"
|
||||
field :media, :media do
|
||||
arg(:id, non_null(:id), description: "The media ID")
|
||||
resolve(&Media.media/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :media_mutations do
|
||||
@desc "Upload a media"
|
||||
field :upload_media, :media do
|
||||
arg(:name, non_null(:string), description: "The media's name")
|
||||
arg(:alt, :string, description: "The media's alternative text")
|
||||
arg(:file, non_null(:upload), description: "The media file")
|
||||
resolve(&Media.upload_media/3)
|
||||
end
|
||||
|
||||
@desc """
|
||||
Remove a media
|
||||
"""
|
||||
field :remove_media, :deleted_object do
|
||||
arg(:id, non_null(:id), description: "The media's ID")
|
||||
resolve(&Media.remove_media/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,68 +0,0 @@
|
||||
defmodule Mobilizon.GraphQL.Schema.PictureType do
|
||||
@moduledoc """
|
||||
Schema representation for Pictures
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
alias Mobilizon.GraphQL.Resolvers.Picture
|
||||
|
||||
@desc "A picture"
|
||||
object :picture do
|
||||
field(:id, :id, description: "The picture's ID")
|
||||
field(:alt, :string, description: "The picture's alternative text")
|
||||
field(:name, :string, description: "The picture's name")
|
||||
field(:url, :string, description: "The picture's full URL")
|
||||
field(:content_type, :string, description: "The picture's detected content type")
|
||||
field(:size, :integer, description: "The picture's size")
|
||||
end
|
||||
|
||||
@desc """
|
||||
A paginated list of pictures
|
||||
"""
|
||||
object :paginated_picture_list do
|
||||
field(:elements, list_of(:picture), description: "The list of pictures")
|
||||
field(:total, :integer, description: "The total number of pictures in the list")
|
||||
end
|
||||
|
||||
@desc "An attached picture or a link to a picture"
|
||||
input_object :picture_input do
|
||||
# Either a full picture object
|
||||
field(:picture, :picture_input_object, description: "A full picture attached")
|
||||
# Or directly the ID of an existing picture
|
||||
field(:picture_id, :id, description: "The ID of an existing picture")
|
||||
end
|
||||
|
||||
@desc "An attached picture"
|
||||
input_object :picture_input_object do
|
||||
field(:name, non_null(:string), description: "The picture's name")
|
||||
field(:alt, :string, description: "The picture's alternative text")
|
||||
field(:file, non_null(:upload), description: "The picture file")
|
||||
field(:actor_id, :id, description: "The picture owner")
|
||||
end
|
||||
|
||||
object :picture_queries do
|
||||
@desc "Get a picture"
|
||||
field :picture, :picture do
|
||||
arg(:id, non_null(:id), description: "The picture ID")
|
||||
resolve(&Picture.picture/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :picture_mutations do
|
||||
@desc "Upload a picture"
|
||||
field :upload_picture, :picture do
|
||||
arg(:name, non_null(:string), description: "The picture's name")
|
||||
arg(:alt, :string, description: "The picture's alternative text")
|
||||
arg(:file, non_null(:upload), description: "The picture file")
|
||||
resolve(&Picture.upload_picture/3)
|
||||
end
|
||||
|
||||
@desc """
|
||||
Remove a picture
|
||||
"""
|
||||
field :remove_picture, :deleted_object do
|
||||
arg(:id, non_null(:id), description: "The picture's ID")
|
||||
resolve(&Picture.remove_picture/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,7 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
Schema representation for Posts
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
alias Mobilizon.GraphQL.Resolvers.{Picture, Post, Tag}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Media, Post, Tag}
|
||||
|
||||
@desc "A post"
|
||||
object :post do
|
||||
@@ -25,9 +25,9 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
description: "The post's tags"
|
||||
)
|
||||
|
||||
field(:picture, :picture,
|
||||
description: "The posts's picture",
|
||||
resolve: &Picture.picture/3
|
||||
field(:picture, :media,
|
||||
description: "The posts's media",
|
||||
resolve: &Media.media/3
|
||||
)
|
||||
end
|
||||
|
||||
@@ -76,9 +76,9 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
description: "The list of tags associated to the post"
|
||||
)
|
||||
|
||||
arg(:picture, :picture_input,
|
||||
arg(:picture, :media_input,
|
||||
description:
|
||||
"The banner for the post, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the post, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
resolve(&Post.create_post/3)
|
||||
@@ -99,9 +99,9 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
|
||||
arg(:tags, list_of(:string), description: "The list of tags associated to the post")
|
||||
|
||||
arg(:picture, :picture_input,
|
||||
arg(:picture, :media_input,
|
||||
description:
|
||||
"The banner for the post, either as an object or directly the ID of an existing Picture"
|
||||
"The banner for the post, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
resolve(&Post.update_post/3)
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.GraphQL.Resolvers.{Picture, User}
|
||||
alias Mobilizon.GraphQL.Resolvers.{Media, User}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
|
||||
import_types(Schema.SortType)
|
||||
@@ -111,7 +111,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
description: "The IP adress the user's currently signed-in with"
|
||||
)
|
||||
|
||||
field(:media, :paginated_picture_list, description: "The user's media objects") do
|
||||
field(:media, :paginated_media_list, description: "The user's media objects") do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated user media list"
|
||||
@@ -122,7 +122,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
end
|
||||
|
||||
field(:media_size, :integer,
|
||||
resolve: &Picture.user_size/3,
|
||||
resolve: &Media.user_size/3,
|
||||
description: "The total size of all the media from this user (from all their actors)"
|
||||
)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user