Merge remote-tracking branch 'origin/develop' into feature/bbs
This commit is contained in:
commit
6ad8ddfd29
830 changed files with 12375 additions and 67372 deletions
52
test/bookmark_test.exs
Normal file
52
test/bookmark_test.exs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
defmodule Pleroma.BookmarkTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
describe "create/2" do
|
||||
test "with valid params" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
|
||||
{:ok, bookmark} = Bookmark.create(user.id, activity.id)
|
||||
assert bookmark.user_id == user.id
|
||||
assert bookmark.activity_id == activity.id
|
||||
end
|
||||
|
||||
test "with invalid params" do
|
||||
{:error, changeset} = Bookmark.create(nil, "")
|
||||
refute changeset.valid?
|
||||
|
||||
assert changeset.errors == [
|
||||
user_id: {"can't be blank", [validation: :required]},
|
||||
activity_id: {"can't be blank", [validation: :required]}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "destroy/2" do
|
||||
test "with valid params" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
|
||||
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
|
||||
|
||||
{:ok, _deleted_bookmark} = Bookmark.destroy(user.id, activity.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get/2" do
|
||||
test "gets a bookmark" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
"Scientists Discover The Secret Behind Tenshi Eating A Corndog Being So Cute – Science Daily"
|
||||
})
|
||||
|
||||
{:ok, bookmark} = Bookmark.create(user.id, activity.id)
|
||||
assert bookmark == Bookmark.get(user.id, activity.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
106
test/emoji_test.exs
Normal file
106
test/emoji_test.exs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
defmodule Pleroma.EmojiTest do
|
||||
use ExUnit.Case, async: true
|
||||
alias Pleroma.Emoji
|
||||
|
||||
describe "get_all/0" do
|
||||
setup do
|
||||
emoji_list = Emoji.get_all()
|
||||
{:ok, emoji_list: emoji_list}
|
||||
end
|
||||
|
||||
test "first emoji", %{emoji_list: emoji_list} do
|
||||
[emoji | _others] = emoji_list
|
||||
{code, path, tags} = emoji
|
||||
|
||||
assert tuple_size(emoji) == 3
|
||||
assert is_binary(code)
|
||||
assert is_binary(path)
|
||||
assert is_list(tags)
|
||||
end
|
||||
|
||||
test "random emoji", %{emoji_list: emoji_list} do
|
||||
emoji = Enum.random(emoji_list)
|
||||
{code, path, tags} = emoji
|
||||
|
||||
assert tuple_size(emoji) == 3
|
||||
assert is_binary(code)
|
||||
assert is_binary(path)
|
||||
assert is_list(tags)
|
||||
end
|
||||
end
|
||||
|
||||
describe "match_extra/2" do
|
||||
setup do
|
||||
groups = [
|
||||
"list of files": ["/emoji/custom/first_file.png", "/emoji/custom/second_file.png"],
|
||||
"wildcard folder": "/emoji/custom/*/file.png",
|
||||
"wildcard files": "/emoji/custom/folder/*.png",
|
||||
"special file": "/emoji/custom/special.png"
|
||||
]
|
||||
|
||||
{:ok, groups: groups}
|
||||
end
|
||||
|
||||
test "config for list of files", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/custom/first_file.png")
|
||||
|> to_string()
|
||||
|
||||
assert group == "list of files"
|
||||
end
|
||||
|
||||
test "config with wildcard folder", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/custom/some_folder/file.png")
|
||||
|> to_string()
|
||||
|
||||
assert group == "wildcard folder"
|
||||
end
|
||||
|
||||
test "config with wildcard folder and subfolders", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/custom/some_folder/another_folder/file.png")
|
||||
|> to_string()
|
||||
|
||||
assert group == "wildcard folder"
|
||||
end
|
||||
|
||||
test "config with wildcard files", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/custom/folder/some_file.png")
|
||||
|> to_string()
|
||||
|
||||
assert group == "wildcard files"
|
||||
end
|
||||
|
||||
test "config with wildcard files and subfolders", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/custom/folder/another_folder/some_file.png")
|
||||
|> to_string()
|
||||
|
||||
assert group == "wildcard files"
|
||||
end
|
||||
|
||||
test "config for special file", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/custom/special.png")
|
||||
|> to_string()
|
||||
|
||||
assert group == "special file"
|
||||
end
|
||||
|
||||
test "no mathing returns nil", %{groups: groups} do
|
||||
group =
|
||||
groups
|
||||
|> Emoji.match_extra("/emoji/some_undefined.png")
|
||||
|
||||
refute group
|
||||
end
|
||||
end
|
||||
end
|
||||
306
test/fixtures/httpoison_mock/emelie.atom
vendored
Normal file
306
test/fixtures/httpoison_mock/emelie.atom
vendored
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
<?xml version="1.0"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0">
|
||||
<id>https://mastodon.social/users/emelie.atom</id>
|
||||
<title>emelie 🎨</title>
|
||||
<subtitle>23 / #Sweden / #Artist / #Equestrian / #GameDev
|
||||
|
||||
If I ain't spending time with my pets, I'm probably drawing. 🐴 🐱 🐰</subtitle>
|
||||
<updated>2019-02-04T20:22:19Z</updated>
|
||||
<logo>https://files.mastodon.social/accounts/avatars/000/015/657/original/e7163f98280da1a4.png</logo>
|
||||
<author>
|
||||
<id>https://mastodon.social/users/emelie</id>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
|
||||
<uri>https://mastodon.social/users/emelie</uri>
|
||||
<name>emelie</name>
|
||||
<email>emelie@mastodon.social</email>
|
||||
<summary type="html"><p>23 / <a href="https://mastodon.social/tags/sweden" class="mention hashtag" rel="tag">#<span>Sweden</span></a> / <a href="https://mastodon.social/tags/artist" class="mention hashtag" rel="tag">#<span>Artist</span></a> / <a href="https://mastodon.social/tags/equestrian" class="mention hashtag" rel="tag">#<span>Equestrian</span></a> / <a href="https://mastodon.social/tags/gamedev" class="mention hashtag" rel="tag">#<span>GameDev</span></a></p><p>If I ain&apos;t spending time with my pets, I&apos;m probably drawing. 🐴 🐱 🐰</p></summary>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie"/>
|
||||
<link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/015/657/original/e7163f98280da1a4.png"/>
|
||||
<link rel="header" type="image/png" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/015/657/original/847f331f3dd9e38b.png"/>
|
||||
<poco:preferredUsername>emelie</poco:preferredUsername>
|
||||
<poco:displayName>emelie 🎨</poco:displayName>
|
||||
<poco:note>23 / #Sweden / #Artist / #Equestrian / #GameDev
|
||||
|
||||
If I ain't spending time with my pets, I'm probably drawing. 🐴 🐱 🐰</poco:note>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
</author>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie.atom"/>
|
||||
<link rel="hub" href="https://mastodon.social/api/push"/>
|
||||
<link rel="salmon" href="https://mastodon.social/api/salmon/15657"/>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101850331907006641</id>
|
||||
<published>2019-04-01T09:58:50Z</published>
|
||||
<updated>2019-04-01T09:58:50Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101850331907006641"/>
|
||||
<content type="html" xml:lang="en"><p>Me: I&apos;m going to make this vital change to my world building in the morning, no way I&apos;ll forget this, it&apos;s too big of a deal<br />Also me: forgets</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101850331907006641"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17854598.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94383214:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101849626603073336</id>
|
||||
<published>2019-04-01T06:59:28Z</published>
|
||||
<updated>2019-04-01T06:59:28Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849626603073336"/>
|
||||
<content type="html" xml:lang="sv"><p><span class="h-card"><a href="https://mastodon.social/@Fergant" class="u-url mention">@<span>Fergant</span></a></span> Dom är i stort sett religiös skrift vid det här laget 👏👏</p><p>har dock bara läst svenska översättningen, kanske är dags att jag läser dom på engelska</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Fergant"/>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849626603073336"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17852590.atom"/>
|
||||
<thr:in-reply-to ref="https://mastodon.social/users/Fergant/statuses/101849606513357387" href="https://mastodon.social/@Fergant/101849606513357387"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94362529:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101849580030237068</id>
|
||||
<published>2019-04-01T06:47:37Z</published>
|
||||
<updated>2019-04-01T06:47:37Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849580030237068"/>
|
||||
<content type="html" xml:lang="en"><p>What&apos;s you people&apos;s favourite fantasy books? Give me some hot tips 🌞</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849580030237068"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17852464.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94362529:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101849550599949363</id>
|
||||
<published>2019-04-01T06:40:08Z</published>
|
||||
<updated>2019-04-01T06:40:08Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849550599949363"/>
|
||||
<content type="html" xml:lang="en"><p>Stick them legs out 💃 <a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag">#<span>mastocats</span></a></p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<category term="mastocats"/>
|
||||
<link rel="enclosure" type="image/jpeg" length="516384" href="https://files.mastodon.social/media_attachments/files/013/051/707/original/125a310abe9a34aa.jpeg"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849550599949363"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17852407.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94361580:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101849191533152720</id>
|
||||
<published>2019-04-01T05:08:49Z</published>
|
||||
<updated>2019-04-01T05:08:49Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849191533152720"/>
|
||||
<content type="html" xml:lang="en"><p>long 🐱 <a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag">#<span>mastocats</span></a></p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<category term="mastocats"/>
|
||||
<link rel="enclosure" type="image/jpeg" length="305208" href="https://files.mastodon.social/media_attachments/files/013/049/940/original/f2dbbfe7de3a17d2.jpeg"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849191533152720"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17851663.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94351141:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101849165031453009</id>
|
||||
<published>2019-04-01T05:02:05Z</published>
|
||||
<updated>2019-04-01T05:02:05Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849165031453009"/>
|
||||
<content type="html" xml:lang="en"><p>You gotta take whatever bellyrubbing opportunity you can get before she changes her mind 🦁 <a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag">#<span>mastocats</span></a></p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<category term="mastocats"/>
|
||||
<link rel="enclosure" type="video/mp4" length="9838915" href="https://files.mastodon.social/media_attachments/files/013/049/816/original/e7831178a5e0d6d4.mp4"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849165031453009"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17851558.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94350309:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101846512530748693</id>
|
||||
<published>2019-03-31T17:47:31Z</published>
|
||||
<updated>2019-03-31T17:47:31Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101846512530748693"/>
|
||||
<content type="html" xml:lang="en"><p>Hello look at this boy having a decent haircut for once <a href="https://mastodon.social/tags/mastohorses" class="mention hashtag" rel="tag">#<span>mastohorses</span></a> <a href="https://mastodon.social/tags/equestrian" class="mention hashtag" rel="tag">#<span>equestrian</span></a></p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<category term="equestrian"/>
|
||||
<category term="mastohorses"/>
|
||||
<link rel="enclosure" type="image/jpeg" length="461632" href="https://files.mastodon.social/media_attachments/files/013/033/387/original/301e8ab668cd61d2.jpeg"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101846512530748693"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17842424.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-31:objectId=94256415:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101846181093805500</id>
|
||||
<published>2019-03-31T16:23:14Z</published>
|
||||
<updated>2019-03-31T16:23:14Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101846181093805500"/>
|
||||
<content type="html" xml:lang="en"><p>Sorry did I disturb the who-is-the-longest-cat competition ? <a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag">#<span>mastocats</span></a></p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<category term="mastocats"/>
|
||||
<link rel="enclosure" type="image/jpeg" length="211384" href="https://files.mastodon.social/media_attachments/files/013/030/725/original/5b4886730cbbd25c.jpeg"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101846181093805500"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17841108.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-31:objectId=94245239:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101845897513133849</id>
|
||||
<published>2019-03-31T15:11:07Z</published>
|
||||
<updated>2019-03-31T15:11:07Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101845897513133849"/>
|
||||
<summary xml:lang="en">more earthsea ramblings</summary>
|
||||
<content type="html" xml:lang="en"><p>I&apos;m re-watching Tales from Earthsea for the first time since I read the books, and that Therru doesn&apos;t squash Cob like a spider, as Orm Embar did is a wasted opportunity tbh</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101845897513133849"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17840088.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-31:objectId=94232455:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101841219051533307</id>
|
||||
<published>2019-03-30T19:21:19Z</published>
|
||||
<updated>2019-03-30T19:21:19Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101841219051533307"/>
|
||||
<content type="html" xml:lang="en"><p>I gave my cats some mackerel and they ate it all in 0.3 seconds, and now they won&apos;t stop meowing for more, and I&apos;m tired plz shut up</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101841219051533307"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17826587.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-30:objectId=94075000:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101839949762341381</id>
|
||||
<published>2019-03-30T13:58:31Z</published>
|
||||
<updated>2019-03-30T13:58:31Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101839949762341381"/>
|
||||
<content type="html" xml:lang="en"><p>yet I&apos;m confused about this american dude with a gun, like the heck r ya doin in mah ghibli</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101839949762341381"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17821757.atom"/>
|
||||
<thr:in-reply-to ref="https://mastodon.social/users/emelie/statuses/101839928677863590" href="https://mastodon.social/@emelie/101839928677863590"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-30:objectId=94026360:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101839928677863590</id>
|
||||
<published>2019-03-30T13:53:09Z</published>
|
||||
<updated>2019-03-30T13:53:09Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101839928677863590"/>
|
||||
<content type="html" xml:lang="en"><p>2 hours into Ni no Kuni 2 and I&apos;ve already sold my soul to this game</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101839928677863590"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17821713.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-30:objectId=94026360:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101836329521599438</id>
|
||||
<published>2019-03-29T22:37:51Z</published>
|
||||
<updated>2019-03-29T22:37:51Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101836329521599438"/>
|
||||
<content type="html" xml:lang="en"><p>Pippi Longstocking the original one-punch /man</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101836329521599438"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17811608.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93907854:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101835905282948341</id>
|
||||
<published>2019-03-29T20:49:57Z</published>
|
||||
<updated>2019-03-29T20:49:57Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835905282948341"/>
|
||||
<content type="html" xml:lang="en"><p>I&apos;ve had so much wine I thought I had a 3rd brother</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835905282948341"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809862.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93892966:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101835878059204660</id>
|
||||
<published>2019-03-29T20:43:02Z</published>
|
||||
<updated>2019-03-29T20:43:02Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835878059204660"/>
|
||||
<content type="html" xml:lang="en"><p>ååååhhh booi</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835878059204660"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809734.atom"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93892010:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101835848050598939</id>
|
||||
<published>2019-03-29T20:35:24Z</published>
|
||||
<updated>2019-03-29T20:35:24Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835848050598939"/>
|
||||
<content type="html" xml:lang="en"><p><span class="h-card"><a href="https://thraeryn.net/@thraeryn" class="u-url mention">@<span>thraeryn</span></a></span> if I spent 1 hour and a half watching this monstrosity, I need to</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://thraeryn.net/users/thraeryn"/>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835848050598939"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809591.atom"/>
|
||||
<thr:in-reply-to ref="https://thraeryn.net/users/thraeryn/statuses/101835839202826007" href="https://thraeryn.net/@thraeryn/101835839202826007"/>
|
||||
<ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93888827:objectType=Conversation"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>https://mastodon.social/users/emelie/statuses/101835823138262290</id>
|
||||
<published>2019-03-29T20:29:04Z</published>
|
||||
<updated>2019-03-29T20:29:04Z</updated>
|
||||
<title>New status by emelie</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835823138262290"/>
|
||||
<summary xml:lang="en">medical, fluids mention</summary>
|
||||
<content type="html" xml:lang="en"><p><span class="h-card"><a href="https://icosahedron.website/@Trev" class="u-url mention">@<span>Trev</span></a></span> *hugs* ✨</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://icosahedron.website/users/Trev"/>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835823138262290"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809468.atom"/>
|
||||
<thr:in-reply-to ref="https://icosahedron.website/users/Trev/statuses/101835812250051801" href="https://icosahedron.website/@Trev/101835812250051801"/>
|
||||
<ostatus:conversation ref="tag:icosahedron.website,2019-03-29:objectId=12220882:objectType=Conversation"/>
|
||||
</entry>
|
||||
</feed>
|
||||
64
test/fixtures/httpoison_mock/status.emelie.json
vendored
Normal file
64
test/fixtures/httpoison_mock/status.emelie.json
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"sensitive": "as:sensitive",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"Emoji": "toot:Emoji",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "https://mastodon.social/users/emelie/statuses/101849165031453009",
|
||||
"type": "Note",
|
||||
"summary": null,
|
||||
"inReplyTo": null,
|
||||
"published": "2019-04-01T05:02:05Z",
|
||||
"url": "https://mastodon.social/@emelie/101849165031453009",
|
||||
"attributedTo": "https://mastodon.social/users/emelie",
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"cc": [
|
||||
"https://mastodon.social/users/emelie/followers"
|
||||
],
|
||||
"sensitive": false,
|
||||
"atomUri": "https://mastodon.social/users/emelie/statuses/101849165031453009",
|
||||
"inReplyToAtomUri": null,
|
||||
"conversation": "tag:mastodon.social,2019-04-01:objectId=94350309:objectType=Conversation",
|
||||
"content": "<p>You gotta take whatever bellyrubbing opportunity you can get before she changes her mind 🦁 <a href=\"https://mastodon.social/tags/mastocats\" class=\"mention hashtag\" rel=\"tag\">#<span>mastocats</span></a></p>",
|
||||
"contentMap": {
|
||||
"en": "<p>You gotta take whatever bellyrubbing opportunity you can get before she changes her mind 🦁 <a href=\"https://mastodon.social/tags/mastocats\" class=\"mention hashtag\" rel=\"tag\">#<span>mastocats</span></a></p>"
|
||||
},
|
||||
"attachment": [
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "video/mp4",
|
||||
"url": "https://files.mastodon.social/media_attachments/files/013/049/816/original/e7831178a5e0d6d4.mp4",
|
||||
"name": null
|
||||
}
|
||||
],
|
||||
"tag": [
|
||||
{
|
||||
"type": "Hashtag",
|
||||
"href": "https://mastodon.social/tags/mastocats",
|
||||
"name": "#mastocats"
|
||||
}
|
||||
],
|
||||
"replies": {
|
||||
"id": "https://mastodon.social/users/emelie/statuses/101849165031453009/replies",
|
||||
"type": "Collection",
|
||||
"first": {
|
||||
"type": "CollectionPage",
|
||||
"partOf": "https://mastodon.social/users/emelie/statuses/101849165031453009/replies",
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
}
|
||||
36
test/fixtures/httpoison_mock/webfinger_emelie.json
vendored
Normal file
36
test/fixtures/httpoison_mock/webfinger_emelie.json
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"aliases": [
|
||||
"https://mastodon.social/@emelie",
|
||||
"https://mastodon.social/users/emelie"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://mastodon.social/@emelie",
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html"
|
||||
},
|
||||
{
|
||||
"href": "https://mastodon.social/users/emelie.atom",
|
||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||
"type": "application/atom+xml"
|
||||
},
|
||||
{
|
||||
"href": "https://mastodon.social/users/emelie",
|
||||
"rel": "self",
|
||||
"type": "application/activity+json"
|
||||
},
|
||||
{
|
||||
"href": "https://mastodon.social/api/salmon/15657",
|
||||
"rel": "salmon"
|
||||
},
|
||||
{
|
||||
"href": "data:application/magic-public-key,RSA.u3CWs1oAJPE3ZJ9sj6Ut_Mu-mTE7MOijsQc8_6c73XVVuhIEomiozJIH7l8a7S1n5SYL4UuiwcubSOi7u1bbGpYnp5TYhN-Cxvq_P80V4_ncNIPSQzS49it7nSLeG5pA21lGPDA44huquES1un6p9gSmbTwngVX9oe4MYuUeh0Z7vijjU13Llz1cRq_ZgPQPgfz-2NJf-VeXnvyDZDYxZPVBBlrMl3VoGbu0M5L8SjY35559KCZ3woIvqRolcoHXfgvJMdPcJgSZVYxlCw3dA95q9jQcn6s87CPSUs7bmYEQCrDVn5m5NER5TzwBmP4cgJl9AaDVWQtRd4jFZNTxlQ==.AQAB",
|
||||
"rel": "magic-public-key"
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://mastodon.social/authorize_interaction?uri={uri}"
|
||||
}
|
||||
],
|
||||
"subject": "acct:emelie@mastodon.social"
|
||||
}
|
||||
64
test/fixtures/lambadalambda.json
vendored
Normal file
64
test/fixtures/lambadalambda.json
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"Emoji": "toot:Emoji",
|
||||
"IdentityProof": "toot:IdentityProof",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "https://mastodon.social/users/lambadalambda",
|
||||
"type": "Person",
|
||||
"following": "https://mastodon.social/users/lambadalambda/following",
|
||||
"followers": "https://mastodon.social/users/lambadalambda/followers",
|
||||
"inbox": "https://mastodon.social/users/lambadalambda/inbox",
|
||||
"outbox": "https://mastodon.social/users/lambadalambda/outbox",
|
||||
"featured": "https://mastodon.social/users/lambadalambda/collections/featured",
|
||||
"preferredUsername": "lambadalambda",
|
||||
"name": "Critical Value",
|
||||
"summary": "\u003cp\u003e\u003c/p\u003e",
|
||||
"url": "https://mastodon.social/@lambadalambda",
|
||||
"manuallyApprovesFollowers": false,
|
||||
"publicKey": {
|
||||
"id": "https://mastodon.social/users/lambadalambda#main-key",
|
||||
"owner": "https://mastodon.social/users/lambadalambda",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"tag": [],
|
||||
"attachment": [],
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://mastodon.social/inbox"
|
||||
},
|
||||
"icon": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/gif",
|
||||
"url": "https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"
|
||||
},
|
||||
"image": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/gif",
|
||||
"url": "https://files.mastodon.social/accounts/headers/000/000/264/original/28b26104f83747d2.gif"
|
||||
}
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ defmodule Pleroma.FormatterTest do
|
|||
end
|
||||
|
||||
test "gives a replacement for user links when the user is using Osada" do
|
||||
mike = User.get_or_fetch("mike@osada.macgirvin.com")
|
||||
{:ok, mike} = User.get_or_fetch("mike@osada.macgirvin.com")
|
||||
|
||||
text = "@mike@osada.macgirvin.com test"
|
||||
|
||||
|
|
@ -245,10 +245,10 @@ defmodule Pleroma.FormatterTest do
|
|||
end
|
||||
|
||||
test "it adds cool emoji" do
|
||||
text = "I love :moominmamma:"
|
||||
text = "I love :firefox:"
|
||||
|
||||
expected_result =
|
||||
"I love <img height=\"32px\" width=\"32px\" alt=\"moominmamma\" title=\"moominmamma\" src=\"/finmoji/128px/moominmamma-128.png\" />"
|
||||
"I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\" />"
|
||||
|
||||
assert Formatter.emojify(text) == expected_result
|
||||
end
|
||||
|
|
@ -263,15 +263,17 @@ defmodule Pleroma.FormatterTest do
|
|||
}
|
||||
|
||||
expected_result =
|
||||
"I love <img height=\"32px\" width=\"32px\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
|
||||
"I love <img class=\"emoji\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
|
||||
|
||||
assert Formatter.emojify(text, custom_emoji) == expected_result
|
||||
end
|
||||
|
||||
test "it returns the emoji used in the text" do
|
||||
text = "I love :moominmamma:"
|
||||
text = "I love :firefox:"
|
||||
|
||||
assert Formatter.get_emoji(text) == [{"moominmamma", "/finmoji/128px/moominmamma-128.png"}]
|
||||
assert Formatter.get_emoji(text) == [
|
||||
{"firefox", "/emoji/Firefox.gif", ["Gif", "Fun"]}
|
||||
]
|
||||
end
|
||||
|
||||
test "it returns a nice empty result when no emojis are present" do
|
||||
|
|
|
|||
22
test/healthcheck_test.exs
Normal file
22
test/healthcheck_test.exs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
defmodule Pleroma.HealthcheckTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Healthcheck
|
||||
|
||||
test "system_info/0" do
|
||||
result = Healthcheck.system_info() |> Map.from_struct()
|
||||
|
||||
assert Map.keys(result) == [:active, :healthy, :idle, :memory_used, :pool_size]
|
||||
end
|
||||
|
||||
describe "check_health/1" do
|
||||
test "pool size equals active connections" do
|
||||
result = Healthcheck.check_health(%Healthcheck{pool_size: 10, active: 10})
|
||||
refute result.healthy
|
||||
end
|
||||
|
||||
test "chech_health/1" do
|
||||
result = Healthcheck.check_health(%Healthcheck{pool_size: 10, active: 9})
|
||||
assert result.healthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -20,6 +20,18 @@ defmodule Pleroma.HTMLTest do
|
|||
<img src="http://example.com/image.jpg" onerror="alert('hacked')">
|
||||
"""
|
||||
|
||||
@html_span_class_sample """
|
||||
<span class="animate-spin">hi</span>
|
||||
"""
|
||||
|
||||
@html_span_microformats_sample """
|
||||
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
@html_span_invalid_microformats_sample """
|
||||
<span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
describe "StripTags scrubber" do
|
||||
test "works as expected" do
|
||||
expected = """
|
||||
|
|
@ -64,6 +76,36 @@ defmodule Pleroma.HTMLTest do
|
|||
|
||||
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||
end
|
||||
|
||||
test "does not allow spans with invalid classes" do
|
||||
expected = """
|
||||
<span>hi</span>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||
end
|
||||
|
||||
test "does allow microformats" do
|
||||
expected = """
|
||||
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@html_span_microformats_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||
end
|
||||
|
||||
test "filters invalid microformats markup" do
|
||||
expected = """
|
||||
<span class="h-card"><a>@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(
|
||||
@html_span_invalid_microformats_sample,
|
||||
Pleroma.HTML.Scrubber.TwitterText
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "default scrubber" do
|
||||
|
|
@ -88,5 +130,34 @@ defmodule Pleroma.HTMLTest do
|
|||
|
||||
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
|
||||
test "does not allow spans with invalid classes" do
|
||||
expected = """
|
||||
<span>hi</span>
|
||||
"""
|
||||
|
||||
assert expected == HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
|
||||
test "does allow microformats" do
|
||||
expected = """
|
||||
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@html_span_microformats_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
|
||||
test "filters invalid microformats markup" do
|
||||
expected = """
|
||||
<span class="h-card"><a>@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(
|
||||
@html_span_invalid_microformats_sample,
|
||||
Pleroma.HTML.Scrubber.Default
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ defmodule Pleroma.MediaProxyTest do
|
|||
import Pleroma.Web.MediaProxy
|
||||
alias Pleroma.Web.MediaProxy.MediaProxyController
|
||||
|
||||
setup do
|
||||
enabled = Pleroma.Config.get([:media_proxy, :enabled])
|
||||
on_exit(fn -> Pleroma.Config.put([:media_proxy, :enabled], enabled) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "when enabled" do
|
||||
setup do
|
||||
enabled = Pleroma.Config.get([:media_proxy, :enabled])
|
||||
|
||||
unless enabled do
|
||||
Pleroma.Config.put([:media_proxy, :enabled], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:media_proxy, :enabled], enabled) end)
|
||||
end
|
||||
|
||||
Pleroma.Config.put([:media_proxy, :enabled], true)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
|
@ -177,4 +177,13 @@ defmodule Pleroma.MediaProxyTest do
|
|||
{:ok, decoded} = decode_url(sig, base64)
|
||||
decoded
|
||||
end
|
||||
|
||||
test "mediaproxy whitelist" do
|
||||
Pleroma.Config.put([:media_proxy, :enabled], true)
|
||||
Pleroma.Config.put([:media_proxy, :whitelist], ["google.com", "feld.me"])
|
||||
url = "https://feld.me/foo.png"
|
||||
|
||||
unencoded = url(url)
|
||||
assert unencoded == url
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,21 +29,102 @@ defmodule Pleroma.NotificationTest do
|
|||
assert notification.activity_id == activity.id
|
||||
assert other_notification.activity_id == activity.id
|
||||
end
|
||||
|
||||
test "it creates a notification for subscribed users" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} = TwitterAPI.create_status(user, %{"status" => "Akariiiin"})
|
||||
{:ok, [notification]} = Notification.create_notifications(status)
|
||||
|
||||
assert notification.user_id == subscriber.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "create_notification" do
|
||||
test "it doesn't create a notification for user if the user blocks the activity author" do
|
||||
activity = insert(:note_activity)
|
||||
author = User.get_by_ap_id(activity.data["actor"])
|
||||
author = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
user = insert(:user)
|
||||
{:ok, user} = User.block(user, author)
|
||||
|
||||
assert nil == Notification.create_notification(activity, user)
|
||||
end
|
||||
|
||||
test "it doesn't create a notificatin for the user if the user mutes the activity author" do
|
||||
muter = insert(:user)
|
||||
muted = insert(:user)
|
||||
{:ok, _} = User.mute(muter, muted)
|
||||
muter = Repo.get(User, muter.id)
|
||||
{:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
|
||||
|
||||
assert nil == Notification.create_notification(activity, muter)
|
||||
end
|
||||
|
||||
test "it doesn't create a notification for an activity from a muted thread" do
|
||||
muter = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
|
||||
CommonAPI.add_mute(muter, activity)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
"status" => "Hi @#{muter.nickname}",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
})
|
||||
|
||||
assert nil == Notification.create_notification(activity, muter)
|
||||
end
|
||||
|
||||
test "it disables notifications from people on remote instances" do
|
||||
user = insert(:user, info: %{notification_settings: %{"remote" => false}})
|
||||
other_user = insert(:user)
|
||||
|
||||
create_activity = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => other_user.ap_id,
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "Hi @#{user.nickname}",
|
||||
"attributedTo" => other_user.ap_id
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{local: false} = activity} = Transmogrifier.handle_incoming(create_activity)
|
||||
assert nil == Notification.create_notification(activity, user)
|
||||
end
|
||||
|
||||
test "it disables notifications from people on the local instance" do
|
||||
user = insert(:user, info: %{notification_settings: %{"local" => false}})
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
|
||||
assert nil == Notification.create_notification(activity, user)
|
||||
end
|
||||
|
||||
test "it disables notifications from followers" do
|
||||
follower = insert(:user)
|
||||
followed = insert(:user, info: %{notification_settings: %{"followers" => false}})
|
||||
User.follow(follower, followed)
|
||||
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
|
||||
assert nil == Notification.create_notification(activity, followed)
|
||||
end
|
||||
|
||||
test "it disables notifications from people the user follows" do
|
||||
follower = insert(:user, info: %{notification_settings: %{"follows" => false}})
|
||||
followed = insert(:user)
|
||||
User.follow(follower, followed)
|
||||
follower = Repo.get(User, follower.id)
|
||||
{:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
|
||||
assert nil == Notification.create_notification(activity, follower)
|
||||
end
|
||||
|
||||
test "it doesn't create a notification for user if he is the activity author" do
|
||||
activity = insert(:note_activity)
|
||||
author = User.get_by_ap_id(activity.data["actor"])
|
||||
author = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
|
||||
assert nil == Notification.create_notification(activity, author)
|
||||
end
|
||||
|
|
@ -84,6 +165,28 @@ defmodule Pleroma.NotificationTest do
|
|||
{:ok, dupe} = TwitterAPI.repeat(user, status.id)
|
||||
assert nil == Notification.create_notification(dupe, retweeted_user)
|
||||
end
|
||||
|
||||
test "it doesn't create duplicate notifications for follow+subscribed users" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = TwitterAPI.follow(subscriber, %{"user_id" => user.id})
|
||||
User.subscribe(subscriber, user)
|
||||
{:ok, status} = TwitterAPI.create_status(user, %{"status" => "Akariiiin"})
|
||||
{:ok, [_notif]} = Notification.create_notifications(status)
|
||||
end
|
||||
|
||||
test "it doesn't create subscription notifications if the recipient cannot see the status" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} =
|
||||
TwitterAPI.create_status(user, %{"status" => "inwisible", "visibility" => "direct"})
|
||||
|
||||
assert {:ok, []} == Notification.create_notifications(status)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get notification" do
|
||||
|
|
|
|||
58
test/object/containment_test.exs
Normal file
58
test/object/containment_test.exs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
defmodule Pleroma.Object.ContainmentTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Object.Containment
|
||||
alias Pleroma.User
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "general origin containment" do
|
||||
test "contain_origin_from_id() catches obvious spoofing attempts" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json"
|
||||
}
|
||||
|
||||
:error =
|
||||
Containment.contain_origin_from_id(
|
||||
"http://example.org/~alyssa/activities/1234.json",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "contain_origin_from_id() allows alternate IDs within the same origin domain" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json"
|
||||
}
|
||||
|
||||
:ok =
|
||||
Containment.contain_origin_from_id(
|
||||
"http://example.com/~alyssa/activities/1234",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "contain_origin_from_id() allows matching IDs" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json"
|
||||
}
|
||||
|
||||
:ok =
|
||||
Containment.contain_origin_from_id(
|
||||
"http://example.com/~alyssa/activities/1234.json",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "users cannot be collided through fake direction spoofing attempts" do
|
||||
_user =
|
||||
insert(:user, %{
|
||||
nickname: "rye@niu.moe",
|
||||
local: false,
|
||||
ap_id: "https://niu.moe/users/rye",
|
||||
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
|
||||
})
|
||||
|
||||
{:error, _} = User.get_or_fetch_by_ap_id("https://n1u.moe/users/rye")
|
||||
end
|
||||
end
|
||||
end
|
||||
90
test/object/fetcher_test.exs
Normal file
90
test/object/fetcher_test.exs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
defmodule Pleroma.Object.FetcherTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
import Tesla.Mock
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "actor origin containment" do
|
||||
test "it rejects objects with a bogus origin" do
|
||||
{:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity.json")
|
||||
end
|
||||
|
||||
test "it rejects objects when attributedTo is wrong (variant 1)" do
|
||||
{:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity2.json")
|
||||
end
|
||||
|
||||
test "it rejects objects when attributedTo is wrong (variant 2)" do
|
||||
{:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity3.json")
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetching an object" do
|
||||
test "it fetches an object" do
|
||||
{:ok, object} =
|
||||
Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
assert activity.data["id"]
|
||||
|
||||
{:ok, object_again} =
|
||||
Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert [attachment] = object.data["attachment"]
|
||||
assert is_list(attachment["url"])
|
||||
|
||||
assert object == object_again
|
||||
end
|
||||
|
||||
test "it works with objects only available via Ostatus" do
|
||||
{:ok, object} = Fetcher.fetch_object_from_id("https://shitposter.club/notice/2827873")
|
||||
assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
assert activity.data["id"]
|
||||
|
||||
{:ok, object_again} = Fetcher.fetch_object_from_id("https://shitposter.club/notice/2827873")
|
||||
|
||||
assert object == object_again
|
||||
end
|
||||
|
||||
test "it correctly stitches up conversations between ostatus and ap" do
|
||||
last = "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
{:ok, object} = Fetcher.fetch_object_from_id(last)
|
||||
|
||||
object = Object.get_by_ap_id(object.data["inReplyTo"])
|
||||
assert object
|
||||
end
|
||||
end
|
||||
|
||||
describe "implementation quirks" do
|
||||
test "it can fetch plume articles" do
|
||||
{:ok, object} =
|
||||
Fetcher.fetch_object_from_id(
|
||||
"https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"
|
||||
)
|
||||
|
||||
assert object
|
||||
end
|
||||
|
||||
test "it can fetch peertube videos" do
|
||||
{:ok, object} =
|
||||
Fetcher.fetch_object_from_id(
|
||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
||||
)
|
||||
|
||||
assert object
|
||||
end
|
||||
|
||||
test "all objects with fake directions are rejected by the object fetcher" do
|
||||
{:error, _} =
|
||||
Fetcher.fetch_and_contain_remote_object_from_id(
|
||||
"https://info.pleroma.site/activity4.json"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,9 +5,15 @@
|
|||
defmodule Pleroma.ObjectTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "returns an object by it's AP id" do
|
||||
object = insert(:note)
|
||||
found_object = Object.get_by_ap_id(object.data["id"])
|
||||
|
|
@ -58,4 +64,26 @@ defmodule Pleroma.ObjectTest do
|
|||
assert cached_object.data["type"] == "Tombstone"
|
||||
end
|
||||
end
|
||||
|
||||
describe "normalizer" do
|
||||
test "fetches unknown objects by default" do
|
||||
%Object{} =
|
||||
object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
|
||||
end
|
||||
|
||||
test "fetches unknown objects when fetch_remote is explicitly true" do
|
||||
%Object{} =
|
||||
object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367", true)
|
||||
|
||||
assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
|
||||
end
|
||||
|
||||
test "does not fetch unknown objects when fetch_remote is false" do
|
||||
assert is_nil(
|
||||
Object.normalize("http://mastodon.example.org/@admin/99541947525187367", false)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -47,16 +47,18 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do
|
|||
|> assign(:auth_user, user)
|
||||
|
||||
conn =
|
||||
with_mock User,
|
||||
reset_password: fn user, %{password: password, password_confirmation: password} ->
|
||||
send(self(), :reset_password)
|
||||
{:ok, user}
|
||||
end do
|
||||
conn
|
||||
|> LegacyAuthenticationPlug.call(%{})
|
||||
with_mocks([
|
||||
{:crypt, [], [crypt: fn _password, password_hash -> password_hash end]},
|
||||
{User, [],
|
||||
[
|
||||
reset_password: fn user, %{password: password, password_confirmation: password} ->
|
||||
{:ok, user}
|
||||
end
|
||||
]}
|
||||
]) do
|
||||
LegacyAuthenticationPlug.call(conn, %{})
|
||||
end
|
||||
|
||||
assert_received :reset_password
|
||||
assert conn.assigns.user == user
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,26 @@ defmodule Pleroma.Plugs.OAuthPlugTest do
|
|||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with valid token(downcase) in url parameters, it assings the user", opts do
|
||||
conn =
|
||||
:get
|
||||
|> build_conn("/?access_token=#{opts[:token]}")
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> fetch_query_params()
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with valid token(downcase) in body parameters, it assigns the user", opts do
|
||||
conn =
|
||||
:post
|
||||
|> build_conn("/api/v1/statuses", access_token: opts[:token], status: "test")
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with invalid token, it not assigns the user", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|
|
|
|||
59
test/registration_test.exs
Normal file
59
test/registration_test.exs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.RegistrationTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Registration
|
||||
alias Pleroma.Repo
|
||||
|
||||
describe "generic changeset" do
|
||||
test "requires :provider, :uid" do
|
||||
registration = build(:registration, provider: nil, uid: nil)
|
||||
|
||||
cs = Registration.changeset(registration, %{})
|
||||
refute cs.valid?
|
||||
|
||||
assert [
|
||||
provider: {"can't be blank", [validation: :required]},
|
||||
uid: {"can't be blank", [validation: :required]}
|
||||
] == cs.errors
|
||||
end
|
||||
|
||||
test "ensures uniqueness of [:provider, :uid]" do
|
||||
registration = insert(:registration)
|
||||
registration2 = build(:registration, provider: registration.provider, uid: registration.uid)
|
||||
|
||||
cs = Registration.changeset(registration2, %{})
|
||||
assert cs.valid?
|
||||
|
||||
assert {:error,
|
||||
%Ecto.Changeset{
|
||||
errors: [
|
||||
uid:
|
||||
{"has already been taken",
|
||||
[constraint: :unique, constraint_name: "registrations_provider_uid_index"]}
|
||||
]
|
||||
}} = Repo.insert(cs)
|
||||
|
||||
# Note: multiple :uid values per [:user_id, :provider] are intentionally allowed
|
||||
cs2 = Registration.changeset(registration2, %{uid: "available.uid"})
|
||||
assert cs2.valid?
|
||||
assert {:ok, _} = Repo.insert(cs2)
|
||||
|
||||
cs3 = Registration.changeset(registration2, %{provider: "provider2"})
|
||||
assert cs3.valid?
|
||||
assert {:ok, _} = Repo.insert(cs3)
|
||||
end
|
||||
|
||||
test "allows `nil` :user_id (user-unbound registration)" do
|
||||
registration = build(:registration, user_id: nil)
|
||||
cs = Registration.changeset(registration, %{})
|
||||
assert cs.valid?
|
||||
assert {:ok, _} = Repo.insert(cs)
|
||||
end
|
||||
end
|
||||
end
|
||||
64
test/scheduled_activity_test.exs
Normal file
64
test/scheduled_activity_test.exs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ScheduledActivityTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.DataCase
|
||||
alias Pleroma.ScheduledActivity
|
||||
import Pleroma.Factory
|
||||
|
||||
setup context do
|
||||
DataCase.ensure_local_uploader(context)
|
||||
end
|
||||
|
||||
describe "creation" do
|
||||
test "when daily user limit is exceeded" do
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(6), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
attrs = %{params: %{}, scheduled_at: today}
|
||||
{:ok, _} = ScheduledActivity.create(user, attrs)
|
||||
{:ok, _} = ScheduledActivity.create(user, attrs)
|
||||
{:error, changeset} = ScheduledActivity.create(user, attrs)
|
||||
assert changeset.errors == [scheduled_at: {"daily limit exceeded", []}]
|
||||
end
|
||||
|
||||
test "when total user limit is exceeded" do
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(6), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
tomorrow =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.hours(36), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
{:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: today})
|
||||
{:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: today})
|
||||
{:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
|
||||
{:error, changeset} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
|
||||
assert changeset.errors == [scheduled_at: {"total limit exceeded", []}]
|
||||
end
|
||||
|
||||
test "when scheduled_at is earlier than 5 minute from now" do
|
||||
user = insert(:user)
|
||||
|
||||
scheduled_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(4), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
attrs = %{params: %{}, scheduled_at: scheduled_at}
|
||||
{:error, changeset} = ScheduledActivity.create(user, attrs)
|
||||
assert changeset.errors == [scheduled_at: {"must be at least 5 minutes from now", []}]
|
||||
end
|
||||
end
|
||||
end
|
||||
19
test/scheduled_activity_worker_test.exs
Normal file
19
test/scheduled_activity_worker_test.exs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ScheduledActivityWorkerTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.ScheduledActivity
|
||||
import Pleroma.Factory
|
||||
|
||||
test "creates a status from the scheduled activity" do
|
||||
user = insert(:user)
|
||||
scheduled_activity = insert(:scheduled_activity, user: user, params: %{status: "hi"})
|
||||
Pleroma.ScheduledActivityWorker.perform(:execute, scheduled_activity.id)
|
||||
|
||||
refute Repo.get(ScheduledActivity, scheduled_activity.id)
|
||||
activity = Repo.all(Pleroma.Activity) |> Enum.find(&(&1.actor == user.ap_id))
|
||||
assert Pleroma.Object.normalize(activity).data["content"] == "hi"
|
||||
end
|
||||
end
|
||||
|
|
@ -216,7 +216,7 @@ defmodule Pleroma.Factory do
|
|||
redirect_uris: "https://example.com/callback",
|
||||
scopes: ["read", "write", "follow", "push"],
|
||||
website: "https://example.com",
|
||||
client_id: "aaabbb==",
|
||||
client_id: Ecto.UUID.generate(),
|
||||
client_secret: "aaa;/&bbb"
|
||||
}
|
||||
end
|
||||
|
|
@ -240,6 +240,16 @@ defmodule Pleroma.Factory do
|
|||
}
|
||||
end
|
||||
|
||||
def oauth_authorization_factory do
|
||||
%Pleroma.Web.OAuth.Authorization{
|
||||
token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false),
|
||||
scopes: ["read", "write", "follow", "push"],
|
||||
valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10),
|
||||
user: build(:user),
|
||||
app: build(:oauth_app)
|
||||
}
|
||||
end
|
||||
|
||||
def push_subscription_factory do
|
||||
%Pleroma.Web.Push.Subscription{
|
||||
user: build(:user),
|
||||
|
|
@ -257,4 +267,28 @@ defmodule Pleroma.Factory do
|
|||
user: build(:user)
|
||||
}
|
||||
end
|
||||
|
||||
def scheduled_activity_factory do
|
||||
%Pleroma.ScheduledActivity{
|
||||
user: build(:user),
|
||||
scheduled_at: NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(60), :millisecond),
|
||||
params: build(:note) |> Map.from_struct() |> Map.get(:data)
|
||||
}
|
||||
end
|
||||
|
||||
def registration_factory do
|
||||
user = insert(:user)
|
||||
|
||||
%Pleroma.Registration{
|
||||
user: user,
|
||||
provider: "twitter",
|
||||
uid: "171799000",
|
||||
info: %{
|
||||
"name" => "John Doe",
|
||||
"email" => "john@doe.com",
|
||||
"nickname" => "johndoe",
|
||||
"description" => "My bio"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,6 +36,43 @@ defmodule HttpRequestMock do
|
|||
}}
|
||||
end
|
||||
|
||||
def get("https://mastodon.social/users/emelie/statuses/101849165031453009", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/httpoison_mock/status.emelie.json")
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://mastodon.social/users/emelie", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/httpoison_mock/emelie.json")
|
||||
}}
|
||||
end
|
||||
|
||||
def get(
|
||||
"https://mastodon.social/.well-known/webfinger?resource=https://mastodon.social/users/emelie",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/httpoison_mock/webfinger_emelie.json")
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://mastodon.social/users/emelie.atom", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/httpoison_mock/emelie.atom")
|
||||
}}
|
||||
end
|
||||
|
||||
def get(
|
||||
"https://osada.macgirvin.com/.well-known/webfinger?resource=acct:mike@osada.macgirvin.com",
|
||||
_,
|
||||
|
|
@ -679,6 +716,10 @@ defmodule HttpRequestMock do
|
|||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/lambadalambda.atom")}}
|
||||
end
|
||||
|
||||
def get("https://mastodon.social/users/lambadalambda", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/lambadalambda.json")}}
|
||||
end
|
||||
|
||||
def get("https://social.heldscal.la/user/23211", _, _, Accept: "application/activity+json") do
|
||||
{:ok, Tesla.Mock.json(%{"id" => "https://social.heldscal.la/user/23211"}, status: 200)}
|
||||
end
|
||||
|
|
|
|||
62
test/tasks/instance.exs
Normal file
62
test/tasks/instance.exs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
defmodule Pleroma.InstanceTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
setup do
|
||||
File.mkdir_p!(tmp_path())
|
||||
on_exit(fn -> File.rm_rf(tmp_path()) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
defp tmp_path do
|
||||
"/tmp/generated_files/"
|
||||
end
|
||||
|
||||
test "running gen" do
|
||||
mix_task = fn ->
|
||||
Mix.Tasks.Pleroma.Instance.run([
|
||||
"gen",
|
||||
"--output",
|
||||
tmp_path() <> "generated_config.exs",
|
||||
"--output-psql",
|
||||
tmp_path() <> "setup.psql",
|
||||
"--domain",
|
||||
"test.pleroma.social",
|
||||
"--instance-name",
|
||||
"Pleroma",
|
||||
"--admin-email",
|
||||
"admin@example.com",
|
||||
"--notify-email",
|
||||
"notify@example.com",
|
||||
"--dbhost",
|
||||
"dbhost",
|
||||
"--dbname",
|
||||
"dbname",
|
||||
"--dbuser",
|
||||
"dbuser",
|
||||
"--dbpass",
|
||||
"dbpass",
|
||||
"--indexable",
|
||||
"y"
|
||||
])
|
||||
end
|
||||
|
||||
ExUnit.CaptureIO.capture_io(fn ->
|
||||
mix_task.()
|
||||
end)
|
||||
|
||||
generated_config = File.read!(tmp_path() <> "generated_config.exs")
|
||||
assert generated_config =~ "host: \"test.pleroma.social\""
|
||||
assert generated_config =~ "name: \"Pleroma\""
|
||||
assert generated_config =~ "email: \"admin@example.com\""
|
||||
assert generated_config =~ "notify_email: \"notify@example.com\""
|
||||
assert generated_config =~ "hostname: \"dbhost\""
|
||||
assert generated_config =~ "database: \"dbname\""
|
||||
assert generated_config =~ "username: \"dbuser\""
|
||||
assert generated_config =~ "password: \"dbpass\""
|
||||
assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql()
|
||||
end
|
||||
|
||||
defp generated_setup_psql do
|
||||
~s(CREATE USER dbuser WITH ENCRYPTED PASSWORD 'dbpass';\nCREATE DATABASE dbname OWNER dbuser;\n\\c dbname;\n--Extensions made by ecto.migrate that need superuser access\nCREATE EXTENSION IF NOT EXISTS citext;\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\nCREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";\n)
|
||||
end
|
||||
end
|
||||
|
|
@ -31,7 +31,7 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
|
|||
local_user = Relay.get_actor()
|
||||
assert local_user.ap_id =~ "/relay"
|
||||
|
||||
target_user = User.get_by_ap_id(target_instance)
|
||||
target_user = User.get_cached_by_ap_id(target_instance)
|
||||
refute target_user.local
|
||||
|
||||
activity = Utils.fetch_latest_follow(local_user, target_user)
|
||||
|
|
@ -48,7 +48,7 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
|
|||
Mix.Tasks.Pleroma.Relay.run(["follow", target_instance])
|
||||
|
||||
%User{ap_id: follower_id} = local_user = Relay.get_actor()
|
||||
target_user = User.get_by_ap_id(target_instance)
|
||||
target_user = User.get_cached_by_ap_id(target_instance)
|
||||
follow_activity = Utils.fetch_latest_follow(local_user, target_user)
|
||||
|
||||
Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance])
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "created"
|
||||
|
||||
user = User.get_by_nickname(unsaved.nickname)
|
||||
user = User.get_cached_by_nickname(unsaved.nickname)
|
||||
assert user.name == unsaved.name
|
||||
assert user.email == unsaved.email
|
||||
assert user.bio == unsaved.bio
|
||||
|
|
@ -75,7 +75,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "will not be created"
|
||||
|
||||
refute User.get_by_nickname(unsaved.nickname)
|
||||
refute User.get_cached_by_nickname(unsaved.nickname)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ " deleted"
|
||||
|
||||
user = User.get_by_nickname(user.nickname)
|
||||
user = User.get_cached_by_nickname(user.nickname)
|
||||
assert user.info.deactivated
|
||||
end
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ " deactivated"
|
||||
|
||||
user = User.get_by_nickname(user.nickname)
|
||||
user = User.get_cached_by_nickname(user.nickname)
|
||||
assert user.info.deactivated
|
||||
end
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ " activated"
|
||||
|
||||
user = User.get_by_nickname(user.nickname)
|
||||
user = User.get_cached_by_nickname(user.nickname)
|
||||
refute user.info.deactivated
|
||||
end
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "Successfully unsubscribed"
|
||||
|
||||
user = User.get_by_nickname(user.nickname)
|
||||
user = User.get_cached_by_nickname(user.nickname)
|
||||
assert Enum.empty?(user.following)
|
||||
assert user.info.deactivated
|
||||
end
|
||||
|
|
@ -178,7 +178,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ ~r/Admin status .* true/
|
||||
|
||||
user = User.get_by_nickname(user.nickname)
|
||||
user = User.get_cached_by_nickname(user.nickname)
|
||||
assert user.info.is_moderator
|
||||
assert user.info.locked
|
||||
assert user.info.is_admin
|
||||
|
|
@ -204,7 +204,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ ~r/Admin status .* false/
|
||||
|
||||
user = User.get_by_nickname(user.nickname)
|
||||
user = User.get_cached_by_nickname(user.nickname)
|
||||
refute user.info.is_moderator
|
||||
refute user.info.locked
|
||||
refute user.info.is_admin
|
||||
|
|
@ -245,7 +245,97 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
end) =~ "http"
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "Generated"
|
||||
assert message =~ "Generated user invite token one time"
|
||||
end
|
||||
|
||||
test "token is generated with expires_at" do
|
||||
assert capture_io(fn ->
|
||||
Mix.Tasks.Pleroma.User.run([
|
||||
"invite",
|
||||
"--expires-at",
|
||||
Date.to_string(Date.utc_today())
|
||||
])
|
||||
end)
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "Generated user invite token date limited"
|
||||
end
|
||||
|
||||
test "token is generated with max use" do
|
||||
assert capture_io(fn ->
|
||||
Mix.Tasks.Pleroma.User.run([
|
||||
"invite",
|
||||
"--max-use",
|
||||
"5"
|
||||
])
|
||||
end)
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "Generated user invite token reusable"
|
||||
end
|
||||
|
||||
test "token is generated with max use and expires date" do
|
||||
assert capture_io(fn ->
|
||||
Mix.Tasks.Pleroma.User.run([
|
||||
"invite",
|
||||
"--max-use",
|
||||
"5",
|
||||
"--expires-at",
|
||||
Date.to_string(Date.utc_today())
|
||||
])
|
||||
end)
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "Generated user invite token reusable date limited"
|
||||
end
|
||||
end
|
||||
|
||||
describe "running invites" do
|
||||
test "invites are listed" do
|
||||
{:ok, invite} = Pleroma.UserInviteToken.create_invite()
|
||||
|
||||
{:ok, invite2} =
|
||||
Pleroma.UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 15})
|
||||
|
||||
# assert capture_io(fn ->
|
||||
Mix.Tasks.Pleroma.User.run([
|
||||
"invites"
|
||||
])
|
||||
|
||||
# end)
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert_received {:mix_shell, :info, [message2]}
|
||||
assert_received {:mix_shell, :info, [message3]}
|
||||
assert message =~ "Invites list:"
|
||||
assert message2 =~ invite.invite_type
|
||||
assert message3 =~ invite2.invite_type
|
||||
end
|
||||
end
|
||||
|
||||
describe "running revoke_invite" do
|
||||
test "invite is revoked" do
|
||||
{:ok, invite} = Pleroma.UserInviteToken.create_invite(%{expires_at: Date.utc_today()})
|
||||
|
||||
assert capture_io(fn ->
|
||||
Mix.Tasks.Pleroma.User.run([
|
||||
"revoke_invite",
|
||||
invite.token
|
||||
])
|
||||
end)
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ "Invite for token #{invite.token} was revoked."
|
||||
end
|
||||
end
|
||||
|
||||
describe "running delete_activities" do
|
||||
test "activities are deleted" do
|
||||
%{nickname: nickname} = insert(:user)
|
||||
|
||||
assert :ok == Mix.Tasks.Pleroma.User.run(["delete_activities", nickname])
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message == "User #{nickname} statuses deleted."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
96
test/user_invite_token_test.exs
Normal file
96
test/user_invite_token_test.exs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
defmodule Pleroma.UserInviteTokenTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.UserInviteToken
|
||||
|
||||
describe "valid_invite?/1 one time invites" do
|
||||
setup do
|
||||
invite = %UserInviteToken{invite_type: "one_time"}
|
||||
|
||||
{:ok, invite: invite}
|
||||
end
|
||||
|
||||
test "not used returns true", %{invite: invite} do
|
||||
invite = %{invite | used: false}
|
||||
assert UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
|
||||
test "used returns false", %{invite: invite} do
|
||||
invite = %{invite | used: true}
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
end
|
||||
|
||||
describe "valid_invite?/1 reusable invites" do
|
||||
setup do
|
||||
invite = %UserInviteToken{
|
||||
invite_type: "reusable",
|
||||
max_use: 5
|
||||
}
|
||||
|
||||
{:ok, invite: invite}
|
||||
end
|
||||
|
||||
test "with less uses then max use returns true", %{invite: invite} do
|
||||
invite = %{invite | uses: 4}
|
||||
assert UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
|
||||
test "with equal or more uses then max use returns false", %{invite: invite} do
|
||||
invite = %{invite | uses: 5}
|
||||
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
|
||||
invite = %{invite | uses: 6}
|
||||
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
end
|
||||
|
||||
describe "valid_token?/1 date limited invites" do
|
||||
setup do
|
||||
invite = %UserInviteToken{invite_type: "date_limited"}
|
||||
{:ok, invite: invite}
|
||||
end
|
||||
|
||||
test "expires today returns true", %{invite: invite} do
|
||||
invite = %{invite | expires_at: Date.utc_today()}
|
||||
assert UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
|
||||
test "expires yesterday returns false", %{invite: invite} do
|
||||
invite = %{invite | expires_at: Date.add(Date.utc_today(), -1)}
|
||||
invite = Repo.insert!(invite)
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
end
|
||||
|
||||
describe "valid_token?/1 reusable date limited invites" do
|
||||
setup do
|
||||
invite = %UserInviteToken{invite_type: "reusable_date_limited", max_use: 5}
|
||||
{:ok, invite: invite}
|
||||
end
|
||||
|
||||
test "not overdue date and less uses returns true", %{invite: invite} do
|
||||
invite = %{invite | expires_at: Date.utc_today(), uses: 4}
|
||||
assert UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
|
||||
test "overdue date and less uses returns false", %{invite: invite} do
|
||||
invite = %{invite | expires_at: Date.add(Date.utc_today(), -1)}
|
||||
invite = Repo.insert!(invite)
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
|
||||
test "not overdue date with more uses returns false", %{invite: invite} do
|
||||
invite = %{invite | expires_at: Date.utc_today(), uses: 5}
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
|
||||
test "overdue date with more uses returns false", %{invite: invite} do
|
||||
invite = %{invite | expires_at: Date.add(Date.utc_today(), -1), uses: 5}
|
||||
invite = Repo.insert!(invite)
|
||||
refute UserInviteToken.valid_invite?(invite)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.UserTest do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Builders.UserBuilder
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
|
@ -122,9 +123,9 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
{:ok, user} = User.follow(user, followed)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
followed = User.get_by_ap_id(followed.ap_id)
|
||||
followed = User.get_cached_by_ap_id(followed.ap_id)
|
||||
assert followed.info.follower_count == 1
|
||||
|
||||
assert User.ap_followers(followed) in user.following
|
||||
|
|
@ -146,6 +147,15 @@ defmodule Pleroma.UserTest do
|
|||
{:error, _} = User.follow(blockee, blocker)
|
||||
end
|
||||
|
||||
test "can't subscribe to a user who blocked us" do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blocked)
|
||||
|
||||
{:error, _} = User.subscribe(blocked, blocker)
|
||||
end
|
||||
|
||||
test "local users do not automatically follow local locked accounts" do
|
||||
follower = insert(:user, info: %{locked: true})
|
||||
followed = insert(:user, info: %{locked: true})
|
||||
|
|
@ -178,7 +188,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
{:ok, user, _activity} = User.unfollow(user, followed)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert user.following == []
|
||||
end
|
||||
|
|
@ -188,7 +198,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
{:error, _} = User.unfollow(user, user)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.following == [user.ap_id]
|
||||
end
|
||||
|
||||
|
|
@ -200,6 +210,13 @@ defmodule Pleroma.UserTest do
|
|||
refute User.following?(followed, user)
|
||||
end
|
||||
|
||||
test "fetches correct profile for nickname beginning with number" do
|
||||
# Use old-style integer ID to try to reproduce the problem
|
||||
user = insert(:user, %{id: 1080})
|
||||
userwithnumbers = insert(:user, %{nickname: "#{user.id}garbage"})
|
||||
assert userwithnumbers == User.get_cached_by_nickname_or_id(userwithnumbers.nickname)
|
||||
end
|
||||
|
||||
describe "user registration" do
|
||||
@full_user_data %{
|
||||
bio: "A guy",
|
||||
|
|
@ -240,7 +257,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
activity = Repo.one(Pleroma.Activity)
|
||||
assert registered_user.ap_id in activity.recipients
|
||||
assert activity.data["object"]["content"] =~ "cool site"
|
||||
assert Object.normalize(activity).data["content"] =~ "cool site"
|
||||
assert activity.actor == welcome_user.ap_id
|
||||
|
||||
Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
|
||||
|
|
@ -345,7 +362,7 @@ defmodule Pleroma.UserTest do
|
|||
describe "get_or_fetch/1" do
|
||||
test "gets an existing user by nickname" do
|
||||
user = insert(:user)
|
||||
fetched_user = User.get_or_fetch(user.nickname)
|
||||
{:ok, fetched_user} = User.get_or_fetch(user.nickname)
|
||||
|
||||
assert user == fetched_user
|
||||
end
|
||||
|
|
@ -362,7 +379,7 @@ defmodule Pleroma.UserTest do
|
|||
info: %{}
|
||||
)
|
||||
|
||||
fetched_user = User.get_or_fetch(ap_id)
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
freshed_user = refresh_record(user)
|
||||
assert freshed_user == fetched_user
|
||||
end
|
||||
|
|
@ -371,14 +388,14 @@ defmodule Pleroma.UserTest do
|
|||
describe "fetching a user from nickname or trying to build one" do
|
||||
test "gets an existing user" do
|
||||
user = insert(:user)
|
||||
fetched_user = User.get_or_fetch_by_nickname(user.nickname)
|
||||
{:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
|
||||
|
||||
assert user == fetched_user
|
||||
end
|
||||
|
||||
test "gets an existing user, case insensitive" do
|
||||
user = insert(:user, nickname: "nick")
|
||||
fetched_user = User.get_or_fetch_by_nickname("NICK")
|
||||
{:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
|
||||
|
||||
assert user == fetched_user
|
||||
end
|
||||
|
|
@ -386,7 +403,7 @@ defmodule Pleroma.UserTest do
|
|||
test "gets an existing user by fully qualified nickname" do
|
||||
user = insert(:user)
|
||||
|
||||
fetched_user =
|
||||
{:ok, fetched_user} =
|
||||
User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
|
||||
|
||||
assert user == fetched_user
|
||||
|
|
@ -396,24 +413,24 @@ defmodule Pleroma.UserTest do
|
|||
user = insert(:user, nickname: "nick")
|
||||
casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
|
||||
|
||||
fetched_user = User.get_or_fetch_by_nickname(casing_altered_fqn)
|
||||
{:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
|
||||
|
||||
assert user == fetched_user
|
||||
end
|
||||
|
||||
test "fetches an external user via ostatus if no user exists" do
|
||||
fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
|
||||
{:ok, fetched_user} = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
|
||||
assert fetched_user.nickname == "shp@social.heldscal.la"
|
||||
end
|
||||
|
||||
test "returns nil if no user could be fetched" do
|
||||
fetched_user = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
|
||||
assert fetched_user == nil
|
||||
{:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
|
||||
assert fetched_user == "not found nonexistant@social.heldscal.la"
|
||||
end
|
||||
|
||||
test "returns nil for nonexistant local user" do
|
||||
fetched_user = User.get_or_fetch_by_nickname("nonexistant")
|
||||
assert fetched_user == nil
|
||||
{:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
|
||||
assert fetched_user == "not found nonexistant"
|
||||
end
|
||||
|
||||
test "updates an existing user, if stale" do
|
||||
|
|
@ -431,7 +448,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
assert orig_user.last_refreshed_at == a_week_ago
|
||||
|
||||
user = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
{:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
assert user.info.source_data["endpoints"]
|
||||
|
||||
refute user.last_refreshed_at == orig_user.last_refreshed_at
|
||||
|
|
@ -539,8 +556,8 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
{:ok, res} = User.get_friends(user)
|
||||
|
||||
followed_one = User.get_by_ap_id(followed_one.ap_id)
|
||||
followed_two = User.get_by_ap_id(followed_two.ap_id)
|
||||
followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
|
||||
followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
|
||||
assert Enum.member?(res, followed_one)
|
||||
assert Enum.member?(res, followed_two)
|
||||
refute Enum.member?(res, not_followed)
|
||||
|
|
@ -551,7 +568,7 @@ defmodule Pleroma.UserTest do
|
|||
test "it sets the info->note_count property" do
|
||||
note = insert(:note)
|
||||
|
||||
user = User.get_by_ap_id(note.data["actor"])
|
||||
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
assert user.info.note_count == 0
|
||||
|
||||
|
|
@ -562,7 +579,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
test "it increases the info->note_count property" do
|
||||
note = insert(:note)
|
||||
user = User.get_by_ap_id(note.data["actor"])
|
||||
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
assert user.info.note_count == 0
|
||||
|
||||
|
|
@ -577,7 +594,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
test "it decreases the info->note_count property" do
|
||||
note = insert(:note)
|
||||
user = User.get_by_ap_id(note.data["actor"])
|
||||
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
assert user.info.note_count == 0
|
||||
|
||||
|
|
@ -679,7 +696,7 @@ defmodule Pleroma.UserTest do
|
|||
assert User.following?(blocked, blocker)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blocked)
|
||||
blocked = Repo.get(User, blocked.id)
|
||||
blocked = User.get_cached_by_id(blocked.id)
|
||||
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
||||
|
|
@ -697,7 +714,7 @@ defmodule Pleroma.UserTest do
|
|||
refute User.following?(blocked, blocker)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blocked)
|
||||
blocked = Repo.get(User, blocked.id)
|
||||
blocked = User.get_cached_by_id(blocked.id)
|
||||
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
||||
|
|
@ -715,13 +732,29 @@ defmodule Pleroma.UserTest do
|
|||
assert User.following?(blocked, blocker)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blocked)
|
||||
blocked = Repo.get(User, blocked.id)
|
||||
blocked = User.get_cached_by_id(blocked.id)
|
||||
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
||||
refute User.following?(blocker, blocked)
|
||||
refute User.following?(blocked, blocker)
|
||||
end
|
||||
|
||||
test "blocks tear down blocked->blocker subscription relationships" do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
|
||||
{:ok, blocker} = User.subscribe(blocked, blocker)
|
||||
|
||||
assert User.subscribed_to?(blocked, blocker)
|
||||
refute User.subscribed_to?(blocker, blocked)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blocked)
|
||||
|
||||
assert User.blocks?(blocker, blocked)
|
||||
refute User.subscribed_to?(blocker, blocked)
|
||||
refute User.subscribed_to?(blocked, blocker)
|
||||
end
|
||||
end
|
||||
|
||||
describe "domain blocking" do
|
||||
|
|
@ -792,6 +825,16 @@ defmodule Pleroma.UserTest do
|
|||
assert false == user.info.deactivated
|
||||
end
|
||||
|
||||
test ".delete_user_activities deletes all create activities" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
|
||||
{:ok, _} = User.delete_user_activities(user)
|
||||
|
||||
# TODO: Remove favorites, repeats, delete activities.
|
||||
refute Activity.get_by_id(activity.id)
|
||||
end
|
||||
|
||||
test ".delete deactivates a user, all follow relationships and all create activities" do
|
||||
user = insert(:user)
|
||||
followed = insert(:user)
|
||||
|
|
@ -809,9 +852,9 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
{:ok, _} = User.delete(user)
|
||||
|
||||
followed = Repo.get(User, followed.id)
|
||||
follower = Repo.get(User, follower.id)
|
||||
user = Repo.get(User, user.id)
|
||||
followed = User.get_cached_by_id(followed.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert user.info.deactivated
|
||||
|
||||
|
|
@ -820,7 +863,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
# TODO: Remove favorites, repeats, delete activities.
|
||||
|
||||
refute Repo.get(Activity, activity.id)
|
||||
refute Activity.get_by_id(activity.id)
|
||||
end
|
||||
|
||||
test "get_public_key_for_ap_id fetches a user that's not in the db" do
|
||||
|
|
@ -965,7 +1008,7 @@ defmodule Pleroma.UserTest do
|
|||
results = User.search("http://mastodon.example.org/users/admin", resolve: true)
|
||||
result = results |> List.first()
|
||||
|
||||
user = User.get_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
user = User.get_cached_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
|
||||
assert length(results) == 1
|
||||
assert user == result |> Map.put(:search_rank, nil) |> Map.put(:search_type, nil)
|
||||
|
|
@ -1060,7 +1103,7 @@ defmodule Pleroma.UserTest do
|
|||
expected_text =
|
||||
"A.k.a. <span class='h-card'><a data-user='#{remote_user.id}' class='u-url mention' href='#{
|
||||
remote_user.ap_id
|
||||
}'>" <> "@<span>nick@domain.com</span></a></span>"
|
||||
}'>@<span>nick@domain.com</span></a></span>"
|
||||
|
||||
assert expected_text == User.parse_bio(bio, user)
|
||||
end
|
||||
|
|
@ -1082,30 +1125,20 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "bookmarks" do
|
||||
test "follower count is updated when a follower is blocked" do
|
||||
user = insert(:user)
|
||||
follower = insert(:user)
|
||||
follower2 = insert(:user)
|
||||
follower3 = insert(:user)
|
||||
|
||||
{:ok, activity1} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "heweoo!"
|
||||
})
|
||||
{:ok, follower} = Pleroma.User.follow(follower, user)
|
||||
{:ok, _follower2} = Pleroma.User.follow(follower2, user)
|
||||
{:ok, _follower3} = Pleroma.User.follow(follower3, user)
|
||||
|
||||
id1 = activity1.data["object"]["id"]
|
||||
{:ok, _} = Pleroma.User.block(user, follower)
|
||||
|
||||
{:ok, activity2} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "heweoo!"
|
||||
})
|
||||
user_show = Pleroma.Web.TwitterAPI.UserView.render("show.json", %{user: user})
|
||||
|
||||
id2 = activity2.data["object"]["id"]
|
||||
|
||||
assert {:ok, user_state1} = User.bookmark(user, id1)
|
||||
assert user_state1.bookmarks == [id1]
|
||||
|
||||
assert {:ok, user_state2} = User.unbookmark(user, id1)
|
||||
assert user_state2.bookmarks == []
|
||||
|
||||
assert {:ok, user_state3} = User.bookmark(user, id2)
|
||||
assert user_state3.bookmarks == [id2]
|
||||
assert Map.get(user_show, "followers_count") == 2
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
alias Pleroma.Activity
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.ActivityPub.UserView
|
||||
|
|
@ -51,7 +50,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|> put_req_header("accept", "application/json")
|
||||
|> get("/users/#{user.nickname}")
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
|
||||
end
|
||||
|
|
@ -66,7 +65,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|> put_req_header("accept", "application/activity+json")
|
||||
|> get("/users/#{user.nickname}")
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
|
||||
end
|
||||
|
|
@ -84,7 +83,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
)
|
||||
|> get("/users/#{user.nickname}")
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
|
||||
end
|
||||
|
|
@ -254,6 +253,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
test "it accepts messages from actors that are followed by the user", %{conn: conn} do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user, %{ap_id: "http://mastodon.example.org/users/actor"})
|
||||
|
||||
{:ok, recipient} = User.follow(recipient, actor)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("attributedTo", actor.ap_id)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("actor", actor.ap_id)
|
||||
|> Map.put("object", object)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{recipient.nickname}/inbox", data)
|
||||
|
||||
assert "ok" == json_response(conn, 200)
|
||||
:timer.sleep(500)
|
||||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
test "it rejects reads from other users", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
otheruser = insert(:user)
|
||||
|
|
@ -543,7 +572,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
user = insert(:user)
|
||||
|
||||
Enum.each(1..15, fn _ ->
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = insert(:user)
|
||||
User.follow(user, other_user)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -84,17 +84,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, status_two} = CommonAPI.post(user, %{"status" => ". #essais"})
|
||||
{:ok, status_three} = CommonAPI.post(user, %{"status" => ". #test #reject"})
|
||||
|
||||
fetch_one = ActivityPub.fetch_activities([], %{"tag" => "test"})
|
||||
fetch_two = ActivityPub.fetch_activities([], %{"tag" => ["test", "essais"]})
|
||||
fetch_one = ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => "test"})
|
||||
|
||||
fetch_two =
|
||||
ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => ["test", "essais"]})
|
||||
|
||||
fetch_three =
|
||||
ActivityPub.fetch_activities([], %{
|
||||
"type" => "Create",
|
||||
"tag" => ["test", "essais"],
|
||||
"tag_reject" => ["reject"]
|
||||
})
|
||||
|
||||
fetch_four =
|
||||
ActivityPub.fetch_activities([], %{
|
||||
"type" => "Create",
|
||||
"tag" => ["test"],
|
||||
"tag_all" => ["test", "reject"]
|
||||
})
|
||||
|
|
@ -192,8 +196,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
}
|
||||
|
||||
{:ok, %Activity{} = activity} = ActivityPub.insert(data)
|
||||
assert is_binary(activity.data["object"]["id"])
|
||||
assert %Object{} = Object.get_by_ap_id(activity.data["object"]["id"])
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert is_binary(object.data["id"])
|
||||
assert %Object{} = Object.get_by_ap_id(activity.data["object"])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -206,7 +212,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
to: ["user1", "user1", "user2"],
|
||||
actor: user,
|
||||
context: "",
|
||||
object: %{}
|
||||
object: %{
|
||||
"to" => ["user1", "user1", "user2"],
|
||||
"type" => "Note",
|
||||
"content" => "testing"
|
||||
}
|
||||
})
|
||||
|
||||
assert activity.data["to"] == ["user1", "user2"]
|
||||
|
|
@ -218,18 +228,30 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
user = insert(:user)
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "1", "visibility" => "public"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "1",
|
||||
"visibility" => "public"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "2", "visibility" => "unlisted"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "2",
|
||||
"visibility" => "unlisted"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "2", "visibility" => "private"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "2",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "3", "visibility" => "direct"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "3",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.info.note_count == 2
|
||||
end
|
||||
|
||||
|
|
@ -244,25 +266,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
# public
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 1
|
||||
assert object.data["repliesCount"] == 1
|
||||
|
||||
# unlisted
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 2
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
# private
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 2
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
# direct
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 2
|
||||
assert object.data["repliesCount"] == 2
|
||||
end
|
||||
end
|
||||
|
|
@ -322,7 +340,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, user} = User.block(user, %{ap_id: activity_three.data["actor"]})
|
||||
{:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
|
||||
%Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
|
||||
activity_three = Repo.get(Activity, activity_three.id)
|
||||
activity_three = Activity.get_by_id(activity_three.id)
|
||||
|
||||
activities =
|
||||
ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
|
||||
|
|
@ -341,6 +359,51 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert Enum.member?(activities, activity_one)
|
||||
end
|
||||
|
||||
test "doesn't return transitive interactions concerning blocked users" do
|
||||
blocker = insert(:user)
|
||||
blockee = insert(:user)
|
||||
friend = insert(:user)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blockee)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
|
||||
|
||||
{:ok, activity_two} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"})
|
||||
|
||||
{:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
|
||||
|
||||
{:ok, activity_four} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"})
|
||||
|
||||
activities = ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
|
||||
|
||||
assert Enum.member?(activities, activity_one)
|
||||
refute Enum.member?(activities, activity_two)
|
||||
refute Enum.member?(activities, activity_three)
|
||||
refute Enum.member?(activities, activity_four)
|
||||
end
|
||||
|
||||
test "doesn't return announce activities concerning blocked users" do
|
||||
blocker = insert(:user)
|
||||
blockee = insert(:user)
|
||||
friend = insert(:user)
|
||||
|
||||
{:ok, blocker} = User.block(blocker, blockee)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
|
||||
|
||||
{:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
|
||||
|
||||
{:ok, activity_three, _} = CommonAPI.repeat(activity_two.id, friend)
|
||||
|
||||
activities =
|
||||
ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
|
||||
|> Enum.map(fn act -> act.id end)
|
||||
|
||||
assert Enum.member?(activities, activity_one.id)
|
||||
refute Enum.member?(activities, activity_two.id)
|
||||
refute Enum.member?(activities, activity_three.id)
|
||||
end
|
||||
|
||||
test "doesn't return muted activities" do
|
||||
activity_one = insert(:note_activity)
|
||||
activity_two = insert(:note_activity)
|
||||
|
|
@ -380,7 +443,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, user} = User.mute(user, %User{ap_id: activity_three.data["actor"]})
|
||||
{:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
|
||||
%Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
|
||||
activity_three = Repo.get(Activity, activity_three.id)
|
||||
activity_three = Activity.get_by_id(activity_three.id)
|
||||
|
||||
activities =
|
||||
ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true})
|
||||
|
|
@ -559,7 +622,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, _, _, object} = ActivityPub.unlike(user, object)
|
||||
assert object.data["like_count"] == 0
|
||||
|
||||
assert Repo.get(Activity, like_activity.id) == nil
|
||||
assert Activity.get_by_id(like_activity.id) == nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -610,7 +673,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert unannounce_activity.data["actor"] == user.ap_id
|
||||
assert unannounce_activity.data["context"] == announce_activity.data["context"]
|
||||
|
||||
assert Repo.get(Activity, announce_activity.id) == nil
|
||||
assert Activity.get_by_id(announce_activity.id) == nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -645,43 +708,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "fetching an object" do
|
||||
test "it fetches an object" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
assert activity.data["id"]
|
||||
|
||||
{:ok, object_again} =
|
||||
ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert [attachment] = object.data["attachment"]
|
||||
assert is_list(attachment["url"])
|
||||
|
||||
assert object == object_again
|
||||
end
|
||||
|
||||
test "it works with objects only available via Ostatus" do
|
||||
{:ok, object} = ActivityPub.fetch_object_from_id("https://shitposter.club/notice/2827873")
|
||||
assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
assert activity.data["id"]
|
||||
|
||||
{:ok, object_again} =
|
||||
ActivityPub.fetch_object_from_id("https://shitposter.club/notice/2827873")
|
||||
|
||||
assert object == object_again
|
||||
end
|
||||
|
||||
test "it correctly stitches up conversations between ostatus and ap" do
|
||||
last = "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
{:ok, object} = ActivityPub.fetch_object_from_id(last)
|
||||
|
||||
object = Object.get_by_ap_id(object.data["inReplyTo"])
|
||||
assert object
|
||||
end
|
||||
end
|
||||
|
||||
describe "following / unfollowing" do
|
||||
test "creates a follow activity" do
|
||||
follower = insert(:user)
|
||||
|
|
@ -749,7 +775,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert delete.data["actor"] == note.data["actor"]
|
||||
assert delete.data["object"] == note.data["object"]["id"]
|
||||
|
||||
assert Repo.get(Activity, delete.id) != nil
|
||||
assert Activity.get_by_id(delete.id) != nil
|
||||
|
||||
assert Repo.get(Object, object.id).data["type"] == "Tombstone"
|
||||
end
|
||||
|
|
@ -758,23 +784,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
user = insert(:user, info: %{note_count: 10})
|
||||
|
||||
{:ok, a1} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "yeah", "visibility" => "public"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "public"
|
||||
})
|
||||
|
||||
{:ok, a2} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "yeah", "visibility" => "unlisted"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "unlisted"
|
||||
})
|
||||
|
||||
{:ok, a3} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "yeah", "visibility" => "private"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
{:ok, a4} =
|
||||
CommonAPI.post(Repo.get(User, user.id), %{"status" => "yeah", "visibility" => "direct"})
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
{:ok, _} = a1.data["object"]["id"] |> Object.get_by_ap_id() |> ActivityPub.delete()
|
||||
{:ok, _} = a2.data["object"]["id"] |> Object.get_by_ap_id() |> ActivityPub.delete()
|
||||
{:ok, _} = a3.data["object"]["id"] |> Object.get_by_ap_id() |> ActivityPub.delete()
|
||||
{:ok, _} = a4.data["object"]["id"] |> Object.get_by_ap_id() |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a1) |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a2) |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a3) |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a4) |> ActivityPub.delete()
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.info.note_count == 10
|
||||
end
|
||||
|
||||
|
|
@ -814,22 +852,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
_ = CommonAPI.delete(direct_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 2
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
_ = CommonAPI.delete(private_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 2
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
_ = CommonAPI.delete(public_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 1
|
||||
assert object.data["repliesCount"] == 1
|
||||
|
||||
_ = CommonAPI.delete(unlisted_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert data["object"]["repliesCount"] == 0
|
||||
assert object.data["repliesCount"] == 0
|
||||
end
|
||||
end
|
||||
|
|
@ -871,7 +905,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
activities = ActivityPub.fetch_activities([user1.ap_id | user1.following])
|
||||
|
||||
private_activity_1 = Activity.get_by_ap_id_with_object(private_activity_1.data["id"])
|
||||
assert [public_activity, private_activity_1, private_activity_3] == activities
|
||||
|
||||
assert [public_activity, private_activity_1, private_activity_3] ==
|
||||
activities
|
||||
|
||||
assert length(activities) == 3
|
||||
|
||||
activities = ActivityPub.contain_timeline(activities, user1)
|
||||
|
|
@ -881,15 +918,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "it can fetch plume articles" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_id(
|
||||
"https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"
|
||||
)
|
||||
|
||||
assert object
|
||||
end
|
||||
|
||||
describe "update" do
|
||||
test "it creates an update activity with the new user data" do
|
||||
user = insert(:user)
|
||||
|
|
@ -911,15 +939,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "it can fetch peertube videos" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_id(
|
||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
||||
)
|
||||
|
||||
assert object
|
||||
end
|
||||
|
||||
test "returned pinned statuses" do
|
||||
Pleroma.Config.put([:instance, :max_pinned_statuses], 3)
|
||||
user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
use Pleroma.DataCase
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
|
@ -50,16 +51,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|> Map.put("object", object)
|
||||
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
returned_object = Object.normalize(returned_activity.data["object"])
|
||||
|
||||
assert activity =
|
||||
Activity.get_create_by_object_ap_id(
|
||||
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
||||
)
|
||||
|
||||
assert returned_activity.data["object"]["inReplyToAtomUri"] ==
|
||||
"https://shitposter.club/notice/2827873"
|
||||
|
||||
assert returned_activity.data["object"]["inReplyToStatusId"] == activity.id
|
||||
assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
|
||||
end
|
||||
|
||||
test "it works for incoming notices" do
|
||||
|
|
@ -82,7 +81,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
object = data["object"]
|
||||
object = Object.normalize(data["object"]).data
|
||||
assert object["id"] == "http://mastodon.example.org/users/admin/statuses/99512778738411822"
|
||||
|
||||
assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
|
@ -100,7 +99,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
assert object["sensitive"] == true
|
||||
|
||||
user = User.get_by_ap_id(object["actor"])
|
||||
user = User.get_cached_by_ap_id(object["actor"])
|
||||
|
||||
assert user.info.note_count == 1
|
||||
end
|
||||
|
|
@ -109,7 +108,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
assert Enum.at(data["object"]["tag"], 2) == "moo"
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert Enum.at(object.data["tag"], 2) == "moo"
|
||||
end
|
||||
|
||||
test "it works for incoming notices with contentMap" do
|
||||
|
|
@ -117,8 +118,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert data["object"]["content"] ==
|
||||
assert object.data["content"] ==
|
||||
"<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
|
||||
end
|
||||
|
||||
|
|
@ -126,8 +128,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data = File.read!("test/fixtures/kroeg-post-activity.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert data["object"]["content"] ==
|
||||
assert object.data["content"] ==
|
||||
"<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
|
||||
end
|
||||
|
||||
|
|
@ -143,24 +146,27 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert data["object"]["emoji"] == %{
|
||||
assert object.data["emoji"] == %{
|
||||
"icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
|
||||
}
|
||||
|
||||
data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert "test" in data["object"]["tag"]
|
||||
assert "test" in object.data["tag"]
|
||||
end
|
||||
|
||||
test "it works for incoming notices with url not being a string (prismo)" do
|
||||
data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert data["object"]["url"] == "https://prismo.news/posts/83"
|
||||
assert object.data["url"] == "https://prismo.news/posts/83"
|
||||
end
|
||||
|
||||
test "it cleans up incoming notices which are not really DMs" do
|
||||
|
|
@ -182,15 +188,15 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["to"] == []
|
||||
assert data["cc"] == to
|
||||
|
||||
object = data["object"]
|
||||
object_data = Object.normalize(activity).data
|
||||
|
||||
assert object["to"] == []
|
||||
assert object["cc"] == to
|
||||
assert object_data["to"] == []
|
||||
assert object_data["cc"] == to
|
||||
end
|
||||
|
||||
test "it works for incoming follow requests" do
|
||||
|
|
@ -206,7 +212,27 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Follow"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
|
||||
assert User.following?(User.get_by_ap_id(data["actor"]), user)
|
||||
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
|
||||
Pleroma.Config.put([:user, :deny_follow_blocked], true)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
|
||||
|
||||
{:ok, user} = User.block(user, target)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
%Activity{} = activity = Activity.get_by_ap_id(id)
|
||||
|
||||
assert activity.data["state"] == "reject"
|
||||
end
|
||||
|
||||
test "it works for incoming follow requests from hubzilla" do
|
||||
|
|
@ -223,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
|
||||
assert data["type"] == "Follow"
|
||||
assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
|
||||
assert User.following?(User.get_by_ap_id(data["actor"]), user)
|
||||
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it works for incoming likes" do
|
||||
|
|
@ -233,14 +259,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data =
|
||||
File.read!("test/fixtures/mastodon-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"]["id"])
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Like"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
assert data["object"] == activity.data["object"]["id"]
|
||||
assert data["object"] == activity.data["object"]
|
||||
end
|
||||
|
||||
test "it returns an error for incoming unlikes wihout a like activity" do
|
||||
|
|
@ -250,7 +276,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"]["id"])
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
assert Transmogrifier.handle_incoming(data) == :error
|
||||
end
|
||||
|
|
@ -262,7 +288,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
like_data =
|
||||
File.read!("test/fixtures/mastodon-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"]["id"])
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
{:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
|
||||
|
||||
|
|
@ -304,7 +330,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"]["id"])
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
|
|
@ -314,7 +340,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
|
||||
|
||||
assert data["object"] == activity.data["object"]["id"]
|
||||
assert data["object"] == activity.data["object"]
|
||||
|
||||
assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
|
||||
end
|
||||
|
|
@ -326,7 +352,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"]["id"])
|
||||
|> Map.put("object", Object.normalize(activity).data["id"])
|
||||
|> Map.put("to", ["http://mastodon.example.org/users/admin/followers"])
|
||||
|> Map.put("cc", [])
|
||||
|
||||
|
|
@ -452,7 +478,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("id", activity.data["object"]["id"])
|
||||
|> Map.put("id", activity.data["object"])
|
||||
|
||||
data =
|
||||
data
|
||||
|
|
@ -461,7 +487,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute Repo.get(Activity, activity.id)
|
||||
refute Activity.get_by_id(activity.id)
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
|
|
@ -473,7 +499,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("id", activity.data["object"]["id"])
|
||||
|> Map.put("id", activity.data["object"])
|
||||
|
||||
data =
|
||||
data
|
||||
|
|
@ -481,7 +507,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert Repo.get(Activity, activity.id)
|
||||
assert Activity.get_by_id(activity.id)
|
||||
end
|
||||
|
||||
test "it works for incoming unannounces with an existing notice" do
|
||||
|
|
@ -491,7 +517,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
announce_data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"]["id"])
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
{:ok, %Activity{data: announce_data, local: false}} =
|
||||
Transmogrifier.handle_incoming(announce_data)
|
||||
|
|
@ -506,7 +532,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"]["type"] == "Announce"
|
||||
assert data["object"]["object"] == activity.data["object"]["id"]
|
||||
assert data["object"]["object"] == activity.data["object"]
|
||||
|
||||
assert data["object"]["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
|
||||
|
|
@ -534,7 +560,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["object"]["object"] == user.ap_id
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
refute User.following?(User.get_by_ap_id(data["actor"]), user)
|
||||
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it works for incoming blocks" do
|
||||
|
|
@ -551,7 +577,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["object"] == user.ap_id
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
blocker = User.get_by_ap_id(data["actor"])
|
||||
blocker = User.get_cached_by_ap_id(data["actor"])
|
||||
|
||||
assert User.blocks?(blocker, user)
|
||||
end
|
||||
|
|
@ -578,8 +604,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["object"] == blocked.ap_id
|
||||
assert data["actor"] == blocker.ap_id
|
||||
|
||||
blocker = User.get_by_ap_id(data["actor"])
|
||||
blocked = User.get_by_ap_id(data["object"])
|
||||
blocker = User.get_cached_by_ap_id(data["actor"])
|
||||
blocked = User.get_cached_by_ap_id(data["object"])
|
||||
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
||||
|
|
@ -608,7 +634,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["object"]["object"] == user.ap_id
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
blocker = User.get_by_ap_id(data["actor"])
|
||||
blocker = User.get_cached_by_ap_id(data["actor"])
|
||||
|
||||
refute User.blocks?(blocker, user)
|
||||
end
|
||||
|
|
@ -639,7 +665,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
assert activity.data["object"] == follow_activity.data["id"]
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
assert User.following?(follower, followed) == true
|
||||
end
|
||||
|
|
@ -661,7 +687,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
|
||||
assert activity.data["object"] == follow_activity.data["id"]
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
assert User.following?(follower, followed) == true
|
||||
end
|
||||
|
|
@ -681,7 +707,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
|
||||
assert activity.data["object"] == follow_activity.data["id"]
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
assert User.following?(follower, followed) == true
|
||||
end
|
||||
|
|
@ -700,7 +726,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
refute User.following?(follower, followed) == true
|
||||
end
|
||||
|
|
@ -719,7 +745,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
refute User.following?(follower, followed) == true
|
||||
end
|
||||
|
|
@ -744,7 +770,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
{:ok, activity} = Transmogrifier.handle_incoming(reject_data)
|
||||
refute activity.local
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
assert User.following?(follower, followed) == false
|
||||
end
|
||||
|
|
@ -766,7 +792,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
{:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data)
|
||||
|
||||
follower = Repo.get(User, follower.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
assert User.following?(follower, followed) == false
|
||||
end
|
||||
|
|
@ -785,7 +811,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
test "it remaps video URLs as attachments if necessary" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_id(
|
||||
Fetcher.fetch_object_from_id(
|
||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
||||
)
|
||||
|
||||
|
|
@ -940,7 +966,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
test "it strips internal fields" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu :moominmamma:"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu :firefox:"})
|
||||
|
||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
|
||||
|
|
@ -1020,7 +1046,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"})
|
||||
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.info.note_count == 1
|
||||
|
||||
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
|
||||
|
|
@ -1028,13 +1054,10 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert user.info.note_count == 1
|
||||
assert user.follower_address == "https://niu.moe/users/rye/followers"
|
||||
|
||||
# Wait for the background task
|
||||
:timer.sleep(1000)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.info.note_count == 1
|
||||
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
assert user.follower_address in activity.recipients
|
||||
|
||||
assert %{
|
||||
|
|
@ -1057,10 +1080,10 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
refute "..." in activity.recipients
|
||||
|
||||
unrelated_activity = Repo.get(Activity, unrelated_activity.id)
|
||||
unrelated_activity = Activity.get_by_id(unrelated_activity.id)
|
||||
refute user.follower_address in unrelated_activity.recipients
|
||||
|
||||
user_two = Repo.get(User, user_two.id)
|
||||
user_two = User.get_cached_by_id(user_two.id)
|
||||
assert user.follower_address in user_two.following
|
||||
refute "..." in user_two.following
|
||||
end
|
||||
|
|
@ -1093,10 +1116,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
end
|
||||
|
||||
describe "actor origin containment" do
|
||||
test "it rejects objects with a bogus origin" do
|
||||
{:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity.json")
|
||||
end
|
||||
|
||||
test "it rejects activities which reference objects with bogus origins" do
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -1110,10 +1129,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
:error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it rejects objects when attributedTo is wrong (variant 1)" do
|
||||
{:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity2.json")
|
||||
end
|
||||
|
||||
test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -1127,10 +1142,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
:error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it rejects objects when attributedTo is wrong (variant 2)" do
|
||||
{:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity3.json")
|
||||
end
|
||||
|
||||
test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -1145,62 +1156,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "general origin containment" do
|
||||
test "contain_origin_from_id() catches obvious spoofing attempts" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json"
|
||||
}
|
||||
|
||||
:error =
|
||||
Transmogrifier.contain_origin_from_id(
|
||||
"http://example.org/~alyssa/activities/1234.json",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "contain_origin_from_id() allows alternate IDs within the same origin domain" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json"
|
||||
}
|
||||
|
||||
:ok =
|
||||
Transmogrifier.contain_origin_from_id(
|
||||
"http://example.com/~alyssa/activities/1234",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "contain_origin_from_id() allows matching IDs" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json"
|
||||
}
|
||||
|
||||
:ok =
|
||||
Transmogrifier.contain_origin_from_id(
|
||||
"http://example.com/~alyssa/activities/1234.json",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "users cannot be collided through fake direction spoofing attempts" do
|
||||
insert(:user, %{
|
||||
nickname: "rye@niu.moe",
|
||||
local: false,
|
||||
ap_id: "https://niu.moe/users/rye",
|
||||
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
|
||||
})
|
||||
|
||||
{:error, _} = User.get_or_fetch_by_ap_id("https://n1u.moe/users/rye")
|
||||
end
|
||||
|
||||
test "all objects with fake directions are rejected by the object fetcher" do
|
||||
{:error, _} =
|
||||
ActivityPub.fetch_and_contain_remote_object_from_id(
|
||||
"https://info.pleroma.site/activity4.json"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "reserialization" do
|
||||
test "successfully reserializes a message with inReplyTo == nil" do
|
||||
user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,33 @@
|
|||
defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "fetch the latest Follow" do
|
||||
test "fetches the latest Follow activity" do
|
||||
%Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
|
||||
follower = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
followed = User.get_cached_by_ap_id(activity.data["object"])
|
||||
|
||||
assert activity == Utils.fetch_latest_follow(follower, followed)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch the latest Block" do
|
||||
test "fetches the latest Block activity" do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
||||
|
||||
assert activity == Utils.fetch_latest_block(blocker, blocked)
|
||||
end
|
||||
end
|
||||
|
||||
describe "determine_explicit_mentions()" do
|
||||
test "works with an object that has mentions" do
|
||||
object = %{
|
||||
|
|
@ -169,4 +192,16 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
assert Utils.fetch_ordered_collection("http://example.com/outbox", 5) == [0, 1]
|
||||
end
|
||||
end
|
||||
|
||||
test "make_json_ld_header/0" do
|
||||
assert Utils.make_json_ld_header() == %{
|
||||
"@context" => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"http://localhost:4001/schemas/litepub-0.1.jsonld",
|
||||
%{
|
||||
"@language" => "und"
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserInviteToken
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "/api/pleroma/admin/user" do
|
||||
|
|
@ -75,6 +75,50 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/user/follow" do
|
||||
test "allows to force-follow another user" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
user = insert(:user)
|
||||
follower = insert(:user)
|
||||
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> post("/api/pleroma/admin/user/follow", %{
|
||||
"follower" => follower.nickname,
|
||||
"followed" => user.nickname
|
||||
})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
assert User.following?(follower, user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/user/unfollow" do
|
||||
test "allows to force-unfollow another user" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
user = insert(:user)
|
||||
follower = insert(:user)
|
||||
|
||||
User.follow(follower, user)
|
||||
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> post("/api/pleroma/admin/user/unfollow", %{
|
||||
"follower" => follower.nickname,
|
||||
"followed" => user.nickname
|
||||
})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
follower = User.get_cached_by_id(follower.id)
|
||||
|
||||
refute User.following?(follower, user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /api/pleroma/admin/users/tag" do
|
||||
setup do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
|
|
@ -101,13 +145,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
user2: user2
|
||||
} do
|
||||
assert json_response(conn, :no_content)
|
||||
assert Repo.get(User, user1.id).tags == ["x", "foo", "bar"]
|
||||
assert Repo.get(User, user2.id).tags == ["y", "foo", "bar"]
|
||||
assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
|
||||
assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
|
||||
end
|
||||
|
||||
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
|
||||
assert json_response(conn, :no_content)
|
||||
assert Repo.get(User, user3.id).tags == ["unchanged"]
|
||||
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -137,13 +181,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
user2: user2
|
||||
} do
|
||||
assert json_response(conn, :no_content)
|
||||
assert Repo.get(User, user1.id).tags == []
|
||||
assert Repo.get(User, user2.id).tags == ["y"]
|
||||
assert User.get_cached_by_id(user1.id).tags == []
|
||||
assert User.get_cached_by_id(user2.id).tags == ["y"]
|
||||
end
|
||||
|
||||
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
|
||||
assert json_response(conn, :no_content)
|
||||
assert Repo.get(User, user3.id).tags == ["unchanged"]
|
||||
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -213,7 +257,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
conn
|
||||
|> put("/api/pleroma/admin/activation_status/#{user.nickname}", %{status: false})
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.info.deactivated == true
|
||||
assert json_response(conn, :no_content)
|
||||
end
|
||||
|
|
@ -225,7 +269,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
conn
|
||||
|> put("/api/pleroma/admin/activation_status/#{user.nickname}", %{status: true})
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.info.deactivated == false
|
||||
assert json_response(conn, :no_content)
|
||||
end
|
||||
|
|
@ -273,13 +317,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert token_record
|
||||
refute token_record.used
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
Pleroma.UserEmail.user_invitation_email(
|
||||
notify_email = Pleroma.Config.get([:instance, :notify_email])
|
||||
instance_name = Pleroma.Config.get([:instance, :name])
|
||||
|
||||
email =
|
||||
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||
user,
|
||||
token_record,
|
||||
recipient_email,
|
||||
recipient_name
|
||||
)
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {recipient_name, recipient_email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -597,4 +649,136 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"tags" => []
|
||||
}
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/invite_token" do
|
||||
test "without options" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> get("/api/pleroma/admin/invite_token")
|
||||
|
||||
token = json_response(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(token)
|
||||
refute invite.used
|
||||
refute invite.expires_at
|
||||
refute invite.max_use
|
||||
assert invite.invite_type == "one_time"
|
||||
end
|
||||
|
||||
test "with expires_at" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> get("/api/pleroma/admin/invite_token", %{
|
||||
"invite" => %{"expires_at" => Date.to_string(Date.utc_today())}
|
||||
})
|
||||
|
||||
token = json_response(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(token)
|
||||
|
||||
refute invite.used
|
||||
assert invite.expires_at == Date.utc_today()
|
||||
refute invite.max_use
|
||||
assert invite.invite_type == "date_limited"
|
||||
end
|
||||
|
||||
test "with max_use" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> get("/api/pleroma/admin/invite_token", %{
|
||||
"invite" => %{"max_use" => 150}
|
||||
})
|
||||
|
||||
token = json_response(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(token)
|
||||
refute invite.used
|
||||
refute invite.expires_at
|
||||
assert invite.max_use == 150
|
||||
assert invite.invite_type == "reusable"
|
||||
end
|
||||
|
||||
test "with max use and expires_at" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> get("/api/pleroma/admin/invite_token", %{
|
||||
"invite" => %{"max_use" => 150, "expires_at" => Date.to_string(Date.utc_today())}
|
||||
})
|
||||
|
||||
token = json_response(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(token)
|
||||
refute invite.used
|
||||
assert invite.expires_at == Date.utc_today()
|
||||
assert invite.max_use == 150
|
||||
assert invite.invite_type == "reusable_date_limited"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/invites" do
|
||||
test "no invites" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> get("/api/pleroma/admin/invites")
|
||||
|
||||
assert json_response(conn, 200) == %{"invites" => []}
|
||||
end
|
||||
|
||||
test "with invite" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> get("/api/pleroma/admin/invites")
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
"invites" => [
|
||||
%{
|
||||
"expires_at" => nil,
|
||||
"id" => invite.id,
|
||||
"invite_type" => "one_time",
|
||||
"max_use" => nil,
|
||||
"token" => invite.token,
|
||||
"used" => false,
|
||||
"uses" => 0
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/revoke_invite" do
|
||||
test "with token" do
|
||||
admin = insert(:user, info: %{is_admin: true})
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> post("/api/pleroma/admin/revoke_invite", %{"token" => invite.token})
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
"expires_at" => nil,
|
||||
"id" => invite.id,
|
||||
"invite_type" => "one_time",
|
||||
"max_use" => nil,
|
||||
"token" => invite.token,
|
||||
"used" => true,
|
||||
"uses" => 0
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
42
test/web/auth/authenticator_test.exs
Normal file
42
test/web/auth/authenticator_test.exs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.AuthenticatorTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.Auth.Authenticator
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "fetch_user/1" do
|
||||
test "returns user by name" do
|
||||
user = insert(:user)
|
||||
assert Authenticator.fetch_user(user.nickname) == user
|
||||
end
|
||||
|
||||
test "returns user by email" do
|
||||
user = insert(:user)
|
||||
assert Authenticator.fetch_user(user.email) == user
|
||||
end
|
||||
|
||||
test "returns nil" do
|
||||
assert Authenticator.fetch_user("email") == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_credentials/1" do
|
||||
test "returns name and password from authorization params" do
|
||||
params = %{"authorization" => %{"name" => "test", "password" => "test-pass"}}
|
||||
assert Authenticator.fetch_credentials(params) == {:ok, {"test", "test-pass"}}
|
||||
end
|
||||
|
||||
test "returns name and password with grant_type 'password'" do
|
||||
params = %{"grant_type" => "password", "username" => "test", "password" => "test-pass"}
|
||||
assert Authenticator.fetch_credentials(params) == {:ok, {"test", "test-pass"}}
|
||||
end
|
||||
|
||||
test "returns error" do
|
||||
assert Authenticator.fetch_credentials(%{}) == {:error, :invalid_credentials}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.Web.CommonAPITest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
|
|
@ -32,24 +33,26 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu #2HU"})
|
||||
|
||||
assert activity.data["object"]["tag"] == ["2hu"]
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert object.data["tag"] == ["2hu"]
|
||||
end
|
||||
|
||||
test "it adds emoji in the object" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ":moominmamma:"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ":firefox:"})
|
||||
|
||||
assert activity.data["object"]["emoji"]["moominmamma"]
|
||||
assert Object.normalize(activity).data["emoji"]["firefox"]
|
||||
end
|
||||
|
||||
test "it adds emoji when updating profiles" do
|
||||
user = insert(:user, %{name: ":karjalanpiirakka:"})
|
||||
user = insert(:user, %{name: ":firefox:"})
|
||||
|
||||
CommonAPI.update(user)
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
[karjalanpiirakka] = user.info.source_data["tag"]
|
||||
[firefox] = user.info.source_data["tag"]
|
||||
|
||||
assert karjalanpiirakka["name"] == ":karjalanpiirakka:"
|
||||
assert firefox["name"] == ":firefox:"
|
||||
end
|
||||
|
||||
describe "posting" do
|
||||
|
|
@ -64,8 +67,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
"content_type" => "text/html"
|
||||
})
|
||||
|
||||
content = activity.data["object"]["content"]
|
||||
assert content == "<p><b>2hu</b></p>alert('xss')"
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||
end
|
||||
|
||||
test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||
|
|
@ -79,8 +83,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
"content_type" => "text/markdown"
|
||||
})
|
||||
|
||||
content = activity.data["object"]["content"]
|
||||
assert content == "<p><b>2hu</b></p>alert('xss')"
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -37,21 +37,21 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
end
|
||||
|
||||
test "parses emoji from name and bio" do
|
||||
{:ok, user} = UserBuilder.insert(%{name: ":karjalanpiirakka:", bio: ":perkele:"})
|
||||
{:ok, user} = UserBuilder.insert(%{name: ":blank:", bio: ":firefox:"})
|
||||
|
||||
expected = [
|
||||
%{
|
||||
"type" => "Emoji",
|
||||
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}/finmoji/128px/perkele-128.png"},
|
||||
"name" => ":perkele:"
|
||||
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}/emoji/Firefox.gif"},
|
||||
"name" => ":firefox:"
|
||||
},
|
||||
%{
|
||||
"type" => "Emoji",
|
||||
"icon" => %{
|
||||
"type" => "Image",
|
||||
"url" => "#{Endpoint.url()}/finmoji/128px/karjalanpiirakka-128.png"
|
||||
"url" => "#{Endpoint.url()}/emoji/blank.png"
|
||||
},
|
||||
"name" => ":karjalanpiirakka:"
|
||||
"name" => ":blank:"
|
||||
}
|
||||
]
|
||||
|
||||
|
|
@ -119,6 +119,31 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for bare text/bbcode" do
|
||||
text = "[b]hello world[/b]"
|
||||
expected = "<strong>hello world</strong>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "[b]hello world![/b]\n\nsecond paragraph!"
|
||||
expected = "<strong>hello world!</strong><br>\n<br>\nsecond paragraph!"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "[b]hello world![/b]\n\n<strong>second paragraph!</strong>"
|
||||
|
||||
expected =
|
||||
"<strong>hello world!</strong><br>\n<br>\n<strong>second paragraph!</strong>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for text/markdown with mentions" do
|
||||
{:ok, user} =
|
||||
UserBuilder.insert(%{nickname: "user__test", ap_id: "http://foo.com/user__test"})
|
||||
|
|
@ -153,4 +178,40 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
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()
|
||||
|
||||
expected =
|
||||
date
|
||||
|> DateTime.from_iso8601()
|
||||
|> elem(1)
|
||||
|> Calendar.Strftime.strftime!("%a %b %d %H:%M:%S %z %Y")
|
||||
|
||||
assert Utils.date_to_asctime(date) == expected
|
||||
end
|
||||
|
||||
test "when date is a binary in wrong format" do
|
||||
date = DateTime.utc_now()
|
||||
|
||||
expected = ""
|
||||
|
||||
assert Utils.date_to_asctime(date) == expected
|
||||
end
|
||||
|
||||
test "when date is a Unix timestamp" do
|
||||
date = DateTime.utc_now() |> DateTime.to_unix()
|
||||
|
||||
expected = ""
|
||||
|
||||
assert Utils.date_to_asctime(date) == expected
|
||||
end
|
||||
|
||||
test "when date is nil" do
|
||||
expected = ""
|
||||
|
||||
assert Utils.date_to_asctime(nil) == expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -56,14 +56,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
bot: false,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: "public",
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
pleroma: %{
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
relationship: %{}
|
||||
}
|
||||
}
|
||||
|
|
@ -71,6 +74,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
assert expected == AccountView.render("account.json", %{user: user})
|
||||
end
|
||||
|
||||
test "Represent the user account for the account owner" do
|
||||
user = insert(:user)
|
||||
|
||||
notification_settings = %{
|
||||
"remote" => true,
|
||||
"local" => true,
|
||||
"followers" => true,
|
||||
"follows" => true
|
||||
}
|
||||
|
||||
privacy = user.info.default_scope
|
||||
|
||||
assert %{
|
||||
pleroma: %{notification_settings: ^notification_settings},
|
||||
source: %{privacy: ^privacy}
|
||||
} = AccountView.render("account.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "Represent a Service(bot) account" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
|
|
@ -100,14 +121,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
bot: true,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: "public",
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
pleroma: %{
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
relationship: %{}
|
||||
}
|
||||
}
|
||||
|
|
@ -142,6 +166,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
blocking: true,
|
||||
muting: false,
|
||||
muting_notifications: false,
|
||||
subscribing: false,
|
||||
requested: false,
|
||||
domain_blocking: false,
|
||||
showing_reblogs: true,
|
||||
|
|
@ -154,15 +179,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
test "represent an embedded relationship" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
info: %{note_count: 5, follower_count: 3, source_data: %{"type" => "Service"}},
|
||||
info: %{note_count: 5, follower_count: 0, source_data: %{"type" => "Service"}},
|
||||
nickname: "shp@shitposter.club",
|
||||
inserted_at: ~N[2017-08-15 15:47:06.597036]
|
||||
})
|
||||
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, other_user} = User.follow(other_user, user)
|
||||
{:ok, other_user} = User.block(other_user, user)
|
||||
{:ok, _} = User.follow(insert(:user), user)
|
||||
|
||||
expected = %{
|
||||
id: to_string(user.id),
|
||||
|
|
@ -171,7 +196,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
display_name: user.name,
|
||||
locked: false,
|
||||
created_at: "2017-08-15T15:47:06.000Z",
|
||||
followers_count: 3,
|
||||
followers_count: 1,
|
||||
following_count: 0,
|
||||
statuses_count: 5,
|
||||
note: user.bio,
|
||||
|
|
@ -185,19 +210,23 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
bot: true,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: "public",
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
pleroma: %{
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
relationship: %{
|
||||
id: to_string(user.id),
|
||||
following: false,
|
||||
followed_by: false,
|
||||
blocking: true,
|
||||
subscribing: false,
|
||||
muting: false,
|
||||
muting_notifications: false,
|
||||
requested: false,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -21,7 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
mentioned_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{mentioned_user.nickname}"})
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
|
|
@ -44,7 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
|
||||
{:ok, favorite_activity, _object} = CommonAPI.favorite(create_activity.id, another_user)
|
||||
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
||||
create_activity = Repo.get(Activity, create_activity.id)
|
||||
create_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
|
|
@ -66,7 +66,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
|
||||
{:ok, reblog_activity, _object} = CommonAPI.repeat(create_activity.id, another_user)
|
||||
{:ok, [notification]} = Notification.create_notifications(reblog_activity)
|
||||
reblog_activity = Repo.get(Activity, create_activity.id)
|
||||
reblog_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
|
|
|
|||
68
test/web/mastodon_api/scheduled_activity_view_test.exs
Normal file
68
test/web/mastodon_api/scheduled_activity_view_test.exs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ScheduledActivityViewTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.ScheduledActivity
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
import Pleroma.Factory
|
||||
|
||||
test "A scheduled activity with a media attachment" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hi"})
|
||||
|
||||
scheduled_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(10), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
file = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
|
||||
|
||||
attrs = %{
|
||||
params: %{
|
||||
"media_ids" => [upload.id],
|
||||
"status" => "hi",
|
||||
"sensitive" => true,
|
||||
"spoiler_text" => "spoiler",
|
||||
"visibility" => "unlisted",
|
||||
"in_reply_to_id" => to_string(activity.id)
|
||||
},
|
||||
scheduled_at: scheduled_at
|
||||
}
|
||||
|
||||
{:ok, scheduled_activity} = ScheduledActivity.create(user, attrs)
|
||||
result = ScheduledActivityView.render("show.json", %{scheduled_activity: scheduled_activity})
|
||||
|
||||
expected = %{
|
||||
id: to_string(scheduled_activity.id),
|
||||
media_attachments:
|
||||
%{"media_ids" => [upload.id]}
|
||||
|> Utils.attachments_from_ids()
|
||||
|> Enum.map(&StatusView.render("attachment.json", %{attachment: &1})),
|
||||
params: %{
|
||||
in_reply_to_id: to_string(activity.id),
|
||||
media_ids: [upload.id],
|
||||
poll: nil,
|
||||
scheduled_at: nil,
|
||||
sensitive: true,
|
||||
spoiler_text: "spoiler",
|
||||
text: "hi",
|
||||
visibility: "unlisted"
|
||||
},
|
||||
scheduled_at: Utils.to_masto_date(scheduled_activity.scheduled_at)
|
||||
}
|
||||
|
||||
assert expected == result
|
||||
end
|
||||
end
|
||||
|
|
@ -6,8 +6,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
|
|
@ -53,14 +55,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
|
||||
test "a note with null content" do
|
||||
note = insert(:note_activity)
|
||||
note_object = Object.normalize(note.data["object"])
|
||||
|
||||
data =
|
||||
note.data
|
||||
|> put_in(["object", "content"], nil)
|
||||
note_object.data
|
||||
|> Map.put("content", nil)
|
||||
|
||||
note =
|
||||
note
|
||||
|> Map.put(:data, data)
|
||||
Object.change(note_object, %{data: data})
|
||||
|> Object.update_and_set_cache()
|
||||
|
||||
User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
|
|
@ -101,7 +103,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
muted: false,
|
||||
pinned: false,
|
||||
sensitive: false,
|
||||
spoiler_text: note.data["object"]["summary"],
|
||||
spoiler_text: HtmlSanitizeEx.basic_html(note.data["object"]["summary"]),
|
||||
visibility: "public",
|
||||
media_attachments: [],
|
||||
mentions: [],
|
||||
|
|
@ -126,7 +128,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
],
|
||||
pleroma: %{
|
||||
local: true,
|
||||
conversation_id: convo_id
|
||||
conversation_id: convo_id,
|
||||
in_reply_to_account_acct: nil,
|
||||
content: %{"text/plain" => HtmlSanitizeEx.strip_tags(note.data["object"]["content"])},
|
||||
spoiler_text: %{"text/plain" => HtmlSanitizeEx.strip_tags(note.data["object"]["summary"])}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -149,6 +154,25 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
assert status.muted == true
|
||||
end
|
||||
|
||||
test "tells if the status is bookmarked" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Cute girls doing cute things"})
|
||||
status = StatusView.render("status.json", %{activity: activity})
|
||||
|
||||
assert status.bookmarked == false
|
||||
|
||||
status = StatusView.render("status.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.bookmarked == false
|
||||
|
||||
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
|
||||
|
||||
status = StatusView.render("status.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.bookmarked == true
|
||||
end
|
||||
|
||||
test "a reply" do
|
||||
note = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
|
@ -175,7 +199,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
|
||||
status = StatusView.render("status.json", %{activity: activity})
|
||||
|
||||
actor = Repo.get_by(User, ap_id: activity.actor)
|
||||
actor = User.get_cached_by_ap_id(activity.actor)
|
||||
|
||||
assert status.mentions ==
|
||||
Enum.map([user, actor], fn u -> AccountView.render("mention.json", %{user: u}) end)
|
||||
|
|
@ -228,7 +252,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
user = insert(:user)
|
||||
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_id(
|
||||
Pleroma.Object.Fetcher.fetch_object_from_id(
|
||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
||||
)
|
||||
|
||||
|
|
|
|||
18
test/web/metadata/rel_me_test.exs
Normal file
18
test/web/metadata/rel_me_test.exs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
defmodule Pleroma.Web.Metadata.Providers.RelMeTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Web.Metadata.Providers.RelMe
|
||||
|
||||
test "it renders all links with rel='me' from user bio" do
|
||||
bio =
|
||||
~s(<a href="https://some-link.com">https://some-link.com</a> <a rel="me" href="https://another-link.com">https://another-link.com</a>
|
||||
<link href="http://some.com"> <link rel="me" href="http://some3.com>")
|
||||
|
||||
user = insert(:user, %{bio: bio})
|
||||
|
||||
assert RelMe.build_tags(%{user: user}) == [
|
||||
{:link, [rel: "me", href: "http://some3.com>"], []},
|
||||
{:link, [rel: "me", href: "https://another-link.com"], []}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
@ -5,266 +5,713 @@
|
|||
defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
alias Pleroma.Registration
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
test "redirects with oauth authorization" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write", "follow"])
|
||||
@session_opts [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "test",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read write",
|
||||
"state" => "statepassed"
|
||||
}
|
||||
})
|
||||
describe "in OAuth consumer mode, " do
|
||||
setup do
|
||||
oauth_consumer_strategies_path = [:auth, :oauth_consumer_strategies]
|
||||
oauth_consumer_strategies = Pleroma.Config.get(oauth_consumer_strategies_path)
|
||||
Pleroma.Config.put(oauth_consumer_strategies_path, ~w(twitter facebook))
|
||||
|
||||
target = redirected_to(conn)
|
||||
assert target =~ app.redirect_uris
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put(oauth_consumer_strategies_path, oauth_consumer_strategies)
|
||||
end)
|
||||
|
||||
query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
|
||||
|
||||
assert %{"state" => "statepassed", "code" => code} = query
|
||||
auth = Repo.get_by(Authorization, token: code)
|
||||
assert auth
|
||||
assert auth.scopes == ["read", "write"]
|
||||
end
|
||||
|
||||
test "returns 401 for wrong credentials", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "wrong",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "statepassed",
|
||||
"scope" => Enum.join(app.scopes, " ")
|
||||
}
|
||||
})
|
||||
|> html_response(:unauthorized)
|
||||
|
||||
# Keep the details
|
||||
assert result =~ app.client_id
|
||||
assert result =~ app.redirect_uris
|
||||
|
||||
# Error message
|
||||
assert result =~ "Invalid Username/Password"
|
||||
end
|
||||
|
||||
test "returns 401 for missing scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "test",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "statepassed",
|
||||
"scope" => ""
|
||||
}
|
||||
})
|
||||
|> html_response(:unauthorized)
|
||||
|
||||
# Keep the details
|
||||
assert result =~ app.client_id
|
||||
assert result =~ app.redirect_uris
|
||||
|
||||
# Error message
|
||||
assert result =~ "This action is outside the authorized scopes"
|
||||
end
|
||||
|
||||
test "returns 401 for scopes beyond app scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
result =
|
||||
conn
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "test",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "statepassed",
|
||||
"scope" => "read write follow"
|
||||
}
|
||||
})
|
||||
|> html_response(:unauthorized)
|
||||
|
||||
# Keep the details
|
||||
assert result =~ app.client_id
|
||||
assert result =~ app.redirect_uris
|
||||
|
||||
# Error message
|
||||
assert result =~ "This action is outside the authorized scopes"
|
||||
end
|
||||
|
||||
test "issues a token for an all-body request" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user, ["write"])
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => auth.token,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token, "me" => ap_id} = json_response(conn, 200)
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
assert token
|
||||
assert token.scopes == auth.scopes
|
||||
assert user.ap_id == ap_id
|
||||
end
|
||||
|
||||
test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|
||||
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
# Note: "scope" param is intentionally omitted
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token} = json_response(conn, 200)
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
assert token
|
||||
assert token.scopes == app.scopes
|
||||
end
|
||||
|
||||
test "issues a token for request with HTTP basic auth client credentials" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["scope1", "scope2", "scope3"])
|
||||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user, ["scope1", "scope2"])
|
||||
assert auth.scopes == ["scope1", "scope2"]
|
||||
|
||||
app_encoded =
|
||||
(URI.encode_www_form(app.client_id) <> ":" <> URI.encode_www_form(app.client_secret))
|
||||
|> Base.encode64()
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> put_req_header("authorization", "Basic " <> app_encoded)
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => auth.token,
|
||||
"redirect_uri" => app.redirect_uris
|
||||
})
|
||||
|
||||
assert %{"access_token" => token, "scope" => scope} = json_response(conn, 200)
|
||||
|
||||
assert scope == "scope1 scope2"
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
assert token
|
||||
assert token.scopes == ["scope1", "scope2"]
|
||||
end
|
||||
|
||||
test "rejects token exchange with invalid client credentials" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app)
|
||||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> put_req_header("authorization", "Basic JTIxOiVGMCU5RiVBNCVCNwo=")
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => auth.token,
|
||||
"redirect_uri" => app.redirect_uris
|
||||
})
|
||||
|
||||
assert resp = json_response(conn, 400)
|
||||
assert %{"error" => _} = resp
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
end
|
||||
|
||||
test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do
|
||||
setting = Pleroma.Config.get([:instance, :account_activation_required])
|
||||
|
||||
unless setting do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
|
||||
[
|
||||
app: insert(:oauth_app),
|
||||
conn:
|
||||
build_conn()
|
||||
|> Plug.Session.call(Plug.Session.init(@session_opts))
|
||||
|> fetch_session()
|
||||
]
|
||||
end
|
||||
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|
||||
info_change = Pleroma.User.Info.confirmation_changeset(user.info, :unconfirmed)
|
||||
test "GET /oauth/authorize renders auth forms, including OAuth consumer form", %{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/authorize",
|
||||
%{
|
||||
"response_type" => "code",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read"
|
||||
}
|
||||
)
|
||||
|
||||
{:ok, user} =
|
||||
user
|
||||
|> Ecto.Changeset.change()
|
||||
|> Ecto.Changeset.put_embed(:info, info_change)
|
||||
|> Repo.update()
|
||||
assert response = html_response(conn, 200)
|
||||
assert response =~ "Sign in with Twitter"
|
||||
assert response =~ o_auth_path(conn, :prepare_request)
|
||||
end
|
||||
|
||||
refute Pleroma.User.auth_active?(user)
|
||||
test "GET /oauth/prepare_request encodes parameters as `state` and redirects", %{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/prepare_request",
|
||||
%{
|
||||
"provider" => "twitter",
|
||||
"authorization" => %{
|
||||
"scope" => "read follow",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
app = insert(:oauth_app)
|
||||
assert response = html_response(conn, 302)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
redirect_query = URI.parse(redirected_to(conn)).query
|
||||
assert %{"state" => state_param} = URI.decode_query(redirect_query)
|
||||
assert {:ok, state_components} = Poison.decode(state_param)
|
||||
|
||||
expected_client_id = app.client_id
|
||||
expected_redirect_uri = app.redirect_uris
|
||||
|
||||
assert %{
|
||||
"scope" => "read follow",
|
||||
"client_id" => ^expected_client_id,
|
||||
"redirect_uri" => ^expected_redirect_uri,
|
||||
"state" => "a_state"
|
||||
} = state_components
|
||||
end
|
||||
|
||||
test "with user-bound registration, GET /oauth/<provider>/callback redirects to `redirect_uri` with `code`",
|
||||
%{app: app, conn: conn} do
|
||||
registration = insert(:registration)
|
||||
|
||||
state_params = %{
|
||||
"scope" => Enum.join(app.scopes, " "),
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => ""
|
||||
}
|
||||
|
||||
assert resp = json_response(conn, 403)
|
||||
assert %{"error" => _} = resp
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
with_mock Pleroma.Web.Auth.Authenticator,
|
||||
get_registration: fn _ -> {:ok, registration} end do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/twitter/callback",
|
||||
%{
|
||||
"oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
|
||||
"oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
|
||||
"provider" => "twitter",
|
||||
"state" => Poison.encode!(state_params)
|
||||
}
|
||||
)
|
||||
|
||||
assert response = html_response(conn, 302)
|
||||
assert redirected_to(conn) =~ ~r/#{app.redirect_uris}\?code=.+/
|
||||
end
|
||||
end
|
||||
|
||||
test "with user-unbound registration, GET /oauth/<provider>/callback renders registration_details page",
|
||||
%{app: app, conn: conn} do
|
||||
registration = insert(:registration, user: nil)
|
||||
|
||||
state_params = %{
|
||||
"scope" => "read write",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state"
|
||||
}
|
||||
|
||||
with_mock Pleroma.Web.Auth.Authenticator,
|
||||
get_registration: fn _ -> {:ok, registration} end do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/twitter/callback",
|
||||
%{
|
||||
"oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
|
||||
"oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
|
||||
"provider" => "twitter",
|
||||
"state" => Poison.encode!(state_params)
|
||||
}
|
||||
)
|
||||
|
||||
assert response = html_response(conn, 200)
|
||||
assert response =~ ~r/name="op" type="submit" value="register"/
|
||||
assert response =~ ~r/name="op" type="submit" value="connect"/
|
||||
assert response =~ Registration.email(registration)
|
||||
assert response =~ Registration.nickname(registration)
|
||||
end
|
||||
end
|
||||
|
||||
test "on authentication error, GET /oauth/<provider>/callback redirects to `redirect_uri`", %{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
state_params = %{
|
||||
"scope" => Enum.join(app.scopes, " "),
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => ""
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:ueberauth_failure, %{errors: [%{message: "(error description)"}]})
|
||||
|> get(
|
||||
"/oauth/twitter/callback",
|
||||
%{
|
||||
"oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
|
||||
"oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
|
||||
"provider" => "twitter",
|
||||
"state" => Poison.encode!(state_params)
|
||||
}
|
||||
)
|
||||
|
||||
assert response = html_response(conn, 302)
|
||||
assert redirected_to(conn) == app.redirect_uris
|
||||
assert get_flash(conn, :error) == "Failed to authenticate: (error description)."
|
||||
end
|
||||
|
||||
test "GET /oauth/registration_details renders registration details form", %{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/registration_details",
|
||||
%{
|
||||
"authorization" => %{
|
||||
"scopes" => app.scopes,
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state",
|
||||
"nickname" => nil,
|
||||
"email" => "john@doe.com"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert response = html_response(conn, 200)
|
||||
assert response =~ ~r/name="op" type="submit" value="register"/
|
||||
assert response =~ ~r/name="op" type="submit" value="connect"/
|
||||
end
|
||||
|
||||
test "with valid params, POST /oauth/register?op=register redirects to `redirect_uri` with `code`",
|
||||
%{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:registration_id, registration.id)
|
||||
|> post(
|
||||
"/oauth/register",
|
||||
%{
|
||||
"op" => "register",
|
||||
"authorization" => %{
|
||||
"scopes" => app.scopes,
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state",
|
||||
"nickname" => "availablenick",
|
||||
"email" => "available@email.com"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert response = html_response(conn, 302)
|
||||
assert redirected_to(conn) =~ ~r/#{app.redirect_uris}\?code=.+/
|
||||
end
|
||||
|
||||
test "with invalid params, POST /oauth/register?op=register renders registration_details page",
|
||||
%{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
another_user = insert(:user)
|
||||
registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
|
||||
|
||||
params = %{
|
||||
"op" => "register",
|
||||
"authorization" => %{
|
||||
"scopes" => app.scopes,
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state",
|
||||
"nickname" => "availablenickname",
|
||||
"email" => "available@email.com"
|
||||
}
|
||||
}
|
||||
|
||||
for {bad_param, bad_param_value} <-
|
||||
[{"nickname", another_user.nickname}, {"email", another_user.email}] do
|
||||
bad_registration_attrs = %{
|
||||
"authorization" => Map.put(params["authorization"], bad_param, bad_param_value)
|
||||
}
|
||||
|
||||
bad_params = Map.merge(params, bad_registration_attrs)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:registration_id, registration.id)
|
||||
|> post("/oauth/register", bad_params)
|
||||
|
||||
assert html_response(conn, 403) =~ ~r/name="op" type="submit" value="register"/
|
||||
assert get_flash(conn, :error) == "Error: #{bad_param} has already been taken."
|
||||
end
|
||||
end
|
||||
|
||||
test "with valid params, POST /oauth/register?op=connect redirects to `redirect_uri` with `code`",
|
||||
%{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword"))
|
||||
registration = insert(:registration, user: nil)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:registration_id, registration.id)
|
||||
|> post(
|
||||
"/oauth/register",
|
||||
%{
|
||||
"op" => "connect",
|
||||
"authorization" => %{
|
||||
"scopes" => app.scopes,
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state",
|
||||
"name" => user.nickname,
|
||||
"password" => "testpassword"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert response = html_response(conn, 302)
|
||||
assert redirected_to(conn) =~ ~r/#{app.redirect_uris}\?code=.+/
|
||||
end
|
||||
|
||||
test "with invalid params, POST /oauth/register?op=connect renders registration_details page",
|
||||
%{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
user = insert(:user)
|
||||
registration = insert(:registration, user: nil)
|
||||
|
||||
params = %{
|
||||
"op" => "connect",
|
||||
"authorization" => %{
|
||||
"scopes" => app.scopes,
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "a_state",
|
||||
"name" => user.nickname,
|
||||
"password" => "wrong password"
|
||||
}
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:registration_id, registration.id)
|
||||
|> post("/oauth/register", params)
|
||||
|
||||
assert html_response(conn, 401) =~ ~r/name="op" type="submit" value="connect"/
|
||||
assert get_flash(conn, :error) == "Invalid Username/Password"
|
||||
end
|
||||
end
|
||||
|
||||
test "rejects an invalid authorization code" do
|
||||
app = insert(:oauth_app)
|
||||
describe "GET /oauth/authorize" do
|
||||
setup do
|
||||
[
|
||||
app: insert(:oauth_app, redirect_uris: "https://redirect.url"),
|
||||
conn:
|
||||
build_conn()
|
||||
|> Plug.Session.call(Plug.Session.init(@session_opts))
|
||||
|> fetch_session()
|
||||
]
|
||||
end
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => "Imobviouslyinvalid",
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
test "renders authentication page", %{app: app, conn: conn} do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/authorize",
|
||||
%{
|
||||
"response_type" => "code",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read"
|
||||
}
|
||||
)
|
||||
|
||||
assert resp = json_response(conn, 400)
|
||||
assert %{"error" => _} = json_response(conn, 400)
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
assert html_response(conn, 200) =~ ~s(type="submit")
|
||||
end
|
||||
|
||||
test "properly handles internal calls with `authorization`-wrapped params", %{
|
||||
app: app,
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/oauth/authorize",
|
||||
%{
|
||||
"authorization" => %{
|
||||
"response_type" => "code",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert html_response(conn, 200) =~ ~s(type="submit")
|
||||
end
|
||||
|
||||
test "renders authentication page if user is already authenticated but `force_login` is tru-ish",
|
||||
%{app: app, conn: conn} do
|
||||
token = insert(:oauth_token, app_id: app.id)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:oauth_token, token.token)
|
||||
|> get(
|
||||
"/oauth/authorize",
|
||||
%{
|
||||
"response_type" => "code",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read",
|
||||
"force_login" => "true"
|
||||
}
|
||||
)
|
||||
|
||||
assert html_response(conn, 200) =~ ~s(type="submit")
|
||||
end
|
||||
|
||||
test "redirects to app if user is already authenticated", %{app: app, conn: conn} do
|
||||
token = insert(:oauth_token, app_id: app.id)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:oauth_token, token.token)
|
||||
|> get(
|
||||
"/oauth/authorize",
|
||||
%{
|
||||
"response_type" => "code",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read"
|
||||
}
|
||||
)
|
||||
|
||||
assert redirected_to(conn) == "https://redirect.url"
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /oauth/authorize" do
|
||||
test "redirects with oauth authorization" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write", "follow"])
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "test",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"scope" => "read write",
|
||||
"state" => "statepassed"
|
||||
}
|
||||
})
|
||||
|
||||
target = redirected_to(conn)
|
||||
assert target =~ app.redirect_uris
|
||||
|
||||
query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
|
||||
|
||||
assert %{"state" => "statepassed", "code" => code} = query
|
||||
auth = Repo.get_by(Authorization, token: code)
|
||||
assert auth
|
||||
assert auth.scopes == ["read", "write"]
|
||||
end
|
||||
|
||||
test "returns 401 for wrong credentials", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "wrong",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "statepassed",
|
||||
"scope" => Enum.join(app.scopes, " ")
|
||||
}
|
||||
})
|
||||
|> html_response(:unauthorized)
|
||||
|
||||
# Keep the details
|
||||
assert result =~ app.client_id
|
||||
assert result =~ app.redirect_uris
|
||||
|
||||
# Error message
|
||||
assert result =~ "Invalid Username/Password"
|
||||
end
|
||||
|
||||
test "returns 401 for missing scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "test",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "statepassed",
|
||||
"scope" => ""
|
||||
}
|
||||
})
|
||||
|> html_response(:unauthorized)
|
||||
|
||||
# Keep the details
|
||||
assert result =~ app.client_id
|
||||
assert result =~ app.redirect_uris
|
||||
|
||||
# Error message
|
||||
assert result =~ "This action is outside the authorized scopes"
|
||||
end
|
||||
|
||||
test "returns 401 for scopes beyond app scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
result =
|
||||
conn
|
||||
|> post("/oauth/authorize", %{
|
||||
"authorization" => %{
|
||||
"name" => user.nickname,
|
||||
"password" => "test",
|
||||
"client_id" => app.client_id,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"state" => "statepassed",
|
||||
"scope" => "read write follow"
|
||||
}
|
||||
})
|
||||
|> html_response(:unauthorized)
|
||||
|
||||
# Keep the details
|
||||
assert result =~ app.client_id
|
||||
assert result =~ app.redirect_uris
|
||||
|
||||
# Error message
|
||||
assert result =~ "This action is outside the authorized scopes"
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /oauth/token" do
|
||||
test "issues a token for an all-body request" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user, ["write"])
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => auth.token,
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token, "me" => ap_id} = json_response(conn, 200)
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
assert token
|
||||
assert token.scopes == auth.scopes
|
||||
assert user.ap_id == ap_id
|
||||
end
|
||||
|
||||
test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|
||||
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
# Note: "scope" param is intentionally omitted
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token} = json_response(conn, 200)
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
assert token
|
||||
assert token.scopes == app.scopes
|
||||
end
|
||||
|
||||
test "issues a token for request with HTTP basic auth client credentials" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["scope1", "scope2", "scope3"])
|
||||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user, ["scope1", "scope2"])
|
||||
assert auth.scopes == ["scope1", "scope2"]
|
||||
|
||||
app_encoded =
|
||||
(URI.encode_www_form(app.client_id) <> ":" <> URI.encode_www_form(app.client_secret))
|
||||
|> Base.encode64()
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> put_req_header("authorization", "Basic " <> app_encoded)
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => auth.token,
|
||||
"redirect_uri" => app.redirect_uris
|
||||
})
|
||||
|
||||
assert %{"access_token" => token, "scope" => scope} = json_response(conn, 200)
|
||||
|
||||
assert scope == "scope1 scope2"
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
assert token
|
||||
assert token.scopes == ["scope1", "scope2"]
|
||||
end
|
||||
|
||||
test "rejects token exchange with invalid client credentials" do
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app)
|
||||
|
||||
{:ok, auth} = Authorization.create_authorization(app, user)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> put_req_header("authorization", "Basic JTIxOiVGMCU5RiVBNCVCNwo=")
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => auth.token,
|
||||
"redirect_uri" => app.redirect_uris
|
||||
})
|
||||
|
||||
assert resp = json_response(conn, 400)
|
||||
assert %{"error" => _} = resp
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
end
|
||||
|
||||
test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do
|
||||
setting = Pleroma.Config.get([:instance, :account_activation_required])
|
||||
|
||||
unless setting do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
|
||||
end
|
||||
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|
||||
info_change = Pleroma.User.Info.confirmation_changeset(user.info, :unconfirmed)
|
||||
|
||||
{:ok, user} =
|
||||
user
|
||||
|> Ecto.Changeset.change()
|
||||
|> Ecto.Changeset.put_embed(:info, info_change)
|
||||
|> Repo.update()
|
||||
|
||||
refute Pleroma.User.auth_active?(user)
|
||||
|
||||
app = insert(:oauth_app)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert resp = json_response(conn, 403)
|
||||
assert %{"error" => _} = resp
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
end
|
||||
|
||||
test "rejects token exchange for valid credentials belonging to deactivated user" do
|
||||
password = "testpassword"
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
|
||||
info: %{deactivated: true}
|
||||
)
|
||||
|
||||
app = insert(:oauth_app)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert resp = json_response(conn, 403)
|
||||
assert %{"error" => _} = resp
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
end
|
||||
|
||||
test "rejects an invalid authorization code" do
|
||||
app = insert(:oauth_app)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => "Imobviouslyinvalid",
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert resp = json_response(conn, 400)
|
||||
assert %{"error" => _} = json_response(conn, 400)
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -116,10 +116,10 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenterTest do
|
|||
|
||||
{:ok, announce, _object} = ActivityPub.announce(user, object)
|
||||
|
||||
announce = Repo.get(Activity, announce.id)
|
||||
announce = Activity.get_by_id(announce.id)
|
||||
|
||||
note_user = User.get_cached_by_ap_id(note.data["actor"])
|
||||
note = Repo.get(Activity, note.id)
|
||||
note = Activity.get_by_id(note.id)
|
||||
|
||||
note_xml =
|
||||
ActivityRepresenter.to_simple_form(note, note_user, true)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.OStatus.DeleteHandlingTest do
|
|||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.OStatus
|
||||
|
||||
setup do
|
||||
|
|
@ -32,10 +31,10 @@ defmodule Pleroma.Web.OStatus.DeleteHandlingTest do
|
|||
|
||||
{:ok, [delete]} = OStatus.handle_incoming(incoming)
|
||||
|
||||
refute Repo.get(Activity, note.id)
|
||||
refute Repo.get(Activity, like.id)
|
||||
refute Activity.get_by_id(note.id)
|
||||
refute Activity.get_by_id(like.id)
|
||||
assert Object.get_by_ap_id(note.data["object"]["id"]).data["type"] == "Tombstone"
|
||||
assert Repo.get(Activity, second_note.id)
|
||||
assert Activity.get_by_id(second_note.id)
|
||||
assert Object.get_by_ap_id(second_note.data["object"]["id"])
|
||||
|
||||
assert delete.data["type"] == "Delete"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
|||
use Pleroma.Web.ConnCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.OStatus.ActivityRepresenter
|
||||
|
|
@ -41,7 +40,8 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
|||
assert response(conn, 200)
|
||||
|
||||
# Set a wrong magic-key for a user so it has to refetch
|
||||
salmon_user = User.get_by_ap_id("http://gs.example.org:4040/index.php/user/1")
|
||||
salmon_user = User.get_cached_by_ap_id("http://gs.example.org:4040/index.php/user/1")
|
||||
|
||||
# Wrong key
|
||||
info_cng =
|
||||
User.Info.remote_user_creation(salmon_user.info, %{
|
||||
|
|
@ -52,7 +52,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
|||
salmon_user
|
||||
|> Ecto.Changeset.change()
|
||||
|> Ecto.Changeset.put_embed(:info, info_cng)
|
||||
|> Repo.update()
|
||||
|> User.update_and_set_cache()
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|
|
@ -86,7 +86,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
|||
|
||||
test "gets an object", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
user = User.get_by_ap_id(note_activity.data["actor"])
|
||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["object"]["id"]))
|
||||
url = "/objects/#{uuid}"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,34 +28,35 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
test "handle incoming note - GS, Salmon" do
|
||||
incoming = File.read!("test/fixtures/incoming_note_activity.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
user = User.get_by_ap_id(activity.data["actor"])
|
||||
user = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
assert user.info.note_count == 1
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert object.data["type"] == "Note"
|
||||
|
||||
assert activity.data["object"]["id"] ==
|
||||
"tag:gs.example.org:4040,2017-04-23:noticeId=29:objectType=note"
|
||||
assert object.data["id"] == "tag:gs.example.org:4040,2017-04-23:noticeId=29:objectType=note"
|
||||
|
||||
assert activity.data["published"] == "2017-04-23T14:51:03+00:00"
|
||||
assert activity.data["object"]["published"] == "2017-04-23T14:51:03+00:00"
|
||||
assert object.data["published"] == "2017-04-23T14:51:03+00:00"
|
||||
|
||||
assert activity.data["context"] ==
|
||||
"tag:gs.example.org:4040,2017-04-23:objectType=thread:nonce=f09e22f58abd5c7b"
|
||||
|
||||
assert "http://pleroma.example.org:4000/users/lain3" in activity.data["to"]
|
||||
assert activity.data["object"]["emoji"] == %{"marko" => "marko.png", "reimu" => "reimu.png"}
|
||||
assert object.data["emoji"] == %{"marko" => "marko.png", "reimu" => "reimu.png"}
|
||||
assert activity.local == false
|
||||
end
|
||||
|
||||
test "handle incoming notes - GS, subscription" do
|
||||
incoming = File.read!("test/fixtures/ostatus_incoming_post.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert activity.data["object"]["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert activity.data["object"]["content"] == "Will it blend?"
|
||||
assert object.data["type"] == "Note"
|
||||
assert object.data["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert object.data["content"] == "Will it blend?"
|
||||
user = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
assert User.ap_followers(user) in activity.data["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
|
|
@ -64,20 +65,22 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
test "handle incoming notes with attachments - GS, subscription" do
|
||||
incoming = File.read!("test/fixtures/incoming_websub_gnusocial_attachments.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert activity.data["object"]["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert activity.data["object"]["attachment"] |> length == 2
|
||||
assert activity.data["object"]["external_url"] == "https://social.heldscal.la/notice/2020923"
|
||||
assert object.data["type"] == "Note"
|
||||
assert object.data["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert object.data["attachment"] |> length == 2
|
||||
assert object.data["external_url"] == "https://social.heldscal.la/notice/2020923"
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
end
|
||||
|
||||
test "handle incoming notes with tags" do
|
||||
incoming = File.read!("test/fixtures/ostatus_incoming_post_tag.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["object"]["tag"] == ["nsfw"]
|
||||
assert object.data["tag"] == ["nsfw"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
end
|
||||
|
||||
|
|
@ -92,10 +95,11 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
|
||||
incoming = File.read!("test/fixtures/incoming_reply_mastodon.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert activity.data["object"]["actor"] == "https://mastodon.social/users/lambadalambda"
|
||||
assert object.data["type"] == "Note"
|
||||
assert object.data["actor"] == "https://mastodon.social/users/lambadalambda"
|
||||
assert activity.data["context"] == "2hu"
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
end
|
||||
|
|
@ -103,42 +107,47 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
test "handle incoming notes - Mastodon, with CW" do
|
||||
incoming = File.read!("test/fixtures/mastodon-note-cw.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert activity.data["object"]["actor"] == "https://mastodon.social/users/lambadalambda"
|
||||
assert activity.data["object"]["summary"] == "technologic"
|
||||
assert object.data["type"] == "Note"
|
||||
assert object.data["actor"] == "https://mastodon.social/users/lambadalambda"
|
||||
assert object.data["summary"] == "technologic"
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
end
|
||||
|
||||
test "handle incoming unlisted messages, put public into cc" do
|
||||
incoming = File.read!("test/fixtures/mastodon-note-unlisted.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["cc"]
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in activity.data["object"]["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["object"]["cc"]
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in object.data["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in object.data["cc"]
|
||||
end
|
||||
|
||||
test "handle incoming retweets - Mastodon, with CW" do
|
||||
incoming = File.read!("test/fixtures/cw_retweet.xml")
|
||||
{:ok, [[_activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
|
||||
retweeted_object = Object.normalize(retweeted_activity.data["object"])
|
||||
|
||||
assert retweeted_activity.data["object"]["summary"] == "Hey."
|
||||
assert retweeted_object.data["summary"] == "Hey."
|
||||
end
|
||||
|
||||
test "handle incoming notes - GS, subscription, reply" do
|
||||
incoming = File.read!("test/fixtures/ostatus_incoming_reply.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert activity.data["object"]["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert object.data["type"] == "Note"
|
||||
assert object.data["actor"] == "https://social.heldscal.la/user/23211"
|
||||
|
||||
assert activity.data["object"]["content"] ==
|
||||
assert object.data["content"] ==
|
||||
"@<a href=\"https://gs.archae.me/user/4687\" class=\"h-card u-url p-nickname mention\" title=\"shpbot\">shpbot</a> why not indeed."
|
||||
|
||||
assert activity.data["object"]["inReplyTo"] ==
|
||||
assert object.data["inReplyTo"] ==
|
||||
"tag:gs.archae.me,2017-04-30:noticeId=778260:objectType=note"
|
||||
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
|
|
@ -150,17 +159,18 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
|
||||
assert activity.data["type"] == "Announce"
|
||||
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert activity.data["object"] == retweeted_activity.data["object"]["id"]
|
||||
assert activity.data["object"] == retweeted_activity.data["object"]
|
||||
assert "https://pleroma.soykaf.com/users/lain" in activity.data["to"]
|
||||
refute activity.local
|
||||
|
||||
retweeted_activity = Repo.get(Activity, retweeted_activity.id)
|
||||
retweeted_activity = Activity.get_by_id(retweeted_activity.id)
|
||||
retweeted_object = Object.normalize(retweeted_activity.data["object"])
|
||||
assert retweeted_activity.data["type"] == "Create"
|
||||
assert retweeted_activity.data["actor"] == "https://pleroma.soykaf.com/users/lain"
|
||||
refute retweeted_activity.local
|
||||
assert retweeted_activity.data["object"]["announcement_count"] == 1
|
||||
assert String.contains?(retweeted_activity.data["object"]["content"], "mastodon")
|
||||
refute String.contains?(retweeted_activity.data["object"]["content"], "Test account")
|
||||
assert retweeted_object.data["announcement_count"] == 1
|
||||
assert String.contains?(retweeted_object.data["content"], "mastodon")
|
||||
refute String.contains?(retweeted_object.data["content"], "Test account")
|
||||
end
|
||||
|
||||
test "handle incoming retweets - GS, subscription - local message" do
|
||||
|
|
@ -181,7 +191,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
assert user.ap_id in activity.data["to"]
|
||||
refute activity.local
|
||||
|
||||
retweeted_activity = Repo.get(Activity, retweeted_activity.id)
|
||||
retweeted_activity = Activity.get_by_id(retweeted_activity.id)
|
||||
assert note_activity.id == retweeted_activity.id
|
||||
assert retweeted_activity.data["type"] == "Create"
|
||||
assert retweeted_activity.data["actor"] == user.ap_id
|
||||
|
|
@ -192,10 +202,11 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
test "handle incoming retweets - Mastodon, salmon" do
|
||||
incoming = File.read!("test/fixtures/share.xml")
|
||||
{:ok, [[activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
|
||||
retweeted_object = Object.normalize(retweeted_activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Announce"
|
||||
assert activity.data["actor"] == "https://mastodon.social/users/lambadalambda"
|
||||
assert activity.data["object"] == retweeted_activity.data["object"]["id"]
|
||||
assert activity.data["object"] == retweeted_activity.data["object"]
|
||||
|
||||
assert activity.data["id"] ==
|
||||
"tag:mastodon.social,2017-05-03:objectId=4934452:objectType=Status"
|
||||
|
|
@ -204,7 +215,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
assert retweeted_activity.data["type"] == "Create"
|
||||
assert retweeted_activity.data["actor"] == "https://pleroma.soykaf.com/users/lain"
|
||||
refute retweeted_activity.local
|
||||
refute String.contains?(retweeted_activity.data["object"]["content"], "Test account")
|
||||
refute String.contains?(retweeted_object.data["content"], "Test account")
|
||||
end
|
||||
|
||||
test "handle incoming favorites - GS, websub" do
|
||||
|
|
@ -214,7 +225,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
|
||||
assert activity.data["type"] == "Like"
|
||||
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
|
||||
assert activity.data["object"] == favorited_activity.data["object"]["id"]
|
||||
assert activity.data["object"] == favorited_activity.data["object"]
|
||||
|
||||
assert activity.data["id"] ==
|
||||
"tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061643:2017-05-05T09:12:50+00:00"
|
||||
|
|
@ -223,7 +234,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
assert favorited_activity.data["type"] == "Create"
|
||||
assert favorited_activity.data["actor"] == "https://shitposter.club/user/1"
|
||||
|
||||
assert favorited_activity.data["object"]["id"] ==
|
||||
assert favorited_activity.data["object"] ==
|
||||
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
||||
|
||||
refute favorited_activity.local
|
||||
|
|
@ -258,17 +269,17 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
test "handle incoming replies" do
|
||||
incoming = File.read!("test/fixtures/incoming_note_activity_answer.xml")
|
||||
{:ok, [activity]} = OStatus.handle_incoming(incoming)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
assert activity.data["type"] == "Create"
|
||||
assert activity.data["object"]["type"] == "Note"
|
||||
assert object.data["type"] == "Note"
|
||||
|
||||
assert activity.data["object"]["inReplyTo"] ==
|
||||
assert object.data["inReplyTo"] ==
|
||||
"http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc"
|
||||
|
||||
assert "http://pleroma.example.org:4000/users/lain5" in activity.data["to"]
|
||||
|
||||
assert activity.data["object"]["id"] ==
|
||||
"tag:gs.example.org:4040,2017-04-25:noticeId=55:objectType=note"
|
||||
assert object.data["id"] == "tag:gs.example.org:4040,2017-04-25:noticeId=55:objectType=note"
|
||||
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
|
||||
end
|
||||
|
|
@ -285,8 +296,8 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
assert activity.data["object"] == "https://pawoo.net/users/pekorino"
|
||||
refute activity.local
|
||||
|
||||
follower = User.get_by_ap_id(activity.data["actor"])
|
||||
followed = User.get_by_ap_id(activity.data["object"])
|
||||
follower = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
followed = User.get_cached_by_ap_id(activity.data["object"])
|
||||
|
||||
assert User.following?(follower, followed)
|
||||
end
|
||||
|
|
@ -309,8 +320,8 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
assert activity.data["object"]["object"] == "https://pawoo.net/users/pekorino"
|
||||
refute activity.local
|
||||
|
||||
follower = User.get_by_ap_id(activity.data["actor"])
|
||||
followed = User.get_by_ap_id(activity.data["object"]["object"])
|
||||
follower = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
followed = User.get_cached_by_ap_id(activity.data["object"]["object"])
|
||||
|
||||
refute User.following?(follower, followed)
|
||||
end
|
||||
|
|
@ -344,7 +355,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
|
||||
{:ok, user} = OStatus.find_or_make_user(uri)
|
||||
|
||||
user = Repo.get(Pleroma.User, user.id)
|
||||
user = Pleroma.User.get_cached_by_id(user.id)
|
||||
assert user.name == "Constance Variable"
|
||||
assert user.nickname == "lambadalambda@social.heldscal.la"
|
||||
assert user.local == false
|
||||
|
|
@ -495,7 +506,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
|
||||
assert activity.data["actor"] == "https://shitposter.club/user/1"
|
||||
|
||||
assert activity.data["object"]["id"] ==
|
||||
assert activity.data["object"] ==
|
||||
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
||||
end)
|
||||
end
|
||||
|
|
@ -504,7 +515,7 @@ defmodule Pleroma.Web.OStatusTest do
|
|||
url = "https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056"
|
||||
{:ok, [activity]} = OStatus.fetch_activity_from_url(url)
|
||||
assert activity.data["actor"] == "https://social.sakamoto.gq/users/eal"
|
||||
assert activity.data["object"]["id"] == url
|
||||
assert activity.data["object"] == url
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
defmodule Pleroma.Web.Push.ImplTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.Push.Impl
|
||||
alias Pleroma.Web.Push.Subscription
|
||||
|
||||
|
|
@ -52,29 +54,27 @@ defmodule Pleroma.Web.Push.ImplTest do
|
|||
data: %{alerts: %{"follow" => true, "mention" => false}}
|
||||
)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "<Lorem ipsum dolor sit amet."})
|
||||
|
||||
notif =
|
||||
insert(:notification,
|
||||
user: user,
|
||||
activity: %Pleroma.Activity{
|
||||
data: %{
|
||||
"type" => "Create",
|
||||
"actor" => user.ap_id,
|
||||
"object" => %{"content" => "<Lorem ipsum dolor sit amet."}
|
||||
}
|
||||
}
|
||||
activity: activity
|
||||
)
|
||||
|
||||
assert Impl.perform_send(notif) == [:ok, :ok]
|
||||
assert Impl.perform(notif) == [:ok, :ok]
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns error if notif does not match " do
|
||||
assert Impl.perform_send(%{}) == :error
|
||||
assert Impl.perform(%{}) == :error
|
||||
end
|
||||
|
||||
test "successful message sending" do
|
||||
assert Impl.push_message(@message, @sub, @api_key, %Subscription{}) == :ok
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "fail message sending" do
|
||||
assert Impl.push_message(
|
||||
@message,
|
||||
|
|
@ -98,48 +98,65 @@ defmodule Pleroma.Web.Push.ImplTest do
|
|||
end
|
||||
|
||||
test "renders body for create activity" do
|
||||
user = insert(:user, nickname: "Bob")
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert Impl.format_body(
|
||||
%{
|
||||
activity: %{
|
||||
data: %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" =>
|
||||
"<span>Lorem ipsum dolor sit amet</span>, consectetur :bear: adipiscing elit. Fusce sagittis finibus turpis."
|
||||
}
|
||||
}
|
||||
}
|
||||
activity: activity
|
||||
},
|
||||
%{nickname: "Bob"}
|
||||
user,
|
||||
object
|
||||
) ==
|
||||
"@Bob: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..."
|
||||
end
|
||||
|
||||
test "renders body for follow activity" do
|
||||
assert Impl.format_body(%{activity: %{data: %{"type" => "Follow"}}}, %{nickname: "Bob"}) ==
|
||||
user = insert(:user, nickname: "Bob")
|
||||
other_user = insert(:user)
|
||||
{:ok, _, _, activity} = CommonAPI.follow(user, other_user)
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert Impl.format_body(%{activity: activity}, user, object) ==
|
||||
"@Bob has followed you"
|
||||
end
|
||||
|
||||
test "renders body for announce activity" do
|
||||
user = insert(:user)
|
||||
|
||||
note =
|
||||
insert(:note, %{
|
||||
data: %{
|
||||
"content" =>
|
||||
"<span>Lorem ipsum dolor sit amet</span>, consectetur :bear: adipiscing elit. Fusce sagittis finibus turpis."
|
||||
}
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
|
||||
})
|
||||
|
||||
note_activity = insert(:note_activity, %{note: note})
|
||||
announce_activity = insert(:announce_activity, %{user: user, note_activity: note_activity})
|
||||
{:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user)
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert Impl.format_body(%{activity: announce_activity}, user) ==
|
||||
assert Impl.format_body(%{activity: announce_activity}, user, object) ==
|
||||
"@#{user.nickname} repeated: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..."
|
||||
end
|
||||
|
||||
test "renders body for like activity" do
|
||||
assert Impl.format_body(%{activity: %{data: %{"type" => "Like"}}}, %{nickname: "Bob"}) ==
|
||||
user = insert(:user, nickname: "Bob")
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
|
||||
})
|
||||
|
||||
{:ok, activity, _} = CommonAPI.favorite(activity.id, user)
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert Impl.format_body(%{activity: activity}, user, object) ==
|
||||
"@Bob has favorited your post"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ defmodule Pleroma.Web.Salmon.SalmonTest do
|
|||
}
|
||||
|
||||
{:ok, activity} = Repo.insert(%Activity{data: activity_data, recipients: activity_data["to"]})
|
||||
user = Repo.get_by(User, ap_id: activity.data["actor"])
|
||||
user = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
{:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
|
||||
|
||||
poster = fn url, _data, _headers ->
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import Swoosh.TestAssertions
|
||||
|
||||
@banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
|
||||
|
||||
|
|
@ -269,7 +270,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
test "returns one status", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
|
||||
actor = Repo.get_by!(User, ap_id: activity.data["actor"])
|
||||
actor = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|
|
@ -719,7 +720,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post("/api/friendships/create.json", %{user_id: followed.id})
|
||||
|
||||
current_user = Repo.get(User, current_user.id)
|
||||
current_user = User.get_cached_by_id(current_user.id)
|
||||
assert User.ap_followers(followed) in current_user.following
|
||||
|
||||
assert json_response(conn, 200) ==
|
||||
|
|
@ -734,8 +735,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post("/api/friendships/create.json", %{user_id: followed.id})
|
||||
|
||||
current_user = Repo.get(User, current_user.id)
|
||||
followed = Repo.get(User, followed.id)
|
||||
current_user = User.get_cached_by_id(current_user.id)
|
||||
followed = User.get_cached_by_id(followed.id)
|
||||
|
||||
refute User.ap_followers(followed) in current_user.following
|
||||
|
||||
|
|
@ -764,7 +765,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post("/api/friendships/destroy.json", %{user_id: followed.id})
|
||||
|
||||
current_user = Repo.get(User, current_user.id)
|
||||
current_user = User.get_cached_by_id(current_user.id)
|
||||
assert current_user.following == [current_user.ap_id]
|
||||
|
||||
assert json_response(conn, 200) ==
|
||||
|
|
@ -788,7 +789,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post("/api/blocks/create.json", %{user_id: blocked.id})
|
||||
|
||||
current_user = Repo.get(User, current_user.id)
|
||||
current_user = User.get_cached_by_id(current_user.id)
|
||||
assert User.blocks?(current_user, blocked)
|
||||
|
||||
assert json_response(conn, 200) ==
|
||||
|
|
@ -815,7 +816,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post("/api/blocks/destroy.json", %{user_id: blocked.id})
|
||||
|
||||
current_user = Repo.get(User, current_user.id)
|
||||
current_user = User.get_cached_by_id(current_user.id)
|
||||
assert current_user.info.blocks == []
|
||||
|
||||
assert json_response(conn, 200) ==
|
||||
|
|
@ -846,7 +847,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
|
||||
|
||||
current_user = Repo.get(User, current_user.id)
|
||||
current_user = User.get_cached_by_id(current_user.id)
|
||||
assert is_map(current_user.avatar)
|
||||
|
||||
assert json_response(conn, 200) ==
|
||||
|
|
@ -954,8 +955,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post(request_path)
|
||||
|
||||
activity = Repo.get(Activity, note_activity.id)
|
||||
activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
|
||||
activity = Activity.get_by_id(note_activity.id)
|
||||
activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
assert json_response(response, 200) ==
|
||||
ActivityView.render("activity.json", %{
|
||||
|
|
@ -992,8 +993,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> with_credentials(current_user.nickname, "test")
|
||||
|> post(request_path)
|
||||
|
||||
activity = Repo.get(Activity, note_activity.id)
|
||||
activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
|
||||
activity = Activity.get_by_id(note_activity.id)
|
||||
activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
assert json_response(response, 200) ==
|
||||
ActivityView.render("activity.json", %{
|
||||
|
|
@ -1021,7 +1022,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|
||||
user = json_response(conn, 200)
|
||||
|
||||
fetched_user = Repo.get_by(User, nickname: "lain")
|
||||
fetched_user = User.get_cached_by_nickname("lain")
|
||||
assert user == UserView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
|
|
@ -1063,8 +1064,14 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
test "it sends an email to user", %{user: user} do
|
||||
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
Pleroma.UserEmail.password_reset_email(user, token_record.token)
|
||||
email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
|
||||
notify_email = Pleroma.Config.get([:instance, :notify_email])
|
||||
instance_name = Pleroma.Config.get([:instance, :name])
|
||||
|
||||
assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -1109,7 +1116,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
test "it confirms the user account", %{conn: conn, user: user} do
|
||||
get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
refute user.info.confirmation_pending
|
||||
refute user.info.confirmation_token
|
||||
|
|
@ -1163,7 +1170,15 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|> assign(:user, user)
|
||||
|> post("/api/account/resend_confirmation_email?email=#{user.email}")
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(Pleroma.UserEmail.account_confirmation_email(user))
|
||||
email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
|
||||
notify_email = Pleroma.Config.get([:instance, :notify_email])
|
||||
instance_name = Pleroma.Config.get([:instance, :name])
|
||||
|
||||
assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1596,6 +1611,34 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|
||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
# Broken before the change to class="emoji" and non-<img/> in the DB
|
||||
@tag :skip
|
||||
test "it formats emojos", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> post("/api/account/update_profile.json", %{
|
||||
"bio" => "I love our :moominmamma:"
|
||||
})
|
||||
|
||||
assert response = json_response(conn, 200)
|
||||
|
||||
assert %{
|
||||
"description" => "I love our :moominmamma:",
|
||||
"description_html" =>
|
||||
~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
|
||||
_
|
||||
} = response
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> get("/api/users/show.json?user_id=#{user.nickname}")
|
||||
|
||||
assert response == json_response(conn, 200)
|
||||
end
|
||||
end
|
||||
|
||||
defp valid_user(_context) do
|
||||
|
|
@ -1727,7 +1770,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
})
|
||||
|
||||
assert json_response(conn, 200) == %{"status" => "success"}
|
||||
fetched_user = Repo.get(User, current_user.id)
|
||||
fetched_user = User.get_cached_by_id(current_user.id)
|
||||
assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
|
||||
end
|
||||
end
|
||||
|
|
@ -1768,8 +1811,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|
||||
{:ok, _activity} = ActivityPub.follow(other_user, user)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
other_user = Repo.get(User, other_user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
|
||||
|
|
@ -1808,8 +1851,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|
||||
{:ok, _activity} = ActivityPub.follow(other_user, user)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
other_user = Repo.get(User, other_user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
|
||||
|
|
@ -1831,8 +1874,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
|
||||
{:ok, _activity} = ActivityPub.follow(other_user, user)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
other_user = Repo.get(User, other_user.id)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
|
||||
|
|
@ -1901,7 +1944,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
|||
describe "POST /api/media/metadata/create" do
|
||||
setup do
|
||||
object = insert(:note)
|
||||
user = User.get_by_ap_id(object.data["actor"])
|
||||
user = User.get_cached_by_ap_id(object.data["actor"])
|
||||
%{object: object, user: user}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "create a status" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user, %{nickname: "shp", ap_id: "shp"})
|
||||
|
|
@ -36,18 +41,19 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
|
||||
input = %{
|
||||
"status" =>
|
||||
"Hello again, @shp.<script></script>\nThis is on another :moominmamma: line. #2hu #epic #phantasmagoric",
|
||||
"Hello again, @shp.<script></script>\nThis is on another :firefox: line. #2hu #epic #phantasmagoric",
|
||||
"media_ids" => [object.id]
|
||||
}
|
||||
|
||||
{:ok, activity = %Activity{}} = TwitterAPI.create_status(user, input)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
expected_text =
|
||||
"Hello again, <span class='h-card'><a data-user='#{mentioned_user.id}' class='u-url mention' href='shp'>@<span>shp</span></a></span>.<script></script><br>This is on another :moominmamma: line. <a class='hashtag' data-tag='2hu' href='http://localhost:4001/tag/2hu' rel='tag'>#2hu</a> <a class='hashtag' data-tag='epic' href='http://localhost:4001/tag/epic' rel='tag'>#epic</a> <a class='hashtag' data-tag='phantasmagoric' href='http://localhost:4001/tag/phantasmagoric' rel='tag'>#phantasmagoric</a><br><a href=\"http://example.org/image.jpg\" class='attachment'>image.jpg</a>"
|
||||
"Hello again, <span class='h-card'><a data-user='#{mentioned_user.id}' class='u-url mention' href='shp'>@<span>shp</span></a></span>.<script></script><br>This is on another :firefox: line. <a class='hashtag' data-tag='2hu' href='http://localhost:4001/tag/2hu' rel='tag'>#2hu</a> <a class='hashtag' data-tag='epic' href='http://localhost:4001/tag/epic' rel='tag'>#epic</a> <a class='hashtag' data-tag='phantasmagoric' href='http://localhost:4001/tag/phantasmagoric' rel='tag'>#phantasmagoric</a><br><a href=\"http://example.org/image.jpg\" class='attachment'>image.jpg</a>"
|
||||
|
||||
assert get_in(activity.data, ["object", "content"]) == expected_text
|
||||
assert get_in(activity.data, ["object", "type"]) == "Note"
|
||||
assert get_in(activity.data, ["object", "actor"]) == user.ap_id
|
||||
assert get_in(object.data, ["content"]) == expected_text
|
||||
assert get_in(object.data, ["type"]) == "Note"
|
||||
assert get_in(object.data, ["actor"]) == user.ap_id
|
||||
assert get_in(activity.data, ["actor"]) == user.ap_id
|
||||
assert Enum.member?(get_in(activity.data, ["cc"]), User.ap_followers(user))
|
||||
|
||||
|
|
@ -59,21 +65,20 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
assert Enum.member?(get_in(activity.data, ["to"]), "shp")
|
||||
assert activity.local == true
|
||||
|
||||
assert %{"moominmamma" => "http://localhost:4001/finmoji/128px/moominmamma-128.png"} =
|
||||
activity.data["object"]["emoji"]
|
||||
assert %{"firefox" => "http://localhost:4001/emoji/Firefox.gif"} = object.data["emoji"]
|
||||
|
||||
# hashtags
|
||||
assert activity.data["object"]["tag"] == ["2hu", "epic", "phantasmagoric"]
|
||||
assert object.data["tag"] == ["2hu", "epic", "phantasmagoric"]
|
||||
|
||||
# Add a context
|
||||
assert is_binary(get_in(activity.data, ["context"]))
|
||||
assert is_binary(get_in(activity.data, ["object", "context"]))
|
||||
assert is_binary(get_in(object.data, ["context"]))
|
||||
|
||||
assert is_list(activity.data["object"]["attachment"])
|
||||
assert is_list(object.data["attachment"])
|
||||
|
||||
assert activity.data["object"] == Object.get_by_ap_id(activity.data["object"]["id"]).data
|
||||
assert activity.data["object"] == object.data["id"]
|
||||
|
||||
user = User.get_by_ap_id(user.ap_id)
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.info.note_count == 1
|
||||
end
|
||||
|
|
@ -86,6 +91,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
}
|
||||
|
||||
{:ok, activity = %Activity{}} = TwitterAPI.create_status(user, input)
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
input = %{
|
||||
"status" => "Here's your (you).",
|
||||
|
|
@ -93,14 +99,14 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
}
|
||||
|
||||
{:ok, reply = %Activity{}} = TwitterAPI.create_status(user, input)
|
||||
reply_object = Object.normalize(reply.data["object"])
|
||||
|
||||
assert get_in(reply.data, ["context"]) == get_in(activity.data, ["context"])
|
||||
|
||||
assert get_in(reply.data, ["object", "context"]) ==
|
||||
get_in(activity.data, ["object", "context"])
|
||||
assert get_in(reply_object.data, ["context"]) == get_in(object.data, ["context"])
|
||||
|
||||
assert get_in(reply.data, ["object", "inReplyTo"]) == get_in(activity.data, ["object", "id"])
|
||||
assert get_in(reply.data, ["object", "inReplyToStatusId"]) == activity.id
|
||||
assert get_in(reply_object.data, ["inReplyTo"]) == get_in(activity.data, ["object"])
|
||||
assert Activity.get_in_reply_to_activity(reply).id == activity.id
|
||||
end
|
||||
|
||||
test "Follow another user using user_id" do
|
||||
|
|
@ -123,7 +129,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
|
||||
assert User.ap_followers(followed) in user.following
|
||||
|
||||
followed = User.get_by_ap_id(followed.ap_id)
|
||||
followed = User.get_cached_by_ap_id(followed.ap_id)
|
||||
assert followed.info.follower_count == 1
|
||||
|
||||
{:error, msg} = TwitterAPI.follow(user, %{"screen_name" => followed.nickname})
|
||||
|
|
@ -275,7 +281,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
|
||||
fetched_user = Repo.get_by(User, nickname: "lain")
|
||||
fetched_user = User.get_cached_by_nickname("lain")
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
|
|
@ -293,13 +299,12 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
|
||||
fetched_user = Repo.get_by(User, nickname: "lain")
|
||||
fetched_user = User.get_cached_by_nickname("lain")
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
@moduletag skip: "needs 'account_activation_required: true' in config"
|
||||
test "it sends confirmation email if :account_activation_required is specified in instance config" do
|
||||
setting = Pleroma.Config.get([:instance, :account_activation_required])
|
||||
|
||||
|
|
@ -321,7 +326,16 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
|
||||
assert user.info.confirmation_pending
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(Pleroma.UserEmail.account_confirmation_email(user))
|
||||
email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
|
||||
|
||||
notify_email = Pleroma.Config.get([:instance, :notify_email])
|
||||
instance_name = Pleroma.Config.get([:instance, :name])
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
test "it registers a new user and parses mentions in the bio" do
|
||||
|
|
@ -353,68 +367,313 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
assert user2.bio == expected_text
|
||||
end
|
||||
|
||||
@moduletag skip: "needs 'registrations_open: false' in config"
|
||||
test "it registers a new user via invite token and returns the user." do
|
||||
{:ok, token} = UserInviteToken.create_token()
|
||||
describe "register with one time token" do
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :registrations_open])
|
||||
|
||||
data = %{
|
||||
"nickname" => "vinny",
|
||||
"email" => "pasta@pizza.vs",
|
||||
"fullname" => "Vinny Vinesauce",
|
||||
"bio" => "streamer",
|
||||
"password" => "hiptofbees",
|
||||
"confirm" => "hiptofbees",
|
||||
"token" => token.token
|
||||
}
|
||||
if setting do
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :registrations_open], setting) end)
|
||||
end
|
||||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
:ok
|
||||
end
|
||||
|
||||
fetched_user = Repo.get_by(User, nickname: "vinny")
|
||||
token = Repo.get_by(UserInviteToken, token: token.token)
|
||||
test "returns user on success" do
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
|
||||
assert token.used == true
|
||||
data = %{
|
||||
"nickname" => "vinny",
|
||||
"email" => "pasta@pizza.vs",
|
||||
"fullname" => "Vinny Vinesauce",
|
||||
"bio" => "streamer",
|
||||
"password" => "hiptofbees",
|
||||
"confirm" => "hiptofbees",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
|
||||
fetched_user = User.get_cached_by_nickname("vinny")
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
|
||||
assert invite.used == true
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
test "returns error on invalid token" do
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => "DudeLetMeInImAFairy"
|
||||
}
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Invalid token"
|
||||
refute User.get_cached_by_nickname("GrimReaper")
|
||||
end
|
||||
|
||||
test "returns error on expired token" do
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
UserInviteToken.update_invite!(invite, used: true)
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute User.get_cached_by_nickname("GrimReaper")
|
||||
end
|
||||
end
|
||||
|
||||
@moduletag skip: "needs 'registrations_open: false' in config"
|
||||
test "it returns an error if invalid token submitted" do
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => "DudeLetMeInImAFairy"
|
||||
}
|
||||
describe "registers with date limited token" do
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :registrations_open])
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
if setting do
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :registrations_open], setting) end)
|
||||
end
|
||||
|
||||
assert msg == "Invalid token"
|
||||
refute Repo.get_by(User, nickname: "GrimReaper")
|
||||
data = %{
|
||||
"nickname" => "vinny",
|
||||
"email" => "pasta@pizza.vs",
|
||||
"fullname" => "Vinny Vinesauce",
|
||||
"bio" => "streamer",
|
||||
"password" => "hiptofbees",
|
||||
"confirm" => "hiptofbees"
|
||||
}
|
||||
|
||||
check_fn = fn invite ->
|
||||
data = Map.put(data, "token", invite.token)
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
fetched_user = User.get_cached_by_nickname("vinny")
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
{:ok, data: data, check_fn: check_fn}
|
||||
end
|
||||
|
||||
test "returns user on success", %{check_fn: check_fn} do
|
||||
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today()})
|
||||
|
||||
check_fn.(invite)
|
||||
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
|
||||
refute invite.used
|
||||
end
|
||||
|
||||
test "returns user on token which expired tomorrow", %{check_fn: check_fn} do
|
||||
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), 1)})
|
||||
|
||||
check_fn.(invite)
|
||||
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
|
||||
refute invite.used
|
||||
end
|
||||
|
||||
test "returns an error on overdue date", %{data: data} do
|
||||
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1)})
|
||||
|
||||
data = Map.put(data, "token", invite.token)
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute User.get_cached_by_nickname("vinny")
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
|
||||
refute invite.used
|
||||
end
|
||||
end
|
||||
|
||||
@moduletag skip: "needs 'registrations_open: false' in config"
|
||||
test "it returns an error if expired token submitted" do
|
||||
{:ok, token} = UserInviteToken.create_token()
|
||||
UserInviteToken.mark_as_used(token.token)
|
||||
describe "registers with reusable token" do
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :registrations_open])
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => token.token
|
||||
}
|
||||
if setting do
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :registrations_open], setting) end)
|
||||
end
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
:ok
|
||||
end
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute Repo.get_by(User, nickname: "GrimReaper")
|
||||
test "returns user on success, after him registration fails" do
|
||||
{:ok, invite} = UserInviteToken.create_invite(%{max_use: 100})
|
||||
|
||||
UserInviteToken.update_invite!(invite, uses: 99)
|
||||
|
||||
data = %{
|
||||
"nickname" => "vinny",
|
||||
"email" => "pasta@pizza.vs",
|
||||
"fullname" => "Vinny Vinesauce",
|
||||
"bio" => "streamer",
|
||||
"password" => "hiptofbees",
|
||||
"confirm" => "hiptofbees",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
fetched_user = User.get_cached_by_nickname("vinny")
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
|
||||
assert invite.used == true
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute User.get_cached_by_nickname("GrimReaper")
|
||||
end
|
||||
end
|
||||
|
||||
describe "registers with reusable date limited token" do
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :registrations_open])
|
||||
|
||||
if setting do
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :registrations_open], setting) end)
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "returns user on success" do
|
||||
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
|
||||
|
||||
data = %{
|
||||
"nickname" => "vinny",
|
||||
"email" => "pasta@pizza.vs",
|
||||
"fullname" => "Vinny Vinesauce",
|
||||
"bio" => "streamer",
|
||||
"password" => "hiptofbees",
|
||||
"confirm" => "hiptofbees",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
fetched_user = User.get_cached_by_nickname("vinny")
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
|
||||
refute invite.used
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
test "error after max uses" do
|
||||
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
|
||||
|
||||
UserInviteToken.update_invite!(invite, uses: 99)
|
||||
|
||||
data = %{
|
||||
"nickname" => "vinny",
|
||||
"email" => "pasta@pizza.vs",
|
||||
"fullname" => "Vinny Vinesauce",
|
||||
"bio" => "streamer",
|
||||
"password" => "hiptofbees",
|
||||
"confirm" => "hiptofbees",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
fetched_user = User.get_cached_by_nickname("vinny")
|
||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
assert invite.used == true
|
||||
|
||||
assert UserView.render("show.json", %{user: user}) ==
|
||||
UserView.render("show.json", %{user: fetched_user})
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute User.get_cached_by_nickname("GrimReaper")
|
||||
end
|
||||
|
||||
test "returns error on overdue date" do
|
||||
{:ok, invite} =
|
||||
UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute User.get_cached_by_nickname("GrimReaper")
|
||||
end
|
||||
|
||||
test "returns error on with overdue date and after max" do
|
||||
{:ok, invite} =
|
||||
UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
|
||||
|
||||
UserInviteToken.update_invite!(invite, uses: 100)
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
"email" => "death@reapers.afterlife",
|
||||
"fullname" => "Reaper Grim",
|
||||
"bio" => "Your time has come",
|
||||
"password" => "scythe",
|
||||
"confirm" => "scythe",
|
||||
"token" => invite.token
|
||||
}
|
||||
|
||||
{:error, msg} = TwitterAPI.register_user(data)
|
||||
|
||||
assert msg == "Expired token"
|
||||
refute User.get_cached_by_nickname("GrimReaper")
|
||||
end
|
||||
end
|
||||
|
||||
test "it returns the error on registration problems" do
|
||||
|
|
@ -429,7 +688,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
{:error, error_object} = TwitterAPI.register_user(data)
|
||||
|
||||
assert is_binary(error_object[:error])
|
||||
refute Repo.get_by(User, nickname: "lain")
|
||||
refute User.get_cached_by_nickname("lain")
|
||||
end
|
||||
|
||||
test "it assigns an integer conversation_id" do
|
||||
|
|
@ -450,7 +709,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
id = "https://mastodon.social/users/lambadalambda"
|
||||
user = insert(:user)
|
||||
{:ok, represented} = TwitterAPI.get_external_profile(user, id)
|
||||
remote = User.get_by_ap_id(id)
|
||||
remote = User.get_cached_by_ap_id(id)
|
||||
|
||||
assert represented["id"] == UserView.render("show.json", %{user: remote, for: user})["id"]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,15 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
|||
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/follow_import" do
|
||||
test "it returns HTTP 200", %{conn: conn} do
|
||||
user1 = insert(:user)
|
||||
|
|
@ -20,6 +26,21 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
|||
assert response == "job started"
|
||||
end
|
||||
|
||||
test "it imports new-style mastodon follow lists", %{conn: conn} do
|
||||
user1 = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user1)
|
||||
|> post("/api/pleroma/follow_import", %{
|
||||
"list" => "Account address,Show boosts\n#{user2.ap_id},true"
|
||||
})
|
||||
|> json_response(:ok)
|
||||
|
||||
assert response == "job started"
|
||||
end
|
||||
|
||||
test "requires 'follow' permission", %{conn: conn} do
|
||||
token1 = insert(:oauth_token, scopes: ["read", "write"])
|
||||
token2 = insert(:oauth_token, scopes: ["follow"])
|
||||
|
|
@ -74,6 +95,26 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "PUT /api/pleroma/notification_settings" do
|
||||
test "it updates notification settings", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> put("/api/pleroma/notification_settings", %{
|
||||
"remote" => false,
|
||||
"followers" => false,
|
||||
"bar" => 1
|
||||
})
|
||||
|> json_response(:ok)
|
||||
|
||||
user = Repo.get(User, user.id)
|
||||
|
||||
assert %{"remote" => false, "local" => true, "followers" => false, "follows" => true} ==
|
||||
user.info.notification_settings
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/statusnet/config.json" do
|
||||
test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
||||
option = Pleroma.Config.get([:instance, :safe_dm_mentions])
|
||||
|
|
@ -164,4 +205,50 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
|||
assert response == Jason.encode!(config |> Enum.into(%{})) |> Jason.decode!()
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/emoji" do
|
||||
test "returns json with custom emoji with tags", %{conn: conn} do
|
||||
emoji =
|
||||
conn
|
||||
|> get("/api/pleroma/emoji")
|
||||
|> json_response(200)
|
||||
|
||||
assert Enum.all?(emoji, fn
|
||||
{_key,
|
||||
%{
|
||||
"image_url" => url,
|
||||
"tags" => tags
|
||||
}} ->
|
||||
is_binary(url) and is_list(tags)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /ostatus_subscribe?acct=...." do
|
||||
test "adds status to pleroma instance if the `acct` is a status", %{conn: conn} do
|
||||
conn =
|
||||
get(
|
||||
conn,
|
||||
"/ostatus_subscribe?acct=https://mastodon.social/users/emelie/statuses/101849165031453009"
|
||||
)
|
||||
|
||||
assert redirected_to(conn) =~ "/notice/"
|
||||
end
|
||||
|
||||
test "show follow account page if the `acct` is a account link", %{conn: conn} do
|
||||
response =
|
||||
get(
|
||||
conn,
|
||||
"/ostatus_subscribe?acct=https://mastodon.social/users/emelie"
|
||||
)
|
||||
|
||||
assert html_response(response, 200) =~ "Log in to follow"
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /api/pleroma/healthcheck", %{conn: conn} do
|
||||
conn = get(conn, "/api/pleroma/healthcheck")
|
||||
|
||||
assert conn.status in [200, 503]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
|
@ -90,16 +91,16 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
test "a create activity with a summary containing emoji" do
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(insert(:user), %{
|
||||
"spoiler_text" => ":woollysocks: meow",
|
||||
"spoiler_text" => ":firefox: meow",
|
||||
"status" => "."
|
||||
})
|
||||
|
||||
result = ActivityView.render("activity.json", activity: activity)
|
||||
|
||||
expected = ":woollysocks: meow"
|
||||
expected = ":firefox: meow"
|
||||
|
||||
expected_html =
|
||||
"<img height=\"32px\" width=\"32px\" alt=\"woollysocks\" title=\"woollysocks\" src=\"http://localhost:4001/finmoji/128px/woollysocks-128.png\" /> meow"
|
||||
"<img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"http://localhost:4001/emoji/Firefox.gif\" /> meow"
|
||||
|
||||
assert result["summary"] == expected
|
||||
assert result["summary_html"] == expected_html
|
||||
|
|
@ -125,10 +126,11 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
other_user = insert(:user, %{nickname: "shp"})
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
result = ActivityView.render("activity.json", activity: activity)
|
||||
|
||||
convo_id = Utils.context_to_conversation_id(activity.data["object"]["context"])
|
||||
convo_id = Utils.context_to_conversation_id(object.data["context"])
|
||||
|
||||
expected = %{
|
||||
"activity_type" => "post",
|
||||
|
|
@ -136,8 +138,8 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
"attentions" => [
|
||||
UserView.render("show.json", %{user: other_user})
|
||||
],
|
||||
"created_at" => activity.data["object"]["published"] |> Utils.date_to_asctime(),
|
||||
"external_url" => activity.data["object"]["id"],
|
||||
"created_at" => object.data["published"] |> Utils.date_to_asctime(),
|
||||
"external_url" => object.data["id"],
|
||||
"fave_num" => 0,
|
||||
"favorited" => false,
|
||||
"id" => activity.id,
|
||||
|
|
@ -161,7 +163,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
}\">@<span>shp</span></a></span>!",
|
||||
"tags" => [],
|
||||
"text" => "Hey @shp!",
|
||||
"uri" => activity.data["object"]["id"],
|
||||
"uri" => object.data["id"],
|
||||
"user" => UserView.render("show.json", %{user: user}),
|
||||
"visibility" => "direct",
|
||||
"card" => nil,
|
||||
|
|
@ -175,8 +177,9 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user, %{nickname: "shp"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
||||
object = Object.normalize(activity.data["object"])
|
||||
|
||||
convo_id = Utils.context_to_conversation_id(activity.data["object"]["context"])
|
||||
convo_id = Utils.context_to_conversation_id(object.data["context"])
|
||||
|
||||
mocks = [
|
||||
{
|
||||
|
|
@ -277,11 +280,11 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
other_user = insert(:user, %{nickname: "shp"})
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
||||
{:ok, announce, _object} = CommonAPI.repeat(activity.id, other_user)
|
||||
{:ok, announce, object} = CommonAPI.repeat(activity.id, other_user)
|
||||
|
||||
convo_id = Utils.context_to_conversation_id(activity.data["object"]["context"])
|
||||
convo_id = Utils.context_to_conversation_id(object.data["context"])
|
||||
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
|
||||
result = ActivityView.render("activity.json", activity: announce)
|
||||
|
||||
|
|
@ -357,7 +360,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
|
||||
test "a peertube video" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_id(
|
||||
Pleroma.Object.Fetcher.fetch_object_from_id(
|
||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
||||
)
|
||||
|
||||
|
|
@ -368,4 +371,14 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|||
assert length(result["attachments"]) == 1
|
||||
assert result["summary"] == "Friday Night"
|
||||
end
|
||||
|
||||
test "special characters are not escaped in text field for status created" do
|
||||
text = "<3 is on the way"
|
||||
|
||||
{:ok, activity} = CommonAPI.post(insert(:user), %{"status" => text})
|
||||
|
||||
result = ActivityView.render("activity.json", activity: activity)
|
||||
|
||||
assert result["text"] == text
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
|
||||
test "A user with emoji in username" do
|
||||
expected =
|
||||
"<img height=\"32px\" width=\"32px\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
|
||||
"<img class=\"emoji\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
|
||||
|
||||
user =
|
||||
insert(:user, %{
|
||||
|
|
@ -89,29 +89,34 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => false,
|
||||
"follows_you" => false,
|
||||
"statusnet_blocking" => false,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
"pleroma" => %{
|
||||
"confirmation_pending" => false,
|
||||
"tags" => []
|
||||
}
|
||||
},
|
||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
||||
"role" => "member"
|
||||
}
|
||||
|
||||
assert represented == UserView.render("show.json", %{user: user})
|
||||
end
|
||||
|
||||
test "User exposes settings for themselves and only for themselves", %{user: user} do
|
||||
as_user = UserView.render("show.json", %{user: user, for: user})
|
||||
assert as_user["default_scope"] == user.info.default_scope
|
||||
assert as_user["no_rich_text"] == user.info.no_rich_text
|
||||
as_stranger = UserView.render("show.json", %{user: user})
|
||||
refute as_stranger["default_scope"]
|
||||
refute as_stranger["no_rich_text"]
|
||||
end
|
||||
|
||||
test "A user for a given other follower", %{user: user} do
|
||||
follower = insert(:user, %{following: [User.ap_followers(user)]})
|
||||
{:ok, user} = User.update_follower_count(user)
|
||||
|
|
@ -137,24 +142,20 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => true,
|
||||
"follows_you" => false,
|
||||
"statusnet_blocking" => false,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
"pleroma" => %{
|
||||
"confirmation_pending" => false,
|
||||
"tags" => []
|
||||
}
|
||||
},
|
||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
||||
"role" => "member"
|
||||
}
|
||||
|
||||
assert represented == UserView.render("show.json", %{user: user, for: follower})
|
||||
|
|
@ -186,24 +187,20 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => false,
|
||||
"follows_you" => true,
|
||||
"statusnet_blocking" => false,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => follower.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
"pleroma" => %{
|
||||
"confirmation_pending" => false,
|
||||
"tags" => []
|
||||
}
|
||||
},
|
||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
||||
"role" => "member"
|
||||
}
|
||||
|
||||
assert represented == UserView.render("show.json", %{user: follower, for: user})
|
||||
|
|
@ -272,27 +269,23 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => false,
|
||||
"follows_you" => false,
|
||||
"statusnet_blocking" => true,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
"pleroma" => %{
|
||||
"confirmation_pending" => false,
|
||||
"tags" => []
|
||||
}
|
||||
},
|
||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
||||
"role" => "member"
|
||||
}
|
||||
|
||||
blocker = Repo.get(User, blocker.id)
|
||||
blocker = User.get_cached_by_id(blocker.id)
|
||||
assert represented == UserView.render("show.json", %{user: user, for: blocker})
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue