Merge branch 'develop' into 'tusooa/quote'

# Conflicts:
#   lib/pleroma/constants.ex
This commit is contained in:
tusooa 2023-08-31 00:35:37 +00:00
commit c525496e75
34 changed files with 483 additions and 46 deletions

15
test/fixtures/xml_billion_laughs.xml vendored Normal file
View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

View file

@ -17,6 +17,8 @@ defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
end
test "merged runtime config" do
assert :ok == File.chmod!("test/fixtures/config/temp.secret.exs", 0o640)
merged =
ReleaseRuntimeProvider.load([], config_path: "test/fixtures/config/temp.secret.exs")
@ -25,6 +27,8 @@ defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
end
test "merged exported config" do
assert :ok == File.chmod!("test/fixtures/config/temp.exported_from_db.secret.exs", 0o640)
ExUnit.CaptureIO.capture_io(fn ->
merged =
ReleaseRuntimeProvider.load([],
@ -37,6 +41,9 @@ defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
end
test "runtime config is merged with exported config" do
assert :ok == File.chmod!("test/fixtures/config/temp.secret.exs", 0o640)
assert :ok == File.chmod!("test/fixtures/config/temp.exported_from_db.secret.exs", 0o640)
merged =
ReleaseRuntimeProvider.load([],
config_path: "test/fixtures/config/temp.secret.exs",

View file

@ -90,4 +90,8 @@ defmodule Pleroma.Emoji.PackTest do
assert updated_pack.files_count == 1
end
test "load_pack/1 ignores path traversal in a forged pack name", %{pack: pack} do
assert {:ok, ^pack} = Pack.load_pack("../../../../../dump_pack")
end
end

View file

@ -592,7 +592,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
end
test "returns list attachments with desc" do
object = insert(:note)
object = insert(:attachment)
desc = Jason.encode!(%{object.id => "test-desc"})
assert Utils.attachments_from_ids_descs(["#{object.id}", "34"], desc) == [
@ -603,7 +603,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
describe "attachments_from_ids/1" do
test "returns attachments with descs" do
object = insert(:note)
object = insert(:attachment)
desc = Jason.encode!(%{object.id => "test-desc"})
assert Utils.attachments_from_ids(%{
@ -615,13 +615,18 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
end
test "returns attachments without descs" do
object = insert(:note)
object = insert(:attachment)
assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}) == [object.data]
end
test "returns [] when not pass media_ids" do
assert Utils.attachments_from_ids(%{}) == []
end
test "checks that the object is of upload type" do
object = insert(:note)
assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}) == []
end
end
describe "maybe_add_list_data/3" do

View file

@ -793,6 +793,49 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, local: local, remote: remote}
end
defp local_and_remote_context_activities do
local_user_1 = insert(:user)
local_user_2 = insert(:user)
remote_user = insert(:user, local: false)
{:ok, %{id: id1, data: %{"context" => context}}} =
CommonAPI.post(local_user_1, %{status: "post"})
{:ok, %{id: id2} = post} =
CommonAPI.post(local_user_2, %{status: "local reply", in_reply_to_status_id: id1})
params = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"actor" => remote_user.ap_id,
"type" => "Create",
"context" => context,
"id" => "#{remote_user.ap_id}/activities/1",
"inReplyTo" => post.data["id"],
"object" => %{
"type" => "Note",
"content" => "remote reply",
"context" => context,
"id" => "#{remote_user.ap_id}/objects/1",
"attributedTo" => remote_user.ap_id,
"to" => [
local_user_1.ap_id,
local_user_2.ap_id,
"https://www.w3.org/ns/activitystreams#Public"
]
},
"to" => [
local_user_1.ap_id,
local_user_2.ap_id,
"https://www.w3.org/ns/activitystreams#Public"
]
}
{:ok, job} = Pleroma.Web.Federator.incoming_ap_doc(params)
{:ok, remote_activity} = ObanHelpers.perform(job)
%{locals: [id1, id2], remote: remote_activity.id, context: context}
end
describe "status with restrict unauthenticated activities for local and remote" do
setup do: local_and_remote_activities()
@ -979,6 +1022,230 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
end
end
describe "getting status contexts restricted unauthenticated for local and remote" do
setup do: local_and_remote_context_activities()
setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
test "if user is unauthenticated", %{conn: conn, locals: [post_id, _]} do
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
assert json_response_and_validate_schema(res_conn, 200) == %{
"ancestors" => [],
"descendants" => []
}
end
test "if user is unauthenticated reply", %{conn: conn, locals: [_, reply_id]} do
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
assert json_response_and_validate_schema(res_conn, 200) == %{
"ancestors" => [],
"descendants" => []
}
end
test "if user is authenticated", %{locals: [post_id, reply_id], remote: remote_reply_id} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
%{"ancestors" => [], "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert reply_id in descendant_ids
assert remote_reply_id in descendant_ids
end
test "if user is authenticated reply", %{locals: [post_id, reply_id], remote: remote_reply_id} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
%{"ancestors" => ancestors, "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
ancestor_ids =
ancestors
|> Enum.map(& &1["id"])
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert post_id in ancestor_ids
assert remote_reply_id in descendant_ids
end
end
describe "getting status contexts restricted unauthenticated for local" do
setup do: local_and_remote_context_activities()
setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], false)
test "if user is unauthenticated", %{
conn: conn,
locals: [post_id, reply_id],
remote: remote_reply_id
} do
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
%{"ancestors" => [], "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert reply_id not in descendant_ids
assert remote_reply_id in descendant_ids
end
test "if user is unauthenticated reply", %{
conn: conn,
locals: [post_id, reply_id],
remote: remote_reply_id
} do
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
%{"ancestors" => ancestors, "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
ancestor_ids =
ancestors
|> Enum.map(& &1["id"])
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert post_id not in ancestor_ids
assert remote_reply_id in descendant_ids
end
test "if user is authenticated", %{locals: [post_id, reply_id], remote: remote_reply_id} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
%{"ancestors" => [], "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert reply_id in descendant_ids
assert remote_reply_id in descendant_ids
end
test "if user is authenticated reply", %{locals: [post_id, reply_id], remote: remote_reply_id} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
%{"ancestors" => ancestors, "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
ancestor_ids =
ancestors
|> Enum.map(& &1["id"])
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert post_id in ancestor_ids
assert remote_reply_id in descendant_ids
end
end
describe "getting status contexts restricted unauthenticated for remote" do
setup do: local_and_remote_context_activities()
setup do: clear_config([:restrict_unauthenticated, :activities, :local], false)
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
test "if user is unauthenticated", %{
conn: conn,
locals: [post_id, reply_id],
remote: remote_reply_id
} do
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
%{"ancestors" => [], "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert reply_id in descendant_ids
assert remote_reply_id not in descendant_ids
end
test "if user is unauthenticated reply", %{
conn: conn,
locals: [post_id, reply_id],
remote: remote_reply_id
} do
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
%{"ancestors" => ancestors, "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
ancestor_ids =
ancestors
|> Enum.map(& &1["id"])
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert post_id in ancestor_ids
assert remote_reply_id not in descendant_ids
end
test "if user is authenticated", %{locals: [post_id, reply_id], remote: remote_reply_id} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
%{"ancestors" => [], "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
reply_ids =
descendants
|> Enum.map(& &1["id"])
assert reply_id in reply_ids
assert remote_reply_id in reply_ids
end
test "if user is authenticated reply", %{locals: [post_id, reply_id], remote: remote_reply_id} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
%{"ancestors" => ancestors, "descendants" => descendants} =
json_response_and_validate_schema(res_conn, 200)
ancestor_ids =
ancestors
|> Enum.map(& &1["id"])
descendant_ids =
descendants
|> Enum.map(& &1["id"])
assert post_id in ancestor_ids
assert remote_reply_id in descendant_ids
end
end
describe "deleting a status" do
test "when you created it" do
%{user: author, conn: conn} = oauth_access(["write:statuses"])

View file

@ -180,5 +180,28 @@ defmodule Pleroma.Web.WebFingerTest do
{:ok, _data} = WebFinger.finger("pekorino@pawoo.net")
end
test "refuses to process XML remote entities" do
Tesla.Mock.mock(fn
%{
url: "https://pawoo.net/.well-known/webfinger?resource=acct:pekorino@pawoo.net"
} ->
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/xml_external_entities.xml"),
headers: [{"content-type", "application/xrd+xml"}]
}}
%{url: "https://pawoo.net/.well-known/host-meta"} ->
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/tesla_mock/pawoo.net_host_meta")
}}
end)
assert :error = WebFinger.finger("pekorino@pawoo.net")
end
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Web.XMLTest do
use Pleroma.DataCase, async: true
alias Pleroma.Web.XML
test "refuses to parse any entities from XML" do
data = File.read!("test/fixtures/xml_billion_laughs.xml")
assert(:error == XML.parse_document(data))
end
test "refuses to load external entities from XML" do
data = File.read!("test/fixtures/xml_external_entities.xml")
assert(:error == XML.parse_document(data))
end
end