You requested a full backup of your Pleroma account. It's ready for download:
\n\n" +msgstr "" +"Je hebt een verzoek ingediend voor een volledige back-up van je Pleroma " +"account. Deze is gereed om te downloaden:
\n" +"\n" + +#: lib/pleroma/emails/user_email.ex:384 +#, elixir-autogen, elixir-format +msgctxt "account archive email subject" +msgid "Your account archive is ready" +msgstr "Je account archief is gereed" + +#: lib/pleroma/emails/user_email.ex:188 +#, elixir-autogen, elixir-format +msgctxt "approval pending email body" +msgid "Your account at %{instance_name} is being reviewed by staff. You will receive another email once your account is approved.
\n" +msgstr "" +"Je account bij %{instance_name} zal worden beoordeeld door de beheerders. " +"Je zult een opvolgende e-mail ontvangen wanneer je account goed gekeurd " +"is.
\n" + +#: lib/pleroma/emails/user_email.ex:202 +#, elixir-autogen, elixir-format +msgctxt "approval pending email subject" +msgid "Your account is awaiting approval" +msgstr "Je account is in afwachting van goedkeuring" + +#: lib/pleroma/emails/user_email.ex:158 +#, elixir-autogen, elixir-format +msgctxt "confirmation email body" +msgid "Email confirmation is required to activate the account.
\nPlease click the following link to activate your account.
\n" +msgstr "" +"Bevestiging via e-mail is vereist om je account te activeren.
\n" +"Je kunt je account activeren door op deze " +"link te klikken.
\n" + +#: lib/pleroma/emails/user_email.ex:174 +#, elixir-autogen, elixir-format +msgctxt "confirmation email subject" +msgid "%{instance_name} account confirmation" +msgstr "%{instance_name} account bevestiging" + +#: lib/pleroma/emails/user_email.ex:310 +#, elixir-autogen, elixir-format +msgctxt "digest email subject" +msgid "Your digest from %{instance_name}" +msgstr "Je overzicht van %{instance_name}" + +#: lib/pleroma/emails/user_email.ex:81 +#, elixir-autogen, elixir-format +msgctxt "password reset email body" +msgid "Someone has requested password change for your account at %{instance_name}.
\nIf it was you, visit the following link to proceed: reset password.
\nIf it was someone else, nothing to worry about: your data is secure and your password has not been changed.
\n" +msgstr "" +"Iemand heeft een verzoek ingediend om het wachtwoord van je account bij " +"%{instance_name} te herstellen.
\n" +"Als je dit zelf geweest bent, volg dan de volgende link om door te gaan: " +"wachtwoord herstellen.
\n" +"Indien je dit niet geweest bent, hoef je geen verdere acties te " +"ondernemen: je gegevens zijn veilig en je wachtwoord is niet gewijzigd.
\n" + +#: lib/pleroma/emails/user_email.ex:98 +#, elixir-autogen, elixir-format +msgctxt "password reset email subject" +msgid "Password reset" +msgstr "Wachtwoord herstellen" + +#: lib/pleroma/emails/user_email.ex:215 +#, elixir-autogen, elixir-format +msgctxt "successful registration email body" +msgid "Your account at %{instance_name} has been registered successfully.
\nNo further action is required to activate your account.
\n" +msgstr "" +"Het registreren van je account bij %{instance_name} is gelukt.
\n" +"Er zijn geen verdere stappen vereist om je account te activeren.
\n" + +#: lib/pleroma/emails/user_email.ex:231 +#, elixir-autogen, elixir-format +msgctxt "successful registration email subject" +msgid "Account registered on %{instance_name}" +msgstr "Account registratie bij %{instance_name}" + +#: lib/pleroma/emails/user_email.ex:119 +#, elixir-autogen, elixir-format +msgctxt "user invitation email body" +msgid "%{inviter_name} invites you to join %{instance_name}, an instance of Pleroma federated social networking platform.
\nClick the following link to register: accept invitation.
\n" +msgstr "" +"%{inviter_name} nodigt je uit om je te registreren bij %{instance_name}, " +"een instantie van het Pleroma gefedereerde sociale netwerk.
\n" +"Om je te registreren, klink op de volgende link: uitnodiging accepteren.
\n" + +#: lib/pleroma/emails/user_email.ex:136 +#, elixir-autogen, elixir-format +msgctxt "user invitation email subject" +msgid "Invitation to %{instance_name}" +msgstr "Uitnodiging van %{instance_name}" + +#: lib/pleroma/emails/user_email.ex:53 +#, elixir-autogen, elixir-format +msgctxt "welcome email html body" +msgid "Welcome to %{instance_name}!" +msgstr "Welkom bij %{instance_name}!" + +#: lib/pleroma/emails/user_email.ex:41 +#, elixir-autogen, elixir-format +msgctxt "welcome email subject" +msgid "Welcome to %{instance_name}!" +msgstr "Welkom bij %{instance_name}!" + +#: lib/pleroma/emails/user_email.ex:65 +#, elixir-autogen, elixir-format +msgctxt "welcome email text body" +msgid "Welcome to %{instance_name}!" +msgstr "Welkom bij %{instance_name}!" + +#: lib/pleroma/emails/user_email.ex:368 +#, elixir-autogen, elixir-format +msgctxt "account archive email body - admin requested" +msgid "Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:
\n\n" +msgstr "" +"Beheerder @%{admin_nickname} heeft een verzoek ingediend voor een " +"volledige back-up van je Pleroma account. Deze is gereed om te " +"downloaden:
\n" +"\n" diff --git a/priv/repo/migrations/20220711182322_add_associated_object_id_function.exs b/priv/repo/migrations/20220711182322_add_associated_object_id_function.exs new file mode 100644 index 000000000..76348f31a --- /dev/null +++ b/priv/repo/migrations/20220711182322_add_associated_object_id_function.exs @@ -0,0 +1,37 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authorsnya, ich bin eine Brotperson
", + "icon": { + "type": "Image", + "url": "https://mk.absturztau.be/files/webpublic-3b5594f4-fa52-4548-b4e3-c379ae2143ed", + "sensitive": false, + "name": null + }, + "image": { + "type": "Image", + "url": "https://mk.absturztau.be/files/webpublic-0d03b03d-b14b-4916-ac3d-8a137118ec84", + "sensitive": false, + "name": null + }, + "tag": [], + "manuallyApprovesFollowers": true, + "discoverable": false, + "publicKey": { + "id": "https://mk.absturztau.be/users/8ozbzjs3o8#main-key", + "type": "Key", + "owner": "https://mk.absturztau.be/users/8ozbzjs3o8", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuN/S1spBGmh8FXI1Bt16\nXB7Cc0QutBp7UPgmDNHjOfsq0zrF4g3L1UBxvrpU0XX77XPMCd9yPvGwAYURH2mv\ntIcYuE+R90VLDmBu5MTVthcG2D874eCZ2rD2YsEYmN5AjTX7QBIqCck+qDhVWkkM\nEZ6S5Ht6IJ5Of74eKffXElQI/C6QB+9uEDOmPk0jCzgI5gw7xvJqFj/DIF4kUUAu\nA89JqaFZzZlkrSrj4cr48bLN/YOmpdaHu0BKHaDSHct4+MqlixqovgdB6RboCEDw\ne4Aeav7+Q0Y9oGIvuggg0Q+nCubnVNnaPyzd817tpPVzyZmTts+DKyDuv90SX3nR\nsPaNa5Ty60eqplUk4b7X1gSvuzBJUFBxTVV84WnjwoeoydaS6rSyjCDPGLBjaByc\nFyWMMEb/zlQyhLZfBlvT7k96wRSsMszh2hDALWmgYIhq/jNwINvALJ1GKLNHHKZ4\nyz2LnxVpRm2rWrZzbvtcnSQOt3LaPSZn8Wgwv4buyHF02iuVuIamZVtKexsE1Ixl\nIi9qa3AKEc5gOzYXhRhvHaruzoCehUbb/UHC5c8Tto8L5G1xYzjLP3qj3PT9w/wM\n+k1Ra/4JhuAnVFROOoOmx9rIELLHH7juY2nhM7plGhyt1M5gysgqEloij8QzyQU2\nZK1YlAERG2XFO6br8omhcmECAwEAAQ==\n-----END PUBLIC KEY-----\n" + }, + "isCat": true, + "vcard:Address": "Vienna, Austria" +} \ No newline at end of file diff --git a/test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json b/test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json new file mode 100644 index 000000000..b45ab78e4 --- /dev/null +++ b/test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json @@ -0,0 +1 @@ +{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","Hashtag":"as:Hashtag","quoteUrl":"as:quoteUrl","toot":"http://joinmastodon.org/ns#","Emoji":"toot:Emoji","featured":"toot:featured","discoverable":"toot:discoverable","schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value","misskey":"https://misskey-hub.net/ns#","_misskey_content":"misskey:_misskey_content","_misskey_quote":"misskey:_misskey_quote","_misskey_reaction":"misskey:_misskey_reaction","_misskey_votes":"misskey:_misskey_votes","_misskey_talk":"misskey:_misskey_talk","isCat":"misskey:isCat","vcard":"http://www.w3.org/2006/vcard/ns#"}],"id":"https://mk.absturztau.be/notes/93e7nm8wqg/activity","actor":"https://mk.absturztau.be/users/8ozbzjs3o8","type":"Create","published":"2022-08-01T11:06:49.568Z","object":{"id":"https://mk.absturztau.be/notes/93e7nm8wqg","type":"Note","attributedTo":"https://mk.absturztau.be/users/8ozbzjs3o8","summary":null,"content":"meow
","_misskey_content":"meow","published":"2022-08-01T11:06:49.568Z","to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://mk.absturztau.be/users/8ozbzjs3o8/followers"],"inReplyTo":null,"attachment":[],"sensitive":false,"tag":[]},"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://mk.absturztau.be/users/8ozbzjs3o8/followers"]} \ No newline at end of file diff --git a/test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg.json b/test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg.json new file mode 100644 index 000000000..1b931a9a4 --- /dev/null +++ b/test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg.json @@ -0,0 +1,44 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "sensitive": "as:sensitive", + "Hashtag": "as:Hashtag", + "quoteUrl": "as:quoteUrl", + "toot": "http://joinmastodon.org/ns#", + "Emoji": "toot:Emoji", + "featured": "toot:featured", + "discoverable": "toot:discoverable", + "schema": "http://schema.org#", + "PropertyValue": "schema:PropertyValue", + "value": "schema:value", + "misskey": "https://misskey-hub.net/ns#", + "_misskey_content": "misskey:_misskey_content", + "_misskey_quote": "misskey:_misskey_quote", + "_misskey_reaction": "misskey:_misskey_reaction", + "_misskey_votes": "misskey:_misskey_votes", + "_misskey_talk": "misskey:_misskey_talk", + "isCat": "misskey:isCat", + "vcard": "http://www.w3.org/2006/vcard/ns#" + } + ], + "id": "https://mk.absturztau.be/notes/93e7nm8wqg", + "type": "Note", + "attributedTo": "https://mk.absturztau.be/users/8ozbzjs3o8", + "summary": null, + "content": "meow
", + "_misskey_content": "meow", + "published": "2022-08-01T11:06:49.568Z", + "to": [ + "https://www.w3.org/ns/activitystreams#Public" + ], + "cc": [ + "https://mk.absturztau.be/users/8ozbzjs3o8/followers" + ], + "inReplyTo": null, + "attachment": [], + "sensitive": false, + "tag": [] +} \ No newline at end of file diff --git a/test/fixtures/tesla_mock/p.helene.moe-AM7S6vZQmL6pI9TgPY.json b/test/fixtures/tesla_mock/p.helene.moe-AM7S6vZQmL6pI9TgPY.json new file mode 100644 index 000000000..a1ef5e20b --- /dev/null +++ b/test/fixtures/tesla_mock/p.helene.moe-AM7S6vZQmL6pI9TgPY.json @@ -0,0 +1,36 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://p.helene.moe/schemas/litepub-0.1.jsonld", + { + "@language": "und" + } + ], + "actor": "https://p.helene.moe/users/helene", + "attachment": [], + "attributedTo": "https://p.helene.moe/users/helene", + "cc": [ + "https://p.helene.moe/users/helene/followers" + ], + "content": "@mametsuko meow", + "context": "https://p.helene.moe/contexts/cc324643-5583-4c3f-91d2-c6ed37db159d", + "conversation": "https://p.helene.moe/contexts/cc324643-5583-4c3f-91d2-c6ed37db159d", + "id": "https://p.helene.moe/objects/fd5910ac-d9dc-412e-8d1d-914b203296c4", + "inReplyTo": "https://mk.absturztau.be/notes/93e7nm8wqg", + "published": "2022-08-02T13:46:58.403996Z", + "sensitive": null, + "source": "@mametsuko@mk.absturztau.be meow", + "summary": "", + "tag": [ + { + "href": "https://mk.absturztau.be/users/8ozbzjs3o8", + "name": "@mametsuko@mk.absturztau.be", + "type": "Mention" + } + ], + "to": [ + "https://mk.absturztau.be/users/8ozbzjs3o8", + "https://www.w3.org/ns/activitystreams#Public" + ], + "type": "Note" +} \ No newline at end of file diff --git a/test/pleroma/activity/ir/topics_test.exs b/test/pleroma/activity/ir/topics_test.exs index 311f85dea..d299fea63 100644 --- a/test/pleroma/activity/ir/topics_test.exs +++ b/test/pleroma/activity/ir/topics_test.exs @@ -13,6 +13,29 @@ defmodule Pleroma.Activity.Ir.TopicsTest do import Mock + describe "chat message" do + test "Create produces no topics" do + activity = %Activity{ + object: %Object{data: %{"type" => "ChatMessage"}}, + data: %{"type" => "Create"} + } + + assert [] == Topics.get_activity_topics(activity) + end + + test "Delete produces user and user:pleroma_chat" do + activity = %Activity{ + object: %Object{data: %{"type" => "ChatMessage"}}, + data: %{"type" => "Delete"} + } + + topics = Topics.get_activity_topics(activity) + assert [_, _] = topics + assert "user" in topics + assert "user:pleroma_chat" in topics + end + end + describe "poll answer" do test "produce no topics" do activity = %Activity{object: %Object{data: %{"type" => "Answer"}}} @@ -35,7 +58,7 @@ defmodule Pleroma.Activity.Ir.TopicsTest do setup do activity = %Activity{ object: %Object{data: %{"type" => "Note"}}, - data: %{"to" => [Pleroma.Constants.as_public()]} + data: %{"to" => [Pleroma.Constants.as_public()], "type" => "Create"} } {:ok, activity: activity} @@ -114,6 +137,55 @@ defmodule Pleroma.Activity.Ir.TopicsTest do end end + describe "public visibility Announces" do + setup do + activity = %Activity{ + object: %Object{data: %{"attachment" => []}}, + data: %{"type" => "Announce", "to" => [Pleroma.Constants.as_public()]} + } + + {:ok, activity: activity} + end + + test "does not generate public topics", %{activity: activity} do + topics = Topics.get_activity_topics(activity) + + refute "public" in topics + refute "public:remote" in topics + refute "public:local" in topics + end + end + + describe "local-public visibility create events" do + setup do + activity = %Activity{ + object: %Object{data: %{"attachment" => []}}, + data: %{"type" => "Create", "to" => [Pleroma.Web.ActivityPub.Utils.as_local_public()]} + } + + {:ok, activity: activity} + end + + test "doesn't produce public topics", %{activity: activity} do + topics = Topics.get_activity_topics(activity) + + refute Enum.member?(topics, "public") + end + + test "produces public:local topics", %{activity: activity} do + topics = Topics.get_activity_topics(activity) + + assert Enum.member?(topics, "public:local") + end + + test "with no attachments doesn't produce public:media topics", %{activity: activity} do + topics = Topics.get_activity_topics(activity) + + refute Enum.member?(topics, "public:media") + refute Enum.member?(topics, "public:local:media") + end + end + describe "public visibility create events with attachments" do setup do activity = %Activity{ @@ -152,9 +224,36 @@ defmodule Pleroma.Activity.Ir.TopicsTest do end end + describe "local-public visibility create events with attachments" do + setup do + activity = %Activity{ + object: %Object{data: %{"attachment" => ["foo"]}}, + data: %{"type" => "Create", "to" => [Pleroma.Web.ActivityPub.Utils.as_local_public()]} + } + + {:ok, activity: activity} + end + + test "do not produce public:media topics", %{activity: activity} do + topics = Topics.get_activity_topics(activity) + + refute Enum.member?(topics, "public:media") + end + + test "produces public:local:media topics", %{activity: activity} do + topics = Topics.get_activity_topics(activity) + + assert Enum.member?(topics, "public:local:media") + end + end + describe "non-public visibility" do test "produces direct topic" do - activity = %Activity{object: %Object{data: %{"type" => "Note"}}, data: %{"to" => []}} + activity = %Activity{ + object: %Object{data: %{"type" => "Note"}}, + data: %{"to" => [], "type" => "Create"} + } + topics = Topics.get_activity_topics(activity) assert Enum.member?(topics, "direct") diff --git a/test/pleroma/activity_test.exs b/test/pleroma/activity_test.exs index b5bb4bafe..e38384c9c 100644 --- a/test/pleroma/activity_test.exs +++ b/test/pleroma/activity_test.exs @@ -278,4 +278,78 @@ defmodule Pleroma.ActivityTest do assert Repo.aggregate(Activity, :count, :id) == 2 end + + describe "associated_object_id() sql function" do + test "with json object" do + %{rows: [[object_id]]} = + Ecto.Adapters.SQL.query!( + Pleroma.Repo, + """ + select associated_object_id('{"object": {"id":"foobar"}}'::jsonb); + """ + ) + + assert object_id == "foobar" + end + + test "with string object" do + %{rows: [[object_id]]} = + Ecto.Adapters.SQL.query!( + Pleroma.Repo, + """ + select associated_object_id('{"object": "foobar"}'::jsonb); + """ + ) + + assert object_id == "foobar" + end + + test "with array object" do + %{rows: [[object_id]]} = + Ecto.Adapters.SQL.query!( + Pleroma.Repo, + """ + select associated_object_id('{"object": ["foobar", {}]}'::jsonb); + """ + ) + + assert object_id == "foobar" + end + + test "invalid" do + %{rows: [[object_id]]} = + Ecto.Adapters.SQL.query!( + Pleroma.Repo, + """ + select associated_object_id('{"object": {}}'::jsonb); + """ + ) + + assert is_nil(object_id) + end + + test "invalid object id" do + %{rows: [[object_id]]} = + Ecto.Adapters.SQL.query!( + Pleroma.Repo, + """ + select associated_object_id('{"object": {"id": 123}}'::jsonb); + """ + ) + + assert is_nil(object_id) + end + + test "no object field" do + %{rows: [[object_id]]} = + Ecto.Adapters.SQL.query!( + Pleroma.Repo, + """ + select associated_object_id('{}'::jsonb); + """ + ) + + assert is_nil(object_id) + end + end end diff --git a/test/pleroma/signature_test.exs b/test/pleroma/signature_test.exs index 92d05f26c..b849cbee7 100644 --- a/test/pleroma/signature_test.exs +++ b/test/pleroma/signature_test.exs @@ -109,6 +109,11 @@ defmodule Pleroma.SignatureTest do {:ok, "https://example.com/users/1234"} end + test "it deduces the actor id for gotoSocial" do + assert Signature.key_id_to_actor_id("https://example.com/users/1234/main-key") == + {:ok, "https://example.com/users/1234"} + end + test "it calls webfinger for 'acct:' accounts" do with_mock(Pleroma.Web.WebFinger, finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index 4d7e76266..b8d73ea10 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -554,7 +554,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert activity.data["ok"] == data["ok"] assert activity.data["id"] == given_id assert activity.data["context"] == "blabla" - assert activity.data["context_id"] end test "adds a context when none is there" do @@ -576,8 +575,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert is_binary(activity.data["context"]) assert is_binary(object.data["context"]) - assert activity.data["context_id"] - assert object.data["context_id"] end test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do @@ -1612,7 +1609,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do }) assert Repo.aggregate(Activity, :count, :id) == 1 - assert Repo.aggregate(Object, :count, :id) == 2 + assert Repo.aggregate(Object, :count, :id) == 1 assert Repo.aggregate(Notification, :count, :id) == 0 end end diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs index 781093b1d..c7a62be18 100644 --- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs @@ -103,4 +103,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note) end + + test "a Note without replies/first/items validates" do + insert(:user, ap_id: "https://mastodon.social/users/emelie") + + note = + "test/fixtures/tesla_mock/status.emelie.json" + |> File.read!() + |> Jason.decode!() + |> pop_in(["replies", "first", "items"]) + |> elem(1) + + %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note) + end end diff --git a/test/pleroma/web/activity_pub/object_validators/create_generic_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/create_generic_validator_test.exs index 0a5b44beb..e771260c9 100644 --- a/test/pleroma/web/activity_pub/object_validators/create_generic_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/create_generic_validator_test.exs @@ -23,10 +23,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidatorTest do {:ok, object_data} = ObjectValidator.cast_and_apply(note_activity["object"]) meta = [object_data: ObjectValidator.stringify_keys(object_data)] - %{valid?: true} = CreateGenericValidator.cast_and_validate(note_activity, meta) + assert %{valid?: true} = CreateGenericValidator.cast_and_validate(note_activity, meta) end - test "a Create/Note with mismatched context is invalid" do + test "a Create/Note with mismatched context uses the Note's context" do user = insert(:user) note = %{ @@ -54,6 +54,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidatorTest do {:ok, object_data} = ObjectValidator.cast_and_apply(note_activity["object"]) meta = [object_data: ObjectValidator.stringify_keys(object_data)] - %{valid?: false} = CreateGenericValidator.cast_and_validate(note_activity, meta) + validated = CreateGenericValidator.cast_and_validate(note_activity, meta) + + assert validated.valid? + assert {:context, note["context"]} in validated.changes end end diff --git a/test/pleroma/web/activity_pub/side_effects_test.exs b/test/pleroma/web/activity_pub/side_effects_test.exs index 9d3490ecd..b24831e85 100644 --- a/test/pleroma/web/activity_pub/side_effects_test.exs +++ b/test/pleroma/web/activity_pub/side_effects_test.exs @@ -839,9 +839,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do ]) do {:ok, announce, _} = SideEffects.handle(announce) - assert called( - Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce) - ) + assert called(Pleroma.Web.Streamer.stream(["user", "list"], announce)) assert called(Pleroma.Web.Push.send(:_)) end diff --git a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs index b00fd919b..7c406fbd0 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs @@ -707,4 +707,42 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do } ] end + + test "the standalone note uses its own ID when context is missing" do + insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8") + + activity = + "test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json" + |> File.read!() + |> Jason.decode!() + + {:ok, %Activity{} = modified} = Transmogrifier.handle_incoming(activity) + object = Object.normalize(modified, fetch: false) + + assert object.data["context"] == object.data["id"] + assert modified.data["context"] == object.data["id"] + end + + test "the reply note uses its parent's ID when context is missing and reply is unreachable" do + insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8") + + activity = + "test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json" + |> File.read!() + |> Jason.decode!() + + object = + activity["object"] + |> Map.put("inReplyTo", "https://404.site/object/went-to-buy-milk") + + activity = + activity + |> Map.put("object", object) + + {:ok, %Activity{} = modified} = Transmogrifier.handle_incoming(activity) + object = Object.normalize(modified, fetch: false) + + assert object.data["context"] == object.data["inReplyTo"] + assert modified.data["context"] == object.data["inReplyTo"] + end end diff --git a/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs index d22ec400d..d31070546 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs @@ -33,8 +33,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do assert object.data["context"] == "tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation" - assert object.data["context_id"] - assert object.data["anyOf"] == [] assert Enum.sort(object.data["oneOf"]) == @@ -68,7 +66,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do reply_object = Object.normalize(reply_activity, fetch: false) assert reply_object.data["context"] == object.data["context"] - assert reply_object.data["context_id"] == object.data["context_id"] end test "Mastodon Question activity with HTML tags in plaintext" do diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 6520eabc9..273f2611d 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -108,15 +108,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert activity.data["type"] == "Move" end - test "a reply with mismatched context is rejected" do - insert(:user, ap_id: "https://macgirvin.com/channel/mike") + test "it fixes both the Create and object contexts in a reply" do + insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8") + insert(:user, ap_id: "https://p.helene.moe/users/helene") - note_activity = - "test/fixtures/roadhouse-create-activity.json" + create_activity = + "test/fixtures/create-pleroma-reply-to-misskey-thread.json" |> File.read!() |> Jason.decode!() - assert {:error, _} = Transmogrifier.handle_incoming(note_activity) + assert {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(create_activity) + + object = Object.normalize(activity, fetch: false) + + assert activity.data["context"] == object.data["context"] end end @@ -227,7 +232,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert is_nil(modified["object"]["like_count"]) assert is_nil(modified["object"]["announcements"]) assert is_nil(modified["object"]["announcement_count"]) - assert is_nil(modified["object"]["context_id"]) assert is_nil(modified["object"]["generator"]) end @@ -242,7 +246,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert is_nil(modified["object"]["like_count"]) assert is_nil(modified["object"]["announcements"]) assert is_nil(modified["object"]["announcement_count"]) - assert is_nil(modified["object"]["context_id"]) assert is_nil(modified["object"]["likes"]) end diff --git a/test/pleroma/web/activity_pub/utils_test.exs b/test/pleroma/web/activity_pub/utils_test.exs index 447621718..e42893849 100644 --- a/test/pleroma/web/activity_pub/utils_test.exs +++ b/test/pleroma/web/activity_pub/utils_test.exs @@ -429,7 +429,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do object = Object.normalize(note_activity, fetch: false) res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]}) assert res["context"] == object.data["id"] - assert res["context_id"] == object.id assert res["id"] assert res["published"] end @@ -437,7 +436,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do test "returns map with fake id and published data" do assert %{ "context" => "pleroma:fakecontext", - "context_id" => -1, "id" => "pleroma:fakeid", "published" => _ } = Utils.lazy_put_activity_defaults(%{}, true) @@ -454,13 +452,11 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do }) assert res["context"] == object.data["id"] - assert res["context_id"] == object.id assert res["id"] assert res["published"] assert res["object"]["id"] assert res["object"]["published"] assert res["object"]["context"] == object.data["id"] - assert res["object"]["context_id"] == object.id end end diff --git a/test/pleroma/web/common_api/utils_test.exs b/test/pleroma/web/common_api/utils_test.exs index 5b2019969..b538c5979 100644 --- a/test/pleroma/web/common_api/utils_test.exs +++ b/test/pleroma/web/common_api/utils_test.exs @@ -4,7 +4,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do alias Pleroma.Builders.UserBuilder - alias Pleroma.Object alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI.ActivityDraft alias Pleroma.Web.CommonAPI.Utils @@ -273,22 +272,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do end end - describe "context_to_conversation_id" do - test "creates a mapping object" do - conversation_id = Utils.context_to_conversation_id("random context") - object = Object.get_by_ap_id("random context") - - assert conversation_id == object.id - end - - test "returns an existing mapping for an existing object" do - {:ok, object} = Object.context_mapping("random context") |> Repo.insert() - conversation_id = Utils.context_to_conversation_id("random context") - - assert conversation_id == object.id - end - end - describe "formats date to asctime" do test "when date is in ISO 8601 format" do date = DateTime.utc_now() |> DateTime.to_iso8601() @@ -517,17 +500,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do end end - describe "conversation_id_to_context/1" do - test "returns id" do - object = insert(:note) - assert Utils.conversation_id_to_context(object.id) == object.data["id"] - end - - test "returns error if object not found" do - assert Utils.conversation_id_to_context("123") == {:error, "No such conversation"} - end - end - describe "maybe_notify_mentioned_recipients/2" do test "returns recipients when activity is not `Create`" do activity = insert(:like_activity) diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 0c9a47208..e23bddbff 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -262,6 +262,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do |> Map.put("url", nil) |> Map.put("uri", nil) |> Map.put("created_at", nil) + |> Kernel.put_in(["pleroma", "context"], nil) |> Kernel.put_in(["pleroma", "conversation_id"], nil) fake_conn = @@ -285,6 +286,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do |> Map.put("url", nil) |> Map.put("uri", nil) |> Map.put("created_at", nil) + |> Kernel.put_in(["pleroma", "context"], nil) |> Kernel.put_in(["pleroma", "conversation_id"], nil) assert real_status == fake_status diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs index 297889449..f76b115b7 100644 --- a/test/pleroma/web/mastodon_api/views/status_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/status_view_test.exs @@ -14,10 +14,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do alias Pleroma.User alias Pleroma.UserRelationship alias Pleroma.Web.CommonAPI - alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.StatusView + require Bitwise + import Pleroma.Factory import Tesla.Mock import OpenApiSpex.TestAssertions @@ -226,7 +227,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do object_data = Object.normalize(note, fetch: false).data user = User.get_cached_by_ap_id(note.data["actor"]) - convo_id = Utils.context_to_conversation_id(object_data["context"]) + convo_id = :erlang.crc32(object_data["context"]) |> Bitwise.band(Bitwise.bnot(0x8000_0000)) status = StatusView.render("show.json", %{activity: note}) @@ -280,6 +281,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do pleroma: %{ local: true, conversation_id: convo_id, + context: object_data["context"], in_reply_to_account_acct: nil, content: %{"text/plain" => HTML.strip_tags(object_data["content"])}, spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])}, diff --git a/test/pleroma/web/metadata/providers/twitter_card_test.exs b/test/pleroma/web/metadata/providers/twitter_card_test.exs index 392496993..1a0cea9ce 100644 --- a/test/pleroma/web/metadata/providers/twitter_card_test.exs +++ b/test/pleroma/web/metadata/providers/twitter_card_test.exs @@ -39,6 +39,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do "actor" => user.ap_id, "tag" => [], "id" => "https://pleroma.gov/objects/whatever", + "summary" => "", "content" => "pleroma in a nutshell" } }) @@ -54,6 +55,36 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do ] == result end + test "it uses summary as description if post has one" do + user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994") + {:ok, activity} = CommonAPI.post(user, %{status: "HI"}) + + note = + insert(:note, %{ + data: %{ + "actor" => user.ap_id, + "tag" => [], + "id" => "https://pleroma.gov/objects/whatever", + "summary" => "Public service announcement on caffeine consumption", + "content" => "cofe" + } + }) + + result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id}) + + assert [ + {:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}, + {:meta, + [ + property: "twitter:description", + content: "Public service announcement on caffeine consumption" + ], []}, + {:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"], + []}, + {:meta, [property: "twitter:card", content: "summary"], []} + ] == result + end + test "it renders avatar not attachment if post is nsfw and unfurl_nsfw is disabled" do clear_config([Pleroma.Web.Metadata, :unfurl_nsfw], false) user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994") @@ -65,6 +96,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do "actor" => user.ap_id, "tag" => [], "id" => "https://pleroma.gov/objects/whatever", + "summary" => "", "content" => "pleroma in a nutshell", "sensitive" => true, "attachment" => [ @@ -109,6 +141,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do "actor" => user.ap_id, "tag" => [], "id" => "https://pleroma.gov/objects/whatever", + "summary" => "", "content" => "pleroma in a nutshell", "attachment" => [ %{ diff --git a/test/pleroma/web/metadata/utils_test.exs b/test/pleroma/web/metadata/utils_test.exs index 5f2f4a056..85ef6033a 100644 --- a/test/pleroma/web/metadata/utils_test.exs +++ b/test/pleroma/web/metadata/utils_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Web.Metadata.UtilsTest do alias Pleroma.Web.Metadata.Utils describe "scrub_html_and_truncate/1" do - test "it returns text without encode HTML" do + test "it returns content text without encode HTML if summary is nil" do user = insert(:user) note = @@ -16,6 +16,7 @@ defmodule Pleroma.Web.Metadata.UtilsTest do data: %{ "actor" => user.ap_id, "id" => "https://pleroma.gov/objects/whatever", + "summary" => nil, "content" => "Pleroma's really cool!" } }) @@ -23,6 +24,39 @@ defmodule Pleroma.Web.Metadata.UtilsTest do assert Utils.scrub_html_and_truncate(note) == "Pleroma's really cool!" end + test "it returns context text without encode HTML if summary is empty" do + user = insert(:user) + + note = + insert(:note, %{ + data: %{ + "actor" => user.ap_id, + "id" => "https://pleroma.gov/objects/whatever", + "summary" => "", + "content" => "Pleroma's really cool!" + } + }) + + assert Utils.scrub_html_and_truncate(note) == "Pleroma's really cool!" + end + + test "it returns summary text without encode HTML if summary is filled" do + user = insert(:user) + + note = + insert(:note, %{ + data: %{ + "actor" => user.ap_id, + "id" => "https://pleroma.gov/objects/whatever", + "summary" => "Public service announcement on caffeine consumption", + "content" => "cofe" + } + }) + + assert Utils.scrub_html_and_truncate(note) == + "Public service announcement on caffeine consumption" + end + test "it does not return old content after editing" do user = insert(:user) diff --git a/test/pleroma/web/twitter_api/util_controller_test.exs b/test/pleroma/web/twitter_api/util_controller_test.exs index 5dc72b177..a4da23635 100644 --- a/test/pleroma/web/twitter_api/util_controller_test.exs +++ b/test/pleroma/web/twitter_api/util_controller_test.exs @@ -233,6 +233,102 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do end end + describe "POST /main/ostatus - remote_subscribe/2 - with statuses" do + setup do: clear_config([:instance, :federating], true) + + test "renders subscribe form", %{conn: conn} do + user = insert(:user) + status = insert(:note_activity, %{user: user}) + status_id = status.id + + assert is_binary(status_id) + + response = + conn + |> post("/main/ostatus", %{"status_id" => status_id, "profile" => ""}) + |> response(:ok) + + refute response =~ "Could not find status" + assert response =~ "Interacting with" + end + + test "renders subscribe form with error when status not found", %{conn: conn} do + response = + conn + |> post("/main/ostatus", %{"status_id" => "somerandomid", "profile" => ""}) + |> response(:ok) + + assert response =~ "Could not find status" + refute response =~ "Interacting with" + end + + test "it redirect to webfinger url", %{conn: conn} do + user = insert(:user) + status = insert(:note_activity, %{user: user}) + status_id = status.id + status_ap_id = status.data["object"] + + assert is_binary(status_id) + assert is_binary(status_ap_id) + + user2 = insert(:user, ap_id: "shp@social.heldscal.la") + + conn = + conn + |> post("/main/ostatus", %{ + "status" => %{"status_id" => status_id, "profile" => user2.ap_id} + }) + + assert redirected_to(conn) == + "https://social.heldscal.la/main/ostatussub?profile=#{status_ap_id}" + end + + test "it renders form with error when status not found", %{conn: conn} do + user2 = insert(:user, ap_id: "shp@social.heldscal.la") + + response = + conn + |> post("/main/ostatus", %{ + "status" => %{"status_id" => "somerandomid", "profile" => user2.ap_id} + }) + |> response(:ok) + + assert response =~ "Something went wrong." + end + end + + describe "GET /main/ostatus - show_subscribe_form/2" do + setup do: clear_config([:instance, :federating], true) + + test "it works with users", %{conn: conn} do + user = insert(:user) + + response = + conn + |> get("/main/ostatus", %{"nickname" => user.nickname}) + |> response(:ok) + + refute response =~ "Could not find user" + assert response =~ "Remotely follow #{user.nickname}" + end + + test "it works with statuses", %{conn: conn} do + user = insert(:user) + status = insert(:note_activity, %{user: user}) + status_id = status.id + + assert is_binary(status_id) + + response = + conn + |> get("/main/ostatus", %{"status_id" => status_id}) + |> response(:ok) + + refute response =~ "Could not find status" + assert response =~ "Interacting with" + end + end + test "it returns new captcha", %{conn: conn} do with_mock Pleroma.Captcha, new: fn -> "test_captcha" end do diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index eb844e469..7f6065579 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1084,6 +1084,14 @@ defmodule HttpRequestMock do }} end + def get("https://404.site" <> _, _, _, _) do + {:ok, + %Tesla.Env{ + status: 404, + body: "" + }} + end + def get( "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=acct:lain@zetsubou.xn--q9jyb4c", _, @@ -1401,6 +1409,51 @@ defmodule HttpRequestMock do }} end + def get("https://mk.absturztau.be/users/8ozbzjs3o8", _, _, _) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/mametsuko@mk.absturztau.be.json"), + headers: activitypub_object_headers() + }} + end + + def get("https://p.helene.moe/users/helene", _, _, _) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/helene@p.helene.moe.json"), + headers: activitypub_object_headers() + }} + end + + def get("https://mk.absturztau.be/notes/93e7nm8wqg", _, _, _) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg.json"), + headers: activitypub_object_headers() + }} + end + + def get("https://mk.absturztau.be/notes/93e7nm8wqg/activity", _, _, _) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json"), + headers: activitypub_object_headers() + }} + end + + def get("https://p.helene.moe/objects/fd5910ac-d9dc-412e-8d1d-914b203296c4", _, _, _) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/p.helene.moe-AM7S6vZQmL6pI9TgPY.json"), + headers: activitypub_object_headers() + }} + end + def get(url, query, body, headers) do {:error, "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"}