Merge branch 'develop' into fix/ap-hide-follows

This commit is contained in:
rinpatch 2019-07-12 21:43:06 +03:00
commit 095117a58c
11 changed files with 207 additions and 78 deletions

View File

@ -46,14 +46,6 @@ Has these additional fields under the `pleroma` object:
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials` - `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`
- `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials` - `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials`
### Extensions for PleromaFE
These endpoints added for controlling PleromaFE features over the Mastodon API
- PATCH `/api/v1/accounts/update_avatar`: Set/clear user avatar image
- PATCH `/api/v1/accounts/update_banner`: Set/clear user banner image
- PATCH `/api/v1/accounts/update_background`: Set/clear user background image
### Source ### Source
Has these additional fields under the `pleroma` object: Has these additional fields under the `pleroma` object:

View File

@ -238,6 +238,13 @@ See [Admin-API](Admin-API.md)
] ]
``` ```
## `/api/v1/pleroma/accounts/update_*`
### Set and clear account avatar, banner, and background
- PATCH `/api/v1/pleroma/accounts/update_avatar`: Set/clear user avatar image
- PATCH `/api/v1/pleroma/accounts/update_banner`: Set/clear user banner image
- PATCH `/api/v1/pleroma/accounts/update_background`: Set/clear user background image
## `/api/v1/pleroma/mascot` ## `/api/v1/pleroma/mascot`
### Gets user mascot image ### Gets user mascot image
* Method `GET` * Method `GET`

View File

@ -28,12 +28,7 @@ def remote(conn, %{"sig" => sig64, "url" => url64} = params) do
end end
def filename_matches(has_filename, path, url) do def filename_matches(has_filename, path, url) do
filename = filename = url |> MediaProxy.filename()
url
|> MediaProxy.filename()
|> URI.decode()
path = URI.decode(path)
if has_filename && filename && Path.basename(path) != filename do if has_filename && filename && Path.basename(path) != filename do
{:wrong_filename, filename} {:wrong_filename, filename}

View File

@ -9,6 +9,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
alias Pleroma.Web.Metadata.Utils alias Pleroma.Web.Metadata.Utils
@behaviour Provider @behaviour Provider
@media_types ["image", "audio", "video"]
@impl Provider @impl Provider
def build_tags(%{ def build_tags(%{
@ -81,26 +82,19 @@ defp build_attachments(%{data: %{"attachment" => attachments}}) do
Enum.reduce(attachments, [], fn attachment, acc -> Enum.reduce(attachments, [], fn attachment, acc ->
rendered_tags = rendered_tags =
Enum.reduce(attachment["url"], [], fn url, acc -> Enum.reduce(attachment["url"], [], fn url, acc ->
media_type =
Enum.find(["image", "audio", "video"], fn media_type ->
String.starts_with?(url["mediaType"], media_type)
end)
# TODO: Add additional properties to objects when we have the data available. # TODO: Add additional properties to objects when we have the data available.
# Also, Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image # Also, Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image
# object when a Video or GIF is attached it will display that in Whatsapp Rich Preview. # object when a Video or GIF is attached it will display that in Whatsapp Rich Preview.
case media_type do case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" -> "audio" ->
[ [
{:meta, {:meta, [property: "og:audio", content: Utils.attachment_url(url["href"])], []}
[property: "og:" <> media_type, content: Utils.attachment_url(url["href"])], []}
| acc | acc
] ]
"image" -> "image" ->
[ [
{:meta, {:meta, [property: "og:image", content: Utils.attachment_url(url["href"])], []},
[property: "og:" <> media_type, content: Utils.attachment_url(url["href"])], []},
{:meta, [property: "og:image:width", content: 150], []}, {:meta, [property: "og:image:width", content: 150], []},
{:meta, [property: "og:image:height", content: 150], []} {:meta, [property: "og:image:height", content: 150], []}
| acc | acc
@ -108,8 +102,7 @@ defp build_attachments(%{data: %{"attachment" => attachments}}) do
"video" -> "video" ->
[ [
{:meta, {:meta, [property: "og:video", content: Utils.attachment_url(url["href"])], []}
[property: "og:" <> media_type, content: Utils.attachment_url(url["href"])], []}
| acc | acc
] ]

View File

@ -1,4 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
@ -9,13 +10,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
alias Pleroma.Web.Metadata.Utils alias Pleroma.Web.Metadata.Utils
@behaviour Provider @behaviour Provider
@media_types ["image", "audio", "video"]
@impl Provider @impl Provider
def build_tags(%{ def build_tags(%{activity_id: id, object: object, user: user}) do
activity_id: id,
object: object,
user: user
}) do
attachments = build_attachments(id, object) attachments = build_attachments(id, object)
scrubbed_content = Utils.scrub_html_and_truncate(object) scrubbed_content = Utils.scrub_html_and_truncate(object)
# Zero width space # Zero width space
@ -27,21 +25,12 @@ def build_tags(%{
end end
[ [
{:meta, title_tag(user),
[ {:meta, [property: "twitter:description", content: content], []}
property: "twitter:title",
content: Utils.user_name_string(user)
], []},
{:meta,
[
property: "twitter:description",
content: content
], []}
] ++ ] ++
if attachments == [] or Metadata.activity_nsfw?(object) do if attachments == [] or Metadata.activity_nsfw?(object) do
[ [
{:meta, image_tag(user),
[property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], []},
{:meta, [property: "twitter:card", content: "summary_large_image"], []} {:meta, [property: "twitter:card", content: "summary_large_image"], []}
] ]
else else
@ -53,30 +42,28 @@ def build_tags(%{
def build_tags(%{user: user}) do def build_tags(%{user: user}) do
with truncated_bio = Utils.scrub_html_and_truncate(user.bio || "") do with truncated_bio = Utils.scrub_html_and_truncate(user.bio || "") do
[ [
{:meta, title_tag(user),
[
property: "twitter:title",
content: Utils.user_name_string(user)
], []},
{:meta, [property: "twitter:description", content: truncated_bio], []}, {:meta, [property: "twitter:description", content: truncated_bio], []},
{:meta, [property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], image_tag(user),
[]},
{:meta, [property: "twitter:card", content: "summary"], []} {:meta, [property: "twitter:card", content: "summary"], []}
] ]
end end
end end
defp title_tag(user) do
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}
end
def image_tag(user) do
{:meta, [property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], []}
end
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
Enum.reduce(attachments, [], fn attachment, acc -> Enum.reduce(attachments, [], fn attachment, acc ->
rendered_tags = rendered_tags =
Enum.reduce(attachment["url"], [], fn url, acc -> Enum.reduce(attachment["url"], [], fn url, acc ->
media_type =
Enum.find(["image", "audio", "video"], fn media_type ->
String.starts_with?(url["mediaType"], media_type)
end)
# TODO: Add additional properties to objects when we have the data available. # TODO: Add additional properties to objects when we have the data available.
case media_type do case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" -> "audio" ->
[ [
{:meta, [property: "twitter:card", content: "player"], []}, {:meta, [property: "twitter:card", content: "player"], []},

View File

@ -39,4 +39,11 @@ def user_name_string(user) do
"(@#{user.nickname})" "(@#{user.nickname})"
end end
end end
@spec fetch_media_type(list(String.t()), String.t()) :: String.t() | nil
def fetch_media_type(supported_types, media_type) do
Enum.find(supported_types, fn support_type ->
String.starts_with?(media_type, support_type)
end)
end
end end

View File

@ -322,10 +322,6 @@ defmodule Pleroma.Web.Router do
patch("/accounts/update_credentials", MastodonAPIController, :update_credentials) patch("/accounts/update_credentials", MastodonAPIController, :update_credentials)
patch("/accounts/update_avatar", MastodonAPIController, :update_avatar)
patch("/accounts/update_banner", MastodonAPIController, :update_banner)
patch("/accounts/update_background", MastodonAPIController, :update_background)
post("/statuses", MastodonAPIController, :post_status) post("/statuses", MastodonAPIController, :post_status)
delete("/statuses/:id", MastodonAPIController, :delete_status) delete("/statuses/:id", MastodonAPIController, :delete_status)
@ -360,6 +356,10 @@ defmodule Pleroma.Web.Router do
put("/filters/:id", MastodonAPIController, :update_filter) put("/filters/:id", MastodonAPIController, :update_filter)
delete("/filters/:id", MastodonAPIController, :delete_filter) delete("/filters/:id", MastodonAPIController, :delete_filter)
patch("/pleroma/accounts/update_avatar", MastodonAPIController, :update_avatar)
patch("/pleroma/accounts/update_banner", MastodonAPIController, :update_banner)
patch("/pleroma/accounts/update_background", MastodonAPIController, :update_background)
get("/pleroma/mascot", MastodonAPIController, :get_mascot) get("/pleroma/mascot", MastodonAPIController, :get_mascot)
put("/pleroma/mascot", MastodonAPIController, :set_mascot) put("/pleroma/mascot", MastodonAPIController, :set_mascot)

View File

@ -88,10 +88,10 @@ test "validates signature" do
assert decode_url(sig, base64) == {:error, :invalid_signature} assert decode_url(sig, base64) == {:error, :invalid_signature}
end end
test "filename_matches matches url encoded paths" do test "filename_matches preserves the encoded or decoded path" do
assert MediaProxyController.filename_matches( assert MediaProxyController.filename_matches(
true, true,
"/Hello%20world.jpg", "/Hello world.jpg",
"http://pleroma.social/Hello world.jpg" "http://pleroma.social/Hello world.jpg"
) == :ok ) == :ok
@ -100,19 +100,11 @@ test "filename_matches matches url encoded paths" do
"/Hello%20world.jpg", "/Hello%20world.jpg",
"http://pleroma.social/Hello%20world.jpg" "http://pleroma.social/Hello%20world.jpg"
) == :ok ) == :ok
end
test "filename_matches matches non-url encoded paths" do
assert MediaProxyController.filename_matches(
true,
"/Hello world.jpg",
"http://pleroma.social/Hello%20world.jpg"
) == :ok
assert MediaProxyController.filename_matches( assert MediaProxyController.filename_matches(
true, true,
"/Hello world.jpg", "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg",
"http://pleroma.social/Hello world.jpg" "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"
) == :ok ) == :ok
end end

View File

@ -593,7 +593,7 @@ test "user avatar can be set", %{conn: conn} do
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> patch("/api/v1/accounts/update_avatar", %{img: avatar_image}) |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
user = refresh_record(user) user = refresh_record(user)
@ -618,7 +618,7 @@ test "user avatar can be reset", %{conn: conn} do
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> patch("/api/v1/accounts/update_avatar", %{img: ""}) |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
@ -633,7 +633,7 @@ test "can set profile banner", %{conn: conn} do
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> patch("/api/v1/accounts/update_banner", %{"banner" => @image}) |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
user = refresh_record(user) user = refresh_record(user)
assert user.info.banner["type"] == "Image" assert user.info.banner["type"] == "Image"
@ -647,7 +647,7 @@ test "can reset profile banner", %{conn: conn} do
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> patch("/api/v1/accounts/update_banner", %{"banner" => ""}) |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
user = refresh_record(user) user = refresh_record(user)
assert user.info.banner == %{} assert user.info.banner == %{}
@ -661,7 +661,7 @@ test "background image can be set", %{conn: conn} do
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> patch("/api/v1/accounts/update_background", %{"img" => @image}) |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
user = refresh_record(user) user = refresh_record(user)
assert user.info.background["type"] == "Image" assert user.info.background["type"] == "Image"
@ -674,7 +674,7 @@ test "background image can be reset", %{conn: conn} do
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> patch("/api/v1/accounts/update_background", %{"img" => ""}) |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
user = refresh_record(user) user = refresh_record(user)
assert user.info.background == %{} assert user.info.background == %{}

View File

@ -0,0 +1,33 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Metadata.PlayerViewTest do
use Pleroma.DataCase
alias Pleroma.Web.Metadata.PlayerView
test "it renders audio tag" do
res =
PlayerView.render(
"player.html",
%{"mediaType" => "audio", "href" => "test-href"}
)
|> Phoenix.HTML.safe_to_string()
assert res ==
"<audio controls><source src=\"test-href\" type=\"audio\">Your browser does not support audio playback.</audio>"
end
test "it renders videos tag" do
res =
PlayerView.render(
"player.html",
%{"mediaType" => "video", "href" => "test-href"}
)
|> Phoenix.HTML.safe_to_string()
assert res ==
"<video controls loop><source src=\"test-href\" type=\"video\">Your browser does not support video playback.</video>"
end
end

View File

@ -0,0 +1,123 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.User
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Metadata.Providers.TwitterCard
alias Pleroma.Web.Metadata.Utils
alias Pleroma.Web.Router
test "it renders twitter card for user info" do
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
avatar_url = Utils.attachment_url(User.avatar_url(user))
res = TwitterCard.build_tags(%{user: user})
assert res == [
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
{:meta, [property: "twitter:description", content: "born 19 March 1994"], []},
{:meta, [property: "twitter:image", content: avatar_url], []},
{:meta, [property: "twitter:card", content: "summary"], []}
]
end
test "it does not render attachments if post is nsfw" do
Pleroma.Config.put([Pleroma.Web.Metadata, :unfurl_nsfw], false)
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
note =
insert(:note, %{
data: %{
"actor" => user.ap_id,
"tag" => [],
"id" => "https://pleroma.gov/objects/whatever",
"content" => "pleroma in a nutshell",
"sensitive" => true,
"attachment" => [
%{
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/tenshi.png"}]
},
%{
"url" => [
%{
"mediaType" => "application/octet-stream",
"href" => "https://pleroma.gov/fqa/badapple.sfc"
}
]
},
%{
"url" => [
%{"mediaType" => "video/webm", "href" => "https://pleroma.gov/about/juche.webm"}
]
}
]
}
})
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
assert [
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
{:meta, [property: "twitter:description", content: "“pleroma in a nutshell”"], []},
{:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"],
[]},
{:meta, [property: "twitter:card", content: "summary_large_image"], []}
] == result
end
test "it renders supported types of attachments and skips unknown types" do
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
note =
insert(:note, %{
data: %{
"actor" => user.ap_id,
"tag" => [],
"id" => "https://pleroma.gov/objects/whatever",
"content" => "pleroma in a nutshell",
"attachment" => [
%{
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/tenshi.png"}]
},
%{
"url" => [
%{
"mediaType" => "application/octet-stream",
"href" => "https://pleroma.gov/fqa/badapple.sfc"
}
]
},
%{
"url" => [
%{"mediaType" => "video/webm", "href" => "https://pleroma.gov/about/juche.webm"}
]
}
]
}
})
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
assert [
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
{:meta, [property: "twitter:description", content: "“pleroma in a nutshell”"], []},
{:meta, [property: "twitter:card", content: "summary_large_image"], []},
{:meta, [property: "twitter:player", content: "https://pleroma.gov/tenshi.png"], []},
{:meta, [property: "twitter:card", content: "player"], []},
{:meta,
[
property: "twitter:player",
content: Router.Helpers.o_status_url(Endpoint, :notice_player, activity.id)
], []},
{:meta, [property: "twitter:player:width", content: "480"], []},
{:meta, [property: "twitter:player:height", content: "480"], []}
] == result
end
end