Compare commits
6 Commits
develop
...
feature/19
Author | SHA1 | Date |
---|---|---|
|
1bbbc15925 | |
|
019c211353 | |
|
3000f3ff7c | |
|
19713aca3e | |
|
057da2dd9c | |
|
319177260a |
|
@ -110,6 +110,8 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- Admin API: Importing emoji from a zip file
|
- Admin API: Importing emoji from a zip file
|
||||||
- Pleroma API: Importing the mutes users from CSV files.
|
- Pleroma API: Importing the mutes users from CSV files.
|
||||||
- Pleroma API: Pagination for remote/local packs and emoji.
|
- Pleroma API: Pagination for remote/local packs and emoji.
|
||||||
|
- Mastodon API: Add `filename` parameter to `POST /api/v1/media`, `POST /api/v2/media` and `PUT /api/v1/media/:id`
|
||||||
|
- Mastodon API: Add account setting for providing filename to post attachments
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@ Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
- `mime_type`: mime type of the attachment.
|
- `mime_type`: mime type of the attachment
|
||||||
|
- `filename`: filename of the attachment
|
||||||
|
|
||||||
### Attachment cap
|
### Attachment cap
|
||||||
|
|
||||||
|
@ -77,6 +78,8 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `notification_settings`: object, can be absent. See `/api/pleroma/notification_settings` for the parameters/keys returned.
|
- `notification_settings`: object, can be absent. See `/api/pleroma/notification_settings` for the parameters/keys returned.
|
||||||
- `accepts_chat_messages`: boolean, but can be null if we don't have that information about a user
|
- `accepts_chat_messages`: boolean, but can be null if we don't have that information about a user
|
||||||
- `favicon`: nullable URL string, Favicon image of the user's instance
|
- `favicon`: nullable URL string, Favicon image of the user's instance
|
||||||
|
- `show_attachment_filenames`: boolean, true when the user wants to display post attachment filenames
|
||||||
|
- `skip_thread_containment`: boolean, true when the user has skipping filtering out broken threads enabled
|
||||||
|
|
||||||
### Source
|
### Source
|
||||||
|
|
||||||
|
@ -204,6 +207,7 @@ Additional parameters can be added to the JSON body/Form data:
|
||||||
- `show_role` - if true, user's role (e.g admin, moderator) will be exposed to anyone in the API
|
- `show_role` - if true, user's role (e.g admin, moderator) will be exposed to anyone in the API
|
||||||
- `default_scope` - the scope returned under `privacy` key in Source subentity
|
- `default_scope` - the scope returned under `privacy` key in Source subentity
|
||||||
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
|
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
|
||||||
|
- `show_attachment_filenames` - if true, the post attachment filenames will be displayed
|
||||||
- `skip_thread_containment` - if true, skip filtering out broken threads
|
- `skip_thread_containment` - if true, skip filtering out broken threads
|
||||||
- `allow_following_move` - if true, allows automatically follow moved following accounts
|
- `allow_following_move` - if true, allows automatically follow moved following accounts
|
||||||
- `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
|
- `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
|
||||||
|
|
|
@ -272,7 +272,8 @@ See [Admin-API](admin_api.md)
|
||||||
"url": "https://pleroma.example.org/media/abcdefg.png",
|
"url": "https://pleroma.example.org/media/abcdefg.png",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"pleroma": {
|
"pleroma": {
|
||||||
"mime_type": "image/png"
|
"mime_type": "image/png",
|
||||||
|
"filename": "abcdefg.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -291,7 +292,8 @@ See [Admin-API](admin_api.md)
|
||||||
"url": "https://pleroma.example.org/media/abcdefg.png",
|
"url": "https://pleroma.example.org/media/abcdefg.png",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"pleroma": {
|
"pleroma": {
|
||||||
"mime_type": "image/png"
|
"mime_type": "image/png",
|
||||||
|
"filename": "abcdefg.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -72,6 +72,7 @@ def store(upload, opts \\ []) do
|
||||||
|
|
||||||
with {:ok, upload} <- prepare_upload(upload, opts),
|
with {:ok, upload} <- prepare_upload(upload, opts),
|
||||||
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
|
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
|
||||||
|
:ok <- check_filename_extension(upload.name, opts),
|
||||||
{:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload),
|
{:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload),
|
||||||
description = get_description(opts, upload),
|
description = get_description(opts, upload),
|
||||||
{_, true} <-
|
{_, true} <-
|
||||||
|
@ -89,7 +90,8 @@ def store(upload, opts \\ []) do
|
||||||
"href" => url_from_spec(upload, opts.base_url, url_spec)
|
"href" => url_from_spec(upload, opts.base_url, url_spec)
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name" => description
|
"name" => description,
|
||||||
|
"filename" => Map.get(opts, :filename)
|
||||||
}}
|
}}
|
||||||
else
|
else
|
||||||
{:description_limit, _} ->
|
{:description_limit, _} ->
|
||||||
|
@ -130,6 +132,7 @@ defp get_opts(opts) do
|
||||||
uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
|
uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
|
||||||
filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
|
filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
|
||||||
description: Keyword.get(opts, :description),
|
description: Keyword.get(opts, :description),
|
||||||
|
filename: Keyword.get(opts, :filename),
|
||||||
base_url:
|
base_url:
|
||||||
Keyword.get(
|
Keyword.get(
|
||||||
opts,
|
opts,
|
||||||
|
@ -197,6 +200,16 @@ defp check_file_size(path, size_limit) when is_integer(size_limit) and size_limi
|
||||||
|
|
||||||
defp check_file_size(_, _), do: :ok
|
defp check_file_size(_, _), do: :ok
|
||||||
|
|
||||||
|
defp check_filename_extension(name, %{filename: filename}) when is_binary(filename) do
|
||||||
|
if Path.extname(name) == Path.extname(filename) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, :invalid_filename_extension}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_filename_extension(_, _), do: :ok
|
||||||
|
|
||||||
# Creates a tempfile using the Plug.Upload Genserver which cleans them up
|
# Creates a tempfile using the Plug.Upload Genserver which cleans them up
|
||||||
# automatically.
|
# automatically.
|
||||||
defp tempfile_for_image(data) do
|
defp tempfile_for_image(data) do
|
||||||
|
|
|
@ -138,6 +138,7 @@ defmodule Pleroma.User do
|
||||||
field(:is_discoverable, :boolean, default: false)
|
field(:is_discoverable, :boolean, default: false)
|
||||||
field(:invisible, :boolean, default: false)
|
field(:invisible, :boolean, default: false)
|
||||||
field(:allow_following_move, :boolean, default: true)
|
field(:allow_following_move, :boolean, default: true)
|
||||||
|
field(:show_attachment_filenames, :boolean, default: false)
|
||||||
field(:skip_thread_containment, :boolean, default: false)
|
field(:skip_thread_containment, :boolean, default: false)
|
||||||
field(:actor_type, :string, default: "Person")
|
field(:actor_type, :string, default: "Person")
|
||||||
field(:also_known_as, {:array, :string}, default: [])
|
field(:also_known_as, {:array, :string}, default: [])
|
||||||
|
@ -503,6 +504,7 @@ def update_changeset(struct, params \\ %{}) do
|
||||||
:allow_following_move,
|
:allow_following_move,
|
||||||
:background,
|
:background,
|
||||||
:show_role,
|
:show_role,
|
||||||
|
:show_attachment_filenames,
|
||||||
:skip_thread_containment,
|
:skip_thread_containment,
|
||||||
:fields,
|
:fields,
|
||||||
:raw_fields,
|
:raw_fields,
|
||||||
|
|
|
@ -48,6 +48,7 @@ def render("credentials.json", %{user: user, for: for_user}) do
|
||||||
:hide_followers,
|
:hide_followers,
|
||||||
:hide_favorites,
|
:hide_favorites,
|
||||||
:allow_following_move,
|
:allow_following_move,
|
||||||
|
:show_attachment_filenames,
|
||||||
:show_role,
|
:show_role,
|
||||||
:skip_thread_containment,
|
:skip_thread_containment,
|
||||||
:pleroma_settings_store,
|
:pleroma_settings_store,
|
||||||
|
|
|
@ -604,6 +604,11 @@ defp update_credentials_request do
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "Opaque user settings to be saved on the backend."
|
description: "Opaque user settings to be saved on the backend."
|
||||||
},
|
},
|
||||||
|
show_attachment_filenames: %Schema{
|
||||||
|
allOf: [BooleanLike],
|
||||||
|
nullable: true,
|
||||||
|
description: "Show the attachment filenames"
|
||||||
|
},
|
||||||
skip_thread_containment: %Schema{
|
skip_thread_containment: %Schema{
|
||||||
allOf: [BooleanLike],
|
allOf: [BooleanLike],
|
||||||
nullable: true,
|
nullable: true,
|
||||||
|
@ -642,6 +647,7 @@ defp update_credentials_request do
|
||||||
show_role: false,
|
show_role: false,
|
||||||
default_scope: "private",
|
default_scope: "private",
|
||||||
pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
|
pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
|
||||||
|
show_attachment_filenames: false,
|
||||||
skip_thread_containment: false,
|
skip_thread_containment: false,
|
||||||
allow_following_move: false,
|
allow_following_move: false,
|
||||||
discoverable: false,
|
discoverable: false,
|
||||||
|
|
|
@ -46,6 +46,11 @@ defp create_request do
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "A plain-text description of the media, for accessibility purposes."
|
description: "A plain-text description of the media, for accessibility purposes."
|
||||||
},
|
},
|
||||||
|
filename: %Schema{
|
||||||
|
type: :string,
|
||||||
|
nullable: true,
|
||||||
|
description: "Filename of the media."
|
||||||
|
},
|
||||||
focus: %Schema{
|
focus: %Schema{
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0."
|
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0."
|
||||||
|
@ -85,8 +90,14 @@ defp update_request do
|
||||||
},
|
},
|
||||||
description: %Schema{
|
description: %Schema{
|
||||||
type: :string,
|
type: :string,
|
||||||
|
nullable: true,
|
||||||
description: "A plain-text description of the media, for accessibility purposes."
|
description: "A plain-text description of the media, for accessibility purposes."
|
||||||
},
|
},
|
||||||
|
filename: %Schema{
|
||||||
|
type: :string,
|
||||||
|
nullable: true,
|
||||||
|
description: "Filename of the media."
|
||||||
|
},
|
||||||
focus: %Schema{
|
focus: %Schema{
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0."
|
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0."
|
||||||
|
|
|
@ -76,6 +76,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "whether the user is a moderator of the local instance"
|
description: "whether the user is a moderator of the local instance"
|
||||||
},
|
},
|
||||||
|
show_attachment_filenames: %Schema{type: :boolean},
|
||||||
skip_thread_containment: %Schema{type: :boolean},
|
skip_thread_containment: %Schema{type: :boolean},
|
||||||
tags: %Schema{
|
tags: %Schema{
|
||||||
type: :array,
|
type: :array,
|
||||||
|
@ -172,6 +173,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
||||||
"hide_follows_count" => false,
|
"hide_follows_count" => false,
|
||||||
"is_admin" => false,
|
"is_admin" => false,
|
||||||
"is_moderator" => false,
|
"is_moderator" => false,
|
||||||
|
"show_attachment_filenames" => false,
|
||||||
"skip_thread_containment" => false,
|
"skip_thread_containment" => false,
|
||||||
"accepts_chat_messages" => true,
|
"accepts_chat_messages" => true,
|
||||||
"chat_token" =>
|
"chat_token" =>
|
||||||
|
|
|
@ -50,7 +50,12 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Attachment do
|
||||||
pleroma: %Schema{
|
pleroma: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: %{
|
properties: %{
|
||||||
mime_type: %Schema{type: :string, description: "mime type of the attachment"}
|
mime_type: %Schema{type: :string, description: "mime type of the attachment"},
|
||||||
|
filename: %Schema{
|
||||||
|
type: :string,
|
||||||
|
nullable: true,
|
||||||
|
description: "filename of the attachment"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -62,7 +67,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Attachment do
|
||||||
preview_url: "someurl",
|
preview_url: "someurl",
|
||||||
text_url: "someurl",
|
text_url: "someurl",
|
||||||
description: nil,
|
description: nil,
|
||||||
pleroma: %{mime_type: "image/png"}
|
pleroma: %{
|
||||||
|
mime_type: "image/png",
|
||||||
|
filename: "name.png"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,6 +31,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do
|
||||||
"hide_follows_count" => false,
|
"hide_follows_count" => false,
|
||||||
"hide_follows" => false,
|
"hide_follows" => false,
|
||||||
"background_image" => nil,
|
"background_image" => nil,
|
||||||
|
"show_attachment_filenames" => false,
|
||||||
"skip_thread_containment" => false,
|
"skip_thread_containment" => false,
|
||||||
"hide_followers" => false,
|
"hide_followers" => false,
|
||||||
"relationship" => %{},
|
"relationship" => %{},
|
||||||
|
|
|
@ -278,6 +278,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
"showing_reblogs" => true,
|
"showing_reblogs" => true,
|
||||||
"subscribing" => false
|
"subscribing" => false
|
||||||
},
|
},
|
||||||
|
"show_attachment_filenames" => false,
|
||||||
"skip_thread_containment" => false,
|
"skip_thread_containment" => false,
|
||||||
"tags" => []
|
"tags" => []
|
||||||
},
|
},
|
||||||
|
|
|
@ -255,7 +255,7 @@ def add_attachments(text, attachments) do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_attachment_link(%{"url" => [%{"href" => href} | _]} = attachment) do
|
defp build_attachment_link(%{"url" => [%{"href" => href} | _]} = attachment) do
|
||||||
name = attachment["name"] || URI.decode(Path.basename(href))
|
name = attachment["filename"] || attachment["name"] || URI.decode(Path.basename(href))
|
||||||
href = MediaProxy.url(href)
|
href = MediaProxy.url(href)
|
||||||
"<a href=\"#{href}\" class='attachment'>#{shortname(name)}</a>"
|
"<a href=\"#{href}\" class='attachment'>#{shortname(name)}</a>"
|
||||||
end
|
end
|
||||||
|
|
|
@ -182,6 +182,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p
|
||||||
:hide_followers,
|
:hide_followers,
|
||||||
:hide_follows,
|
:hide_follows,
|
||||||
:hide_favorites,
|
:hide_favorites,
|
||||||
|
:show_attachment_filenames,
|
||||||
:show_role,
|
:show_role,
|
||||||
:skip_thread_containment,
|
:skip_thread_containment,
|
||||||
:allow_following_move,
|
:allow_following_move,
|
||||||
|
|
|
@ -26,7 +26,8 @@ def create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn,
|
||||||
ActivityPub.upload(
|
ActivityPub.upload(
|
||||||
file,
|
file,
|
||||||
actor: User.ap_id(user),
|
actor: User.ap_id(user),
|
||||||
description: Map.get(data, :description)
|
description: Map.get(data, :description),
|
||||||
|
filename: Map.get(data, :filename)
|
||||||
) do
|
) do
|
||||||
attachment_data = Map.put(object.data, "id", object.id)
|
attachment_data = Map.put(object.data, "id", object.id)
|
||||||
|
|
||||||
|
@ -42,7 +43,8 @@ def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn,
|
||||||
ActivityPub.upload(
|
ActivityPub.upload(
|
||||||
file,
|
file,
|
||||||
actor: User.ap_id(user),
|
actor: User.ap_id(user),
|
||||||
description: Map.get(data, :description)
|
description: Map.get(data, :description),
|
||||||
|
filename: Map.get(data, :filename)
|
||||||
) do
|
) do
|
||||||
attachment_data = Map.put(object.data, "id", object.id)
|
attachment_data = Map.put(object.data, "id", object.id)
|
||||||
|
|
||||||
|
@ -55,18 +57,21 @@ def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn,
|
||||||
def create2(_conn, _data), do: {:error, :bad_request}
|
def create2(_conn, _data), do: {:error, :bad_request}
|
||||||
|
|
||||||
@doc "PUT /api/v1/media/:id"
|
@doc "PUT /api/v1/media/:id"
|
||||||
def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do
|
def update(
|
||||||
|
%{assigns: %{user: user}, body_params: body_params} = conn,
|
||||||
|
%{id: id}
|
||||||
|
) do
|
||||||
with %Object{} = object <- Object.get_by_id(id),
|
with %Object{} = object <- Object.get_by_id(id),
|
||||||
:ok <- Object.authorize_access(object, user),
|
:ok <- Object.authorize_access(object, user),
|
||||||
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
|
params <- prepare_update_params(body_params),
|
||||||
|
:ok <- validate_filename(params["filename"], hd(object.data["url"])),
|
||||||
|
{:ok, %Object{data: data}} <- Object.update_data(object, params) do
|
||||||
attachment_data = Map.put(data, "id", object.id)
|
attachment_data = Map.put(data, "id", object.id)
|
||||||
|
|
||||||
render(conn, "attachment.json", %{attachment: attachment_data})
|
render(conn, "attachment.json", %{attachment: attachment_data})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(conn, data), do: show(conn, data)
|
|
||||||
|
|
||||||
@doc "GET /api/v1/media/:id"
|
@doc "GET /api/v1/media/:id"
|
||||||
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
with %Object{data: data, id: object_id} = object <- Object.get_by_id(id),
|
with %Object{data: data, id: object_id} = object <- Object.get_by_id(id),
|
||||||
|
@ -78,4 +83,26 @@ def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(_conn, _data), do: {:error, :bad_request}
|
def show(_conn, _data), do: {:error, :bad_request}
|
||||||
|
|
||||||
|
defp prepare_update_params(body_params) do
|
||||||
|
body_params
|
||||||
|
|> Map.take([:description, :filename])
|
||||||
|
|> Enum.into(%{}, fn
|
||||||
|
{:description, description} ->
|
||||||
|
{"name", description}
|
||||||
|
|
||||||
|
{:filename, filename} ->
|
||||||
|
{"filename", filename}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp validate_filename(nil, _), do: :ok
|
||||||
|
|
||||||
|
defp validate_filename(filename, %{"href" => href}) do
|
||||||
|
if Path.extname(filename) == Path.extname(href) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, :invalid_filename_extension}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -277,6 +277,7 @@ defp do_render("show.json", %{user: user} = opts) do
|
||||||
hide_follows: user.hide_follows,
|
hide_follows: user.hide_follows,
|
||||||
hide_favorites: user.hide_favorites,
|
hide_favorites: user.hide_favorites,
|
||||||
relationship: relationship,
|
relationship: relationship,
|
||||||
|
show_attachment_filenames: user.show_attachment_filenames,
|
||||||
skip_thread_containment: user.skip_thread_containment,
|
skip_thread_containment: user.skip_thread_containment,
|
||||||
background_image: image_url(user.background) |> MediaProxy.url(),
|
background_image: image_url(user.background) |> MediaProxy.url(),
|
||||||
accepts_chat_messages: user.accepts_chat_messages,
|
accepts_chat_messages: user.accepts_chat_messages,
|
||||||
|
|
|
@ -431,7 +431,10 @@ def render("attachment.json", %{attachment: attachment}) do
|
||||||
text_url: href,
|
text_url: href,
|
||||||
type: type,
|
type: type,
|
||||||
description: attachment["name"],
|
description: attachment["name"],
|
||||||
pleroma: %{mime_type: media_type},
|
pleroma: %{
|
||||||
|
mime_type: media_type,
|
||||||
|
filename: attachment["filename"]
|
||||||
|
},
|
||||||
blurhash: attachment["blurhash"]
|
blurhash: attachment["blurhash"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddAttachmentFilenameSettingToUsers do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:users) do
|
||||||
|
add(:show_attachment_filenames, :boolean, default: false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -61,7 +61,8 @@ test "it returns file" do
|
||||||
"mediaType" => "image/jpeg",
|
"mediaType" => "image/jpeg",
|
||||||
"type" => "Link"
|
"type" => "Link"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"filename" => nil
|
||||||
}}
|
}}
|
||||||
|
|
||||||
Task.await(Agent.get(TestUploaderSuccess, fn task_pid -> task_pid end))
|
Task.await(Agent.get(TestUploaderSuccess, fn task_pid -> task_pid end))
|
||||||
|
@ -120,6 +121,57 @@ test "does not allow descriptions longer than the post limit" do
|
||||||
{:error, :description_too_long} = Upload.store(file, description: "123")
|
{:error, :description_too_long} = Upload.store(file, description: "123")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "saves filename from opts" do
|
||||||
|
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||||
|
|
||||||
|
desc = "sample file"
|
||||||
|
filename = "test image.jpg"
|
||||||
|
|
||||||
|
file = %Plug.Upload{
|
||||||
|
content_type: "image/jpg",
|
||||||
|
path: Path.absname("test/fixtures/image_tmp.jpg"),
|
||||||
|
filename: "image.jpg"
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, data} = Upload.store(file, description: desc, filename: filename)
|
||||||
|
|
||||||
|
assert data["name"] == desc
|
||||||
|
assert data["filename"] == filename
|
||||||
|
end
|
||||||
|
|
||||||
|
test "sets filename to nil if opts don't have one" do
|
||||||
|
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||||
|
|
||||||
|
desc = "sample file"
|
||||||
|
filename = "image_tmp.jpg"
|
||||||
|
|
||||||
|
file = %Plug.Upload{
|
||||||
|
content_type: "image/jpg",
|
||||||
|
path: Path.absname("test/fixtures/image_tmp.jpg"),
|
||||||
|
filename: filename
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, data} = Upload.store(file, description: desc)
|
||||||
|
|
||||||
|
assert data["name"] == desc
|
||||||
|
refute data["filename"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag capture_log: true
|
||||||
|
test "raise error when custom filename has different extension than original one" do
|
||||||
|
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||||
|
|
||||||
|
fake_name = "free_coins.exe"
|
||||||
|
|
||||||
|
file = %Plug.Upload{
|
||||||
|
content_type: "image/jpg",
|
||||||
|
path: Path.absname("test/fixtures/image_tmp.jpg"),
|
||||||
|
filename: "image_tmp.jpg"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert Upload.store(file, filename: fake_name) == {:error, :invalid_filename_extension}
|
||||||
|
end
|
||||||
|
|
||||||
test "returns a media url" do
|
test "returns a media url" do
|
||||||
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||||
|
|
||||||
|
|
|
@ -27,15 +27,17 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
||||||
|
|
||||||
test "/api/v1/media", %{conn: conn, image: image} do
|
test "/api/v1/media", %{conn: conn, image: image} do
|
||||||
desc = "Description of the image"
|
desc = "Description of the image"
|
||||||
|
filename = "look at this.jpg"
|
||||||
|
|
||||||
media =
|
media =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "multipart/form-data")
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|> post("/api/v1/media", %{"file" => image, "description" => desc})
|
|> post("/api/v1/media", %{"file" => image, "description" => desc, "filename" => filename})
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert media["type"] == "image"
|
assert media["type"] == "image"
|
||||||
assert media["description"] == desc
|
assert media["description"] == desc
|
||||||
|
assert media["pleroma"]["filename"] == filename
|
||||||
assert media["id"]
|
assert media["id"]
|
||||||
|
|
||||||
object = Object.get_by_id(media["id"])
|
object = Object.get_by_id(media["id"])
|
||||||
|
@ -44,11 +46,12 @@ test "/api/v1/media", %{conn: conn, image: image} do
|
||||||
|
|
||||||
test "/api/v2/media", %{conn: conn, user: user, image: image} do
|
test "/api/v2/media", %{conn: conn, user: user, image: image} do
|
||||||
desc = "Description of the image"
|
desc = "Description of the image"
|
||||||
|
filename = "look at this.jpg"
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "multipart/form-data")
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|
|> post("/api/v2/media", %{"file" => image, "description" => desc, "filename" => filename})
|
||||||
|> json_response_and_validate_schema(202)
|
|> json_response_and_validate_schema(202)
|
||||||
|
|
||||||
assert media_id = response["id"]
|
assert media_id = response["id"]
|
||||||
|
@ -62,14 +65,41 @@ test "/api/v2/media", %{conn: conn, user: user, image: image} do
|
||||||
|
|
||||||
assert media["type"] == "image"
|
assert media["type"] == "image"
|
||||||
assert media["description"] == desc
|
assert media["description"] == desc
|
||||||
|
assert media["pleroma"]["filename"] == filename
|
||||||
assert media["id"]
|
assert media["id"]
|
||||||
|
|
||||||
object = Object.get_by_id(media["id"])
|
object = Object.get_by_id(media["id"])
|
||||||
assert object.data["actor"] == user.ap_id
|
assert object.data["actor"] == user.ap_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "returns error when description is too long", %{conn: conn, image: image} do
|
||||||
|
clear_config([:instance, :description_limit], 2)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|
|> post("/api/v1/media", %{"file" => image, "description" => "test-media"})
|
||||||
|
|> json_response(400)
|
||||||
|
|
||||||
|
assert response["error"] == "description_too_long"
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Update media description" do
|
@tag capture_log: true
|
||||||
|
test "returns error when custom filename has different extension than original one", %{
|
||||||
|
conn: conn,
|
||||||
|
image: image
|
||||||
|
} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|
|> post("/api/v1/media", %{"file" => image, "filename" => "wrong.gif"})
|
||||||
|
|> json_response(400)
|
||||||
|
|
||||||
|
assert response["error"] == "invalid_filename_extension"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Update media" do
|
||||||
setup do: oauth_access(["write:media"])
|
setup do: oauth_access(["write:media"])
|
||||||
|
|
||||||
setup %{user: actor} do
|
setup %{user: actor} do
|
||||||
|
@ -83,21 +113,69 @@ test "/api/v2/media", %{conn: conn, user: user, image: image} do
|
||||||
ActivityPub.upload(
|
ActivityPub.upload(
|
||||||
file,
|
file,
|
||||||
actor: User.ap_id(actor),
|
actor: User.ap_id(actor),
|
||||||
description: "test-m"
|
description: "test-m",
|
||||||
|
filename: "test_image.jpg"
|
||||||
)
|
)
|
||||||
|
|
||||||
[object: object]
|
[object: object]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "/api/v1/media/:id good request", %{conn: conn, object: object} do
|
test "/api/v1/media/:id update description", %{conn: conn, object: object} do
|
||||||
|
new_description = "test-media"
|
||||||
|
|
||||||
media =
|
media =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "multipart/form-data")
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
|
|> put("/api/v1/media/#{object.id}", %{"description" => new_description})
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
assert media["description"] == "test-media"
|
assert media["description"] == new_description
|
||||||
assert refresh_record(object).data["name"] == "test-media"
|
assert refresh_record(object).data["name"] == new_description
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/api/v1/media/:id update filename", %{conn: conn, object: object} do
|
||||||
|
new_filename = "media.jpg"
|
||||||
|
|
||||||
|
media =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|
|> put("/api/v1/media/#{object.id}", %{"filename" => new_filename})
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert media["pleroma"]["filename"] == new_filename
|
||||||
|
assert refresh_record(object).data["filename"] == new_filename
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/api/v1/media/:id update description and filename", %{conn: conn, object: object} do
|
||||||
|
new_description = "test-media"
|
||||||
|
new_filename = "media.jpg"
|
||||||
|
|
||||||
|
media =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|
|> put("/api/v1/media/#{object.id}", %{
|
||||||
|
"description" => new_description,
|
||||||
|
"filename" => new_filename,
|
||||||
|
"foo" => "bar"
|
||||||
|
})
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert media["description"] == new_description
|
||||||
|
assert media["pleroma"]["filename"] == new_filename
|
||||||
|
assert refresh_record(object).data["name"] == new_description
|
||||||
|
assert refresh_record(object).data["filename"] == new_filename
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/api/v1/media/:id filename with a wrong extension", %{conn: conn, object: object} do
|
||||||
|
new_filename = "media.exe"
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|
|> put("/api/v1/media/#{object.id}", %{"filename" => new_filename})
|
||||||
|
|> json_response(400)
|
||||||
|
|
||||||
|
assert response["error"] == "invalid_filename_extension"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,38 @@ test "posting a status", %{conn: conn} do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "posting a status with an attachment", %{user: user, conn: conn} do
|
||||||
|
clear_config([:instance, :attachment_links], true)
|
||||||
|
filename = "an_image.jpg"
|
||||||
|
custom_filename = "look at this.jpg"
|
||||||
|
|
||||||
|
file = %Plug.Upload{
|
||||||
|
content_type: "image/jpg",
|
||||||
|
path: Path.absname("test/fixtures/image.jpg"),
|
||||||
|
filename: filename
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, upload} =
|
||||||
|
ActivityPub.upload(file,
|
||||||
|
actor: user.ap_id,
|
||||||
|
description: "test image",
|
||||||
|
filename: custom_filename
|
||||||
|
)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/statuses", %{
|
||||||
|
"status" => "cofe",
|
||||||
|
"spoiler_text" => "2hu",
|
||||||
|
"media_ids" => [to_string(upload.id)]
|
||||||
|
})
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert String.ends_with?(response["content"], "#{filename}\">#{custom_filename}</a>")
|
||||||
|
assert length(response["media_attachments"]) == 1
|
||||||
|
end
|
||||||
|
|
||||||
test "it fails to create a status if `expires_in` is less or equal than an hour", %{
|
test "it fails to create a status if `expires_in` is less or equal than an hour", %{
|
||||||
conn: conn
|
conn: conn
|
||||||
} do
|
} do
|
||||||
|
@ -166,22 +198,28 @@ test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "posting an undefined status with an attachment", %{user: user, conn: conn} do
|
test "posting an undefined status with an attachment", %{user: user, conn: conn} do
|
||||||
|
clear_config([:instance, :attachment_links], true)
|
||||||
|
filename = "an_image.jpg"
|
||||||
|
description = "test image"
|
||||||
|
|
||||||
file = %Plug.Upload{
|
file = %Plug.Upload{
|
||||||
content_type: "image/jpeg",
|
content_type: "image/jpeg",
|
||||||
path: Path.absname("test/fixtures/image.jpg"),
|
path: Path.absname("test/fixtures/image.jpg"),
|
||||||
filename: "an_image.jpg"
|
filename: filename
|
||||||
}
|
}
|
||||||
|
|
||||||
{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
|
{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id, description: description)
|
||||||
|
|
||||||
conn =
|
response =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "application/json")
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/statuses", %{
|
|> post("/api/v1/statuses", %{
|
||||||
"media_ids" => [to_string(upload.id)]
|
"media_ids" => [to_string(upload.id)]
|
||||||
})
|
})
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert json_response_and_validate_schema(conn, 200)
|
assert String.ends_with?(response["content"], "#{filename}\">#{description}</a>")
|
||||||
|
assert length(response["media_attachments"]) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
test "replying to a status", %{user: user, conn: conn} do
|
test "replying to a status", %{user: user, conn: conn} do
|
||||||
|
@ -413,7 +451,12 @@ test "creates a scheduled activity with a media attachment", %{user: user, conn:
|
||||||
filename: "an_image.jpg"
|
filename: "an_image.jpg"
|
||||||
}
|
}
|
||||||
|
|
||||||
{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
|
{:ok, upload} =
|
||||||
|
ActivityPub.upload(file,
|
||||||
|
actor: user.ap_id,
|
||||||
|
description: "sample image",
|
||||||
|
filename: "look at this.jpg"
|
||||||
|
)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
@ -427,7 +470,8 @@ test "creates a scheduled activity with a media attachment", %{user: user, conn:
|
||||||
assert %{"media_attachments" => [media_attachment]} =
|
assert %{"media_attachments" => [media_attachment]} =
|
||||||
json_response_and_validate_schema(conn, 200)
|
json_response_and_validate_schema(conn, 200)
|
||||||
|
|
||||||
assert %{"type" => "image"} = media_attachment
|
assert %{"description" => "sample image", "type" => "image"} = media_attachment
|
||||||
|
assert media_attachment["pleroma"]["filename"] == "look at this.jpg"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
|
test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
|
||||||
|
|
|
@ -180,6 +180,16 @@ test "updates the user's skip_thread_containment option", %{user: user, conn: co
|
||||||
assert refresh_record(user).skip_thread_containment
|
assert refresh_record(user).skip_thread_containment
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "updates the user's show_attachment_filenames option", %{user: user, conn: conn} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{show_attachment_filenames: "true"})
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert response["pleroma"]["show_attachment_filenames"]
|
||||||
|
assert refresh_record(user).show_attachment_filenames
|
||||||
|
end
|
||||||
|
|
||||||
test "updates the user's hide_follows status", %{conn: conn} do
|
test "updates the user's hide_follows status", %{conn: conn} do
|
||||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_follows: "true"})
|
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_follows: "true"})
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ test "Represent a user account" do
|
||||||
"<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
|
"<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
|
||||||
inserted_at: ~N[2017-08-15 15:47:06.597036],
|
inserted_at: ~N[2017-08-15 15:47:06.597036],
|
||||||
emoji: %{"karjalanpiirakka" => "/file.png"},
|
emoji: %{"karjalanpiirakka" => "/file.png"},
|
||||||
raw_bio: "valid html. a\nb\nc\nd\nf '&<>\""
|
raw_bio: "valid html. a\nb\nc\nd\nf '&<>\"",
|
||||||
|
show_attachment_filenames: true
|
||||||
})
|
})
|
||||||
|
|
||||||
expected = %{
|
expected = %{
|
||||||
|
@ -87,6 +88,7 @@ test "Represent a user account" do
|
||||||
hide_followers_count: false,
|
hide_followers_count: false,
|
||||||
hide_follows_count: false,
|
hide_follows_count: false,
|
||||||
relationship: %{},
|
relationship: %{},
|
||||||
|
show_attachment_filenames: true,
|
||||||
skip_thread_containment: false,
|
skip_thread_containment: false,
|
||||||
accepts_chat_messages: nil
|
accepts_chat_messages: nil
|
||||||
}
|
}
|
||||||
|
@ -185,6 +187,7 @@ test "Represent a Service(bot) account" do
|
||||||
hide_followers_count: false,
|
hide_followers_count: false,
|
||||||
hide_follows_count: false,
|
hide_follows_count: false,
|
||||||
relationship: %{},
|
relationship: %{},
|
||||||
|
show_attachment_filenames: false,
|
||||||
skip_thread_containment: false,
|
skip_thread_containment: false,
|
||||||
accepts_chat_messages: nil
|
accepts_chat_messages: nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,7 +465,8 @@ test "attachments" do
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"blurhash" => "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn",
|
"blurhash" => "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn",
|
||||||
"uuid" => 6
|
"uuid" => 6,
|
||||||
|
"filename" => "an_image.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = %{
|
expected = %{
|
||||||
|
@ -476,7 +477,7 @@ test "attachments" do
|
||||||
preview_url: "someurl",
|
preview_url: "someurl",
|
||||||
text_url: "someurl",
|
text_url: "someurl",
|
||||||
description: nil,
|
description: nil,
|
||||||
pleroma: %{mime_type: "image/png"},
|
pleroma: %{mime_type: "image/png", filename: "an_image.png"},
|
||||||
blurhash: "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn"
|
blurhash: "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue