Merge remote-tracking branch 'remotes/upstream/develop' into 1335-user-api-id-fields-relations

This commit is contained in:
Ivan Tashkinov 2019-11-15 21:40:14 +03:00
commit 01d9c093c3
73 changed files with 3612 additions and 445 deletions

View file

@ -6,6 +6,14 @@ defmodule Pleroma.EmojiTest do
use ExUnit.Case, async: true
alias Pleroma.Emoji
describe "is_unicode_emoji?/1" do
test "tells if a string is an unicode emoji" do
refute Emoji.is_unicode_emoji?("X")
assert Emoji.is_unicode_emoji?("")
assert Emoji.is_unicode_emoji?("🥺")
end
end
describe "get_all/0" do
setup do
emoji_list = Emoji.get_all()

30
test/fixtures/emoji-reaction.json vendored Normal file
View file

@ -0,0 +1,30 @@
{
"type": "EmojiReaction",
"signature": {
"type": "RsaSignature2017",
"signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
"creator": "http://mastodon.example.org/users/admin#main-key",
"created": "2018-02-17T18:57:49Z"
},
"object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
"content": "👌",
"nickname": "lain",
"id": "http://mastodon.example.org/users/admin#reactions/2",
"actor": "http://mastodon.example.org/users/admin",
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"toot": "http://joinmastodon.org/ns#",
"sensitive": "as:sensitive",
"ostatus": "http://ostatus.org#",
"movedTo": "as:movedTo",
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
"conversation": "ostatus:conversation",
"atomUri": "ostatus:atomUri",
"Hashtag": "as:Hashtag",
"Emoji": "toot:Emoji"
}
]
}

14
test/fixtures/misskey-like.json vendored Normal file
View file

@ -0,0 +1,14 @@
{
"@context" : [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{"Hashtag" : "as:Hashtag"}
],
"_misskey_reaction" : "pudding",
"actor": "http://mastodon.example.org/users/admin",
"cc" : ["https://testing.pleroma.lol/users/lain"],
"id" : "https://misskey.xyz/75149198-2f45-46e4-930a-8b0538297075",
"nickname" : "lain",
"object" : "https://testing.pleroma.lol/objects/c331bbf7-2eb9-4801-a709-2a6103492a5a",
"type" : "Like"
}

View file

@ -17,6 +17,16 @@ defmodule Pleroma.Object.ContainmentTest do
end
describe "general origin containment" do
test "works for completely actorless posts" do
assert :error ==
Containment.contain_origin("https://glaceon.social/users/monorail", %{
"deleted" => "2019-10-30T05:48:50.249606Z",
"formerType" => "Note",
"id" => "https://glaceon.social/users/monorail/statuses/103049757364029187",
"type" => "Tombstone"
})
end
test "contain_origin_from_id() catches obvious spoofing attempts" do
data = %{
"id" => "http://example.com/~alyssa/activities/1234.json"

View file

@ -12,163 +12,196 @@ defmodule Pleroma.Plugs.RateLimiterTest do
# Note: each example must work with separate buckets in order to prevent concurrency issues
test "init/1" do
limiter_name = :test_init
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
describe "config" do
test "config is required for plug to work" do
limiter_name = :test_init
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
assert {limiter_name, {1, 1}, []} == RateLimiter.init(limiter_name)
assert nil == RateLimiter.init(:foo)
assert %{limits: {1, 1}, name: :test_init, opts: [name: :test_init]} ==
RateLimiter.init(name: limiter_name)
assert nil == RateLimiter.init(name: :foo)
end
test "it restricts based on config values" do
limiter_name = :test_opts
scale = 80
limit = 5
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
opts = RateLimiter.init(name: limiter_name)
conn = conn(:get, "/")
for i <- 1..5 do
conn = RateLimiter.call(conn, opts)
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
Process.sleep(10)
end
conn = RateLimiter.call(conn, opts)
assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
Process.sleep(50)
conn = conn(:get, "/")
conn = RateLimiter.call(conn, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
refute conn.status == Plug.Conn.Status.code(:too_many_requests)
refute conn.resp_body
refute conn.halted
end
end
test "ip/1" do
assert "127.0.0.1" == RateLimiter.ip(%{remote_ip: {127, 0, 0, 1}})
describe "options" do
test "`bucket_name` option overrides default bucket name" do
limiter_name = :test_bucket_name
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
base_bucket_name = "#{limiter_name}:group1"
opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name)
conn = conn(:get, "/")
RateLimiter.call(conn, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, opts)
assert {:err, :not_found} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
end
test "`params` option allows different queries to be tracked independently" do
limiter_name = :test_params
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
opts = RateLimiter.init(name: limiter_name, params: ["id"])
conn = conn(:get, "/?id=1")
conn = Plug.Conn.fetch_query_params(conn)
conn_2 = conn(:get, "/?id=2")
RateLimiter.call(conn, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
assert {0, 5} = RateLimiter.inspect_bucket(conn_2, limiter_name, opts)
end
test "it supports combination of options modifying bucket name" do
limiter_name = :test_options_combo
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
base_bucket_name = "#{limiter_name}:group1"
opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name, params: ["id"])
id = "100"
conn = conn(:get, "/?id=#{id}")
conn = Plug.Conn.fetch_query_params(conn)
conn_2 = conn(:get, "/?id=#{101}")
RateLimiter.call(conn, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, opts)
assert {0, 5} = RateLimiter.inspect_bucket(conn_2, base_bucket_name, opts)
end
end
test "it restricts by opts" do
limiter_name = :test_opts
scale = 1000
limit = 5
describe "unauthenticated users" do
test "are restricted based on remote IP" do
limiter_name = :test_unauthenticated
Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 5}, {1, 10}])
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
opts = RateLimiter.init(name: limiter_name)
opts = RateLimiter.init(limiter_name)
conn = conn(:get, "/")
bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
conn = %{conn(:get, "/") | remote_ip: {127, 0, 0, 2}}
conn_2 = %{conn(:get, "/") | remote_ip: {127, 0, 0, 3}}
conn = RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
for i <- 1..5 do
conn = RateLimiter.call(conn, opts)
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
refute conn.halted
end
conn = RateLimiter.call(conn, opts)
assert {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
conn = RateLimiter.call(conn, opts)
assert {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
conn = RateLimiter.call(conn, opts)
assert {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn_2 = RateLimiter.call(conn_2, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, opts)
conn = RateLimiter.call(conn, opts)
assert {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
Process.sleep(to_reset)
conn = conn(:get, "/")
conn = RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
refute conn.status == Plug.Conn.Status.code(:too_many_requests)
refute conn.resp_body
refute conn.halted
refute conn_2.status == Plug.Conn.Status.code(:too_many_requests)
refute conn_2.resp_body
refute conn_2.halted
end
end
test "`bucket_name` option overrides default bucket name" do
limiter_name = :test_bucket_name
scale = 1000
limit = 5
describe "authenticated users" do
setup do
Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
base_bucket_name = "#{limiter_name}:group1"
opts = RateLimiter.init({limiter_name, bucket_name: base_bucket_name})
:ok
end
conn = conn(:get, "/")
default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
customized_bucket_name = "#{base_bucket_name}:#{RateLimiter.ip(conn)}"
test "can have limits seperate from unauthenticated connections" do
limiter_name = :test_authenticated
RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(customized_bucket_name, scale, limit)
assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit)
end
scale = 1000
limit = 5
Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {scale, limit}])
test "`params` option appends specified params' values to bucket name" do
limiter_name = :test_params
scale = 1000
limit = 5
opts = RateLimiter.init(name: limiter_name)
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
opts = RateLimiter.init({limiter_name, params: ["id"]})
id = "1"
user = insert(:user)
conn = conn(:get, "/") |> assign(:user, user)
conn = conn(:get, "/?id=#{id}")
conn = Plug.Conn.fetch_query_params(conn)
for i <- 1..5 do
conn = RateLimiter.call(conn, opts)
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
refute conn.halted
end
default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
parametrized_bucket_name = "#{limiter_name}:#{id}:#{RateLimiter.ip(conn)}"
conn = RateLimiter.call(conn, opts)
RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(parametrized_bucket_name, scale, limit)
assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit)
end
assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
test "it supports combination of options modifying bucket name" do
limiter_name = :test_options_combo
scale = 1000
limit = 5
Process.sleep(1550)
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
base_bucket_name = "#{limiter_name}:group1"
opts = RateLimiter.init({limiter_name, bucket_name: base_bucket_name, params: ["id"]})
id = "100"
conn = conn(:get, "/") |> assign(:user, user)
conn = RateLimiter.call(conn, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
conn = conn(:get, "/?id=#{id}")
conn = Plug.Conn.fetch_query_params(conn)
refute conn.status == Plug.Conn.Status.code(:too_many_requests)
refute conn.resp_body
refute conn.halted
end
default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
parametrized_bucket_name = "#{base_bucket_name}:#{id}:#{RateLimiter.ip(conn)}"
test "diffrerent users are counted independently" do
limiter_name = :test_authenticated
Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {1000, 5}])
RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(parametrized_bucket_name, scale, limit)
assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit)
end
opts = RateLimiter.init(name: limiter_name)
test "optional limits for authenticated users" do
limiter_name = :test_authenticated
Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
user = insert(:user)
conn = conn(:get, "/") |> assign(:user, user)
scale = 1000
limit = 5
Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {scale, limit}])
user_2 = insert(:user)
conn_2 = conn(:get, "/") |> assign(:user, user_2)
opts = RateLimiter.init(limiter_name)
for i <- 1..5 do
conn = RateLimiter.call(conn, opts)
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
end
user = insert(:user)
conn = conn(:get, "/") |> assign(:user, user)
bucket_name = "#{limiter_name}:#{user.id}"
conn = RateLimiter.call(conn, opts)
assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
conn = RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
assert {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
assert {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
assert {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
assert {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
conn = RateLimiter.call(conn, opts)
assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
Process.sleep(to_reset)
conn = conn(:get, "/") |> assign(:user, user)
conn = RateLimiter.call(conn, opts)
assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
refute conn.status == Plug.Conn.Status.code(:too_many_requests)
refute conn.resp_body
refute conn.halted
conn_2 = RateLimiter.call(conn_2, opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, opts)
refute conn_2.status == Plug.Conn.Status.code(:too_many_requests)
refute conn_2.resp_body
refute conn_2.halted
end
end
end

View file

@ -16,6 +16,23 @@ defmodule Pleroma.Plugs.UserEnabledPlugTest do
assert ret_conn == conn
end
test "with a user that's not confirmed and a config requiring confirmation, it removes that user",
%{conn: conn} do
old = Pleroma.Config.get([:instance, :account_activation_required])
Pleroma.Config.put([:instance, :account_activation_required], true)
user = insert(:user, confirmation_pending: true)
conn =
conn
|> assign(:user, user)
|> UserEnabledPlug.call(%{})
assert conn.assigns.user == nil
Pleroma.Config.put([:instance, :account_activation_required], old)
end
test "with a user that is deactivated, it removes that user", %{conn: conn} do
user = insert(:user, deactivated: true)

View file

@ -1198,6 +1198,13 @@ defmodule Pleroma.UserTest do
refute User.auth_active?(local_user)
assert User.auth_active?(confirmed_user)
assert User.auth_active?(remote_user)
# also shows unactive for deactivated users
deactivated_but_confirmed =
insert(:user, local: true, confirmation_pending: false, deactivated: true)
refute User.auth_active?(deactivated_but_confirmed)
end
describe "superuser?/1" do

View file

@ -815,6 +815,78 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
describe "react to an object" do
test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
Pleroma.Config.put([:instance, :federating], true)
user = insert(:user)
reactor = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
assert object = Object.normalize(activity)
{:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
assert called(Pleroma.Web.Federator.publish(reaction_activity))
end
test "adds an emoji reaction activity to the db" do
user = insert(:user)
reactor = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
assert object = Object.normalize(activity)
{:ok, reaction_activity, object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
assert reaction_activity
assert reaction_activity.data["actor"] == reactor.ap_id
assert reaction_activity.data["type"] == "EmojiReaction"
assert reaction_activity.data["content"] == "🔥"
assert reaction_activity.data["object"] == object.data["id"]
assert reaction_activity.data["to"] == [User.ap_followers(reactor), activity.data["actor"]]
assert reaction_activity.data["context"] == object.data["context"]
assert object.data["reaction_count"] == 1
assert object.data["reactions"]["🔥"] == [reactor.ap_id]
end
end
describe "unreacting to an object" do
test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
Pleroma.Config.put([:instance, :federating], true)
user = insert(:user)
reactor = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
assert object = Object.normalize(activity)
{:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
assert called(Pleroma.Web.Federator.publish(reaction_activity))
{:ok, unreaction_activity, _object} =
ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
assert called(Pleroma.Web.Federator.publish(unreaction_activity))
end
test "adds an undo activity to the db" do
user = insert(:user)
reactor = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
assert object = Object.normalize(activity)
{:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
{:ok, unreaction_activity, _object} =
ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
assert unreaction_activity.actor == reactor.ap_id
assert unreaction_activity.data["object"] == reaction_activity.data["id"]
object = Object.get_by_ap_id(object.data["id"])
assert object.data["reaction_count"] == 0
assert object.data["reactions"] == %{}
end
end
describe "like an object" do
test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
Pleroma.Config.put([:instance, :federating], true)

View file

@ -0,0 +1,105 @@
# Pleroma: A lightweight social networking server
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
use Pleroma.DataCase
alias Pleroma.Config
alias Pleroma.User
alias Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy
alias Pleroma.Web.ActivityPub.Visibility
clear_config([:mrf_object_age]) do
Config.put(:mrf_object_age,
threshold: 172_800,
actions: [:delist, :strip_followers]
)
end
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "with reject action" do
test "it rejects an old post" do
Config.put([:mrf_object_age, :actions], [:reject])
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
{:reject, _} = ObjectAgePolicy.filter(data)
end
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:reject])
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
|> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
{:ok, _} = ObjectAgePolicy.filter(data)
end
end
describe "with delist action" do
test "it delists an old post" do
Config.put([:mrf_object_age, :actions], [:delist])
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
{:ok, data} = ObjectAgePolicy.filter(data)
assert Visibility.get_visibility(%{data: data}) == "unlisted"
end
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:delist])
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
|> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
{:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
{:ok, ^data} = ObjectAgePolicy.filter(data)
end
end
describe "with strip_followers action" do
test "it strips followers collections from an old post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
{:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
{:ok, data} = ObjectAgePolicy.filter(data)
refute user.follower_address in data["to"]
refute user.follower_address in data["cc"]
end
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
|> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
{:ok, ^data} = ObjectAgePolicy.filter(data)
end
end
end

View file

@ -339,6 +339,80 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert data["object"] == activity.data["object"]
end
test "it works for incoming misskey likes, turning them into EmojiReactions" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
data =
File.read!("test/fixtures/misskey-like.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == data["actor"]
assert data["type"] == "EmojiReaction"
assert data["id"] == data["id"]
assert data["object"] == activity.data["object"]
assert data["content"] == "🍮"
end
test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReactions" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
data =
File.read!("test/fixtures/misskey-like.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"])
|> Map.put("_misskey_reaction", "")
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == data["actor"]
assert data["type"] == "EmojiReaction"
assert data["id"] == data["id"]
assert data["object"] == activity.data["object"]
assert data["content"] == ""
end
test "it works for incoming emoji reactions" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
data =
File.read!("test/fixtures/emoji-reaction.json")
|> Poison.decode!()
|> 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"] == "EmojiReaction"
assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
assert data["object"] == activity.data["object"]
assert data["content"] == "👌"
end
test "it works for incoming emoji reaction undos" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
{:ok, reaction_activity, _object} = CommonAPI.react_with_emoji(activity.id, user, "👌")
data =
File.read!("test/fixtures/mastodon-undo-like.json")
|> Poison.decode!()
|> Map.put("object", reaction_activity.data["id"])
|> Map.put("actor", user.ap_id)
{:ok, activity} = Transmogrifier.handle_incoming(data)
assert activity.actor == user.ap_id
assert activity.data["id"] == data["id"]
assert activity.data["type"] == "Undo"
end
test "it returns an error for incoming unlikes wihout a like activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
@ -553,6 +627,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute Map.has_key?(object.data, "likes")
end
test "it strips internal reactions" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
{:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
%{object: object} = Activity.get_by_id_with_object(activity.id)
assert Map.has_key?(object.data, "reactions")
assert Map.has_key?(object.data, "reaction_count")
object_data = Transmogrifier.strip_internal_fields(object.data)
refute Map.has_key?(object_data, "reactions")
refute Map.has_key?(object_data, "reaction_count")
end
test "it works for incoming update activities" do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()

View file

@ -636,4 +636,47 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
assert updated_object.data["announcement_count"] == 1
end
end
describe "get_reports_grouped_by_status/1" do
setup do
[reporter, target_user] = insert_pair(:user)
first_status = insert(:note_activity, user: target_user)
second_status = insert(:note_activity, user: target_user)
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [first_status.id]
})
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended2",
"status_ids" => [second_status.id]
})
data = [%{activity: first_status.data["id"]}, %{activity: second_status.data["id"]}]
{:ok,
%{
first_status: first_status,
second_status: second_status,
data: data
}}
end
test "works for deprecated reports format", %{
first_status: first_status,
second_status: second_status,
data: data
} do
groups = Utils.get_reports_grouped_by_status(data).groups
first_group = Enum.find(groups, &(&1.status.id == first_status.data["id"]))
second_group = Enum.find(groups, &(&1.status.id == second_status.data["id"]))
assert first_group.status.id == first_status.data["id"]
assert second_group.status.id == second_status.data["id"]
end
end
end

View file

@ -1312,7 +1312,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
describe "PUT /api/pleroma/admin/reports/:id" do
describe "PATCH /api/pleroma/admin/reports" do
setup %{conn: conn} do
admin = insert(:user, is_admin: true)
[reporter, target_user] = insert_pair(:user)
@ -1325,16 +1325,32 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"status_ids" => [activity.id]
})
%{conn: assign(conn, :user, admin), id: report_id, admin: admin}
{:ok, %{id: second_report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel very offended",
"status_ids" => [activity.id]
})
%{
conn: assign(conn, :user, admin),
id: report_id,
admin: admin,
second_report_id: second_report_id
}
end
test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
response =
conn
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})
|> json_response(:ok)
conn
|> patch("/api/pleroma/admin/reports", %{
"reports" => [
%{"state" => "resolved", "id" => id}
]
})
|> json_response(:no_content)
assert response["state"] == "resolved"
activity = Activity.get_by_id(id)
assert activity.data["state"] == "resolved"
log_entry = Repo.one(ModerationLog)
@ -1343,12 +1359,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
test "closes report", %{conn: conn, id: id, admin: admin} do
response =
conn
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})
|> json_response(:ok)
conn
|> patch("/api/pleroma/admin/reports", %{
"reports" => [
%{"state" => "closed", "id" => id}
]
})
|> json_response(:no_content)
assert response["state"] == "closed"
activity = Activity.get_by_id(id)
assert activity.data["state"] == "closed"
log_entry = Repo.one(ModerationLog)
@ -1359,17 +1379,54 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
test "returns 400 when state is unknown", %{conn: conn, id: id} do
conn =
conn
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"})
|> patch("/api/pleroma/admin/reports", %{
"reports" => [
%{"state" => "test", "id" => id}
]
})
assert json_response(conn, :bad_request) == "Unsupported state"
assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
end
test "returns 404 when report is not exist", %{conn: conn} do
conn =
conn
|> put("/api/pleroma/admin/reports/test", %{"state" => "closed"})
|> patch("/api/pleroma/admin/reports", %{
"reports" => [
%{"state" => "closed", "id" => "test"}
]
})
assert json_response(conn, :not_found) == "Not found"
assert hd(json_response(conn, :bad_request))["error"] == "not_found"
end
test "updates state of multiple reports", %{
conn: conn,
id: id,
admin: admin,
second_report_id: second_report_id
} do
conn
|> patch("/api/pleroma/admin/reports", %{
"reports" => [
%{"state" => "resolved", "id" => id},
%{"state" => "closed", "id" => second_report_id}
]
})
|> json_response(:no_content)
activity = Activity.get_by_id(id)
second_activity = Activity.get_by_id(second_report_id)
assert activity.data["state"] == "resolved"
assert second_activity.data["state"] == "closed"
[first_log_entry, second_log_entry] = Repo.all(ModerationLog)
assert ModerationLog.get_log_entry_message(first_log_entry) ==
"@#{admin.nickname} updated report ##{id} with 'resolved' state"
assert ModerationLog.get_log_entry_message(second_log_entry) ==
"@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
end
end
@ -1492,7 +1549,145 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
#
describe "GET /api/pleroma/admin/grouped_reports" do
setup %{conn: conn} do
admin = insert(:user, is_admin: true)
[reporter, target_user] = insert_pair(:user)
date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
first_status =
insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
second_status =
insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
third_status =
insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
{:ok, first_report} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"status_ids" => [first_status.id, second_status.id, third_status.id]
})
{:ok, second_report} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"status_ids" => [first_status.id, second_status.id]
})
{:ok, third_report} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"status_ids" => [first_status.id]
})
%{
conn: assign(conn, :user, admin),
first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
first_status_reports: [first_report, second_report, third_report],
second_status_reports: [first_report, second_report],
third_status_reports: [first_report],
target_user: target_user,
reporter: reporter
}
end
test "returns reports grouped by status", %{
conn: conn,
first_status: first_status,
second_status: second_status,
third_status: third_status,
first_status_reports: first_status_reports,
second_status_reports: second_status_reports,
third_status_reports: third_status_reports,
target_user: target_user,
reporter: reporter
} do
response =
conn
|> get("/api/pleroma/admin/grouped_reports")
|> json_response(:ok)
assert length(response["reports"]) == 3
first_group =
Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"]))
second_group =
Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
third_group =
Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"]))
assert length(first_group["reports"]) == 3
assert length(second_group["reports"]) == 2
assert length(third_group["reports"]) == 1
assert first_group["date"] ==
Enum.max_by(first_status_reports, fn act ->
NaiveDateTime.from_iso8601!(act.data["published"])
end).data["published"]
assert first_group["status"] == %{
"id" => first_status.data["id"],
"content" => first_status.object.data["content"],
"published" => first_status.object.data["published"]
}
assert first_group["account"]["id"] == target_user.id
assert length(first_group["actors"]) == 1
assert hd(first_group["actors"])["id"] == reporter.id
assert Enum.map(first_group["reports"], & &1["id"]) --
Enum.map(first_status_reports, & &1.id) == []
assert second_group["date"] ==
Enum.max_by(second_status_reports, fn act ->
NaiveDateTime.from_iso8601!(act.data["published"])
end).data["published"]
assert second_group["status"] == %{
"id" => second_status.data["id"],
"content" => second_status.object.data["content"],
"published" => second_status.object.data["published"]
}
assert second_group["account"]["id"] == target_user.id
assert length(second_group["actors"]) == 1
assert hd(second_group["actors"])["id"] == reporter.id
assert Enum.map(second_group["reports"], & &1["id"]) --
Enum.map(second_status_reports, & &1.id) == []
assert third_group["date"] ==
Enum.max_by(third_status_reports, fn act ->
NaiveDateTime.from_iso8601!(act.data["published"])
end).data["published"]
assert third_group["status"] == %{
"id" => third_status.data["id"],
"content" => third_status.object.data["content"],
"published" => third_status.object.data["published"]
}
assert third_group["account"]["id"] == target_user.id
assert length(third_group["actors"]) == 1
assert hd(third_group["actors"])["id"] == reporter.id
assert Enum.map(third_group["reports"], & &1["id"]) --
Enum.map(third_status_reports, & &1.id) == []
end
end
describe "POST /api/pleroma/admin/reports/:id/respond" do
setup %{conn: conn} do
admin = insert(:user, is_admin: true)
@ -2269,6 +2464,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
Pleroma.Config.put([:instance, :dynamic_configuration], true)
end
clear_config([:feed, :post_title]) do
Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: ""})
end
test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")

View file

@ -227,6 +227,33 @@ defmodule Pleroma.Web.CommonAPITest do
end
describe "reactions" do
test "reacting to a status with an emoji" do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
{:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
assert reaction.data["actor"] == user.ap_id
assert reaction.data["content"] == "👍"
# TODO: test error case.
end
test "unreacting to a status with an emoji" do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
{:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
{:ok, unreaction, _} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
assert unreaction.data["type"] == "Undo"
assert unreaction.data["object"] == reaction.data["id"]
end
test "repeating a status" do
user = insert(:user)
other_user = insert(:user)
@ -441,6 +468,35 @@ defmodule Pleroma.Web.CommonAPITest do
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
end
test "updates state of multiple reports" do
[reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user)
{:ok, %Activity{id: first_report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [activity.id]
})
{:ok, %Activity{id: second_report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel very offended!",
"status_ids" => [activity.id]
})
{:ok, report_ids} =
CommonAPI.update_report_state([first_report_id, second_report_id], "resolved")
first_report = Activity.get_by_id(first_report_id)
second_report = Activity.get_by_id(second_report_id)
assert report_ids -- [first_report_id, second_report_id] == []
assert first_report.data["state"] == "resolved"
assert second_report.data["state"] == "resolved"
end
end
describe "reblog muting" do

View file

@ -84,6 +84,30 @@ defmodule Pleroma.Web.NodeInfoTest do
Pleroma.Config.put([:instance, :safe_dm_mentions], option)
end
test "it shows if federation is enabled/disabled", %{conn: conn} do
original = Pleroma.Config.get([:instance, :federating])
Pleroma.Config.put([:instance, :federating], true)
response =
conn
|> get("/nodeinfo/2.1.json")
|> json_response(:ok)
assert response["metadata"]["federation"]["enabled"] == true
Pleroma.Config.put([:instance, :federating], false)
response =
conn
|> get("/nodeinfo/2.1.json")
|> json_response(:ok)
assert response["metadata"]["federation"]["enabled"] == false
Pleroma.Config.put([:instance, :federating], original)
end
test "it shows MRF transparency data if enabled", %{conn: conn} do
config = Pleroma.Config.get([:instance, :rewrite_policy])
Pleroma.Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])

View file

@ -469,6 +469,29 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert html_response(conn, 200) =~ ~s(type="submit")
end
test "renders authentication page if user is already authenticated but user request with another client",
%{
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" => "another_client_id",
"redirect_uri" => OAuthController.default_redirect_uri(app),
"scope" => "read"
}
)
assert html_response(conn, 200) =~ ~s(type="submit")
end
test "with existing authentication and non-OOB `redirect_uri`, redirects to app with `token` and `state` params",
%{
app: app,

View file

@ -7,12 +7,72 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
alias Pleroma.Conversation.Participation
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
test "POST /api/v1/pleroma/statuses/:id/react_with_emoji", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
result =
conn
|> assign(:user, other_user)
|> post("/api/v1/pleroma/statuses/#{activity.id}/react_with_emoji", %{"emoji" => ""})
assert %{"id" => id} = json_response(result, 200)
assert to_string(activity.id) == id
end
test "POST /api/v1/pleroma/statuses/:id/unreact_with_emoji", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
{:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "")
result =
conn
|> assign(:user, other_user)
|> post("/api/v1/pleroma/statuses/#{activity.id}/unreact_with_emoji", %{"emoji" => ""})
assert %{"id" => id} = json_response(result, 200)
assert to_string(activity.id) == id
object = Object.normalize(activity)
assert object.data["reaction_count"] == 0
end
test "GET /api/v1/pleroma/statuses/:id/emoji_reactions_by", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
result =
conn
|> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
|> json_response(200)
assert result == %{}
{:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
result =
conn
|> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
|> json_response(200)
[represented_user] = result["🎅"]
assert represented_user["id"] == other_user.id
end
test "/api/v1/pleroma/conversations/:id", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)

View file

@ -0,0 +1,210 @@
defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Activity
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
clear_config_all([:static_fe, :enabled]) do
Pleroma.Config.put([:static_fe, :enabled], true)
end
describe "user profile page" do
test "just the profile as HTML", %{conn: conn} do
user = insert(:user)
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/users/#{user.nickname}")
assert html_response(conn, 200) =~ user.nickname
end
test "renders json unless there's an html accept header", %{conn: conn} do
user = insert(:user)
conn =
conn
|> put_req_header("accept", "application/json")
|> get("/users/#{user.nickname}")
assert json_response(conn, 200)
end
test "404 when user not found", %{conn: conn} do
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/users/limpopo")
assert html_response(conn, 404) =~ "not found"
end
test "profile does not include private messages", %{conn: conn} do
user = insert(:user)
CommonAPI.post(user, %{"status" => "public"})
CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/users/#{user.nickname}")
html = html_response(conn, 200)
assert html =~ ">public<"
refute html =~ ">private<"
end
test "pagination", %{conn: conn} do
user = insert(:user)
Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/users/#{user.nickname}")
html = html_response(conn, 200)
assert html =~ ">test30<"
assert html =~ ">test11<"
refute html =~ ">test10<"
refute html =~ ">test1<"
end
test "pagination, page 2", %{conn: conn} do
user = insert(:user)
activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
{:ok, a11} = Enum.at(activities, 11)
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/users/#{user.nickname}?max_id=#{a11.id}")
html = html_response(conn, 200)
assert html =~ ">test1<"
assert html =~ ">test10<"
refute html =~ ">test20<"
refute html =~ ">test29<"
end
end
describe "notice rendering" do
test "single notice page", %{conn: conn} do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/notice/#{activity.id}")
html = html_response(conn, 200)
assert html =~ "<header>"
assert html =~ user.nickname
assert html =~ "testing a thing!"
end
test "shows the whole thread", %{conn: conn} do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "space: the final frontier"})
CommonAPI.post(user, %{
"status" => "these are the voyages or something",
"in_reply_to_status_id" => activity.id
})
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/notice/#{activity.id}")
html = html_response(conn, 200)
assert html =~ "the final frontier"
assert html =~ "voyages"
end
test "redirect by AP object ID", %{conn: conn} do
user = insert(:user)
{:ok, %Activity{data: %{"object" => object_url}}} =
CommonAPI.post(user, %{"status" => "beam me up"})
conn =
conn
|> put_req_header("accept", "text/html")
|> get(URI.parse(object_url).path)
assert html_response(conn, 302) =~ "redirected"
end
test "redirect by activity ID", %{conn: conn} do
user = insert(:user)
{:ok, %Activity{data: %{"id" => id}}} =
CommonAPI.post(user, %{"status" => "I'm a doctor, not a devops!"})
conn =
conn
|> put_req_header("accept", "text/html")
|> get(URI.parse(id).path)
assert html_response(conn, 302) =~ "redirected"
end
test "404 when notice not found", %{conn: conn} do
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/notice/88c9c317")
assert html_response(conn, 404) =~ "not found"
end
test "404 for private status", %{conn: conn} do
user = insert(:user)
{:ok, activity} =
CommonAPI.post(user, %{"status" => "don't show me!", "visibility" => "private"})
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/notice/#{activity.id}")
assert html_response(conn, 404) =~ "not found"
end
test "302 for remote cached status", %{conn: conn} do
user = insert(:user)
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"to" => user.follower_address,
"cc" => "https://www.w3.org/ns/activitystreams#Public",
"type" => "Create",
"object" => %{
"content" => "blah blah blah",
"type" => "Note",
"attributedTo" => user.ap_id,
"inReplyTo" => nil
},
"actor" => user.ap_id
}
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
conn =
conn
|> put_req_header("accept", "text/html")
|> get("/notice/#{activity.id}")
assert html_response(conn, 302) =~ "redirected"
end
end
end