Page MenuHomePhorge

No OneTemporary

Size
30 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
index f87d97cb4..604805211 100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
@@ -1,38 +1,42 @@
<entry>
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<id><%= @data["id"] %></id>
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
<content type="html"><%= escape(atom_content_encoded(@data)) %></content>
<published><%= to_rfc3339(@data["published"]) %></published>
<updated><%= to_rfc3339(@data["published"]) %></updated>
<ostatus:conversation ref="<%= activity_context(@activity) %>">
<%= activity_context(@activity) %>
</ostatus:conversation>
<link href="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
<%= if @data["summary"] != "" do %>
<summary><%= escape(@data["summary"]) %></summary>
<% end %>
<link type="application/atom+xml" href='<%= activity_link(@activity, @data) %>' rel="self"/>
<link type="text/html" href='<%= activity_link(@activity, @data) %>' rel="alternate"/>
<%= for tag <- Pleroma.Object.hashtags(@object) do %>
<category term="<%= tag %>"></category>
<% end %>
- <%= for attachment <- @data["attachment"] || [] do %>
- <%= unless attachment_previewable?(attachment) do %>
- <link rel="enclosure" href="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>" length="<%= attachment_size(attachment) %>"/>
+ <%= unless @data["sensitive"] do %>
+ <%= for attachment <- @data["attachment"] || [] do %>
+ <%= if size = attachment_size_positive(attachment) do %>
+ <link rel="enclosure" href="<%= escape(attachment_href(attachment) || "") %>" type="<%= escape(attachment_type(attachment) || "application/octet-stream") %>" length="<%= size %>"/>
+ <% else %>
+ <link rel="enclosure" href="<%= escape(attachment_href(attachment) || "") %>" type="<%= escape(attachment_type(attachment) || "application/octet-stream") %>"/>
+ <% end %>
<% end %>
<% end %>
<%= if @data["inReplyTo"] do %>
<thr:in-reply-to ref='<%= @data["inReplyTo"] %>' href='<%= get_href(@data["inReplyTo"]) %>'/>
<% end %>
<%= for {emoji, file} <- @data["emoji"] || %{} do %>
<link name="<%= emoji %>" rel="emoji" href="<%= file %>"/>
<% end %>
</entry>
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
index e2708543f..2127f554f 100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
@@ -1,32 +1,35 @@
<item>
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<guid isPermaLink="true"><%= @data["id"] %></guid>
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
<description><%= activity_description(@data) %></description>
<content:encoded><![CDATA[<%= rss_content_encoded(@data) %>]]></content:encoded>
<pubDate><%= to_rfc2822(@data["published"]) %></pubDate>
<ostatus:conversation ref="<%= activity_context(@activity) %>">
<%= activity_context(@activity) %>
</ostatus:conversation>
<link><%= activity_link(@activity, @data) %></link>
<%= for tag <- Pleroma.Object.hashtags(@object) do %>
<%= if tag && tag != "" do %>
<category><%= tag %></category>
<% end %>
<% end %>
- <%= for attachment <- @data["attachment"] || [] do %>
- <%= size = attachment_size_positive(attachment) %>
- <%= unless attachment_previewable?(attachment) do %>
- <enclosure url="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>" length="<%= size || 0 %>" />
+ <%= unless @data["sensitive"] do %>
+ <%= with [attachment | _] <- @data["attachment"] || [] do %>
+ <%= size = attachment_size_positive(attachment) %>
+ <enclosure url="<%= escape(attachment_href(attachment) || "") %>" type="<%= escape(attachment_type(attachment) || "application/octet-stream") %>" length="<%= size || 0 %>" />
<% end %>
+ <% end %>
+
+ <%= for attachment <- @data["attachment"] || [] do %>
<%= media_content_xml(attachment, @data["sensitive"]) %>
<% end %>
<%= if @data["inReplyTo"] do %>
<thr:in-reply-to ref='<%= @data["inReplyTo"] %>' href='<%= get_href(@data["inReplyTo"]) %>'/>
<% end %>
</item>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
index ae762f9ed..1720ccd37 100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
@@ -1,37 +1,41 @@
<entry>
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<%= render Phoenix.Controller.view_module(@conn), "_tag_author.atom", assigns %>
<id><%= @data["id"] %></id>
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
<content type="html"><%= escape(atom_content_encoded(@data)) %></content>
<published><%= to_rfc3339(@data["published"]) %></published>
<updated><%= to_rfc3339(@data["published"]) %></updated>
<ostatus:conversation ref="<%= activity_context(@activity) %>">
<%= activity_context(@activity) %>
</ostatus:conversation>
<link href="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
<%= if @data["summary"] != "" do %>
<summary><%= escape(@data["summary"]) %></summary>
<% end %>
<link type="application/atom+xml" href='<%= activity_link(@activity, @data) %>' rel="self"/>
<link type="text/html" href='<%= activity_link(@activity, @data) %>' rel="alternate"/>
<%= for tag <- Pleroma.Object.hashtags(@object) do %>
<category term="<%= tag %>"></category>
<% end %>
- <%= for attachment <- @data["attachment"] || [] do %>
- <%= unless attachment_previewable?(attachment) do %>
- <link rel="enclosure" href="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>" length="<%= attachment_size(attachment) %>"/>
+ <%= unless @data["sensitive"] do %>
+ <%= for attachment <- @data["attachment"] || [] do %>
+ <%= if size = attachment_size_positive(attachment) do %>
+ <link rel="enclosure" href="<%= escape(attachment_href(attachment) || "") %>" type="<%= escape(attachment_type(attachment) || "application/octet-stream") %>" length="<%= size %>"/>
+ <% else %>
+ <link rel="enclosure" href="<%= escape(attachment_href(attachment) || "") %>" type="<%= escape(attachment_type(attachment) || "application/octet-stream") %>"/>
+ <% end %>
<% end %>
<% end %>
<%= for {emoji, file} <- @data["emoji"] || %{} do %>
<link name="<%= emoji %>" rel="emoji" href="<%= file %>"/>
<% end %>
</entry>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
index 9b857ee5e..09945605c 100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
@@ -1,22 +1,25 @@
<item>
<guid isPermalink="true"><%= activity_link(@activity, @data) %></guid>
<link><%= activity_link(@activity, @data) %></link>
<pubDate><%= to_rfc2822(@data["published"]) %></pubDate>
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
<description><%= activity_description(@data) %></description>
<content:encoded><![CDATA[<%= rss_content_encoded(@data) %>]]></content:encoded>
- <%= for attachment <- @data["attachment"] || [] do %>
- <%= size = attachment_size_positive(attachment) %>
- <%= unless attachment_previewable?(attachment) do %>
- <enclosure url="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>" length="<%= size || 0 %>"/>
+ <%= unless @data["sensitive"] do %>
+ <%= with [attachment | _] <- @data["attachment"] || [] do %>
+ <%= size = attachment_size_positive(attachment) %>
+ <enclosure url="<%= escape(attachment_href(attachment) || "") %>" type="<%= escape(attachment_type(attachment) || "application/octet-stream") %>" length="<%= size || 0 %>"/>
<% end %>
+ <% end %>
+
+ <%= for attachment <- @data["attachment"] || [] do %>
<%= media_content_xml(attachment, @data["sensitive"]) %>
<% end %>
<%= for tag <- Pleroma.Object.hashtags(@object) do %>
<%= if tag && tag != "" do %>
<category><%= tag %></category>
<% end %>
<% end %>
</item>
diff --git a/test/pleroma/web/feed/tag_controller_test.exs b/test/pleroma/web/feed/tag_controller_test.exs
index 2e20e18d7..0d12f500a 100644
--- a/test/pleroma/web/feed/tag_controller_test.exs
+++ b/test/pleroma/web/feed/tag_controller_test.exs
@@ -1,265 +1,299 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Feed.TagControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
import SweetXml
alias Pleroma.Object
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Feed.FeedView
setup do: clear_config([:feed])
test "gets a feed (ATOM)", %{conn: conn} do
clear_config(
[:feed, :post_title],
%{max_length: 25, omission: "..."}
)
user = insert(:user)
{:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"})
object = Object.normalize(activity1, fetch: false)
object_data =
Map.put(object.data, "attachment", [
%{
"url" => [
%{
"href" =>
- "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
+ "https://peertube.moe/video.mp4?first=one&second=two",
"mediaType" => "video/mp4",
+ "size" => "123",
+ "type" => "Link"
+ }
+ ]
+ },
+ %{
+ "url" => [
+ %{
+ "href" => "https://peertube.moe/notes.pdf",
+ "mediaType" => "application/pdf",
"type" => "Link"
}
]
}
])
object
|> Ecto.Changeset.change(data: object_data)
|> Pleroma.Repo.update()
{:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"})
{:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"})
response =
conn
|> put_req_header("accept", "application/atom+xml")
|> get(tag_feed_path(conn, :feed, "pleromaart.atom"))
|> response(200)
xml = parse(response)
assert xpath(xml, ~x"//feed/title/text()") == ~c"#pleromaart"
assert xpath(xml, ~x"//feed/entry/title/text()"l) == [
~c"42 This is :moominmamm...",
~c"yeah #PleromaArt"
]
assert xpath(xml, ~x"//feed/entry/author/name/text()"ls) == [user.nickname, user.nickname]
+ assert xpath(xml, ~x"//feed/entry/link[@rel='enclosure']/@href"sl) == [
+ "https://peertube.moe/video.mp4?first=one&second=two",
+ "https://peertube.moe/notes.pdf"
+ ]
+
+ assert xpath(xml, ~x"//feed/entry/link[@rel='enclosure']/@length"sl) == ["123"]
+
conn =
conn
|> put_req_header("accept", "application/atom+xml")
|> get("/tags/pleromaart.atom", %{"max_id" => activity2.id})
assert get_resp_header(conn, "content-type") == ["application/atom+xml; charset=utf-8"]
resp = response(conn, 200)
xml = parse(resp)
assert xpath(xml, ~x"//feed/title/text()") == ~c"#pleromaart"
assert xpath(xml, ~x"//feed/entry/title/text()"l) == [
~c"yeah #PleromaArt"
]
end
test "gets a feed (RSS)", %{conn: conn} do
clear_config(
[:feed, :post_title],
%{max_length: 25, omission: "..."}
)
user = insert(:user)
{:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"})
object = Object.normalize(activity1, fetch: false)
object_data =
Map.put(object.data, "attachment", [
%{
"url" => [
%{
"href" =>
- "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
+ "https://peertube.moe/video.mp4?first=one&second=two",
"mediaType" => "video/mp4",
+ "size" => "123",
+ "type" => "Link"
+ }
+ ]
+ },
+ %{
+ "url" => [
+ %{
+ "href" => "https://peertube.moe/notes.pdf",
+ "mediaType" => "application/pdf",
"type" => "Link"
}
]
}
])
edited_at = NaiveDateTime.add(object.updated_at, 60)
object
|> Ecto.Changeset.change(data: object_data, updated_at: edited_at)
|> Pleroma.Repo.update()
{:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"})
{:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"})
response =
conn
|> put_req_header("accept", "application/rss+xml")
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|> response(200)
xml = parse(response)
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
assert xpath(xml, ~x"//channel/description/text()"s) ==
"These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse."
assert xpath(xml, ~x"//channel/link/text()") ==
~c"#{Pleroma.Web.Endpoint.url()}/tags/pleromaart.rss"
assert xpath(xml, ~x"//channel/webfeeds:logo/text()") ==
~c"#{Pleroma.Web.Endpoint.url()}/static/logo.svg"
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
~c"42 This is :moominmamm...",
~c"yeah #PleromaArt"
]
assert xpath(xml, ~x"//channel/item/pubDate/text()"sl) == [
FeedView.to_rfc2822(activity2.data["published"]),
FeedView.to_rfc2822(activity1.data["published"])
]
assert xpath(xml, ~x"//channel/lastBuildDate/text()"s) ==
FeedView.to_rfc2822(edited_at)
assert xpath(xml, ~x"//channel/item/media:content/@url"sl) == [
- "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4"
+ "https://peertube.moe/video.mp4?first=one&second=two",
+ "https://peertube.moe/notes.pdf"
+ ]
+
+ assert xpath(xml, ~x"//channel/item/enclosure/@url"sl) == [
+ "https://peertube.moe/video.mp4?first=one&second=two"
]
+ assert xpath(xml, ~x"//channel/item/enclosure/@length"sl) == ["123"]
+
obj1 = Object.normalize(activity1, fetch: false)
obj2 = Object.normalize(activity2, fetch: false)
assert xpath(xml, ~x"//channel/item/description/text()"sl) == [
HtmlEntities.decode(FeedView.activity_content(obj2.data)),
HtmlEntities.decode(FeedView.activity_content(obj1.data))
]
response =
conn
|> put_req_header("accept", "application/rss+xml")
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|> response(200)
xml = parse(response)
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
assert xpath(xml, ~x"//channel/description/text()"s) ==
"These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse."
conn =
conn
|> put_req_header("accept", "application/rss+xml")
|> get("/tags/pleromaart.rss", %{"max_id" => activity2.id})
assert get_resp_header(conn, "content-type") == ["application/rss+xml; charset=utf-8"]
resp = response(conn, 200)
xml = parse(resp)
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
~c"yeah #PleromaArt"
]
end
test "does not fabricate lastBuildDate for an empty RSS feed", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/rss+xml")
|> get(tag_feed_path(conn, :feed, "empty.rss"))
|> response(200)
refute response =~ "<lastBuildDate>"
end
describe "private instance" do
setup do: clear_config([:instance, :public], false)
test "returns 404 for tags feed", %{conn: conn} do
conn
|> put_req_header("accept", "application/rss+xml")
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|> response(404)
end
end
describe "restricted for unauthenticated" do
test "returns 404 when local timeline is disabled", %{conn: conn} do
clear_config([:restrict_unauthenticated, :timelines], %{local: true, federated: false})
conn
|> put_req_header("accept", "application/rss+xml")
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|> response(404)
end
test "returns local posts only when federated timeline is disabled", %{conn: conn} do
clear_config([:restrict_unauthenticated, :timelines], %{local: false, federated: true})
local_user = insert(:user)
remote_user = insert(:user, local: false)
local_note =
insert(:note,
user: local_user,
data: %{
"content" => "local post #PleromaArt",
"summary" => "",
"tag" => ["pleromaart"]
}
)
remote_note =
insert(:note,
user: remote_user,
data: %{
"content" => "remote post #PleromaArt",
"summary" => "",
"tag" => ["pleromaart"]
},
local: false
)
insert(:note_activity, user: local_user, note: local_note)
insert(:note_activity, user: remote_user, note: remote_note, local: false)
response =
conn
|> put_req_header("accept", "application/rss+xml")
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|> response(200)
xml = parse(response)
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
~c"local post #PleromaArt"
]
end
end
end
diff --git a/test/pleroma/web/feed/user_controller_test.exs b/test/pleroma/web/feed/user_controller_test.exs
index 5dfe6aa89..e1f9fd403 100644
--- a/test/pleroma/web/feed/user_controller_test.exs
+++ b/test/pleroma/web/feed/user_controller_test.exs
@@ -1,338 +1,395 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Feed.UserControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
import SweetXml
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Feed.FeedView
setup do: clear_config([:static_fe, :enabled], false)
describe "feed" do
setup do: clear_config([:feed])
setup do
clear_config(
[:feed, :post_title],
%{max_length: 15, omission: "..."}
)
activity = insert(:note_activity)
note =
insert(:note,
data: %{
"content" => "This & this is :moominmamma: note ",
"source" => "This & this is :moominmamma: note ",
"attachment" => [
%{
"url" => [
%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
]
}
],
"inReplyTo" => activity.data["id"],
"context" => "2hu & as",
"summary" => "2hu & as"
}
)
note_activity = insert(:note_activity, note: note)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
note2 =
insert(:note,
user: user,
data: %{
"content" => "42 & This is :moominmamma: note ",
"inReplyTo" => activity.data["id"]
}
)
note_activity2 = insert(:note_activity, note: note2)
note3 =
insert(:note,
user: user,
data: %{
"content" => "This note tests whether HTML entities are truncated properly",
"summary" => "Won't, didn't fail",
"inReplyTo" => note_activity2.id
}
)
_note_activity3 = insert(:note_activity, note: note3)
object = Object.normalize(note_activity, fetch: false)
encoded_title = FeedView.activity_title(note3.data)
[user: user, object: object, max_id: note_activity2.id, encoded_title: encoded_title]
end
test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_id} do
resp =
conn
|> put_req_header("accept", "application/atom+xml")
|> get(user_feed_path(conn, :feed, user.nickname))
|> response(200)
activity_titles =
resp
|> SweetXml.parse()
|> SweetXml.xpath(~x"//entry/title/text()"l)
assert activity_titles == [~c"Won't, didn'...", ~c"2hu", ~c"2hu & as"]
assert resp =~ FeedView.escape(object.data["content"])
assert resp =~ FeedView.escape(object.data["summary"])
assert resp =~ FeedView.escape(object.data["context"])
resp =
conn
|> put_req_header("accept", "application/atom+xml")
|> get("/users/#{user.nickname}/feed", %{"max_id" => max_id})
|> response(200)
activity_titles =
resp
|> SweetXml.parse()
|> SweetXml.xpath(~x"//entry/title/text()"l)
assert activity_titles == [~c"2hu & as"]
end
test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id} do
resp =
conn
|> put_req_header("accept", "application/rss+xml")
|> get("/users/#{user.nickname}/feed.rss")
|> response(200)
activity_titles =
resp
|> SweetXml.parse()
|> SweetXml.xpath(~x"//item/title/text()"l)
assert activity_titles == [~c"Won't, didn'...", ~c"2hu", ~c"2hu & as"]
assert resp =~ FeedView.escape(object.data["content"])
assert resp =~ FeedView.escape(object.data["summary"])
assert resp =~ FeedView.escape(object.data["context"])
resp =
conn
|> put_req_header("accept", "application/rss+xml")
|> get("/users/#{user.nickname}/feed.rss", %{"max_id" => max_id})
|> response(200)
activity_titles =
resp
|> SweetXml.parse()
|> SweetXml.xpath(~x"//item/title/text()"l)
assert activity_titles == [~c"2hu & as"]
end
test "escapes query parameters in feed self links", %{conn: conn, user: user} do
for format <- ~w[atom rss] do
response =
conn
|> get("/users/#{user.nickname}/feed.#{format}?first=one&second=two")
|> response(200)
assert response =~ "first=one&amp;second=two"
refute response =~ "first=one&second=two"
end
end
+ test "does not expose sensitive attachments as enclosures", %{
+ conn: conn,
+ object: object,
+ user: user
+ } do
+ object
+ |> Ecto.Changeset.change(data: Map.put(object.data, "sensitive", true))
+ |> Pleroma.Repo.update!()
+
+ atom_response =
+ conn
+ |> get("/users/#{user.nickname}/feed.atom")
+ |> response(200)
+
+ rss_response =
+ conn
+ |> get("/users/#{user.nickname}/feed.rss")
+ |> response(200)
+
+ refute atom_response =~ "rel=\"enclosure\""
+ refute rss_response =~ "<enclosure "
+ end
+
+ test "uses enclosure fallbacks for user feeds", %{conn: conn, object: object, user: user} do
+ attachment = %{"url" => [%{"href" => "https://example.com/file.bin"}]}
+
+ object
+ |> Ecto.Changeset.change(data: Map.put(object.data, "attachment", [attachment]))
+ |> Pleroma.Repo.update!()
+
+ atom_xml =
+ conn
+ |> get("/users/#{user.nickname}/feed.atom")
+ |> response(200)
+ |> parse()
+
+ assert xpath(atom_xml, ~x"//entry/link[@rel='enclosure']/@href"sl) == [
+ "https://example.com/file.bin"
+ ]
+
+ assert xpath(atom_xml, ~x"//entry/link[@rel='enclosure']/@type"sl) == [
+ "application/octet-stream"
+ ]
+
+ assert xpath(atom_xml, ~x"//entry/link[@rel='enclosure']/@length"sl) == []
+
+ rss_xml =
+ conn
+ |> get("/users/#{user.nickname}/feed.rss")
+ |> response(200)
+ |> parse()
+
+ assert xpath(rss_xml, ~x"//item/enclosure/@url"sl) == ["https://example.com/file.bin"]
+ assert xpath(rss_xml, ~x"//item/enclosure/@type"sl) == ["application/octet-stream"]
+ assert xpath(rss_xml, ~x"//item/enclosure/@length"sl) == ["0"]
+ end
+
test "returns 404 for a missing feed", %{conn: conn} do
conn =
conn
|> put_req_header("accept", "application/atom+xml")
|> get(user_feed_path(conn, :feed, "nonexisting"))
assert response(conn, 404)
end
test "returns noindex meta for missing user", %{conn: conn} do
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/users/nonexisting")
assert html_response(conn, 200) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">"
end
test "returns feed with public and unlisted activities", %{conn: conn} do
user = insert(:user)
{:ok, _} = CommonAPI.post(user, %{status: "public", visibility: "public"})
{:ok, _} = CommonAPI.post(user, %{status: "direct", visibility: "direct"})
{:ok, _} = CommonAPI.post(user, %{status: "unlisted", visibility: "unlisted"})
{:ok, _} = CommonAPI.post(user, %{status: "private", visibility: "private"})
resp =
conn
|> put_req_header("accept", "application/atom+xml")
|> get(user_feed_path(conn, :feed, user.nickname))
|> response(200)
activity_titles =
resp
|> SweetXml.parse()
|> SweetXml.xpath(~x"//entry/title/text()"l)
|> Enum.sort()
assert activity_titles == [~c"public", ~c"unlisted"]
end
test "returns 404 when the user is remote", %{conn: conn} do
user = insert(:user, local: false)
{:ok, _} = CommonAPI.post(user, %{status: "test"})
assert conn
|> put_req_header("accept", "application/atom+xml")
|> get(user_feed_path(conn, :feed, user.nickname))
|> response(404)
end
test "does not require authentication on non-federating instances", %{conn: conn} do
clear_config([:instance, :federating], false)
user = insert(:user)
conn
|> put_req_header("accept", "application/rss+xml")
|> get("/users/#{user.nickname}/feed.rss")
|> response(200)
end
test "does not mangle HTML entities midway", %{
conn: conn,
user: user,
object: object,
encoded_title: encoded_title
} do
resp =
conn
|> put_req_header("accept", "application/atom+xml")
|> get(user_feed_path(conn, :feed, user.nickname))
|> response(200)
activity_titles =
resp
|> SweetXml.parse()
|> SweetXml.xpath(~x"//entry/title/text()"l)
assert activity_titles == [~c"Won't, didn'...", ~c"2hu", ~c"2hu & as"]
assert resp =~ FeedView.escape(object.data["content"])
assert resp =~ FeedView.escape(object.data["summary"])
assert resp =~ FeedView.escape(object.data["context"])
assert resp =~ encoded_title
end
end
# Note: see ActivityPubControllerTest for JSON format tests
describe "feed_redirect" do
test "with html format, it redirects to user feed", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> get("/users/#{user.nickname}")
|> response(200)
assert response ==
Pleroma.Web.Fallback.RedirectController.redirector_with_meta(
conn,
%{user: user}
).resp_body
end
test "with html format, it falls back to frontend when user is remote", %{conn: conn} do
user = insert(:user, local: false)
{:ok, _} = CommonAPI.post(user, %{status: "test"})
response =
conn
|> get("/users/#{user.nickname}")
|> response(200)
assert response =~ "</html>"
end
test "with html format, it falls back to frontend when user is not found", %{conn: conn} do
response =
conn
|> get("/users/jimm")
|> response(200)
assert response =~ "</html>"
end
test "with non-html / non-json format, it redirects to user feed in atom format", %{
conn: conn
} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
conn =
conn
|> put_req_header("accept", "application/xml")
|> get("/users/#{user.nickname}")
assert conn.status == 302
assert redirected_to(conn) ==
"#{Pleroma.Web.Endpoint.url()}/users/#{user.nickname}/feed.atom"
end
test "redirects to rss feed when explicitly requested", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
conn =
conn
|> put_req_header("accept", "application/xml")
|> get("/users/#{user.nickname}.rss")
assert conn.status == 302
assert redirected_to(conn) ==
"#{Pleroma.Web.Endpoint.url()}/users/#{user.nickname}/feed.rss"
end
test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/xml")
|> get(user_feed_path(conn, :feed, "jimm"))
|> response(404)
assert response == ~S({"error":"Not found"})
end
end
describe "private instance" do
setup do: clear_config([:instance, :public])
test "returns 404 for user feed", %{conn: conn} do
clear_config([:instance, :public], false)
user = insert(:user)
{:ok, _} = CommonAPI.post(user, %{status: "test"})
assert conn
|> put_req_header("accept", "application/atom+xml")
|> get(user_feed_path(conn, :feed, user.nickname))
|> response(404)
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 19, 6:27 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769032
Default Alt Text
(30 KB)

Event Timeline