Refactor media upload

Use Upload Media logic from Pleroma

Backend changes for picture upload

Move AS <-> Model conversion to separate module

Front changes

Downgrade apollo-client: https://github.com/Akryum/vue-apollo/issues/577

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2019-05-22 14:12:11 +02:00
parent 9724bc8e9f
commit f90089e1bf
113 changed files with 4718 additions and 1328 deletions

View File

@@ -5,6 +5,7 @@ defmodule MobilizonWeb.Resolvers.Event do
alias Mobilizon.Activity
alias Mobilizon.Events
alias Mobilizon.Events.{Event, Participant}
alias Mobilizon.Media.Picture
alias Mobilizon.Actors.Actor
alias Mobilizon.Users.User
@@ -185,16 +186,27 @@ defmodule MobilizonWeb.Resolvers.Event do
@doc """
Create an event
"""
def create_event(_parent, args, %{context: %{current_user: _user}}) do
with {:ok, %Activity{data: %{"object" => %{"type" => "Event"} = object}}} <-
def create_event(_parent, args, %{context: %{current_user: _user}} = _resolution) do
with {:ok, args} <- save_attached_picture(args),
{:ok, %Activity{data: %{"object" => %{"type" => "Event"} = object}}} <-
MobilizonWeb.API.Events.create_event(args) do
{:ok,
%Event{
title: object["name"],
description: object["content"],
uuid: object["uuid"],
url: object["id"]
}}
res = %{
title: object["name"],
description: object["content"],
uuid: object["uuid"],
url: object["id"]
}
res =
if Map.has_key?(object, "attachment"),
do:
Map.put(res, :picture, %{
name: object["attachment"] |> hd() |> Map.get("name"),
url: object["attachment"] |> hd() |> Map.get("url") |> hd() |> Map.get("href")
}),
else: res
{:ok, res}
end
end
@@ -202,6 +214,22 @@ defmodule MobilizonWeb.Resolvers.Event do
{:error, "You need to be logged-in to create events"}
end
# If we have an attached picture, just transmit it. It will be handled by
# Mobilizon.Service.ActivityPub.Utils.make_picture_data/1
@spec save_attached_picture(map()) :: {:ok, map()}
defp save_attached_picture(%{picture: %{picture: %Plug.Upload{} = _picture}} = args), do: args
# 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}
@doc """
Delete an event
"""

View File

@@ -47,12 +47,17 @@ defmodule MobilizonWeb.Resolvers.Person do
@doc """
This function is used to create more identities from an existing user
"""
def create_person(_parent, %{preferred_username: _preferred_username} = args, %{
context: %{current_user: user}
}) do
def create_person(
_parent,
%{preferred_username: _preferred_username} = args,
%{
context: %{current_user: user}
} = _resolution
) do
args = Map.put(args, :user_id, user.id)
with {:ok, %Actor{} = new_person} <- Actors.new_person(args) do
with args <- save_attached_pictures(args),
{:ok, %Actor{} = new_person} <- Actors.new_person(args) do
{:ok, new_person}
end
end
@@ -64,6 +69,21 @@ defmodule MobilizonWeb.Resolvers.Person do
{:error, "You need to be logged-in to create a new identity"}
end
defp save_attached_pictures(args) do
Enum.reduce([:avatar, :banner], args, fn key, args ->
if Map.has_key?(args, key) do
pic = args[key][:picture]
with {:ok, %{"name" => name, "url" => [%{"href" => url, "mediaType" => content_type}]}} <-
MobilizonWeb.Upload.store(pic.file, type: key, description: pic.alt) do
Map.put(args, key, %{"name" => name, "url" => url, "mediaType" => content_type})
end
else
args
end
end)
end
@doc """
This function is used to register a person afterwards the user has been created (but not activated)
"""
@@ -71,6 +91,7 @@ defmodule MobilizonWeb.Resolvers.Person do
with {:ok, %User{} = user} <- Users.get_user_by_email(args.email),
{:no_actor, nil} <- {:no_actor, Users.get_actor_for_user(user)},
args <- Map.put(args, :user_id, user.id),
args <- save_attached_pictures(args),
{:ok, %Actor{} = new_person} <- Actors.new_person(args) do
{:ok, new_person}
else

View File

@@ -0,0 +1,64 @@
defmodule MobilizonWeb.Resolvers.Picture do
@moduledoc """
Handles the picture-related GraphQL calls
"""
alias Mobilizon.Media
alias Mobilizon.Media.Picture
@doc """
Get picture for an event's pic
"""
def picture(%{picture_id: picture_id} = _parent, _args, _resolution) do
with {:ok, picture} <- do_fetch_picture(picture_id) do
{:ok, picture}
end
end
@doc """
Get picture for an event that has an attached
See MobilizonWeb.Resolvers.Event.create_event/3
"""
def picture(%{picture: picture} = _parent, _args, _resolution) do
{:ok, picture}
end
def picture(_parent, %{id: picture_id}, _resolution), do: do_fetch_picture(picture_id)
def picture(_parent, _args, _resolution) do
{:ok, nil}
end
@spec do_fetch_picture(nil) :: {:error, nil}
defp do_fetch_picture(nil), do: {:error, nil}
@spec do_fetch_picture(String.t()) :: {:ok, Picture.t()} | {:error, :not_found}
defp do_fetch_picture(picture_id) do
with %Picture{id: id, file: file} = _pic <- Media.get_picture(picture_id) do
{:ok, %{name: file.name, url: file.url, id: id}}
else
_err ->
{:error, "Picture with ID #{picture_id} was not found"}
end
end
@spec upload_picture(map(), map(), map()) :: {:ok, Picture.t()} | {:error, any()}
def upload_picture(_parent, %{file: %Plug.Upload{} = file} = args, %{
context: %{
current_user: _user
}
}) do
with {:ok, %{"url" => [%{"href" => url}]}} <- MobilizonWeb.Upload.store(file),
args <- Map.put(args, :url, url),
{:ok, picture = %Picture{}} <- Media.create_picture(%{"file" => args}) do
{:ok, %{name: picture.file.name, url: picture.file.url, id: picture.id}}
else
err ->
{:error, err}
end
end
def upload_picture(_parent, _args, _resolution) do
{:error, "You need to login to upload a picture"}
end
end