Merge remote-tracking branch 'origin/develop' into translate-posts
This commit is contained in:
commit
d818a3d762
166 changed files with 3161 additions and 1181 deletions
117
test/fixtures/bastianallgeier.json
vendored
117
test/fixtures/bastianallgeier.json
vendored
|
|
@ -1,117 +0,0 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"Curve25519Key": "toot:Curve25519Key",
|
||||
"Device": "toot:Device",
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"cipherText": "toot:cipherText",
|
||||
"claim": {
|
||||
"@id": "toot:claim",
|
||||
"@type": "@id"
|
||||
},
|
||||
"deviceId": "toot:deviceId",
|
||||
"devices": {
|
||||
"@id": "toot:devices",
|
||||
"@type": "@id"
|
||||
},
|
||||
"discoverable": "toot:discoverable",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"featuredTags": {
|
||||
"@id": "toot:featuredTags",
|
||||
"@type": "@id"
|
||||
},
|
||||
"fingerprintKey": {
|
||||
"@id": "toot:fingerprintKey",
|
||||
"@type": "@id"
|
||||
},
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
},
|
||||
"identityKey": {
|
||||
"@id": "toot:identityKey",
|
||||
"@type": "@id"
|
||||
},
|
||||
"indexable": "toot:indexable",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"memorial": "toot:memorial",
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"messageType": "toot:messageType",
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"schema": "http://schema.org#",
|
||||
"suspended": "toot:suspended",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"value": "schema:value"
|
||||
}
|
||||
],
|
||||
"attachment": [
|
||||
{
|
||||
"name": "Website",
|
||||
"type": "PropertyValue",
|
||||
"value": "<a href=\"https://bastianallgeier.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">bastianallgeier.com</span><span class=\"invisible\"></span></a>"
|
||||
},
|
||||
{
|
||||
"name": "Project",
|
||||
"type": "PropertyValue",
|
||||
"value": "<a href=\"https://getkirby.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">getkirby.com</span><span class=\"invisible\"></span></a>"
|
||||
},
|
||||
{
|
||||
"name": "Github",
|
||||
"type": "PropertyValue",
|
||||
"value": "<a href=\"https://github.com/bastianallgeier\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">github.com/bastianallgeier</span><span class=\"invisible\"></span></a>"
|
||||
}
|
||||
],
|
||||
"devices": "https://mastodon.social/users/bastianallgeier/collections/devices",
|
||||
"discoverable": true,
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://mastodon.social/inbox"
|
||||
},
|
||||
"featured": "https://mastodon.social/users/bastianallgeier/collections/featured",
|
||||
"featuredTags": "https://mastodon.social/users/bastianallgeier/collections/tags",
|
||||
"followers": "https://mastodon.social/users/bastianallgeier/followers",
|
||||
"following": "https://mastodon.social/users/bastianallgeier/following",
|
||||
"icon": {
|
||||
"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "https://files.mastodon.social/accounts/avatars/000/007/393/original/0180a20079617c71.jpg"
|
||||
},
|
||||
"id": "https://mastodon.social/users/bastianallgeier",
|
||||
"image": {
|
||||
"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "https://files.mastodon.social/accounts/headers/000/007/393/original/13d644ab46d50478.jpeg"
|
||||
},
|
||||
"inbox": "https://mastodon.social/users/bastianallgeier/inbox",
|
||||
"indexable": false,
|
||||
"manuallyApprovesFollowers": false,
|
||||
"memorial": false,
|
||||
"name": "Bastian Allgeier",
|
||||
"outbox": "https://mastodon.social/users/bastianallgeier/outbox",
|
||||
"preferredUsername": "bastianallgeier",
|
||||
"publicKey": {
|
||||
"id": "https://mastodon.social/users/bastianallgeier#main-key",
|
||||
"owner": "https://mastodon.social/users/bastianallgeier",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3fz+hpgVztO9z6HUhyzv\nwP++ERBBoIwSLKf1TyIM8bvzGFm2YXaO5uxu1HvumYFTYc3ACr3q4j8VUb7NMxkQ\nlzu4QwPjOFJ43O+fY+HSPORXEDW5fXDGC5DGpox4+i08LxRmx7L6YPRUSUuPN8nI\nWyq1Qsq1zOQrNY/rohMXkBdSXxqC3yIRqvtLt4otCgay/5tMogJWkkS6ZKyFhb9z\nwVVy1fsbV10c9C+SHy4NH26CKaTtpTYLRBMjhTCS8bX8iDSjGIf2aZgYs1ir7gEz\n9wf5CvLiENmVWGwm64t6KSEAkA4NJ1hzgHUZPCjPHZE2SmhO/oHaxokTzqtbbENJ\n1QIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"published": "2016-11-01T00:00:00Z",
|
||||
"summary": "<p>Designer & developer. Creator of Kirby CMS</p>",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
"url": "https://mastodon.social/@bastianallgeier"
|
||||
}
|
||||
|
|
@ -1,62 +1,109 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"claim": {
|
||||
"@id": "toot:claim",
|
||||
"@type": "@id"
|
||||
},
|
||||
"memorial": "toot:memorial",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"blurhash": "toot:blurhash",
|
||||
"conversation": "ostatus:conversation",
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"discoverable": "toot:discoverable",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
},
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"votersCount": "toot:votersCount",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"Emoji": "toot:Emoji",
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"sensitive": "as:sensitive",
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"Device": "toot:Device",
|
||||
"schema": "http://schema.org#",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"votersCount": "toot:votersCount"
|
||||
"cipherText": "toot:cipherText",
|
||||
"suspended": "toot:suspended",
|
||||
"messageType": "toot:messageType",
|
||||
"featuredTags": {
|
||||
"@id": "toot:featuredTags",
|
||||
"@type": "@id"
|
||||
},
|
||||
"Curve25519Key": "toot:Curve25519Key",
|
||||
"deviceId": "toot:deviceId",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"devices": {
|
||||
"@id": "toot:devices",
|
||||
"@type": "@id"
|
||||
},
|
||||
"value": "schema:value",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"identityKey": {
|
||||
"@id": "toot:identityKey",
|
||||
"@type": "@id"
|
||||
},
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"indexable": "toot:indexable",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"fingerprintKey": {
|
||||
"@id": "toot:fingerprintKey",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"atomUri": "https://chaos.social/users/distantnative/statuses/109336635639931467",
|
||||
"attachment": [
|
||||
{
|
||||
"blurhash": "UAK1zS00OXIUxuMxIUM{?b-:-;W:Di?b%2M{",
|
||||
"height": 960,
|
||||
"mediaType": "image/jpeg",
|
||||
"name": null,
|
||||
"type": "Document",
|
||||
"url": "https://assets.chaos.social/media_attachments/files/109/336/634/286/114/657/original/2e6122063d8bfb26.jpeg",
|
||||
"width": 346
|
||||
}
|
||||
],
|
||||
"attributedTo": "https://chaos.social/users/distantnative",
|
||||
"cc": [
|
||||
"https://chaos.social/users/distantnative/followers"
|
||||
],
|
||||
"content": "<p>Favorite piece of anthropology meta discourse.</p>",
|
||||
"contentMap": {
|
||||
"en": "<p>Favorite piece of anthropology meta discourse.</p>"
|
||||
},
|
||||
"conversation": "tag:chaos.social,2022-11-13:objectId=71843781:objectType=Conversation",
|
||||
"id": "https://chaos.social/users/distantnative/statuses/109336635639931467",
|
||||
"actor": "https://phpc.social/users/denniskoch",
|
||||
"cc": [],
|
||||
"id": "https://phpc.social/users/denniskoch/statuses/112847382711461301/activity",
|
||||
"inReplyTo": null,
|
||||
"inReplyToAtomUri": null,
|
||||
"published": "2022-11-13T13:04:20Z",
|
||||
"replies": {
|
||||
"first": {
|
||||
"items": [],
|
||||
"next": "https://chaos.social/users/distantnative/statuses/109336635639931467/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://chaos.social/users/distantnative/statuses/109336635639931467/replies",
|
||||
"type": "CollectionPage"
|
||||
"object": {
|
||||
"atomUri": "https://phpc.social/users/denniskoch/statuses/112847382711461301",
|
||||
"attachment": [],
|
||||
"attributedTo": "https://phpc.social/users/denniskoch",
|
||||
"cc": [],
|
||||
"content": "<p><span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@bastianallgeier\" class=\"u-url mention\">@<span>bastianallgeier</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://chaos.social/@distantnative\" class=\"u-url mention\">@<span>distantnative</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://fosstodon.org/@kev\" class=\"u-url mention\">@<span>kev</span></a></span> Another main argument: Discord is popular. Many people have an account, so you can just join an server quickly. Also you know the app and how to get around.</p>",
|
||||
"contentMap": {
|
||||
"en": "<p><span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@bastianallgeier\" class=\"u-url mention\">@<span>bastianallgeier</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://chaos.social/@distantnative\" class=\"u-url mention\">@<span>distantnative</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://fosstodon.org/@kev\" class=\"u-url mention\">@<span>kev</span></a></span> Another main argument: Discord is popular. Many people have an account, so you can just join an server quickly. Also you know the app and how to get around.</p>"
|
||||
},
|
||||
"id": "https://chaos.social/users/distantnative/statuses/109336635639931467/replies",
|
||||
"type": "Collection"
|
||||
"conversation": "tag:mastodon.social,2024-07-25:objectId=760068442:objectType=Conversation",
|
||||
"id": "https://phpc.social/users/denniskoch/statuses/112847382711461301",
|
||||
"published": "2024-07-25T13:33:29Z",
|
||||
"replies": null,
|
||||
"sensitive": false,
|
||||
"tag": [],
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type": "Note",
|
||||
"url": "https://phpc.social/@denniskoch/112847382711461301"
|
||||
},
|
||||
"published": "2024-07-25T13:33:29Z",
|
||||
"signature": {
|
||||
"created": "2024-07-25T13:33:29Z",
|
||||
"creator": "https://phpc.social/users/denniskoch#main-key",
|
||||
"signatureValue": "slz9BKJzd2n1S44wdXGOU+bV/wsskdgAaUpwxj8R16mYOL8+DTpE6VnfSKoZGsBBJT8uG5gnVfVEz1YsTUYtymeUgLMh7cvd8VnJnZPS+oixbmBRVky/Myf91TEgQQE7G4vDmTdB4ii54hZrHcOOYYf5FKPNRSkMXboKA6LMqNtekhbI+JTUJYIB02WBBK6PUyo15f6B1RJ6HGWVgud9NE0y1EZXfrkqUt682p8/9D49ORf7AwjXUJibKic2RbPvhEBj70qUGfBm4vvgdWhSUn1IG46xh+U0+NrTSUED82j1ZVOeua/2k/igkGs8cSBkY35quXTkPz6gbqCCH66CuA==",
|
||||
"type": "RsaSignature2017"
|
||||
},
|
||||
"sensitive": false,
|
||||
"summary": null,
|
||||
"tag": [],
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type": "Note",
|
||||
"url": "https://chaos.social/@distantnative/109336635639931467"
|
||||
"type": "Create"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ defmodule Pleroma.HTMLTest do
|
|||
<span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
@mention_hashtags_sample """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
describe "StripTags scrubber" do
|
||||
test "works as expected" do
|
||||
expected = """
|
||||
|
|
@ -126,6 +130,15 @@ defmodule Pleroma.HTMLTest do
|
|||
Pleroma.HTML.Scrubber.TwitterText
|
||||
)
|
||||
end
|
||||
|
||||
test "does allow mention hashtags" do
|
||||
expected = """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@mention_hashtags_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
end
|
||||
|
||||
describe "default scrubber" do
|
||||
|
|
@ -189,6 +202,15 @@ defmodule Pleroma.HTMLTest do
|
|||
Pleroma.HTML.Scrubber.Default
|
||||
)
|
||||
end
|
||||
|
||||
test "does allow mention hashtags" do
|
||||
expected = """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@mention_hashtags_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_first_external_url_from_object" do
|
||||
|
|
|
|||
|
|
@ -268,6 +268,17 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
end)
|
||||
end
|
||||
|
||||
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
||||
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||
|
||||
capture_log(fn ->
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} =
|
||||
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
||||
test "accepts valid token on client-sent event", %{token: token} do
|
||||
assert {:ok, pid} = start_socket()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@ defmodule Pleroma.ObjectTest do
|
|||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Hashtag
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
|
@ -176,8 +174,9 @@ defmodule Pleroma.ObjectTest do
|
|||
|
||||
filename = Path.basename(href)
|
||||
|
||||
assert {:ok, files} = File.ls(uploads_dir)
|
||||
assert filename in files
|
||||
expected_path = Path.join([uploads_dir, Pleroma.Upload.Filter.Dedupe.shard_path(filename)])
|
||||
|
||||
assert File.exists?(expected_path)
|
||||
|
||||
Object.delete(note)
|
||||
|
||||
|
|
@ -185,8 +184,7 @@ defmodule Pleroma.ObjectTest do
|
|||
|
||||
assert Object.get_by_id(note.id).data["deleted"]
|
||||
assert Object.get_by_id(attachment.id) == nil
|
||||
assert {:ok, files} = File.ls(uploads_dir)
|
||||
refute filename in files
|
||||
refute File.exists?(expected_path)
|
||||
end
|
||||
|
||||
test "with objects that have legacy data.url attribute" do
|
||||
|
|
@ -282,148 +280,6 @@ defmodule Pleroma.ObjectTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "get_by_id_and_maybe_refetch" do
|
||||
setup do
|
||||
mock(fn
|
||||
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_original.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
}
|
||||
|
||||
env ->
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
|
||||
mock_modified = fn resp ->
|
||||
mock(fn
|
||||
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
|
||||
resp
|
||||
|
||||
env ->
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
end
|
||||
|
||||
on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
|
||||
|
||||
[mock_modified: mock_modified]
|
||||
end
|
||||
|
||||
test "refetches if the time since the last refetch is greater than the interval", %{
|
||||
mock_modified: mock_modified
|
||||
} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
mock_modified.(%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
||||
end
|
||||
|
||||
test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
assert capture_log(fn ->
|
||||
mock_modified.(%Tesla.Env{status: 404, body: ""})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
end) =~
|
||||
"[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
|
||||
end
|
||||
|
||||
test "does not refetch if the time since the last refetch is greater than the interval", %{
|
||||
mock_modified: mock_modified
|
||||
} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
mock_modified.(%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
end
|
||||
|
||||
test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
user = insert(:user)
|
||||
activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
{:ok, activity} = CommonAPI.favorite(activity.id, user)
|
||||
object = Object.get_by_ap_id(activity.data["object"])
|
||||
|
||||
assert object.data["like_count"] == 1
|
||||
|
||||
mock_modified.(%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
||||
|
||||
assert updated_object.data["like_count"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe ":hashtags association" do
|
||||
test "Hashtag records are created with Object record and updated on its change" do
|
||||
user = insert(:user)
|
||||
|
|
|
|||
19
test/pleroma/release_task_test.exs
Normal file
19
test/pleroma/release_task_test.exs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ReleaseTaskTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.ReleaseTasks
|
||||
|
||||
test "finding the module" do
|
||||
task = "search.meilisearch"
|
||||
assert Mix.Tasks.Pleroma.Search.Meilisearch == ReleaseTasks.find_module(task)
|
||||
|
||||
task = "user"
|
||||
assert Mix.Tasks.Pleroma.User == ReleaseTasks.find_module(task)
|
||||
|
||||
refute ReleaseTasks.find_module("doesnt.exist")
|
||||
end
|
||||
end
|
||||
|
|
@ -10,6 +10,10 @@ defmodule Pleroma.Upload.Filter.DedupeTest do
|
|||
|
||||
@shasum "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781"
|
||||
|
||||
test "generates a shard path for a shasum" do
|
||||
assert "e3/03/97/" <> _path = Dedupe.shard_path(@shasum)
|
||||
end
|
||||
|
||||
test "adds shasum" do
|
||||
File.cp!(
|
||||
"test/fixtures/image.jpg",
|
||||
|
|
@ -23,10 +27,12 @@ defmodule Pleroma.Upload.Filter.DedupeTest do
|
|||
tempfile: Path.absname("test/fixtures/image_tmp.jpg")
|
||||
}
|
||||
|
||||
expected_path = Dedupe.shard_path(@shasum <> ".jpg")
|
||||
|
||||
assert {
|
||||
:ok,
|
||||
:filtered,
|
||||
%Pleroma.Upload{id: @shasum, path: @shasum <> ".jpg"}
|
||||
%Pleroma.Upload{id: @shasum, path: ^expected_path}
|
||||
} = Dedupe.filter(upload)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@ defmodule Pleroma.UploadTest do
|
|||
|
||||
test "copies the file to the configured folder with deduping" do
|
||||
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||
expected_filename = "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
|
||||
|
||||
expected_path = Pleroma.Upload.Filter.Dedupe.shard_path(expected_filename)
|
||||
|
||||
file = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
|
|
@ -159,8 +162,7 @@ defmodule Pleroma.UploadTest do
|
|||
{:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.Dedupe])
|
||||
|
||||
assert List.first(data["url"])["href"] ==
|
||||
Pleroma.Upload.base_url() <>
|
||||
"e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
|
||||
Path.join([Pleroma.Upload.base_url(), expected_path])
|
||||
end
|
||||
|
||||
test "copies the file to the configured folder without deduping" do
|
||||
|
|
|
|||
|
|
@ -25,11 +25,12 @@ defmodule Pleroma.User.ImportTest do
|
|||
user3.nickname
|
||||
]
|
||||
|
||||
{:ok, job} = User.Import.follow_import(user1, identifiers)
|
||||
{:ok, jobs} = User.Import.follows_import(user1, identifiers)
|
||||
|
||||
for job <- jobs do
|
||||
assert {:ok, %User{}} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
assert {:ok, result} = ObanHelpers.perform(job)
|
||||
assert is_list(result)
|
||||
assert result == [refresh_record(user2), refresh_record(user3)]
|
||||
assert User.following?(user1, user2)
|
||||
assert User.following?(user1, user3)
|
||||
end
|
||||
|
|
@ -44,11 +45,12 @@ defmodule Pleroma.User.ImportTest do
|
|||
user3.nickname
|
||||
]
|
||||
|
||||
{:ok, job} = User.Import.blocks_import(user1, identifiers)
|
||||
{:ok, jobs} = User.Import.blocks_import(user1, identifiers)
|
||||
|
||||
for job <- jobs do
|
||||
assert {:ok, %User{}} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
assert {:ok, result} = ObanHelpers.perform(job)
|
||||
assert is_list(result)
|
||||
assert result == [user2, user3]
|
||||
assert User.blocks?(user1, user2)
|
||||
assert User.blocks?(user1, user3)
|
||||
end
|
||||
|
|
@ -63,11 +65,12 @@ defmodule Pleroma.User.ImportTest do
|
|||
user3.nickname
|
||||
]
|
||||
|
||||
{:ok, job} = User.Import.mutes_import(user1, identifiers)
|
||||
{:ok, jobs} = User.Import.mutes_import(user1, identifiers)
|
||||
|
||||
for job <- jobs do
|
||||
assert {:ok, %User{}} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
assert {:ok, result} = ObanHelpers.perform(job)
|
||||
assert is_list(result)
|
||||
assert result == [user2, user3]
|
||||
assert User.mutes?(user1, user2)
|
||||
assert User.mutes?(user1, user3)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -657,7 +657,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
end
|
||||
|
||||
test "without valid signature, " <>
|
||||
"it only accepts Create activities and requires enabled federation",
|
||||
"it accepts Create activities and requires enabled federation",
|
||||
%{conn: conn} do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!()
|
||||
|
|
@ -684,6 +684,54 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|> json_response(400)
|
||||
end
|
||||
|
||||
# When activity is delivered to the inbox and we cannot immediately verify signature
|
||||
# we capture all the params and process it later in the Oban job.
|
||||
# Once we begin processing it through Oban we risk fetching the actor to validate the
|
||||
# activity which just leads to inserting a new user to process a Delete not relevant to us.
|
||||
test "Activities of certain types from an unknown actor are discarded", %{conn: conn} do
|
||||
example_bad_types =
|
||||
Pleroma.Constants.activity_types() --
|
||||
Pleroma.Constants.allowed_activity_types_from_strangers()
|
||||
|
||||
Enum.each(example_bad_types, fn bad_type ->
|
||||
params =
|
||||
%{
|
||||
"type" => bad_type,
|
||||
"actor" => "https://unknown.mastodon.instance/users/somebody"
|
||||
}
|
||||
|> Jason.encode!()
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, false)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", params)
|
||||
|> json_response(400)
|
||||
|
||||
assert all_enqueued() == []
|
||||
end)
|
||||
end
|
||||
|
||||
test "Unknown activity types are discarded", %{conn: conn} do
|
||||
unknown_types = ["Poke", "Read", "Dazzle"]
|
||||
|
||||
Enum.each(unknown_types, fn bad_type ->
|
||||
params =
|
||||
%{
|
||||
"type" => bad_type,
|
||||
"actor" => "https://unknown.mastodon.instance/users/somebody"
|
||||
}
|
||||
|> Jason.encode!()
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", params)
|
||||
|> json_response(400)
|
||||
|
||||
assert all_enqueued() == []
|
||||
end)
|
||||
end
|
||||
|
||||
test "accepts Add/Remove activities", %{conn: conn} do
|
||||
object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
|
||||
|
||||
|
|
@ -1272,6 +1320,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
html_body: ~r/#{note.data["object"]}/i
|
||||
)
|
||||
end
|
||||
|
||||
test "it accepts an incoming Block", %{conn: conn, data: data} do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("type", "Block")
|
||||
|> Map.put("to", [user.ap_id])
|
||||
|> Map.put("cc", [])
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{user.nickname}/inbox", data)
|
||||
|
||||
assert "ok" == json_response(conn, 200)
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /users/:nickname/outbox" do
|
||||
|
|
@ -1575,6 +1644,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert json_response(conn, 403)
|
||||
end
|
||||
|
||||
test "it rejects update activity of object from other actor", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
note_object = Object.normalize(note_activity, fetch: false)
|
||||
user = insert(:user)
|
||||
|
||||
data = %{
|
||||
type: "Update",
|
||||
object: %{
|
||||
id: note_object.data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{user.nickname}/outbox", data)
|
||||
|
||||
assert json_response(conn, 400)
|
||||
assert note_object == Object.normalize(note_activity, fetch: false)
|
||||
end
|
||||
|
||||
test "it increases like count when receiving a like action", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
note_object = Object.normalize(note_activity, fetch: false)
|
||||
|
|
|
|||
|
|
@ -232,12 +232,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest 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
|
||||
|
||||
|
|
@ -432,6 +434,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
assert user.birthday == ~D[2001-02-12]
|
||||
end
|
||||
|
||||
test "fetches avatar description" do
|
||||
user_id = "https://example.com/users/marcin"
|
||||
|
||||
user_data =
|
||||
"test/fixtures/users_mock/user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "marcin")
|
||||
|> 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} = ActivityPub.make_user_from_ap_id(user_id)
|
||||
|
||||
assert user.avatar["name"] == "image description"
|
||||
end
|
||||
end
|
||||
|
||||
test "it fetches the appropriate tag-restricted posts" do
|
||||
|
|
|
|||
155
test/pleroma/web/activity_pub/mrf/remote_report_policy_test.exs
Normal file
155
test/pleroma/web/activity_pub/mrf/remote_report_policy_test.exs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
defmodule Pleroma.Web.ActivityPub.MRF.RemoteReportPolicyTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy
|
||||
|
||||
setup do
|
||||
clear_config([:mrf_remote_report, :reject_all], false)
|
||||
end
|
||||
|
||||
test "doesn't impact local report" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "http://localhost:4001/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects anonymous report if `reject_anonymous: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves anonymous report if `reject_anonymous: false`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects report on third party if `reject_third_party: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_third_party], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves report on first party if `reject_third_party: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_third_party], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["http://localhost:4001/actor"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves report on third party if `reject_third_party: false`" do
|
||||
clear_config([:mrf_remote_report, :reject_third_party], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects empty message report if `reject_empty_message: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects empty message report (\"\") if `reject_empty_message: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"],
|
||||
"content" => ""
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves empty message report if `reject_empty_message: false`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves anonymous, empty message report with all settings disabled" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "reject remote report if `reject_all: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_all], true)
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"content" => "Transphobia",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
end
|
||||
|
|
@ -252,6 +252,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity has a matching host" do
|
||||
|
|
@ -260,6 +261,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_message = build_remote_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
refute SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity matches with wildcard domain" do
|
||||
|
|
@ -268,6 +270,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_message = build_remote_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
refute SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "actor has a matching host" do
|
||||
|
|
@ -276,6 +279,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_user = build_remote_user()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_user)
|
||||
refute SimplePolicy.id_filter(remote_user["id"])
|
||||
end
|
||||
|
||||
test "reject Announce when object would be rejected" do
|
||||
|
|
@ -288,6 +292,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
}
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(announce)
|
||||
# Note: Non-Applicable for id_filter/1
|
||||
end
|
||||
|
||||
test "reject by URI object" do
|
||||
|
|
@ -300,6 +305,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
}
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(announce)
|
||||
# Note: Non-Applicable for id_filter/1
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -370,6 +376,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "is not empty but activity doesn't have a matching host" do
|
||||
|
|
@ -380,6 +388,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
refute SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity has a matching host" do
|
||||
|
|
@ -390,6 +400,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity matches with wildcard domain" do
|
||||
|
|
@ -400,6 +412,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "actor has a matching host" do
|
||||
|
|
@ -408,6 +422,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
assert SimplePolicy.id_filter(remote_user["id"])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,23 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
result = UserView.render("user.json", %{user: user})
|
||||
assert result["icon"]["url"] == "https://someurl"
|
||||
assert result["image"]["url"] == "https://somebanner"
|
||||
|
||||
refute result["icon"]["name"]
|
||||
refute 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
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.FallbackTest do
|
|||
resp = get(conn, "/foo")
|
||||
|
||||
assert html_response(resp, 200) =~ "<title>a cool title</title>"
|
||||
refute html_response(resp, 200) =~ "initial-results"
|
||||
assert html_response(resp, 200) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||
end
|
||||
|
||||
test "GET /*path", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -191,4 +191,60 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
|> 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
|
||||
|
|
|
|||
|
|
@ -147,6 +147,15 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
|||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|
||||
|> json_response_and_validate_schema(202)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert media_id = response["id"]
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
|||
"file" => large_binary,
|
||||
"description" => desc
|
||||
})
|
||||
|> json_response_and_validate_schema(202)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert media_id = response["id"]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Object
|
||||
|
|
@ -27,6 +28,33 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
|||
response = json_response_and_validate_schema(conn, 200)
|
||||
id = to_string(object.id)
|
||||
assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
|
||||
|
||||
# Local activities should not generate an Oban job to refresh
|
||||
assert activity.local
|
||||
|
||||
refute_enqueued(
|
||||
worker: Pleroma.Workers.PollWorker,
|
||||
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||
)
|
||||
end
|
||||
|
||||
test "creates an oban job to refresh poll if activity is remote", %{conn: conn} do
|
||||
user = insert(:user, local: false)
|
||||
question = insert(:question, user: user)
|
||||
activity = insert(:question_activity, question: question, local: false)
|
||||
|
||||
# Ensure this is not represented as a local activity
|
||||
refute activity.local
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
get(conn, "/api/v1/polls/#{object.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PollWorker,
|
||||
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||
)
|
||||
end
|
||||
|
||||
test "does not expose polls for private statuses", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -430,6 +430,75 @@ 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 "limit", %{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 = Config.get([:instance, :description_limit], 100)
|
||||
|
||||
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 "Strip / from upload files", %{user: user, conn: conn} do
|
||||
new_image = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
hide_follows_count: false,
|
||||
relationship: %{},
|
||||
skip_thread_containment: false,
|
||||
accepts_chat_messages: nil
|
||||
accepts_chat_messages: nil,
|
||||
avatar_description: "",
|
||||
header_description: ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +342,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
hide_follows_count: false,
|
||||
relationship: %{},
|
||||
skip_thread_containment: false,
|
||||
accepts_chat_messages: nil
|
||||
accepts_chat_messages: nil,
|
||||
avatar_description: "",
|
||||
header_description: ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -456,6 +460,45 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "relationship does not indicate following if a FollowingRelationship is missing" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
|
||||
# Create a follow relationship with the real Follow Activity and Accept it
|
||||
assert {:ok, _, _, _} = CommonAPI.follow(other_user, user)
|
||||
assert {:ok, _} = CommonAPI.accept_follow_request(user, other_user)
|
||||
|
||||
assert %{data: %{"state" => "accept"}} =
|
||||
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, other_user)
|
||||
|
||||
# Fetch the relationship and forcibly delete it to simulate
|
||||
# a Follow Accept that did not complete processing
|
||||
%{following_relationships: [relationship]} =
|
||||
Pleroma.UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
assert {:ok, _} = Pleroma.Repo.delete(relationship)
|
||||
|
||||
assert %{following_relationships: [], user_relationships: []} ==
|
||||
Pleroma.UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{
|
||||
following: false,
|
||||
followed_by: false,
|
||||
muting: false,
|
||||
muting_notifications: false,
|
||||
subscribing: false,
|
||||
notifying: false,
|
||||
showing_reblogs: true,
|
||||
id: to_string(other_user.id)
|
||||
}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "represent a relationship for the blocking and blocked user" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:chat_mention",
|
||||
account: AccountView.render("show.json", %{user: user, for: recipient}),
|
||||
|
|
@ -75,6 +76,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "mention",
|
||||
account:
|
||||
|
|
@ -99,6 +101,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "favourite",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
|
|
@ -119,6 +122,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "reblog",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
|
|
@ -137,6 +141,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "follow",
|
||||
account: AccountView.render("show.json", %{user: follower, for: followed}),
|
||||
|
|
@ -165,6 +170,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "move",
|
||||
account: AccountView.render("show.json", %{user: old_user, for: follower}),
|
||||
|
|
@ -190,6 +196,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:emoji_reaction",
|
||||
emoji: "☕",
|
||||
|
|
@ -229,6 +236,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:emoji_reaction",
|
||||
emoji: ":dinosaur:",
|
||||
|
|
@ -248,6 +256,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "poll",
|
||||
account:
|
||||
|
|
@ -274,6 +283,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:report",
|
||||
account: AccountView.render("show.json", %{user: reporting_user, for: moderator_user}),
|
||||
|
|
@ -300,6 +310,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "update",
|
||||
account: AccountView.render("show.json", %{user: user, for: repeat_user}),
|
||||
|
|
@ -322,6 +333,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: true, is_muted: true},
|
||||
type: "favourite",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
|
|
@ -345,6 +357,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "status",
|
||||
account:
|
||||
|
|
|
|||
|
|
@ -342,7 +342,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
parent_visible: false,
|
||||
pinned_at: nil,
|
||||
quotes_count: 0,
|
||||
bookmark_folder: nil
|
||||
bookmark_folder: nil,
|
||||
list_id: nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -912,6 +913,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status.visibility == "list"
|
||||
assert status.pleroma.list_id == nil
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert status.pleroma.list_id == list.id
|
||||
end
|
||||
|
||||
test "has a field for parent visibility" do
|
||||
|
|
|
|||
40
test/pleroma/web/metadata/providers/activity_pub_test.exs
Normal file
40
test/pleroma/web/metadata/providers/activity_pub_test.exs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Metadata.Providers.ActivityPubTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.Metadata.Providers.ActivityPub
|
||||
|
||||
setup do: clear_config([Pleroma.Web.Metadata, :unfurl_nsfw])
|
||||
|
||||
test "it renders a link for user info" do
|
||||
user = insert(:user)
|
||||
res = ActivityPub.build_tags(%{user: user})
|
||||
|
||||
assert res == [
|
||||
{:link, [rel: "alternate", type: "application/activity+json", href: user.ap_id], []}
|
||||
]
|
||||
end
|
||||
|
||||
test "it renders a link for a post" do
|
||||
user = insert(:user)
|
||||
{:ok, %{id: activity_id, object: object}} = CommonAPI.post(user, %{status: "hi"})
|
||||
|
||||
result = ActivityPub.build_tags(%{object: object, user: user, activity_id: activity_id})
|
||||
|
||||
assert [
|
||||
{:link,
|
||||
[rel: "alternate", type: "application/activity+json", href: object.data["id"]], []}
|
||||
] == result
|
||||
end
|
||||
|
||||
test "it returns an empty array for anything else" do
|
||||
result = ActivityPub.build_tags(%{})
|
||||
|
||||
assert result == []
|
||||
end
|
||||
end
|
||||
|
|
@ -15,4 +15,10 @@ defmodule Pleroma.Web.Metadata.Providers.FeedTest do
|
|||
[rel: "alternate", type: "application/atom+xml", href: "/users/lain/feed.atom"], []}
|
||||
]
|
||||
end
|
||||
|
||||
test "it doesn't render a link to remote user's feed" do
|
||||
user = insert(:user, nickname: "lain@lain.com", local: false)
|
||||
|
||||
assert Feed.build_tags(%{user: user}) == []
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,19 @@ defmodule Pleroma.Web.NodeInfoTest do
|
|||
|> get(href)
|
||||
|> json_response(200)
|
||||
end)
|
||||
|
||||
accept_types = [
|
||||
"application/activity+json",
|
||||
"application/json",
|
||||
"application/jrd+json"
|
||||
]
|
||||
|
||||
for type <- accept_types do
|
||||
conn
|
||||
|> put_req_header("accept", type)
|
||||
|> get("/.well-known/nodeinfo")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
|
||||
test "nodeinfo shows staff accounts", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -53,4 +53,21 @@ defmodule Pleroma.Web.OAuth.AppTest do
|
|||
|
||||
assert Enum.sort(App.get_user_apps(user)) == Enum.sort(apps)
|
||||
end
|
||||
|
||||
test "removes orphaned apps" do
|
||||
attrs = %{client_name: "Mastodon-Local", redirect_uris: "."}
|
||||
{:ok, %App{} = old_app} = App.get_or_make(attrs, ["write"])
|
||||
|
||||
attrs = %{client_name: "PleromaFE", redirect_uris: "."}
|
||||
{:ok, %App{} = app} = App.get_or_make(attrs, ["write"])
|
||||
|
||||
# backdate the old app so it's within the threshold for being cleaned up
|
||||
{:ok, _} =
|
||||
"UPDATE apps SET inserted_at = now() - interval '1 hour' WHERE id = #{old_app.id}"
|
||||
|> Pleroma.Repo.query()
|
||||
|
||||
App.remove_orphans()
|
||||
|
||||
assert [app] == Pleroma.Repo.all(App)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,11 +28,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, ^password -> :ok end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
simple_bind: fn _connection, _dn, ^password -> :ok end
|
||||
]}
|
||||
] do
|
||||
conn =
|
||||
|
|
@ -50,7 +46,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
token = Repo.get_by(Token, token: token)
|
||||
|
||||
assert token.user_id == user.id
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -72,10 +67,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
wholeSubtree: fn -> :ok end,
|
||||
search: fn _connection, _options ->
|
||||
{:ok, {:eldap_search_result, [{:eldap_entry, ~c"", []}], []}}
|
||||
end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
|
|
@ -94,7 +85,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
token = Repo.get_by(Token, token: token) |> Repo.preload(:user)
|
||||
|
||||
assert token.user.nickname == user.nickname
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -111,11 +101,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, ^password -> {:error, :invalidCredentials} end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
simple_bind: fn _connection, _dn, ^password -> {:error, :invalidCredentials} end
|
||||
]}
|
||||
] do
|
||||
conn =
|
||||
|
|
@ -129,7 +115,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
})
|
||||
|
||||
assert %{"error" => "Invalid credentials"} = json_response(conn, 400)
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
alias Pleroma.MFA.TOTP
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.OAuthController
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
|
@ -770,6 +771,9 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user, ["write"])
|
||||
|
||||
# Verify app has no associated user yet
|
||||
assert %Pleroma.Web.OAuth.App{user_id: nil} = Repo.get_by(App, %{id: app.id})
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
|
|
@ -786,6 +790,10 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
assert token
|
||||
assert token.scopes == auth.scopes
|
||||
assert user.ap_id == ap_id
|
||||
|
||||
# Verify app has an associated user now
|
||||
user_id = user.id
|
||||
assert %Pleroma.Web.OAuth.App{user_id: ^user_id} = Repo.get_by(App, %{id: app.id})
|
||||
end
|
||||
|
||||
test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
test "it returns HTTP 200", %{conn: conn} do
|
||||
user2 = insert(:user)
|
||||
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"})
|
||||
|
|
@ -38,7 +38,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
"Account address,Show boosts\n#{user2.ap_id},true"
|
||||
end}
|
||||
]) do
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/follow_import", %{
|
||||
|
|
@ -46,9 +46,9 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == [refresh_record(user2)]
|
||||
assert [%Pleroma.User{follower_count: 1}] = job_result
|
||||
assert [{:ok, updated_user}] = ObanHelpers.perform_all()
|
||||
assert updated_user.id == user2.id
|
||||
assert updated_user.follower_count == 1
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response == "job started"
|
||||
assert response == "jobs started"
|
||||
end
|
||||
|
||||
test "requires 'follow' or 'write:follows' permissions" do
|
||||
|
|
@ -102,14 +102,20 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
]
|
||||
|> Enum.join("\n")
|
||||
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/follow_import", %{"list" => identifiers})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == Enum.map(users, &refresh_record/1)
|
||||
results = ObanHelpers.perform_all()
|
||||
|
||||
returned_users =
|
||||
for {_, returned_user} <- results do
|
||||
returned_user
|
||||
end
|
||||
|
||||
assert returned_users == Enum.map(users, &refresh_record/1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -120,7 +126,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
test "it returns HTTP 200", %{conn: conn} do
|
||||
user2 = insert(:user)
|
||||
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"})
|
||||
|
|
@ -133,7 +139,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
with_mocks([
|
||||
{File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end}
|
||||
]) do
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/blocks_import", %{
|
||||
|
|
@ -141,8 +147,14 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == users
|
||||
results = ObanHelpers.perform_all()
|
||||
|
||||
returned_users =
|
||||
for {_, returned_user} <- results do
|
||||
returned_user
|
||||
end
|
||||
|
||||
assert returned_users == users
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -159,14 +171,25 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
]
|
||||
|> Enum.join(" ")
|
||||
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/blocks_import", %{"list" => identifiers})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == users
|
||||
results = ObanHelpers.perform_all()
|
||||
|
||||
returned_user_ids =
|
||||
for {_, user} <- results do
|
||||
user.id
|
||||
end
|
||||
|
||||
original_user_ids =
|
||||
for user <- users do
|
||||
user.id
|
||||
end
|
||||
|
||||
assert match?(^original_user_ids, returned_user_ids)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -177,24 +200,25 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
test "it returns HTTP 200", %{user: user, conn: conn} do
|
||||
user2 = insert(:user)
|
||||
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/mutes_import", %{"list" => "#{user2.ap_id}"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == [user2]
|
||||
[{:ok, result_user}] = ObanHelpers.perform_all()
|
||||
|
||||
assert result_user == refresh_record(user2)
|
||||
assert Pleroma.User.mutes?(user, user2)
|
||||
end
|
||||
|
||||
test "it imports mutes users from file", %{user: user, conn: conn} do
|
||||
users = [user2, user3] = insert_list(2, :user)
|
||||
[user2, user3] = insert_list(2, :user)
|
||||
|
||||
with_mocks([
|
||||
{File, [], read!: fn "mutes_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end}
|
||||
]) do
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/mutes_import", %{
|
||||
|
|
@ -202,14 +226,19 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == users
|
||||
assert Enum.all?(users, &Pleroma.User.mutes?(user, &1))
|
||||
results = ObanHelpers.perform_all()
|
||||
|
||||
returned_users =
|
||||
for {_, returned_user} <- results do
|
||||
returned_user
|
||||
end
|
||||
|
||||
assert Enum.all?(returned_users, &Pleroma.User.mutes?(user, &1))
|
||||
end
|
||||
end
|
||||
|
||||
test "it imports mutes with different nickname variations", %{user: user, conn: conn} do
|
||||
users = [user2, user3, user4, user5, user6] = insert_list(5, :user)
|
||||
[user2, user3, user4, user5, user6] = insert_list(5, :user)
|
||||
|
||||
identifiers =
|
||||
[
|
||||
|
|
@ -221,15 +250,20 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
|
|||
]
|
||||
|> Enum.join(" ")
|
||||
|
||||
assert "job started" ==
|
||||
assert "jobs started" ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/mutes_import", %{"list" => identifiers})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [{:ok, job_result}] = ObanHelpers.perform_all()
|
||||
assert job_result == users
|
||||
assert Enum.all?(users, &Pleroma.User.mutes?(user, &1))
|
||||
results = ObanHelpers.perform_all()
|
||||
|
||||
returned_users =
|
||||
for {_, returned_user} <- results do
|
||||
returned_user
|
||||
end
|
||||
|
||||
assert Enum.all?(returned_users, &Pleroma.User.mutes?(user, &1))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -70,6 +70,24 @@ defmodule Pleroma.Web.Plugs.AuthenticationPlugTest do
|
|||
assert "$pbkdf2" <> _ = user.password_hash
|
||||
end
|
||||
|
||||
test "with an argon2 hash, it updates to a pkbdf2 hash", %{conn: conn} do
|
||||
user = insert(:user, password_hash: Argon2.hash_pwd_salt("123"))
|
||||
assert "$argon2" <> _ = user.password_hash
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_user, user)
|
||||
|> assign(:auth_credentials, %{password: "123"})
|
||||
|> AuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user.id == conn.assigns.auth_user.id
|
||||
assert conn.assigns.token == nil
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert "$pbkdf2" <> _ = user.password_hash
|
||||
end
|
||||
|
||||
describe "checkpw/2" do
|
||||
test "check pbkdf2 hash" do
|
||||
hash =
|
||||
|
|
@ -86,6 +104,14 @@ defmodule Pleroma.Web.Plugs.AuthenticationPlugTest do
|
|||
refute AuthenticationPlug.checkpw("password1", hash)
|
||||
end
|
||||
|
||||
test "check argon2 hash" do
|
||||
hash =
|
||||
"$argon2id$v=19$m=65536,t=8,p=2$zEMMsTuK5KkL5AFWbX7jyQ$VyaQD7PF6e9btz0oH1YiAkWwIGZ7WNDZP8l+a/O171g"
|
||||
|
||||
assert AuthenticationPlug.checkpw("password", hash)
|
||||
refute AuthenticationPlug.checkpw("password1", hash)
|
||||
end
|
||||
|
||||
test "it returns false when hash invalid" do
|
||||
hash =
|
||||
"psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> hd()
|
||||
|> Map.keys()
|
||||
|
||||
assert keys -- ["id", "app_name", "valid_until"] == []
|
||||
assert Enum.sort(keys) == Enum.sort(["id", "app_name", "valid_until", "scopes"])
|
||||
end
|
||||
|
||||
test "revoke token", %{token: token} do
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ defmodule Pleroma.Workers.PollWorkerTest do
|
|||
|
||||
alias Pleroma.Workers.PollWorker
|
||||
|
||||
test "poll notification job" do
|
||||
test "local poll ending notification job" do
|
||||
user = insert(:user)
|
||||
question = insert(:question, user: user)
|
||||
activity = insert(:question_activity, question: question)
|
||||
activity = insert(:question_activity, question: question, user: user)
|
||||
|
||||
PollWorker.schedule_poll_end(activity)
|
||||
|
||||
|
|
@ -44,6 +44,65 @@ defmodule Pleroma.Workers.PollWorkerTest do
|
|||
# Ensure notifications were streamed out when job executes
|
||||
assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], :_))
|
||||
assert called(Pleroma.Web.Push.send(:_))
|
||||
|
||||
# Skip refreshing polls for local activities
|
||||
assert activity.local
|
||||
|
||||
refute_enqueued(
|
||||
worker: PollWorker,
|
||||
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "remote poll ending notification job schedules refresh" do
|
||||
user = insert(:user, local: false)
|
||||
question = insert(:question, user: user)
|
||||
activity = insert(:question_activity, question: question, user: user)
|
||||
|
||||
PollWorker.schedule_poll_end(activity)
|
||||
|
||||
expected_job_args = %{"activity_id" => activity.id, "op" => "poll_end"}
|
||||
|
||||
assert_enqueued(args: expected_job_args)
|
||||
|
||||
[job] = all_enqueued(worker: PollWorker)
|
||||
PollWorker.perform(job)
|
||||
|
||||
refute activity.local
|
||||
|
||||
assert_enqueued(
|
||||
worker: PollWorker,
|
||||
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||
)
|
||||
end
|
||||
|
||||
test "poll refresh" do
|
||||
user = insert(:user, local: false)
|
||||
question = insert(:question, user: user)
|
||||
activity = insert(:question_activity, question: question)
|
||||
|
||||
PollWorker.new(%{"op" => "refresh", "activity_id" => activity.id})
|
||||
|> Oban.insert()
|
||||
|
||||
expected_job_args = %{"activity_id" => activity.id, "op" => "refresh"}
|
||||
|
||||
assert_enqueued(args: expected_job_args)
|
||||
|
||||
with_mocks([
|
||||
{
|
||||
Pleroma.Web.Streamer,
|
||||
[],
|
||||
[
|
||||
stream: fn _, _ -> nil end
|
||||
]
|
||||
}
|
||||
]) do
|
||||
[job] = all_enqueued(worker: PollWorker)
|
||||
PollWorker.perform(job)
|
||||
|
||||
# Ensure updates are streamed out
|
||||
assert called(Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], :_))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
|||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Workers.ReceiverWorker
|
||||
|
||||
|
|
@ -51,25 +52,106 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
|||
})
|
||||
end
|
||||
|
||||
describe "cancels on a failed user fetch" do
|
||||
setup do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://springfield.social/users/bart"} ->
|
||||
%Tesla.Env{
|
||||
status: 403,
|
||||
body: ""
|
||||
}
|
||||
|
||||
%{url: "https://springfield.social/users/troymcclure"} ->
|
||||
%Tesla.Env{
|
||||
status: 404,
|
||||
body: ""
|
||||
}
|
||||
|
||||
%{url: "https://springfield.social/users/hankscorpio"} ->
|
||||
%Tesla.Env{
|
||||
status: 410,
|
||||
body: ""
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
test "when request returns a 403" do
|
||||
params =
|
||||
insert(:note_activity).data
|
||||
|> Map.put("actor", "https://springfield.social/users/bart")
|
||||
|
||||
{:ok, oban_job} =
|
||||
Federator.incoming_ap_doc(%{
|
||||
method: "POST",
|
||||
req_headers: [],
|
||||
request_path: "/inbox",
|
||||
params: params,
|
||||
query_string: ""
|
||||
})
|
||||
|
||||
assert {:cancel, {:error, :forbidden}} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
|
||||
test "when request returns a 404" do
|
||||
params =
|
||||
insert(:note_activity).data
|
||||
|> Map.put("actor", "https://springfield.social/users/troymcclure")
|
||||
|
||||
{:ok, oban_job} =
|
||||
Federator.incoming_ap_doc(%{
|
||||
method: "POST",
|
||||
req_headers: [],
|
||||
request_path: "/inbox",
|
||||
params: params,
|
||||
query_string: ""
|
||||
})
|
||||
|
||||
assert {:cancel, {:error, :not_found}} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
|
||||
test "when request returns a 410" do
|
||||
params =
|
||||
insert(:note_activity).data
|
||||
|> Map.put("actor", "https://springfield.social/users/hankscorpio")
|
||||
|
||||
{:ok, oban_job} =
|
||||
Federator.incoming_ap_doc(%{
|
||||
method: "POST",
|
||||
req_headers: [],
|
||||
request_path: "/inbox",
|
||||
params: params,
|
||||
query_string: ""
|
||||
})
|
||||
|
||||
assert {:cancel, {:error, :not_found}} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
|
||||
test "when user account is disabled" do
|
||||
user = insert(:user)
|
||||
|
||||
fake_activity = URI.parse(user.ap_id) |> Map.put(:path, "/fake-activity") |> to_string
|
||||
|
||||
params =
|
||||
insert(:note_activity, user: user).data
|
||||
|> Map.put("id", fake_activity)
|
||||
|
||||
{:ok, %User{}} = User.set_activation(user, false)
|
||||
|
||||
{:ok, oban_job} =
|
||||
Federator.incoming_ap_doc(%{
|
||||
method: "POST",
|
||||
req_headers: [],
|
||||
request_path: "/inbox",
|
||||
params: params,
|
||||
query_string: ""
|
||||
})
|
||||
|
||||
assert {:cancel, {:user_active, false}} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
end
|
||||
|
||||
test "it can validate the signature" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://mastodon.social/users/bastianallgeier"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/bastianallgeier.json"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://mastodon.social/users/bastianallgeier/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "mastodon.social")
|
||||
|> String.replace("{{nickname}}", "bastianallgeier")
|
||||
}
|
||||
|
||||
%{url: "https://phpc.social/users/denniskoch"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
|
|
@ -86,136 +168,10 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
|||
|> String.replace("{{domain}}", "phpc.social")
|
||||
|> String.replace("{{nickname}}", "denniskoch")
|
||||
}
|
||||
|
||||
%{url: "https://mastodon.social/users/bastianallgeier/statuses/112846516276907281"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: File.read!("test/fixtures/receiver_worker_signature_activity.json")
|
||||
}
|
||||
end)
|
||||
|
||||
params = %{
|
||||
"@context" => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
%{
|
||||
"claim" => %{"@id" => "toot:claim", "@type" => "@id"},
|
||||
"memorial" => "toot:memorial",
|
||||
"atomUri" => "ostatus:atomUri",
|
||||
"manuallyApprovesFollowers" => "as:manuallyApprovesFollowers",
|
||||
"blurhash" => "toot:blurhash",
|
||||
"ostatus" => "http://ostatus.org#",
|
||||
"discoverable" => "toot:discoverable",
|
||||
"focalPoint" => %{"@container" => "@list", "@id" => "toot:focalPoint"},
|
||||
"votersCount" => "toot:votersCount",
|
||||
"Hashtag" => "as:Hashtag",
|
||||
"Emoji" => "toot:Emoji",
|
||||
"alsoKnownAs" => %{"@id" => "as:alsoKnownAs", "@type" => "@id"},
|
||||
"sensitive" => "as:sensitive",
|
||||
"movedTo" => %{"@id" => "as:movedTo", "@type" => "@id"},
|
||||
"inReplyToAtomUri" => "ostatus:inReplyToAtomUri",
|
||||
"conversation" => "ostatus:conversation",
|
||||
"Device" => "toot:Device",
|
||||
"schema" => "http://schema.org#",
|
||||
"toot" => "http://joinmastodon.org/ns#",
|
||||
"cipherText" => "toot:cipherText",
|
||||
"suspended" => "toot:suspended",
|
||||
"messageType" => "toot:messageType",
|
||||
"featuredTags" => %{"@id" => "toot:featuredTags", "@type" => "@id"},
|
||||
"Curve25519Key" => "toot:Curve25519Key",
|
||||
"deviceId" => "toot:deviceId",
|
||||
"Ed25519Signature" => "toot:Ed25519Signature",
|
||||
"featured" => %{"@id" => "toot:featured", "@type" => "@id"},
|
||||
"devices" => %{"@id" => "toot:devices", "@type" => "@id"},
|
||||
"value" => "schema:value",
|
||||
"PropertyValue" => "schema:PropertyValue",
|
||||
"messageFranking" => "toot:messageFranking",
|
||||
"publicKeyBase64" => "toot:publicKeyBase64",
|
||||
"identityKey" => %{"@id" => "toot:identityKey", "@type" => "@id"},
|
||||
"Ed25519Key" => "toot:Ed25519Key",
|
||||
"indexable" => "toot:indexable",
|
||||
"EncryptedMessage" => "toot:EncryptedMessage",
|
||||
"fingerprintKey" => %{"@id" => "toot:fingerprintKey", "@type" => "@id"}
|
||||
}
|
||||
],
|
||||
"actor" => "https://phpc.social/users/denniskoch",
|
||||
"cc" => [
|
||||
"https://phpc.social/users/denniskoch/followers",
|
||||
"https://mastodon.social/users/bastianallgeier",
|
||||
"https://chaos.social/users/distantnative",
|
||||
"https://fosstodon.org/users/kev"
|
||||
],
|
||||
"id" => "https://phpc.social/users/denniskoch/statuses/112847382711461301/activity",
|
||||
"object" => %{
|
||||
"atomUri" => "https://phpc.social/users/denniskoch/statuses/112847382711461301",
|
||||
"attachment" => [],
|
||||
"attributedTo" => "https://phpc.social/users/denniskoch",
|
||||
"cc" => [
|
||||
"https://phpc.social/users/denniskoch/followers",
|
||||
"https://mastodon.social/users/bastianallgeier",
|
||||
"https://chaos.social/users/distantnative",
|
||||
"https://fosstodon.org/users/kev"
|
||||
],
|
||||
"content" =>
|
||||
"<p><span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@bastianallgeier\" class=\"u-url mention\">@<span>bastianallgeier</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://chaos.social/@distantnative\" class=\"u-url mention\">@<span>distantnative</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://fosstodon.org/@kev\" class=\"u-url mention\">@<span>kev</span></a></span> Another main argument: Discord is popular. Many people have an account, so you can just join an server quickly. Also you know the app and how to get around.</p>",
|
||||
"contentMap" => %{
|
||||
"en" =>
|
||||
"<p><span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@bastianallgeier\" class=\"u-url mention\">@<span>bastianallgeier</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://chaos.social/@distantnative\" class=\"u-url mention\">@<span>distantnative</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://fosstodon.org/@kev\" class=\"u-url mention\">@<span>kev</span></a></span> Another main argument: Discord is popular. Many people have an account, so you can just join an server quickly. Also you know the app and how to get around.</p>"
|
||||
},
|
||||
"conversation" =>
|
||||
"tag:mastodon.social,2024-07-25:objectId=760068442:objectType=Conversation",
|
||||
"id" => "https://phpc.social/users/denniskoch/statuses/112847382711461301",
|
||||
"inReplyTo" =>
|
||||
"https://mastodon.social/users/bastianallgeier/statuses/112846516276907281",
|
||||
"inReplyToAtomUri" =>
|
||||
"https://mastodon.social/users/bastianallgeier/statuses/112846516276907281",
|
||||
"published" => "2024-07-25T13:33:29Z",
|
||||
"replies" => %{
|
||||
"first" => %{
|
||||
"items" => [],
|
||||
"next" =>
|
||||
"https://phpc.social/users/denniskoch/statuses/112847382711461301/replies?only_other_accounts=true&page=true",
|
||||
"partOf" =>
|
||||
"https://phpc.social/users/denniskoch/statuses/112847382711461301/replies",
|
||||
"type" => "CollectionPage"
|
||||
},
|
||||
"id" => "https://phpc.social/users/denniskoch/statuses/112847382711461301/replies",
|
||||
"type" => "Collection"
|
||||
},
|
||||
"sensitive" => false,
|
||||
"tag" => [
|
||||
%{
|
||||
"href" => "https://mastodon.social/users/bastianallgeier",
|
||||
"name" => "@bastianallgeier@mastodon.social",
|
||||
"type" => "Mention"
|
||||
},
|
||||
%{
|
||||
"href" => "https://chaos.social/users/distantnative",
|
||||
"name" => "@distantnative@chaos.social",
|
||||
"type" => "Mention"
|
||||
},
|
||||
%{
|
||||
"href" => "https://fosstodon.org/users/kev",
|
||||
"name" => "@kev@fosstodon.org",
|
||||
"type" => "Mention"
|
||||
}
|
||||
],
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Note",
|
||||
"url" => "https://phpc.social/@denniskoch/112847382711461301"
|
||||
},
|
||||
"published" => "2024-07-25T13:33:29Z",
|
||||
"signature" => %{
|
||||
"created" => "2024-07-25T13:33:29Z",
|
||||
"creator" => "https://phpc.social/users/denniskoch#main-key",
|
||||
"signatureValue" =>
|
||||
"slz9BKJzd2n1S44wdXGOU+bV/wsskdgAaUpwxj8R16mYOL8+DTpE6VnfSKoZGsBBJT8uG5gnVfVEz1YsTUYtymeUgLMh7cvd8VnJnZPS+oixbmBRVky/Myf91TEgQQE7G4vDmTdB4ii54hZrHcOOYYf5FKPNRSkMXboKA6LMqNtekhbI+JTUJYIB02WBBK6PUyo15f6B1RJ6HGWVgud9NE0y1EZXfrkqUt682p8/9D49ORf7AwjXUJibKic2RbPvhEBj70qUGfBm4vvgdWhSUn1IG46xh+U0+NrTSUED82j1ZVOeua/2k/igkGs8cSBkY35quXTkPz6gbqCCH66CuA==",
|
||||
"type" => "RsaSignature2017"
|
||||
},
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create"
|
||||
}
|
||||
params =
|
||||
File.read!("test/fixtures/receiver_worker_signature_activity.json") |> Jason.decode!()
|
||||
|
||||
req_headers = [
|
||||
["accept-encoding", "gzip"],
|
||||
|
|
@ -245,4 +201,46 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
|||
|
||||
assert {:ok, %Pleroma.Activity{}} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
|
||||
test "cancels due to origin containment" do
|
||||
params =
|
||||
insert(:note_activity).data
|
||||
|> Map.put("id", "https://notorigindomain.com/activity")
|
||||
|
||||
{:ok, oban_job} =
|
||||
Federator.incoming_ap_doc(%{
|
||||
method: "POST",
|
||||
req_headers: [],
|
||||
request_path: "/inbox",
|
||||
params: params,
|
||||
query_string: ""
|
||||
})
|
||||
|
||||
assert {:cancel, :origin_containment_failed} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
|
||||
test "canceled due to deleted object" do
|
||||
params =
|
||||
insert(:announce_activity).data
|
||||
|> Map.put("object", "http://localhost:4001/deleted")
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "http://localhost:4001/deleted"} ->
|
||||
%Tesla.Env{
|
||||
status: 404,
|
||||
body: ""
|
||||
}
|
||||
end)
|
||||
|
||||
{:ok, oban_job} =
|
||||
Federator.incoming_ap_doc(%{
|
||||
method: "POST",
|
||||
req_headers: [],
|
||||
request_path: "/inbox",
|
||||
params: params,
|
||||
query_string: ""
|
||||
})
|
||||
|
||||
assert {:cancel, _} = ReceiverWorker.perform(oban_job)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ defmodule Pleroma.Factory do
|
|||
|
||||
def question_factory(attrs \\ %{}) do
|
||||
user = attrs[:user] || insert(:user)
|
||||
closed = attrs[:closed] || DateTime.utc_now() |> DateTime.add(86_400) |> DateTime.to_iso8601()
|
||||
|
||||
data = %{
|
||||
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
|
||||
|
|
@ -251,7 +252,7 @@ defmodule Pleroma.Factory do
|
|||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [user.follower_address],
|
||||
"context" => Pleroma.Web.ActivityPub.Utils.generate_context_id(),
|
||||
"closed" => DateTime.utc_now() |> DateTime.add(86_400) |> DateTime.to_iso8601(),
|
||||
"closed" => closed,
|
||||
"content" => "Which flavor of ice cream do you prefer?",
|
||||
"oneOf" => [
|
||||
%{
|
||||
|
|
@ -509,7 +510,8 @@ defmodule Pleroma.Factory do
|
|||
%Pleroma.Activity{
|
||||
data: data,
|
||||
actor: data["actor"],
|
||||
recipients: data["to"]
|
||||
recipients: data["to"],
|
||||
local: user.local
|
||||
}
|
||||
|> Map.merge(attrs)
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue