Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into auth-fetch-exception
This commit is contained in:
commit
d3e85da0fd
57 changed files with 1471 additions and 162 deletions
4
test/fixtures/tesla_mock/gleasonator.com_host_meta
vendored
Normal file
4
test/fixtures/tesla_mock/gleasonator.com_host_meta
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" template="https://gleasonator.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
|
||||
</XRD>
|
||||
28
test/fixtures/tesla_mock/webfinger_spoof.json
vendored
Normal file
28
test/fixtures/tesla_mock/webfinger_spoof.json
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"aliases": [
|
||||
"https://gleasonator.com/users/alex",
|
||||
"https://mitra.social/users/alex"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html"
|
||||
},
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "self",
|
||||
"type": "application/activity+json"
|
||||
},
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "self",
|
||||
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://gleasonator.com/ostatus_subscribe?acct={uri}"
|
||||
}
|
||||
],
|
||||
"subject": "acct:trump@whitehouse.gov"
|
||||
}
|
||||
41
test/fixtures/webfinger/graf-imposter-webfinger.json
vendored
Normal file
41
test/fixtures/webfinger/graf-imposter-webfinger.json
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"subject": "acct:graf@poa.st",
|
||||
"aliases": [
|
||||
"https://fba.ryona.agenc/webfingertest"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc/webfingertest"
|
||||
},
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "https://fba.ryona.agenc/webfingertest"
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://fba.ryona.agenc/contact/follow?url={uri}"
|
||||
},
|
||||
{
|
||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||
"type": "application/atom+xml",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"rel": "salmon",
|
||||
"href": "https://fba.ryona.agenc/salmon/friendica"
|
||||
},
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc/hcard/friendica"
|
||||
},
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -112,6 +112,7 @@ defmodule Pleroma.NotificationTest do
|
|||
{:ok, [notification]} = Notification.create_notifications(status)
|
||||
|
||||
assert notification.user_id == subscriber.id
|
||||
assert notification.type == "status"
|
||||
end
|
||||
|
||||
test "does not create a notification for subscribed users if status is a reply" do
|
||||
|
|
@ -136,6 +137,21 @@ defmodule Pleroma.NotificationTest do
|
|||
assert Enum.empty?(subscriber_notifications)
|
||||
end
|
||||
|
||||
test "does not create subscriber notification if mentioned" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "mentioning @#{subscriber.nickname}"})
|
||||
{:ok, [notification] = notifications} = Notification.create_notifications(status)
|
||||
|
||||
assert length(notifications) == 1
|
||||
|
||||
assert notification.user_id == subscriber.id
|
||||
assert notification.type == "mention"
|
||||
end
|
||||
|
||||
test "it sends edited notifications to those who repeated a status" do
|
||||
user = insert(:user)
|
||||
repeated_user = insert(:user)
|
||||
|
|
@ -843,22 +859,6 @@ defmodule Pleroma.NotificationTest do
|
|||
assert Enum.empty?(Notification.for_user(user))
|
||||
end
|
||||
|
||||
test "replying to a deleted post without tagging does not generate a notification" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
{:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
|
||||
|
||||
{:ok, _reply_activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "test reply",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
end
|
||||
|
||||
test "notifications are deleted if a local user is deleted" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
|
|||
49
test/pleroma/search/healthcheck_test.exs
Normal file
49
test/pleroma/search/healthcheck_test.exs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Search.HealthcheckTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Tesla.Mock
|
||||
|
||||
alias Pleroma.Search.Healthcheck
|
||||
|
||||
@good1 "http://good1.example.com/healthz"
|
||||
@good2 "http://good2.example.com/health"
|
||||
@bad "http://bad.example.com/healthy"
|
||||
|
||||
setup do
|
||||
mock(fn
|
||||
%{method: :get, url: @good1} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: ""
|
||||
}
|
||||
|
||||
%{method: :get, url: @good2} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: ""
|
||||
}
|
||||
|
||||
%{method: :get, url: @bad} ->
|
||||
%Tesla.Env{
|
||||
status: 503,
|
||||
body: ""
|
||||
}
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "true for 200 responses" do
|
||||
assert Healthcheck.check([@good1])
|
||||
assert Healthcheck.check([@good1, @good2])
|
||||
end
|
||||
|
||||
test "false if any response is not a 200" do
|
||||
refute Healthcheck.check([@bad])
|
||||
refute Healthcheck.check([@good1, @bad])
|
||||
end
|
||||
end
|
||||
158
test/pleroma/uploaders/ipfs_test.exs
Normal file
158
test/pleroma/uploaders/ipfs_test.exs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Uploaders.IPFSTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Uploaders.IPFS
|
||||
alias Tesla.Multipart
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: Config
|
||||
|
||||
describe "get_final_url" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS] ->
|
||||
[post_gateway_url: "http://localhost:5001"]
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it returns the final url for put_file" do
|
||||
assert IPFS.put_file_endpoint() == "http://localhost:5001/api/v0/add"
|
||||
end
|
||||
|
||||
test "it returns the final url for delete_file" do
|
||||
assert IPFS.delete_file_endpoint() == "http://localhost:5001/api/v0/files/rm"
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_file/1" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Upload, :uploader] -> Pleroma.Uploaders.IPFS end)
|
||||
|> expect(:get, fn [Pleroma.Upload, :base_url] -> nil end)
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :public_endpoint] -> nil end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it returns path to ipfs file with cid as subdomain" do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :get_gateway_url] ->
|
||||
"https://{CID}.ipfs.mydomain.com"
|
||||
end)
|
||||
|
||||
assert IPFS.get_file("testcid") == {
|
||||
:ok,
|
||||
{:url, "https://testcid.ipfs.mydomain.com"}
|
||||
}
|
||||
end
|
||||
|
||||
test "it returns path to ipfs file with cid as path" do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :get_gateway_url] ->
|
||||
"https://ipfs.mydomain.com/ipfs/{CID}"
|
||||
end)
|
||||
|
||||
assert IPFS.get_file("testcid") == {
|
||||
:ok,
|
||||
{:url, "https://ipfs.mydomain.com/ipfs/testcid"}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "put_file/1" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS] ->
|
||||
[post_gateway_url: "http://localhost:5001"]
|
||||
end)
|
||||
|
||||
file_upload = %Pleroma.Upload{
|
||||
name: "image-tet.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: "test_folder/image-tet.jpg",
|
||||
tempfile: Path.absname("test/instance_static/add/shortcode.png")
|
||||
}
|
||||
|
||||
mp =
|
||||
Multipart.new()
|
||||
|> Multipart.add_content_type_param("charset=utf-8")
|
||||
|> Multipart.add_file(file_upload.tempfile)
|
||||
|
||||
[file_upload: file_upload, mp: mp]
|
||||
end
|
||||
|
||||
test "save file", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP,
|
||||
post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"{\"Name\":\"image-tet.jpg\",\"Size\":\"5000\", \"Hash\":\"bafybeicrh7ltzx52yxcwrvxxckfmwhqdgsb6qym6dxqm2a4ymsakeshwoi\"}"
|
||||
}}
|
||||
end do
|
||||
assert IPFS.put_file(file_upload) ==
|
||||
{:ok, {:file, "bafybeicrh7ltzx52yxcwrvxxckfmwhqdgsb6qym6dxqm2a4ymsakeshwoi"}}
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP,
|
||||
post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
|
||||
{:error, "IPFS Gateway upload failed"}
|
||||
end do
|
||||
assert capture_log(fn ->
|
||||
assert IPFS.put_file(file_upload) == {:error, "IPFS Gateway upload failed"}
|
||||
end) =~ "Elixir.Pleroma.Uploaders.IPFS: {:error, \"IPFS Gateway upload failed\"}"
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error if JSON decode fails", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP, [],
|
||||
post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
|
||||
{:ok, %Tesla.Env{status: 200, body: "invalid"}}
|
||||
end do
|
||||
assert capture_log(fn ->
|
||||
assert IPFS.put_file(file_upload) == {:error, "JSON decode failed"}
|
||||
end) =~
|
||||
"Elixir.Pleroma.Uploaders.IPFS: {:error, %Jason.DecodeError"
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error if JSON body doesn't contain Hash key", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP, [],
|
||||
post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
|
||||
{:ok, %Tesla.Env{status: 200, body: "{\"key\": \"value\"}"}}
|
||||
end do
|
||||
assert IPFS.put_file(file_upload) == {:error, "JSON doesn't contain Hash key"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_file/1" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS] ->
|
||||
[post_gateway_url: "http://localhost:5001"]
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test_with_mock "deletes file", Pleroma.HTTP,
|
||||
post: fn "http://localhost:5001/api/v0/files/rm", "", [], params: [arg: "image.jpg"] ->
|
||||
{:ok, %{status: 204}}
|
||||
end do
|
||||
assert :ok = IPFS.delete_file("image.jpg")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -877,109 +877,19 @@ defmodule Pleroma.UserTest do
|
|||
setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true)
|
||||
|
||||
test "for mastodon" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
|> String.replace("{{nickname}}", "a"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
ap_id = "a@mastodon.example"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
assert fetched_user.ap_id == "https://sub.mastodon.example/users/a"
|
||||
assert fetched_user.nickname == "a@mastodon.example"
|
||||
end
|
||||
|
||||
test "for pleroma" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
ap_id = "a@pleroma.example"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
assert fetched_user.ap_id == "https://sub.pleroma.example/users/a"
|
||||
assert fetched_user.nickname == "a@pleroma.example"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
267
test/pleroma/web/activity_pub/mrf/nsfw_api_policy_test.exs
Normal file
267
test/pleroma/web/activity_pub/mrf/nsfw_api_policy_test.exs
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Constants
|
||||
alias Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
@policy :mrf_nsfw_api
|
||||
|
||||
@sfw_url "https://kittens.co/kitty.gif"
|
||||
@nsfw_url "https://b00bies.com/nsfw.jpg"
|
||||
@timeout_url "http://time.out/i.jpg"
|
||||
|
||||
setup_all do
|
||||
clear_config(@policy,
|
||||
url: "http://127.0.0.1:5000/",
|
||||
threshold: 0.7,
|
||||
mark_sensitive: true,
|
||||
unlist: false,
|
||||
reject: false
|
||||
)
|
||||
end
|
||||
|
||||
setup do
|
||||
Tesla.Mock.mock(fn
|
||||
# NSFW URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=#{@nsfw_url}"} ->
|
||||
%Tesla.Env{status: 200, body: ~s({"score":0.99772077798843384,"url":"#{@nsfw_url}"})}
|
||||
|
||||
# SFW URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=#{@sfw_url}"} ->
|
||||
%Tesla.Env{status: 200, body: ~s({"score":0.00011714912398019806,"url":"#{@sfw_url}"})}
|
||||
|
||||
# Timeout URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=#{@timeout_url}"} ->
|
||||
{:error, :timeout}
|
||||
|
||||
# Fallback URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=" <> url} ->
|
||||
body =
|
||||
~s({"error_code":500,"error_reason":"[Errno -2] Name or service not known","url":"#{url}"})
|
||||
|
||||
%Tesla.Env{status: 500, body: body}
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "build_request_url/1" do
|
||||
test "it works" do
|
||||
expected = "http://127.0.0.1:5000/?url=https://b00bies.com/nsfw.jpg"
|
||||
assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
|
||||
end
|
||||
|
||||
test "it adds a trailing slash" do
|
||||
clear_config([@policy, :url], "http://localhost:5000")
|
||||
|
||||
expected = "http://localhost:5000/?url=https://b00bies.com/nsfw.jpg"
|
||||
assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
|
||||
end
|
||||
|
||||
test "it adds a trailing slash preserving the path" do
|
||||
clear_config([@policy, :url], "http://localhost:5000/nsfw_api")
|
||||
|
||||
expected = "http://localhost:5000/nsfw_api/?url=https://b00bies.com/nsfw.jpg"
|
||||
assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "parse_url/1" do
|
||||
test "returns decoded JSON from the API server" do
|
||||
expected = %{"score" => 0.99772077798843384, "url" => @nsfw_url}
|
||||
assert NsfwApiPolicy.parse_url(@nsfw_url) == {:ok, expected}
|
||||
end
|
||||
|
||||
test "warns when the API server fails" do
|
||||
expected = "[NsfwApiPolicy]: The API server failed. Skipping."
|
||||
assert capture_log(fn -> NsfwApiPolicy.parse_url(@timeout_url) end) =~ expected
|
||||
end
|
||||
|
||||
test "returns {:error, _} tuple when the API server fails" do
|
||||
capture_log(fn ->
|
||||
assert {:error, _} = NsfwApiPolicy.parse_url(@timeout_url)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "check_url_nsfw/1" do
|
||||
test "returns {:nsfw, _} tuple" do
|
||||
expected = {:nsfw, %{url: @nsfw_url, score: 0.99772077798843384, threshold: 0.7}}
|
||||
assert NsfwApiPolicy.check_url_nsfw(@nsfw_url) == expected
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} tuple" do
|
||||
expected = {:sfw, %{url: @sfw_url, score: 0.00011714912398019806, threshold: 0.7}}
|
||||
assert NsfwApiPolicy.check_url_nsfw(@sfw_url) == expected
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} on failure" do
|
||||
expected = {:sfw, %{url: @timeout_url, score: nil, threshold: 0.7}}
|
||||
|
||||
capture_log(fn ->
|
||||
assert NsfwApiPolicy.check_url_nsfw(@timeout_url) == expected
|
||||
end)
|
||||
end
|
||||
|
||||
test "works with map URL" do
|
||||
expected = {:nsfw, %{url: @nsfw_url, score: 0.99772077798843384, threshold: 0.7}}
|
||||
assert NsfwApiPolicy.check_url_nsfw(%{"href" => @nsfw_url}) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "check_attachment_nsfw/1" do
|
||||
test "returns {:nsfw, _} if any items are NSFW" do
|
||||
attachment = %{"url" => [%{"href" => @nsfw_url}, @nsfw_url, @sfw_url]}
|
||||
assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:nsfw, attachment}
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} if all items are SFW" do
|
||||
attachment = %{"url" => [%{"href" => @sfw_url}, @sfw_url, @sfw_url]}
|
||||
assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:sfw, attachment}
|
||||
end
|
||||
|
||||
test "works with binary URL" do
|
||||
attachment = %{"url" => @nsfw_url}
|
||||
assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:nsfw, attachment}
|
||||
end
|
||||
end
|
||||
|
||||
describe "check_object_nsfw/1" do
|
||||
test "returns {:nsfw, _} if any items are NSFW" do
|
||||
object = %{"attachment" => [%{"url" => [%{"href" => @nsfw_url}, @sfw_url]}]}
|
||||
assert NsfwApiPolicy.check_object_nsfw(object) == {:nsfw, object}
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} if all items are SFW" do
|
||||
object = %{"attachment" => [%{"url" => [%{"href" => @sfw_url}, @sfw_url]}]}
|
||||
assert NsfwApiPolicy.check_object_nsfw(object) == {:sfw, object}
|
||||
end
|
||||
|
||||
test "works with embedded object" do
|
||||
object = %{"object" => %{"attachment" => [%{"url" => [%{"href" => @nsfw_url}, @sfw_url]}]}}
|
||||
assert NsfwApiPolicy.check_object_nsfw(object) == {:nsfw, object}
|
||||
end
|
||||
end
|
||||
|
||||
describe "unlist/1" do
|
||||
test "unlist addressing" do
|
||||
user = insert(:user)
|
||||
|
||||
object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [user.follower_address, "https://hello.world/users/alex"],
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
expected = %{
|
||||
"to" => [user.follower_address],
|
||||
"cc" => [Constants.as_public(), "https://hello.world/users/alex"],
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert NsfwApiPolicy.unlist(object) == expected
|
||||
end
|
||||
|
||||
test "raise if user isn't found" do
|
||||
object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [],
|
||||
"actor" => "https://hello.world/users/alex"
|
||||
}
|
||||
|
||||
assert_raise(RuntimeError, fn ->
|
||||
NsfwApiPolicy.unlist(object)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mark_sensitive/1" do
|
||||
test "adds nsfw tag and marks sensitive" do
|
||||
object = %{"tag" => ["yolo"]}
|
||||
expected = %{"tag" => ["yolo", "nsfw"], "sensitive" => true}
|
||||
assert NsfwApiPolicy.mark_sensitive(object) == expected
|
||||
end
|
||||
|
||||
test "works with embedded object" do
|
||||
object = %{"object" => %{"tag" => ["yolo"]}}
|
||||
expected = %{"object" => %{"tag" => ["yolo", "nsfw"], "sensitive" => true}}
|
||||
assert NsfwApiPolicy.mark_sensitive(object) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "filter/1" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
nsfw_object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [user.follower_address],
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [%{"url" => @nsfw_url}]
|
||||
}
|
||||
|
||||
sfw_object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [user.follower_address],
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [%{"url" => @sfw_url}]
|
||||
}
|
||||
|
||||
%{user: user, nsfw_object: nsfw_object, sfw_object: sfw_object}
|
||||
end
|
||||
|
||||
test "passes SFW object through", %{sfw_object: object} do
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "passes NSFW object through when actions are disabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :mark_sensitive], false)
|
||||
clear_config([@policy, :unlist], false)
|
||||
clear_config([@policy, :reject], false)
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "passes NSFW object through when :threshold is 1", %{nsfw_object: object} do
|
||||
clear_config([@policy, :reject], true)
|
||||
clear_config([@policy, :threshold], 1)
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "rejects SFW object through when :threshold is 0", %{sfw_object: object} do
|
||||
clear_config([@policy, :reject], true)
|
||||
clear_config([@policy, :threshold], 0)
|
||||
{:reject, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "rejects NSFW when :reject is enabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :reject], true)
|
||||
{:reject, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "passes NSFW through when :reject is disabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :reject], false)
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "unlists NSFW when :unlist is enabled", %{user: user, nsfw_object: object} do
|
||||
clear_config([@policy, :unlist], true)
|
||||
{:ok, object} = NsfwApiPolicy.filter(object)
|
||||
assert object["to"] == [user.follower_address]
|
||||
end
|
||||
|
||||
test "passes NSFW through when :unlist is disabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :unlist], false)
|
||||
{:ok, object} = NsfwApiPolicy.filter(object)
|
||||
assert object["to"] == [Constants.as_public()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -235,6 +235,16 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
assert Activity.get_in_reply_to_activity(activity).id == replied_to.id
|
||||
end
|
||||
|
||||
test "replying to a deleted status", %{user: user, conn: conn} do
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "cofe"})
|
||||
{:ok, _deleted_status} = CommonAPI.delete(status.id, user)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => status.id})
|
||||
|> json_response_and_validate_schema(422)
|
||||
end
|
||||
|
||||
test "replying to a direct message with visibility other than direct", %{
|
||||
user: user,
|
||||
conn: conn
|
||||
|
|
|
|||
|
|
@ -331,4 +331,31 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
test_notifications_rendering([notification], user, [expected])
|
||||
end
|
||||
|
||||
test "Subscribed status notification" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hi"})
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "status",
|
||||
account:
|
||||
AccountView.render("show.json", %{
|
||||
user: user,
|
||||
for: subscriber
|
||||
}),
|
||||
status: StatusView.render("show.json", %{activity: activity, for: subscriber}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], subscriber, [expected])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrlTest do
|
|||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Web.RichMedia.Card
|
||||
alias Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl
|
||||
|
||||
setup do
|
||||
ConfigMock
|
||||
|
|
@ -82,6 +83,12 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrlTest do
|
|||
assert DateTime.diff(scheduled_at, timestamp_dt) == valid_till
|
||||
end
|
||||
|
||||
test "AWS URL for an image without expiration works" do
|
||||
og_data = %{"image" => "https://amazonaws.com/image.png"}
|
||||
|
||||
assert is_nil(AwsSignedUrl.ttl(og_data, ""))
|
||||
end
|
||||
|
||||
defp construct_s3_url(timestamp, valid_till) do
|
||||
"https://pleroma.s3.ap-southeast-1.amazonaws.com/sachin%20%281%29%20_a%20-%25%2Aasdasd%20BNN%20bnnn%20.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIBLWWK6RGDQXDLJQ%2F20190716%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=#{timestamp}&X-Amz-Expires=#{valid_till}&X-Amz-Signature=04ffd6b98634f4b1bbabc62e0fac4879093cd54a6eed24fe8eb38e8369526bbf&X-Amz-SignedHeaders=host"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -76,15 +76,6 @@ defmodule Pleroma.Web.WebFingerTest do
|
|||
{:ok, _data} = WebFinger.finger(user)
|
||||
end
|
||||
|
||||
test "returns the ActivityPub actor URI and subscribe address for an ActivityPub user with the ld+json mimetype" do
|
||||
user = "kaniini@gerzilla.de"
|
||||
|
||||
{:ok, data} = WebFinger.finger(user)
|
||||
|
||||
assert data["ap_id"] == "https://gerzilla.de/channel/kaniini"
|
||||
assert data["subscribe_address"] == "https://gerzilla.de/follow?f=&url={uri}"
|
||||
end
|
||||
|
||||
test "it work for AP-only user" do
|
||||
user = "kpherox@mstdn.jp"
|
||||
|
||||
|
|
@ -99,12 +90,6 @@ defmodule Pleroma.Web.WebFingerTest do
|
|||
assert data["subscribe_address"] == "https://mstdn.jp/authorize_interaction?acct={uri}"
|
||||
end
|
||||
|
||||
test "it works for friendica" do
|
||||
user = "lain@squeet.me"
|
||||
|
||||
{:ok, _data} = WebFinger.finger(user)
|
||||
end
|
||||
|
||||
test "it gets the xrd endpoint" do
|
||||
{:ok, template} = WebFinger.find_lrdd_template("social.heldscal.la")
|
||||
|
||||
|
|
@ -203,5 +188,44 @@ defmodule Pleroma.Web.WebFingerTest do
|
|||
|
||||
assert :error = WebFinger.finger("pekorino@pawoo.net")
|
||||
end
|
||||
|
||||
test "prevents spoofing" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
url: "https://gleasonator.com/.well-known/webfinger?resource=acct:alex@gleasonator.com"
|
||||
} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/webfinger_spoof.json"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}}
|
||||
|
||||
%{url: "https://gleasonator.com/.well-known/host-meta"} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/gleasonator.com_host_meta")
|
||||
}}
|
||||
end)
|
||||
|
||||
{:error, _data} = WebFinger.finger("alex@gleasonator.com")
|
||||
end
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "prevents forgeries" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://fba.ryona.agency/.well-known/webfinger?resource=acct:graf@fba.ryona.agency"} ->
|
||||
fake_webfinger =
|
||||
File.read!("test/fixtures/webfinger/graf-imposter-webfinger.json") |> Jason.decode!()
|
||||
|
||||
Tesla.Mock.json(fake_webfinger)
|
||||
|
||||
%{url: "https://fba.ryona.agency/.well-known/host-meta"} ->
|
||||
{:ok, %Tesla.Env{status: 404}}
|
||||
end)
|
||||
|
||||
assert {:error, _} = WebFinger.finger("graf@fba.ryona.agency")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1521,6 +1521,120 @@ defmodule HttpRequestMock do
|
|||
}}
|
||||
end
|
||||
|
||||
def get("https://mastodon.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.mastodon.example/.well-known/host-meta"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.mastodon.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.mastodon.example")
|
||||
}}
|
||||
end
|
||||
|
||||
def get(
|
||||
"https://sub.mastodon.example/.well-known/webfinger?resource=acct:a@mastodon.example",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "mastodon.example")
|
||||
|> String.replace("{{subdomain}}", "sub.mastodon.example"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.mastodon.example/users/a", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.mastodon.example"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.mastodon.example/users/a/collections/featured", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "sub.mastodon.example")
|
||||
|> String.replace("{{nickname}}", "a"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://pleroma.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.pleroma.example/.well-known/host-meta"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.pleroma.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.pleroma.example")
|
||||
}}
|
||||
end
|
||||
|
||||
def get(
|
||||
"https://sub.pleroma.example/.well-known/webfinger?resource=acct:a@pleroma.example",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "pleroma.example")
|
||||
|> String.replace("{{subdomain}}", "sub.pleroma.example"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.pleroma.example/users/a", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.pleroma.example"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get(url, query, body, headers) do
|
||||
{:error,
|
||||
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue