Merge pull request 'Allow providing avatar/header descriptions' (#1034) from mkljczk/akkoma:avatar-header-descriptions into develop
Reviewed-on: #1034 Reviewed-by: Oneric <oneric@noreply.akkoma>
This commit is contained in:
commit
ee5b6f250f
13 changed files with 471 additions and 23 deletions
|
|
@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
### Added
|
||||
- `{POST,PUT} api/v1/lists` now accepts the `exclusive` parameter from Mastodon allowing followed users in the list to be removed from the home timeline
|
||||
- User profile media now (can) have federated alt text; to this end:
|
||||
- Mastodon-compatible `avatar_description` and `header_description` parameters are added to account API responses and as input for `PATCH /api/v1/accounts/update_credentials`
|
||||
- `pleroma.background_image_descripption` is added to account API responses
|
||||
- `pleroma_background_image_descripption` is added as a new parameter to `PATCH /api/v1/accounts/update_credentials`
|
||||
|
||||
### Fixed
|
||||
- fix date-time format in `* /api/v1/markers` to strictly conform to Mastodon’s ISO 8061 subset
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ Additional parameters can be added to the JSON body/Form data:
|
|||
- `allow_following_move` - if true, allows automatically follow moved following accounts
|
||||
- `also_known_as` - array of ActivityPub IDs, needed for following move
|
||||
- `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
|
||||
- `pleroma_background_image_description` - sets plaintext alt text for the background image of the user. Can be set to "" (an empty string) to delete.
|
||||
- `discoverable` - if true, external services (search bots) etc. are allowed to index / list the account (regardless of this setting, user will still appear in regular search results).
|
||||
- `actor_type` - the type of this account.
|
||||
- `language` - user's preferred language for receiving emails (digest, confirmation, etc.)
|
||||
|
|
|
|||
|
|
@ -398,6 +398,12 @@ defmodule Pleroma.User do
|
|||
end
|
||||
end
|
||||
|
||||
def image_description(image, default \\ "")
|
||||
|
||||
def image_description(%{"summary" => summary}, _default), do: summary
|
||||
def image_description(%{"name" => name}, _default), do: name
|
||||
def image_description(_, default), do: default
|
||||
|
||||
# Should probably be renamed or removed
|
||||
@spec ap_id(User.t()) :: String.t()
|
||||
def ap_id(%User{nickname: nickname}), do: "#{Endpoint.url()}/users/#{nickname}"
|
||||
|
|
@ -566,9 +572,9 @@ defmodule Pleroma.User do
|
|||
|> put_fields()
|
||||
|> put_emoji()
|
||||
|> put_change_if_present(:bio, &{:ok, parse_bio(&1, struct)})
|
||||
|> put_change_if_present(:avatar, &put_upload(&1, :avatar))
|
||||
|> put_change_if_present(:banner, &put_upload(&1, :banner))
|
||||
|> put_change_if_present(:background, &put_upload(&1, :background))
|
||||
|> put_media_update(params, :avatar, :avatar_description)
|
||||
|> put_media_update(params, :banner, :header_description)
|
||||
|> put_media_update(params, :background, :background_description)
|
||||
|> put_change_if_present(
|
||||
:pleroma_settings_store,
|
||||
&{:ok, Map.merge(struct.pleroma_settings_store, &1)}
|
||||
|
|
@ -635,10 +641,38 @@ defmodule Pleroma.User do
|
|||
with {:ok, value} <- fetch_change(changeset, map_field),
|
||||
{:ok, new_value} <- value_function.(value) do
|
||||
put_change(changeset, map_field, new_value)
|
||||
else
|
||||
_ -> changeset
|
||||
end
|
||||
end
|
||||
|
||||
defp validate_image_description(changeset, key, description) do
|
||||
description_limit = Config.get([:instance, :description_limit])
|
||||
|
||||
if is_binary(description) and String.length(description) > description_limit do
|
||||
add_error(changeset, key, "#{key} is too long")
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
defp put_new_media(changeset, media_key, new_image, new_description) do
|
||||
# copy old description if necessary
|
||||
description =
|
||||
if is_binary(new_description) do
|
||||
new_description
|
||||
else
|
||||
old_image = Map.get(changeset.data, media_key)
|
||||
image_description(old_image, nil)
|
||||
end
|
||||
|
||||
with %Plug.Upload{} <- new_image,
|
||||
{:ok, object} <- ActivityPub.upload(new_image, type: media_key, description: description) do
|
||||
put_change(changeset, media_key, object.data)
|
||||
else
|
||||
{:error, :file_too_large} ->
|
||||
Ecto.Changeset.validate_change(changeset, map_field, fn map_field, _value ->
|
||||
[{map_field, "file is too large"}]
|
||||
Ecto.Changeset.validate_change(changeset, media_key, fn media_key, _value ->
|
||||
[{media_key, "file is too large"}]
|
||||
end)
|
||||
|
||||
_ ->
|
||||
|
|
@ -646,10 +680,45 @@ defmodule Pleroma.User do
|
|||
end
|
||||
end
|
||||
|
||||
defp put_upload(value, type) do
|
||||
with %Plug.Upload{} <- value,
|
||||
{:ok, object} <- ActivityPub.upload(value, type: type) do
|
||||
{:ok, object.data}
|
||||
defp maybe_update_image_description(changeset, image_field, desc_key, description)
|
||||
when is_binary(description) do
|
||||
with {:existing_image, %{"id" => id}} <-
|
||||
{:existing_image, Map.get(changeset.data, image_field)},
|
||||
{:object, %Object{} = object} <- {:object, Object.get_by_ap_id(id)},
|
||||
{:ok, object} <- Object.update_data(object, %{"name" => description}) do
|
||||
put_change(changeset, image_field, object.data)
|
||||
else
|
||||
{:existing_image, _} ->
|
||||
if description != "" do
|
||||
add_error(
|
||||
changeset,
|
||||
desc_key,
|
||||
"#{desc_key} needs #{image_field} to be set before or simultaneously"
|
||||
)
|
||||
else
|
||||
changeset
|
||||
end
|
||||
|
||||
_ ->
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_update_image_description(changeset, _, _, _), do: changeset
|
||||
|
||||
defp put_media_update(changeset, params, media_key, description_key) do
|
||||
# We store description and image (url) in a shared JSON blob, but the API
|
||||
# allows both to be updated independently (in Mastodon descriptions can also
|
||||
# exist without image, but we cannot easily do this)
|
||||
description_param = Map.get(params, description_key)
|
||||
changeset = validate_image_description(changeset, description_key, description_param)
|
||||
|
||||
case fetch_change(changeset, media_key) do
|
||||
{:ok, new_image} ->
|
||||
put_new_media(changeset, media_key, new_image, description_param)
|
||||
|
||||
_ ->
|
||||
maybe_update_image_description(changeset, media_key, description_key, description_param)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,22 @@ defmodule Pleroma.User.Fetcher do
|
|||
|
||||
defp get_actor_url(_url), do: nil
|
||||
|
||||
defp normalize_image(%{"url" => url}) do
|
||||
defp maybe_put_description(map, %{"summary" => description}) when is_binary(description) do
|
||||
Map.put(map, "name", description)
|
||||
end
|
||||
|
||||
defp maybe_put_description(map, %{"name" => description}) when is_binary(description) do
|
||||
Map.put(map, "name", description)
|
||||
end
|
||||
|
||||
defp maybe_put_description(map, _), do: map
|
||||
|
||||
defp normalize_image(%{"url" => url} = data) do
|
||||
%{
|
||||
"type" => "Image",
|
||||
"url" => [%{"href" => url}]
|
||||
}
|
||||
|> maybe_put_description(data)
|
||||
end
|
||||
|
||||
defp normalize_image(urls) when is_list(urls), do: urls |> List.first() |> normalize_image()
|
||||
|
|
|
|||
|
|
@ -108,10 +108,20 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||
"alsoKnownAs" => user.also_known_as
|
||||
}
|
||||
|> maybe_put_webfinger(user)
|
||||
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|
||||
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
|
||||
|> Map.merge(
|
||||
maybe_make_image(&User.avatar_url/2, User.image_description(user.avatar), "icon", user)
|
||||
)
|
||||
|> Map.merge(
|
||||
maybe_make_image(&User.banner_url/2, User.image_description(user.banner), "image", user)
|
||||
)
|
||||
# Yes, the key is named ...Url eventhough it is a whole 'Image' object
|
||||
|> Map.merge(maybe_insert_image("backgroundUrl", User.background_url(user)))
|
||||
|> Map.merge(
|
||||
maybe_insert_image(
|
||||
"backgroundUrl",
|
||||
User.background_url(user),
|
||||
User.image_description(user.background)
|
||||
)
|
||||
)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
|
|
@ -314,18 +324,20 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||
|
||||
defp maybe_put_webfinger(data, _), do: data
|
||||
|
||||
defp maybe_make_image(func, key, user) do
|
||||
defp maybe_make_image(func, description, key, user) do
|
||||
image = func.(user, no_default: true)
|
||||
maybe_insert_image(key, image)
|
||||
maybe_insert_image(key, image, description)
|
||||
end
|
||||
|
||||
defp maybe_insert_image(key, image) do
|
||||
defp maybe_insert_image(key, image, description) do
|
||||
if image do
|
||||
%{
|
||||
key => %{
|
||||
"type" => "Image",
|
||||
"url" => image
|
||||
}
|
||||
key =>
|
||||
%{
|
||||
"type" => "Image",
|
||||
"url" => image
|
||||
}
|
||||
|> maybe_put("name", description)
|
||||
}
|
||||
else
|
||||
%{}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
responses: %{
|
||||
200 => Operation.response("Account", "application/json", Account),
|
||||
403 => Operation.response("Error", "application/json", ApiError),
|
||||
413 => Operation.response("Error", "application/json", ApiError)
|
||||
413 => Operation.response("Error", "application/json", ApiError),
|
||||
422 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
@ -616,12 +617,22 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
description: "Avatar image encoded using multipart/form-data",
|
||||
format: :binary
|
||||
},
|
||||
avatar_description: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "Sets description (alt text) of the user’s avatar image."
|
||||
},
|
||||
header: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "Header image encoded using multipart/form-data",
|
||||
format: :binary
|
||||
},
|
||||
header_description: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "Sets description (alt text) of the user’s header image."
|
||||
},
|
||||
locked: %Schema{
|
||||
allOf: [BooleanLike],
|
||||
nullable: true,
|
||||
|
|
@ -710,6 +721,11 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
description: "Sets the background image of the user.",
|
||||
format: :binary
|
||||
},
|
||||
pleroma_background_image_description: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "Sets description (alt text) of the user’s background image."
|
||||
},
|
||||
discoverable: %Schema{
|
||||
allOf: [BooleanLike],
|
||||
nullable: true,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
acct: %Schema{type: :string},
|
||||
avatar_static: %Schema{type: :string, format: :uri},
|
||||
avatar: %Schema{type: :string, format: :uri},
|
||||
avatar_description: %Schema{type: :string},
|
||||
bot: %Schema{type: :boolean},
|
||||
created_at: %Schema{type: :string, format: "date-time"},
|
||||
display_name: %Schema{type: :string},
|
||||
|
|
@ -31,6 +32,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
following_count: %Schema{type: :integer},
|
||||
header_static: %Schema{type: :string, format: :uri},
|
||||
header: %Schema{type: :string, format: :uri},
|
||||
header_description: %Schema{type: :string},
|
||||
id: FlakeID,
|
||||
locked: %Schema{type: :boolean},
|
||||
note: %Schema{type: :string, format: :html},
|
||||
|
|
@ -47,6 +49,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
description: "whether the user allows automatically follow moved following accounts"
|
||||
},
|
||||
background_image: %Schema{type: :string, nullable: true, format: :uri},
|
||||
background_image_description: %Schema{type: :string},
|
||||
is_confirmed: %Schema{
|
||||
type: :boolean,
|
||||
description:
|
||||
|
|
@ -164,6 +167,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
example: %{
|
||||
"acct" => "foobar",
|
||||
"avatar" => "https://mypleroma.com/images/avi.png",
|
||||
"avatar_description" => "closeup of tuxedo cat staring directly into camera",
|
||||
"avatar_static" => "https://mypleroma.com/images/avi.png",
|
||||
"bot" => false,
|
||||
"created_at" => "2020-03-24T13:05:58.000Z",
|
||||
|
|
@ -174,6 +178,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
"followers_count" => 0,
|
||||
"following_count" => 1,
|
||||
"header" => "https://mypleroma.com/images/banner.png",
|
||||
"header_description" => "",
|
||||
"header_static" => "https://mypleroma.com/images/banner.png",
|
||||
"id" => "9tKi3esbG7OQgZ2920",
|
||||
"locked" => false,
|
||||
|
|
@ -181,6 +186,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
"pleroma" => %{
|
||||
"allow_following_move" => true,
|
||||
"background_image" => nil,
|
||||
"background_image_description" => "",
|
||||
"is_confirmed" => false,
|
||||
"hide_favorites" => true,
|
||||
"hide_followers" => false,
|
||||
|
|
|
|||
|
|
@ -200,8 +200,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
|> Maps.put_if_present(:bio, params[:note])
|
||||
|> Maps.put_if_present(:raw_bio, params[:note])
|
||||
|> Maps.put_if_present(:avatar, params[:avatar], user_image_value)
|
||||
|> Maps.put_if_present(:avatar_description, params[:avatar_description])
|
||||
|> Maps.put_if_present(:banner, params[:header], user_image_value)
|
||||
|> Maps.put_if_present(:header_description, params[:header_description])
|
||||
|> Maps.put_if_present(:background, params[:pleroma_background_image], user_image_value)
|
||||
|> Maps.put_if_present(
|
||||
:background_description,
|
||||
params[:pleroma_background_image_description]
|
||||
)
|
||||
|> Maps.put_if_present(
|
||||
:raw_fields,
|
||||
params[:fields_attributes],
|
||||
|
|
@ -256,6 +262,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
with_pleroma_settings: true
|
||||
)
|
||||
else
|
||||
# Map errors to translation string constants
|
||||
{:error, %Ecto.Changeset{errors: [avatar: {"file is too large", _}]}} ->
|
||||
render_error(conn, :request_entity_too_large, "File is too large")
|
||||
|
||||
|
|
@ -265,6 +272,62 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
{:error, %Ecto.Changeset{errors: [background: {"file is too large", _}]}} ->
|
||||
render_error(conn, :request_entity_too_large, "File is too large")
|
||||
|
||||
{:error,
|
||||
%Ecto.Changeset{errors: [{:avatar_description, {"avatar_description is too long", _}} | _]}} ->
|
||||
render_error(conn, :request_entity_too_large, "Avatar description is too long")
|
||||
|
||||
{:error,
|
||||
%Ecto.Changeset{
|
||||
errors: [
|
||||
{:avatar_description,
|
||||
{"avatar_description needs avatar to be set before or simultaneously", _}}
|
||||
| _
|
||||
]
|
||||
}} ->
|
||||
render_error(
|
||||
conn,
|
||||
:unprocessable_entity,
|
||||
"Avatar description needs avatar to be set before or simultaneously"
|
||||
)
|
||||
|
||||
{:error,
|
||||
%Ecto.Changeset{errors: [{:header_description, {"header_description is too long", _}} | _]}} ->
|
||||
render_error(conn, :request_entity_too_large, "Banner description is too long")
|
||||
|
||||
{:error,
|
||||
%Ecto.Changeset{
|
||||
errors: [
|
||||
{:header_description,
|
||||
{"header_description needs banner to be set before or simultaneously", _}}
|
||||
| _
|
||||
]
|
||||
}} ->
|
||||
render_error(
|
||||
conn,
|
||||
:unprocessable_entity,
|
||||
"Banner description needs banner to be set before or simultaneously"
|
||||
)
|
||||
|
||||
{:error,
|
||||
%Ecto.Changeset{
|
||||
errors: [{:background_description, {"background description is too long", _}} | _]
|
||||
}} ->
|
||||
render_error(conn, :request_entity_too_large, "Background description is too long")
|
||||
|
||||
{:error,
|
||||
%Ecto.Changeset{
|
||||
errors: [
|
||||
{:background_description,
|
||||
{"background_description needs background to be set before or simultaneously", _}}
|
||||
| _
|
||||
]
|
||||
}} ->
|
||||
render_error(
|
||||
conn,
|
||||
:unprocessable_entity,
|
||||
"Background description needs background to be set before or simultaneously"
|
||||
)
|
||||
|
||||
_e ->
|
||||
render_error(conn, :forbidden, "Invalid request")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -216,8 +216,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|
||||
avatar = User.avatar_url(user) |> MediaProxy.url()
|
||||
avatar_static = User.avatar_url(user) |> MediaProxy.preview_url(static: true)
|
||||
avatar_description = User.image_description(user.avatar, "")
|
||||
header = User.banner_url(user) |> MediaProxy.url()
|
||||
header_static = User.banner_url(user) |> MediaProxy.preview_url(static: true)
|
||||
header_description = User.image_description(user.banner, "")
|
||||
|
||||
following_count =
|
||||
if !user.hide_follows_count or !user.hide_follows or opts[:for] == user,
|
||||
|
|
@ -287,8 +289,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
url: user.uri || user.ap_id,
|
||||
avatar: avatar,
|
||||
avatar_static: avatar_static,
|
||||
avatar_description: avatar_description,
|
||||
header: header,
|
||||
header_static: header_static,
|
||||
header_description: header_description,
|
||||
emojis: emojis,
|
||||
fields: user.fields,
|
||||
bot: bot,
|
||||
|
|
@ -324,6 +328,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
relationship: relationship,
|
||||
skip_thread_containment: user.skip_thread_containment,
|
||||
background_image: image_url(user.background) |> MediaProxy.url(),
|
||||
background_image_description: User.image_description(user.background, ""),
|
||||
favicon: favicon
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,12 +71,14 @@ defmodule Pleroma.User.FetcherTest do
|
|||
|
||||
assert user.avatar == %{
|
||||
"type" => "Image",
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}]
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}],
|
||||
"name" => "profile picture"
|
||||
}
|
||||
|
||||
assert user.banner == %{
|
||||
"type" => "Image",
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}]
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}],
|
||||
"name" => "profile picture"
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -280,6 +282,35 @@ defmodule Pleroma.User.FetcherTest do
|
|||
{:ok, ^featured_url, %{}} = Fetcher.process_featured_collection(featured_url)
|
||||
end
|
||||
|
||||
test "fetches avatar description" do
|
||||
user_id = "https://example.com/users/nicole"
|
||||
|
||||
user_data =
|
||||
"test/fixtures/users_mock/user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "nicole")
|
||||
|> Jason.decode!()
|
||||
|> Map.delete("featured")
|
||||
|> Map.update("icon", %{}, fn image -> Map.put(image, "name", "image description") end)
|
||||
|> Jason.encode!()
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^user_id
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
{:ok, user} = Fetcher.make_user_from_ap_id(user_id)
|
||||
|
||||
assert user.avatar["name"] == "image description"
|
||||
end
|
||||
|
||||
describe "fetch_follow_information_for_user" do
|
||||
test "synchronizes following/followers counters" do
|
||||
user =
|
||||
|
|
|
|||
|
|
@ -97,6 +97,22 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
assert result["icon"]["url"] == "https://someurl"
|
||||
assert result["image"]["url"] == "https://somebanner"
|
||||
assert result["backgroundUrl"]["url"] == "https://somebackground"
|
||||
assert result["icon"]["name"] == ""
|
||||
assert result["image"]["name"] == ""
|
||||
end
|
||||
|
||||
test "Avatar has a description if the user set one" do
|
||||
user =
|
||||
insert(:user,
|
||||
avatar: %{
|
||||
"url" => [%{"href" => "https://someurl"}],
|
||||
"name" => "a drawing of pleroma-tan using pleroma groups"
|
||||
}
|
||||
)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
assert result["icon"]["name"] == "a drawing of pleroma-tan using pleroma groups"
|
||||
end
|
||||
|
||||
test "renders an invisible user with the invisible property set to true" do
|
||||
|
|
|
|||
|
|
@ -399,6 +399,214 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
|
|||
assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
|
||||
end
|
||||
|
||||
test "adds avatar description with a new avatar", %{user: user, conn: conn} do
|
||||
new_avatar = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
res =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
"avatar" => new_avatar,
|
||||
"avatar_description" => "me and pleroma tan"
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(res, 200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.avatar["name"] == "me and pleroma tan"
|
||||
end
|
||||
|
||||
test "adds avatar description to existing avatar", %{user: user, conn: conn} do
|
||||
new_avatar = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.avatar == %{}
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
|
||||
|
||||
assert conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"avatar_description" => "me and pleroma tan"
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.avatar["name"] == "me and pleroma tan"
|
||||
end
|
||||
|
||||
test "does not wipe media description when uploading new image", %{user: user, conn: conn} do
|
||||
new_avatar = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.avatar == %{}
|
||||
assert User.image_description(user.banner) == ""
|
||||
|
||||
desc = "many woozy akkos in stylised chibi style"
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"header" => new_avatar,
|
||||
"header_description" => desc
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert User.image_description(user.banner) == desc
|
||||
|
||||
conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"header" => new_avatar})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert User.image_description(user.banner) == desc
|
||||
end
|
||||
|
||||
test "adds background description with a new background upload", %{user: user, conn: conn} do
|
||||
image = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
alt = "arctus forest scenery"
|
||||
|
||||
res =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_background_image" => image,
|
||||
"pleroma_background_image_description" => alt
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(res, 200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert User.image_description(user.background) == alt
|
||||
end
|
||||
|
||||
test "updates description of existing background without image reupload", %{
|
||||
user: user,
|
||||
conn: conn
|
||||
} do
|
||||
image = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.avatar == %{}
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"pleroma_background_image" => image})
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert User.image_description(user.background) == ""
|
||||
|
||||
alt1 = "shinyyyyyyy"
|
||||
|
||||
assert conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_background_image_description" => alt1
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert User.image_description(user.background) == alt1
|
||||
|
||||
alt2 = "me and shiny chariot"
|
||||
|
||||
assert conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_background_image_description" => alt2
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert User.image_description(user.background) == alt2
|
||||
end
|
||||
|
||||
test "limits profile media alt text", %{user: user, conn: conn} do
|
||||
new_header = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.banner == %{}
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
|
||||
|
||||
description_limit = 100
|
||||
clear_config([:instance, :description_limit], description_limit)
|
||||
description = String.duplicate(".", description_limit + 1)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"header_description" => description
|
||||
})
|
||||
|
||||
assert %{"error" => "Banner description is too long"} =
|
||||
json_response_and_validate_schema(conn, 413)
|
||||
end
|
||||
|
||||
test "refuses to set a media description without media being present or set", %{conn: conn} do
|
||||
# It not being a possible is a limitation of how we store things.
|
||||
# This test is here to ensure the user will be made aware of it.
|
||||
assert %{"error" => "Avatar description needs avatar to be set before or simultaneously"} =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"avatar_description" => "pure void"
|
||||
})
|
||||
|> json_response_and_validate_schema(422)
|
||||
|
||||
assert %{"error" => "Banner description needs banner to be set before or simultaneously"} =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"header_description" => "pure void"
|
||||
})
|
||||
|> json_response_and_validate_schema(422)
|
||||
|
||||
assert %{
|
||||
"error" =>
|
||||
"Background description needs background to be set before or simultaneously"
|
||||
} =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_background_image_description" => "pure void"
|
||||
})
|
||||
|> json_response_and_validate_schema(422)
|
||||
end
|
||||
|
||||
test "allows wiping media description without media being present or set", %{conn: conn} do
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"avatar_description" => ""})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"header_description" => ""})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_background_image_description" => ""
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "Strip / from upload files", %{user: user, conn: conn} do
|
||||
new_image = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
|
|
|
|||
|
|
@ -71,8 +71,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
},
|
||||
avatar: "http://localhost:4001/images/avi.png",
|
||||
avatar_static: "http://localhost:4001/images/avi.png",
|
||||
avatar_description: "",
|
||||
header: "http://localhost:4001/images/banner.png",
|
||||
header_static: "http://localhost:4001/images/banner.png",
|
||||
header_description: "",
|
||||
emojis: [
|
||||
%{
|
||||
static_url: "/file.png",
|
||||
|
|
@ -98,6 +100,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
ap_id: user.ap_id,
|
||||
also_known_as: ["https://shitposter.zone/users/shp"],
|
||||
background_image: "https://example.com/images/asuka_hospital.png",
|
||||
background_image_description: "",
|
||||
favicon: nil,
|
||||
is_confirmed: true,
|
||||
tags: [],
|
||||
|
|
@ -228,8 +231,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
url: user.ap_id,
|
||||
avatar: "http://localhost:4001/images/avi.png",
|
||||
avatar_static: "http://localhost:4001/images/avi.png",
|
||||
avatar_description: "",
|
||||
header: "http://localhost:4001/images/banner.png",
|
||||
header_static: "http://localhost:4001/images/banner.png",
|
||||
header_description: "",
|
||||
emojis: [],
|
||||
fields: [],
|
||||
bot: true,
|
||||
|
|
@ -257,6 +262,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
ap_id: user.ap_id,
|
||||
also_known_as: [],
|
||||
background_image: nil,
|
||||
background_image_description: "",
|
||||
favicon: "http://localhost:4001/favicon.png",
|
||||
is_confirmed: true,
|
||||
tags: [],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue