Merge branch 'remake-remodel-2' into 'develop'

Ingestion Pipeline Revamp

See merge request pleroma/pleroma!2315
This commit is contained in:
lain 2020-04-06 11:59:01 +00:00
commit 349b9d86dc
38 changed files with 915 additions and 88 deletions

View file

@ -1,4 +1,4 @@
Unless otherwise stated this repository is copyright © 2017-2019 Unless otherwise stated this repository is copyright © 2017-2020
Pleroma Authors <https://pleroma.social/>, and is distributed under Pleroma Authors <https://pleroma.social/>, and is distributed under
The GNU Affero General Public License Version 3, you should have received a The GNU Affero General Public License Version 3, you should have received a
copy of the license file as AGPL-3. copy of the license file as AGPL-3.
@ -23,7 +23,7 @@ priv/static/images/pleroma-fox-tan-shy.png
--- ---
The following files are copyright © 2017-2019 Pleroma Authors The following files are copyright © 2017-2020 Pleroma Authors
<https://pleroma.social/>, and are distributed under the Creative Commons <https://pleroma.social/>, and are distributed under the Creative Commons
Attribution-ShareAlike 4.0 International license, you should have received Attribution-ShareAlike 4.0 International license, you should have received
a copy of the license file as CC-BY-SA-4.0. a copy of the license file as CC-BY-SA-4.0.

View file

@ -32,6 +32,18 @@ defmodule Pleroma.Object.Containment do
get_actor(%{"actor" => actor}) get_actor(%{"actor" => actor})
end end
def get_object(%{"object" => id}) when is_binary(id) do
id
end
def get_object(%{"object" => %{"id" => id}}) when is_binary(id) do
id
end
def get_object(_) do
nil
end
# TODO: We explicitly allow 'tag' URIs through, due to references to legacy OStatus # TODO: We explicitly allow 'tag' URIs through, due to references to legacy OStatus
# objects being present in the test suite environment. Once these objects are # objects being present in the test suite environment. Once these objects are
# removed, please also remove this. # removed, please also remove this.

View file

@ -125,6 +125,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def increase_poll_votes_if_vote(_create_data), do: :noop def increase_poll_votes_if_vote(_create_data), do: :noop
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
def persist(object, meta) do
with local <- Keyword.fetch!(meta, :local),
{recipients, _, _} <- get_recipients(object),
{:ok, activity} <-
Repo.insert(%Activity{
data: object,
local: local,
recipients: recipients,
actor: object["actor"]
}) do
{:ok, activity, meta}
end
end
@spec insert(map(), boolean(), boolean(), boolean()) :: {:ok, Activity.t()} | {:error, any()} @spec insert(map(), boolean(), boolean(), boolean()) :: {:ok, Activity.t()} | {:error, any()}
def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when is_map(map) do def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when is_map(map) do
with nil <- Activity.normalize(map), with nil <- Activity.normalize(map),

View file

@ -0,0 +1,43 @@
defmodule Pleroma.Web.ActivityPub.Builder do
@moduledoc """
This module builds the objects. Meant to be used for creating local objects.
This module encodes our addressing policies and general shape of our objects.
"""
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
@spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
def like(actor, object) do
object_actor = User.get_cached_by_ap_id(object.data["actor"])
# Address the actor of the object, and our actor's follower collection if the post is public.
to =
if Visibility.is_public?(object) do
[actor.follower_address, object.data["actor"]]
else
[object.data["actor"]]
end
# CC everyone who's been addressed in the object, except ourself and the object actor's
# follower collection
cc =
(object.data["to"] ++ (object.data["cc"] || []))
|> List.delete(actor.ap_id)
|> List.delete(object_actor.follower_address)
{:ok,
%{
"id" => Utils.generate_activity_id(),
"actor" => actor.ap_id,
"type" => "Like",
"object" => object.data["id"],
"to" => to,
"cc" => cc,
"context" => object.data["context"]
}, []}
end
end

View file

@ -0,0 +1,37 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@moduledoc """
This module is responsible for validating an object (which can be an activity)
and checking if it is both well formed and also compatible with our view of
the system.
"""
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
def validate(object, meta)
def validate(%{"type" => "Like"} = object, meta) do
with {:ok, object} <-
object |> LikeValidator.cast_and_validate() |> Ecto.Changeset.apply_action(:insert) do
object = stringify_keys(object |> Map.from_struct())
{:ok, object, meta}
end
end
def stringify_keys(object) do
object
|> Map.new(fn {key, val} -> {to_string(key), val} end)
end
def fetch_actor_and_object(object) do
User.get_or_fetch_by_ap_id(object["actor"])
Object.normalize(object["object"])
:ok
end
end

View file

@ -0,0 +1,32 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do
import Ecto.Changeset
alias Pleroma.Object
alias Pleroma.User
def validate_actor_presence(cng, field_name \\ :actor) do
cng
|> validate_change(field_name, fn field_name, actor ->
if User.get_cached_by_ap_id(actor) do
[]
else
[{field_name, "can't find user"}]
end
end)
end
def validate_object_presence(cng, field_name \\ :object) do
cng
|> validate_change(field_name, fn field_name, object ->
if Object.get_cached_by_ap_id(object) do
[]
else
[{field_name, "can't find object"}]
end
end)
end
end

View file

@ -0,0 +1,30 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateNoteValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:id, Types.ObjectID, primary_key: true)
field(:actor, Types.ObjectID)
field(:type, :string)
field(:to, {:array, :string})
field(:cc, {:array, :string})
field(:bto, {:array, :string}, default: [])
field(:bcc, {:array, :string}, default: [])
embeds_one(:object, NoteValidator)
end
def cast_data(data) do
cast(%__MODULE__{}, data, __schema__(:fields))
end
end

View file

@ -0,0 +1,57 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
alias Pleroma.Web.ActivityPub.Utils
import Ecto.Changeset
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
@primary_key false
embedded_schema do
field(:id, Types.ObjectID, primary_key: true)
field(:type, :string)
field(:object, Types.ObjectID)
field(:actor, Types.ObjectID)
field(:context, :string)
field(:to, {:array, :string})
field(:cc, {:array, :string})
end
def cast_and_validate(data) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> cast(data, [:id, :type, :object, :actor, :context, :to, :cc])
end
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Like"])
|> validate_required([:id, :type, :object, :actor, :context, :to, :cc])
|> validate_actor_presence()
|> validate_object_presence()
|> validate_existing_like()
end
def validate_existing_like(%{changes: %{actor: actor, object: object}} = cng) do
if Utils.get_existing_like(actor, %{data: %{"id" => object}}) do
cng
|> add_error(:actor, "already liked this object")
|> add_error(:object, "already liked by this actor")
else
cng
end
end
def validate_existing_like(cng), do: cng
end

View file

@ -0,0 +1,63 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:id, Types.ObjectID, primary_key: true)
field(:to, {:array, :string}, default: [])
field(:cc, {:array, :string}, default: [])
field(:bto, {:array, :string}, default: [])
field(:bcc, {:array, :string}, default: [])
# TODO: Write type
field(:tag, {:array, :map}, default: [])
field(:type, :string)
field(:content, :string)
field(:context, :string)
field(:actor, Types.ObjectID)
field(:attributedTo, Types.ObjectID)
field(:summary, :string)
field(:published, Types.DateTime)
# TODO: Write type
field(:emoji, :map, default: %{})
field(:sensitive, :boolean, default: false)
# TODO: Write type
field(:attachment, {:array, :map}, default: [])
field(:replies_count, :integer, default: 0)
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inRepyTo, :string)
field(:likes, {:array, :string}, default: [])
field(:announcements, {:array, :string}, default: [])
# see if needed
field(:conversation, :string)
field(:context_id, :string)
end
def cast_and_validate(data) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> cast(data, __schema__(:fields))
end
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Note"])
|> validate_required([:id, :actor, :to, :cc, :type, :content, :context])
end
end

View file

@ -0,0 +1,34 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime do
@moduledoc """
The AP standard defines the date fields in AP as xsd:DateTime. Elixir's
DateTime can't parse this, but it can parse the related iso8601. This
module punches the date until it looks like iso8601 and normalizes to
it.
DateTimes without a timezone offset are treated as UTC.
Reference: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published
"""
use Ecto.Type
def type, do: :string
def cast(datetime) when is_binary(datetime) do
with {:ok, datetime, _} <- DateTime.from_iso8601(datetime) do
{:ok, DateTime.to_iso8601(datetime)}
else
{:error, :missing_offset} -> cast("#{datetime}Z")
_e -> :error
end
end
def cast(_), do: :error
def dump(data) do
{:ok, data}
end
def load(data) do
{:ok, data}
end
end

View file

@ -0,0 +1,33 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID do
use Ecto.Type
def type, do: :string
def cast(object) when is_binary(object) do
# Host has to be present and scheme has to be an http scheme (for now)
case URI.parse(object) do
%URI{host: nil} ->
:error
%URI{scheme: scheme} when scheme in ["https", "http"] ->
{:ok, object}
_ ->
:error
end
end
def cast(%{"id" => object}), do: cast(object)
def cast(_) do
:error
end
def dump(data) do
{:ok, data}
end
def load(data) do
{:ok, data}
end
end

View file

@ -0,0 +1,42 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.Pipeline do
alias Pleroma.Activity
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.Federator
@spec common_pipeline(map(), keyword()) :: {:ok, Activity.t(), keyword()} | {:error, any()}
def common_pipeline(object, meta) do
with {_, {:ok, validated_object, meta}} <-
{:validate_object, ObjectValidator.validate(object, meta)},
{_, {:ok, mrfd_object}} <- {:mrf_object, MRF.filter(validated_object)},
{_, {:ok, %Activity{} = activity, meta}} <-
{:persist_object, ActivityPub.persist(mrfd_object, meta)},
{_, {:ok, %Activity{} = activity, meta}} <-
{:execute_side_effects, SideEffects.handle(activity, meta)},
{_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do
{:ok, activity, meta}
else
{:mrf_object, {:reject, _}} -> {:ok, nil, meta}
e -> {:error, e}
end
end
defp maybe_federate(activity, meta) do
with {:ok, local} <- Keyword.fetch(meta, :local) do
if local do
Federator.publish(activity)
{:ok, :federated}
else
{:ok, :not_federated}
end
else
_e -> {:error, :badarg}
end
end
end

View file

@ -0,0 +1,28 @@
defmodule Pleroma.Web.ActivityPub.SideEffects do
@moduledoc """
This module looks at an inserted object and executes the side effects that it
implies. For example, a `Like` activity will increase the like count on the
liked object, a `Follow` activity will add the user to the follower
collection, and so on.
"""
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Utils
def handle(object, meta \\ [])
# Tasks this handles:
# - Add like to object
# - Set up notification
def handle(%{data: %{"type" => "Like"}} = object, meta) do
liked_object = Object.get_by_ap_id(object.data["object"])
Utils.add_like_to_object(object, liked_object)
Notification.create_notifications(object)
{:ok, object, meta}
end
# Nothing to do
def handle(object, meta) do
{:ok, object, meta}
end
end

View file

@ -13,6 +13,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
@ -609,17 +612,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> handle_incoming(options) |> handle_incoming(options)
end end
def handle_incoming( def handle_incoming(%{"type" => "Like"} = data, _options) do
%{"type" => "Like", "object" => object_id, "actor" => _actor, "id" => id} = data, with {_, {:ok, cast_data_sym}} <-
_options {:casting_data,
) do data |> LikeValidator.cast_data() |> Ecto.Changeset.apply_action(:insert)},
with actor <- Containment.get_actor(data), cast_data = ObjectValidator.stringify_keys(Map.from_struct(cast_data_sym)),
{:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor), :ok <- ObjectValidator.fetch_actor_and_object(cast_data),
{:ok, object} <- get_obj_helper(object_id), {_, {:ok, cast_data}} <- {:ensure_context_presence, ensure_context_presence(cast_data)},
{:ok, activity, _object} <- ActivityPub.like(actor, object, id, false) do {_, {:ok, cast_data}} <-
{:ensure_recipients_presence, ensure_recipients_presence(cast_data)},
{_, {:ok, activity, _meta}} <-
{:common_pipeline, Pipeline.common_pipeline(cast_data, local: false)} do
{:ok, activity} {:ok, activity}
else else
_e -> :error e -> {:error, e}
end end
end end
@ -1243,4 +1249,45 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def maybe_fix_user_url(data), do: data def maybe_fix_user_url(data), do: data
def maybe_fix_user_object(data), do: maybe_fix_user_url(data) def maybe_fix_user_object(data), do: maybe_fix_user_url(data)
defp ensure_context_presence(%{"context" => context} = data) when is_binary(context),
do: {:ok, data}
defp ensure_context_presence(%{"object" => object} = data) when is_binary(object) do
with %{data: %{"context" => context}} when is_binary(context) <- Object.normalize(object) do
{:ok, Map.put(data, "context", context)}
else
_ ->
{:error, :no_context}
end
end
defp ensure_context_presence(_) do
{:error, :no_context}
end
defp ensure_recipients_presence(%{"to" => [_ | _], "cc" => [_ | _]} = data),
do: {:ok, data}
defp ensure_recipients_presence(%{"object" => object} = data) do
case Object.normalize(object) do
%{data: %{"actor" => actor}} ->
data =
data
|> Map.put("to", [actor])
|> Map.put("cc", data["cc"] || [])
{:ok, data}
nil ->
{:error, :no_object}
_ ->
{:error, :no_actor}
end
end
defp ensure_recipients_presence(_) do
{:error, :no_object}
end
end end

View file

@ -12,6 +12,8 @@ defmodule Pleroma.Web.CommonAPI do
alias Pleroma.User alias Pleroma.User
alias Pleroma.UserRelationship alias Pleroma.UserRelationship
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
@ -19,6 +21,7 @@ defmodule Pleroma.Web.CommonAPI do
import Pleroma.Web.CommonAPI.Utils import Pleroma.Web.CommonAPI.Utils
require Pleroma.Constants require Pleroma.Constants
require Logger
def follow(follower, followed) do def follow(follower, followed) do
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout]) timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
@ -109,18 +112,51 @@ defmodule Pleroma.Web.CommonAPI do
end end
end end
def favorite(id_or_ap_id, user) do @spec favorite(User.t(), binary()) :: {:ok, Activity.t() | :already_liked} | {:error, any()}
with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)}, def favorite(%User{} = user, id) do
object <- Object.normalize(activity), case favorite_helper(user, id) do
like_activity <- Utils.get_existing_like(user.ap_id, object) do {:ok, _} = res ->
if like_activity do res
{:ok, like_activity, object}
else {:error, :not_found} = res ->
ActivityPub.like(user, object) res
end
{:error, e} ->
Logger.error("Could not favorite #{id}. Error: #{inspect(e, pretty: true)}")
{:error, dgettext("errors", "Could not favorite")}
end
end
def favorite_helper(user, id) do
with {_, %Activity{object: object}} <- {:find_object, Activity.get_by_id_with_object(id)},
{_, {:ok, like_object, meta}} <- {:build_object, Builder.like(user, object)},
{_, {:ok, %Activity{} = activity, _meta}} <-
{:common_pipeline,
Pipeline.common_pipeline(like_object, Keyword.put(meta, :local, true))} do
{:ok, activity}
else else
{:find_activity, _} -> {:error, :not_found} {:find_object, _} ->
_ -> {:error, dgettext("errors", "Could not favorite")} {:error, :not_found}
{:common_pipeline,
{
:error,
{
:validate_object,
{
:error,
changeset
}
}
}} = e ->
if {:object, {"already liked by this actor", []}} in changeset.errors do
{:ok, :already_liked}
else
{:error, e}
end
e ->
{:error, e}
end end
end end

View file

@ -207,9 +207,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/favourite" @doc "POST /api/v1/statuses/:id/favourite"
def favourite(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do def favourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user), with {:ok, _fav} <- CommonAPI.favorite(user, activity_id),
%Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do %Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
end end
end end

View file

@ -537,7 +537,7 @@ defmodule Pleroma.NotificationTest do
"status" => "hey @#{other_user.nickname}!" "status" => "hey @#{other_user.nickname}!"
}) })
{:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user) {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
{enabled_receivers, _disabled_receivers} = {enabled_receivers, _disabled_receivers} =
Notification.get_notified_from_activity(activity_two) Notification.get_notified_from_activity(activity_two)
@ -620,7 +620,7 @@ defmodule Pleroma.NotificationTest do
assert Enum.empty?(Notification.for_user(user)) assert Enum.empty?(Notification.for_user(user))
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, activity.id)
assert length(Notification.for_user(user)) == 1 assert length(Notification.for_user(user)) == 1
@ -637,7 +637,7 @@ defmodule Pleroma.NotificationTest do
assert Enum.empty?(Notification.for_user(user)) assert Enum.empty?(Notification.for_user(user))
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, activity.id)
assert length(Notification.for_user(user)) == 1 assert length(Notification.for_user(user)) == 1
@ -692,7 +692,7 @@ defmodule Pleroma.NotificationTest do
assert Enum.empty?(Notification.for_user(user)) assert Enum.empty?(Notification.for_user(user))
{:error, _} = CommonAPI.favorite(activity.id, other_user) {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
assert Enum.empty?(Notification.for_user(user)) assert Enum.empty?(Notification.for_user(user))
end end

View file

@ -380,7 +380,8 @@ defmodule Pleroma.ObjectTest do
user = insert(:user) user = insert(:user)
activity = Activity.get_create_by_object_ap_id(object.data["id"]) activity = Activity.get_create_by_object_ap_id(object.data["id"])
{:ok, _activity, object} = CommonAPI.favorite(activity.id, user) {:ok, activity} = CommonAPI.favorite(user, activity.id)
object = Object.get_by_ap_id(activity.data["object"])
assert object.data["like_count"] == 1 assert object.data["like_count"] == 1

View file

@ -60,7 +60,7 @@ defmodule Pleroma.StateTest do
other_user = insert(:user) other_user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
_ = CommonAPI.follow(user, other_user) _ = CommonAPI.follow(user, other_user)
CommonAPI.favorite(activity.id, other_user) CommonAPI.favorite(other_user, activity.id)
CommonAPI.repeat(activity.id, other_user) CommonAPI.repeat(activity.id, other_user)
assert %{direct: 0, private: 0, public: 1, unlisted: 0} = assert %{direct: 0, private: 0, public: 1, unlisted: 0} =

View file

@ -102,7 +102,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
{:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"}) {:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})
{:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"}) {:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"})
CommonAPI.favorite(id, user2) CommonAPI.favorite(user2, id)
likes = %{ likes = %{
"first" => "first" =>

View file

@ -1141,8 +1141,8 @@ defmodule Pleroma.UserTest do
object_two = insert(:note, user: follower) object_two = insert(:note, user: follower)
activity_two = insert(:note_activity, user: follower, note: object_two) activity_two = insert(:note_activity, user: follower, note: object_two)
{:ok, like, _} = CommonAPI.favorite(activity_two.id, user) {:ok, like} = CommonAPI.favorite(user, activity_two.id)
{:ok, like_two, _} = CommonAPI.favorite(activity.id, follower) {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
{:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user) {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
{:ok, job} = User.delete(user) {:ok, job} = User.delete(user)

View file

@ -1900,14 +1900,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "}) {:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "})
{:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "}) {:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "})
{:ok, _, _} = CommonAPI.favorite(a4.id, user) {:ok, _} = CommonAPI.favorite(user, a4.id)
{:ok, _, _} = CommonAPI.favorite(a3.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, a3.id)
{:ok, _, _} = CommonAPI.favorite(a3.id, user) {:ok, _} = CommonAPI.favorite(user, a3.id)
{:ok, _, _} = CommonAPI.favorite(a5.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, a5.id)
{:ok, _, _} = CommonAPI.favorite(a5.id, user) {:ok, _} = CommonAPI.favorite(user, a5.id)
{:ok, _, _} = CommonAPI.favorite(a4.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, a4.id)
{:ok, _, _} = CommonAPI.favorite(a1.id, user) {:ok, _} = CommonAPI.favorite(user, a1.id)
{:ok, _, _} = CommonAPI.favorite(a1.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, a1.id)
result = ActivityPub.fetch_favourites(user) result = ActivityPub.fetch_favourites(user)
assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id] assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id]

View file

@ -0,0 +1,83 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
use Pleroma.DataCase
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
describe "likes" do
setup do
user = insert(:user)
{:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"})
valid_like = %{
"to" => [user.ap_id],
"cc" => [],
"type" => "Like",
"id" => Utils.generate_activity_id(),
"object" => post_activity.data["object"],
"actor" => user.ap_id,
"context" => "a context"
}
%{valid_like: valid_like, user: user, post_activity: post_activity}
end
test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do
{:ok, object, _meta} = ObjectValidator.validate(valid_like, [])
assert "id" in Map.keys(object)
end
test "is valid for a valid object", %{valid_like: valid_like} do
assert LikeValidator.cast_and_validate(valid_like).valid?
end
test "it errors when the actor is missing or not known", %{valid_like: valid_like} do
without_actor = Map.delete(valid_like, "actor")
refute LikeValidator.cast_and_validate(without_actor).valid?
with_invalid_actor = Map.put(valid_like, "actor", "invalidactor")
refute LikeValidator.cast_and_validate(with_invalid_actor).valid?
end
test "it errors when the object is missing or not known", %{valid_like: valid_like} do
without_object = Map.delete(valid_like, "object")
refute LikeValidator.cast_and_validate(without_object).valid?
with_invalid_object = Map.put(valid_like, "object", "invalidobject")
refute LikeValidator.cast_and_validate(with_invalid_object).valid?
end
test "it errors when the actor has already like the object", %{
valid_like: valid_like,
user: user,
post_activity: post_activity
} do
_like = CommonAPI.favorite(user, post_activity.id)
refute LikeValidator.cast_and_validate(valid_like).valid?
end
test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do
wrapped_like =
valid_like
|> Map.put("actor", %{"id" => valid_like["actor"]})
|> Map.put("object", %{"id" => valid_like["object"]})
validated = LikeValidator.cast_and_validate(wrapped_like)
assert validated.valid?
assert {:actor, valid_like["actor"]} in validated.changes
assert {:object, valid_like["object"]} in validated.changes
end
end
end

View file

@ -0,0 +1,35 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do
use Pleroma.DataCase
alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator
alias Pleroma.Web.ActivityPub.Utils
import Pleroma.Factory
describe "Notes" do
setup do
user = insert(:user)
note = %{
"id" => Utils.generate_activity_id(),
"type" => "Note",
"actor" => user.ap_id,
"to" => [user.follower_address],
"cc" => [],
"content" => "Hellow this is content.",
"context" => "xxx",
"summary" => "a post"
}
%{user: user, note: note}
end
test "a basic note validates", %{note: note} do
%{valid?: true} = NoteValidator.cast_and_validate(note)
end
end
end

View file

@ -0,0 +1,32 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTimeTest do
alias Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime
use Pleroma.DataCase
test "it validates an xsd:Datetime" do
valid_strings = [
"2004-04-12T13:20:00",
"2004-04-12T13:20:15.5",
"2004-04-12T13:20:00-05:00",
"2004-04-12T13:20:00Z"
]
invalid_strings = [
"2004-04-12T13:00",
"2004-04-1213:20:00",
"99-04-12T13:00",
"2004-04-12"
]
assert {:ok, "2004-04-01T12:00:00Z"} == DateTime.cast("2004-04-01T12:00:00Z")
Enum.each(valid_strings, fn date_time ->
result = DateTime.cast(date_time)
assert {:ok, _} = result
end)
Enum.each(invalid_strings, fn date_time ->
result = DateTime.cast(date_time)
assert :error == result
end)
end
end

View file

@ -0,0 +1,37 @@
defmodule Pleroma.Web.ObjectValidators.Types.ObjectIDTest do
alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID
use Pleroma.DataCase
@uris [
"http://lain.com/users/lain",
"http://lain.com",
"https://lain.com/object/1"
]
@non_uris [
"https://",
"rin",
1,
:x,
%{"1" => 2}
]
test "it accepts http uris" do
Enum.each(@uris, fn uri ->
assert {:ok, uri} == ObjectID.cast(uri)
end)
end
test "it accepts an object with a nested uri id" do
Enum.each(@uris, fn uri ->
assert {:ok, uri} == ObjectID.cast(%{"id" => uri})
end)
end
test "it rejects non-uri strings" do
Enum.each(@non_uris, fn non_uri ->
assert :error == ObjectID.cast(non_uri)
assert :error == ObjectID.cast(%{"id" => non_uri})
end)
end
end

View file

@ -0,0 +1,87 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.PipelineTest do
use Pleroma.DataCase
import Mock
import Pleroma.Factory
describe "common_pipeline/2" do
test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
activity = insert(:note_activity)
meta = [local: true]
with_mocks([
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
{
Pleroma.Web.ActivityPub.MRF,
[],
[filter: fn o -> {:ok, o} end]
},
{
Pleroma.Web.ActivityPub.ActivityPub,
[],
[persist: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.SideEffects,
[],
[handle: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.Federator,
[],
[publish: fn _o -> :ok end]
}
]) do
assert {:ok, ^activity, ^meta} =
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
assert_called(Pleroma.Web.Federator.publish(activity))
end
end
test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do
activity = insert(:note_activity)
meta = [local: false]
with_mocks([
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
{
Pleroma.Web.ActivityPub.MRF,
[],
[filter: fn o -> {:ok, o} end]
},
{
Pleroma.Web.ActivityPub.ActivityPub,
[],
[persist: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.SideEffects,
[],
[handle: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.Federator,
[],
[]
}
]) do
assert {:ok, ^activity, ^meta} =
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
end
end
end
end

View file

@ -0,0 +1,34 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
use Pleroma.DataCase
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
describe "like objects" do
setup do
user = insert(:user)
{:ok, post} = CommonAPI.post(user, %{"status" => "hey"})
{:ok, like_data, _meta} = Builder.like(user, post.object)
{:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
%{like: like, user: user}
end
test "add the like to the original object", %{like: like, user: user} do
{:ok, like, _} = SideEffects.handle(like)
object = Object.get_by_ap_id(like.data["object"])
assert object.data["like_count"] == 1
assert user.ap_id in object.data["likes"]
end
end
end

View file

@ -334,7 +334,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|> Poison.decode!() |> Poison.decode!()
|> Map.put("object", activity.data["object"]) |> Map.put("object", activity.data["object"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
refute Enum.empty?(activity.recipients)
assert data["actor"] == "http://mastodon.example.org/users/admin" assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Like" assert data["type"] == "Like"

View file

@ -59,7 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
object = Object.normalize(note) object = Object.normalize(note)
user = insert(:user) user = insert(:user)
{:ok, like_activity, _} = CommonAPI.favorite(note.id, user) {:ok, like_activity} = CommonAPI.favorite(user, note.id)
result = ObjectView.render("object.json", %{object: like_activity}) result = ObjectView.render("object.json", %{object: like_activity})

View file

@ -284,9 +284,12 @@ defmodule Pleroma.Web.CommonAPITest do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) {:ok, post_activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
{:ok, %Activity{}, _} = CommonAPI.favorite(activity.id, user) {:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id)
assert data["type"] == "Like"
assert data["actor"] == user.ap_id
assert data["object"] == post_activity.data["object"]
end end
test "retweeting a status twice returns the status" do test "retweeting a status twice returns the status" do
@ -298,13 +301,13 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user) {:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user)
end end
test "favoriting a status twice returns the status" do test "favoriting a status twice returns ok, but without the like activity" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
{:ok, %Activity{} = activity, object} = CommonAPI.favorite(activity.id, user) {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
{:ok, ^activity, ^object} = CommonAPI.favorite(activity.id, user) assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)
end end
end end

View file

@ -194,10 +194,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
{:ok, private_activity} = {:ok, private_activity} =
CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"}) CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"})
{:ok, _, _} = CommonAPI.favorite(public_activity.id, user) {:ok, _} = CommonAPI.favorite(user, public_activity.id)
{:ok, _, _} = CommonAPI.favorite(direct_activity.id, user) {:ok, _} = CommonAPI.favorite(user, direct_activity.id)
{:ok, _, _} = CommonAPI.favorite(unlisted_activity.id, user) {:ok, _} = CommonAPI.favorite(user, unlisted_activity.id)
{:ok, _, _} = CommonAPI.favorite(private_activity.id, user) {:ok, _} = CommonAPI.favorite(user, private_activity.id)
activity_ids = activity_ids =
conn conn
@ -274,7 +274,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
{:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"}) {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
{:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user) {:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
{:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user) {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user) {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
@ -310,7 +310,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
{:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"}) {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
{:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user) {:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
{:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user) {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user) {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)

View file

@ -775,7 +775,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
user1 = insert(:user) user1 = insert(:user)
user2 = insert(:user) user2 = insert(:user)
user3 = insert(:user) user3 = insert(:user)
CommonAPI.favorite(activity.id, user2) {:ok, _} = CommonAPI.favorite(user2, activity.id)
{:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id) {:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
{:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1) {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
{:ok, _, _object} = CommonAPI.repeat(activity.id, user2) {:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
@ -850,11 +850,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
activity = insert(:note_activity) activity = insert(:note_activity)
post(conn, "/api/v1/statuses/#{activity.id}/favourite") post(conn, "/api/v1/statuses/#{activity.id}/favourite")
assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") |> json_response(200)
assert post(conn, "/api/v1/statuses/#{activity.id}/favourite")
|> json_response(200)
end end
test "returns 404 error for a wrong id", %{conn: conn} do test "returns 404 error for a wrong id", %{conn: conn} do
conn = post(conn, "/api/v1/statuses/1/favourite") conn =
conn
|> post("/api/v1/statuses/1/favourite")
assert json_response(conn, 404) == %{"error" => "Record not found"} assert json_response(conn, 404) == %{"error" => "Record not found"}
end end
@ -866,7 +870,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "unfavorites a status and returns it", %{user: user, conn: conn} do test "unfavorites a status and returns it", %{user: user, conn: conn} do
activity = insert(:note_activity) activity = insert(:note_activity)
{:ok, _, _} = CommonAPI.favorite(activity.id, user) {:ok, _} = CommonAPI.favorite(user, activity.id)
conn = post(conn, "/api/v1/statuses/#{activity.id}/unfavourite") conn = post(conn, "/api/v1/statuses/#{activity.id}/unfavourite")
@ -1176,7 +1180,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "returns users who have favorited the status", %{conn: conn, activity: activity} do test "returns users who have favorited the status", %{conn: conn, activity: activity} do
other_user = insert(:user) other_user = insert(:user)
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, activity.id)
response = response =
conn conn
@ -1207,7 +1211,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
other_user = insert(:user) other_user = insert(:user)
{:ok, _user_relationship} = User.block(user, other_user) {:ok, _user_relationship} = User.block(user, other_user)
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, activity.id)
response = response =
conn conn
@ -1219,7 +1223,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "does not fail on an unauthenticated request", %{activity: activity} do test "does not fail on an unauthenticated request", %{activity: activity} do
other_user = insert(:user) other_user = insert(:user)
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, activity.id)
response = response =
build_conn() build_conn()
@ -1239,7 +1243,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
"visibility" => "direct" "visibility" => "direct"
}) })
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user) {:ok, _} = CommonAPI.favorite(other_user, activity.id)
favourited_by_url = "/api/v1/statuses/#{activity.id}/favourited_by" favourited_by_url = "/api/v1/statuses/#{activity.id}/favourited_by"
@ -1399,7 +1403,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"}) {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
{:ok, _, _} = CommonAPI.favorite(activity.id, user) {:ok, _} = CommonAPI.favorite(user, activity.id)
first_conn = get(conn, "/api/v1/favourites") first_conn = get(conn, "/api/v1/favourites")
@ -1416,7 +1420,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
"Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
}) })
{:ok, _, _} = CommonAPI.favorite(second_activity.id, user) {:ok, _} = CommonAPI.favorite(user, second_activity.id)
last_like = status["id"] last_like = status["id"]

View file

@ -54,7 +54,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
user = insert(:user) user = insert(:user)
another_user = insert(:user) another_user = insert(:user)
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
{:ok, favorite_activity, _object} = CommonAPI.favorite(create_activity.id, another_user) {:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
{:ok, [notification]} = Notification.create_notifications(favorite_activity) {:ok, [notification]} = Notification.create_notifications(favorite_activity)
create_activity = Activity.get_by_id(create_activity.id) create_activity = Activity.get_by_id(create_activity.id)

View file

@ -136,7 +136,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
user = insert(:user) user = insert(:user)
{:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user) {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
assert like_activity.data["type"] == "Like" assert like_activity.data["type"] == "Like"

View file

@ -138,7 +138,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
user: user user: user
} do } do
[activity | _] = insert_pair(:note_activity) [activity | _] = insert_pair(:note_activity)
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(user, activity.id)
response = response =
conn conn
@ -155,7 +155,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
user: user user: user
} do } do
activity = insert(:note_activity) activity = insert(:note_activity)
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(user, activity.id)
build_conn() build_conn()
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
@ -172,7 +172,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
"visibility" => "direct" "visibility" => "direct"
}) })
CommonAPI.favorite(direct.id, user) CommonAPI.favorite(user, direct.id)
for u <- [user, current_user] do for u <- [user, current_user] do
response = response =
@ -202,7 +202,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
"visibility" => "direct" "visibility" => "direct"
}) })
CommonAPI.favorite(direct.id, user) CommonAPI.favorite(user, direct.id)
response = response =
conn conn
@ -219,7 +219,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
activities = insert_list(10, :note_activity) activities = insert_list(10, :note_activity)
Enum.each(activities, fn activity -> Enum.each(activities, fn activity ->
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(user, activity.id)
end) end)
third_activity = Enum.at(activities, 2) third_activity = Enum.at(activities, 2)
@ -245,7 +245,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
7 7
|> insert_list(:note_activity) |> insert_list(:note_activity)
|> Enum.each(fn activity -> |> Enum.each(fn activity ->
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(user, activity.id)
end) end)
response = response =
@ -277,7 +277,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
test "returns 403 error when user has hidden own favorites", %{conn: conn} do test "returns 403 error when user has hidden own favorites", %{conn: conn} do
user = insert(:user, hide_favorites: true) user = insert(:user, hide_favorites: true)
activity = insert(:note_activity) activity = insert(:note_activity)
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(user, activity.id)
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites")
@ -287,7 +287,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
test "hides favorites for new users by default", %{conn: conn} do test "hides favorites for new users by default", %{conn: conn} do
user = insert(:user) user = insert(:user)
activity = insert(:note_activity) activity = insert(:note_activity)
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(user, activity.id)
assert user.hide_favorites assert user.hide_favorites
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites")

View file

@ -170,7 +170,7 @@ defmodule Pleroma.Web.Push.ImplTest do
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis." "<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
}) })
{:ok, activity, _} = CommonAPI.favorite(activity.id, user) {:ok, activity} = CommonAPI.favorite(user, activity.id)
object = Object.normalize(activity) object = Object.normalize(activity)
assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post" assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post"

View file

@ -64,9 +64,6 @@ defmodule Pleroma.Web.StreamerTest do
blocked = insert(:user) blocked = insert(:user)
{:ok, _user_relationship} = User.block(user, blocked) {:ok, _user_relationship} = User.block(user, blocked)
{:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
{:ok, notif, _} = CommonAPI.favorite(activity.id, blocked)
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end) task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
Streamer.add_socket( Streamer.add_socket(
@ -74,6 +71,9 @@ defmodule Pleroma.Web.StreamerTest do
%{transport_pid: task.pid, assigns: %{user: user}} %{transport_pid: task.pid, assigns: %{user: user}}
) )
{:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
{:ok, notif} = CommonAPI.favorite(blocked, activity.id)
Streamer.stream("user:notification", notif) Streamer.stream("user:notification", notif)
Task.await(task) Task.await(task)
end end
@ -83,10 +83,6 @@ defmodule Pleroma.Web.StreamerTest do
} do } do
user2 = insert(:user) user2 = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
{:ok, activity} = CommonAPI.add_mute(user, activity)
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end) task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
Streamer.add_socket( Streamer.add_socket(
@ -94,6 +90,10 @@ defmodule Pleroma.Web.StreamerTest do
%{transport_pid: task.pid, assigns: %{user: user}} %{transport_pid: task.pid, assigns: %{user: user}}
) )
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
{:ok, activity} = CommonAPI.add_mute(user, activity)
{:ok, notif} = CommonAPI.favorite(user2, activity.id)
Streamer.stream("user:notification", notif) Streamer.stream("user:notification", notif)
Task.await(task) Task.await(task)
end end
@ -103,10 +103,6 @@ defmodule Pleroma.Web.StreamerTest do
} do } do
user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"}) user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end) task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
Streamer.add_socket( Streamer.add_socket(
@ -114,6 +110,10 @@ defmodule Pleroma.Web.StreamerTest do
%{transport_pid: task.pid, assigns: %{user: user}} %{transport_pid: task.pid, assigns: %{user: user}}
) )
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
{:ok, notif} = CommonAPI.favorite(user2, activity.id)
Streamer.stream("user:notification", notif) Streamer.stream("user:notification", notif)
Task.await(task) Task.await(task)
end end
@ -476,7 +476,7 @@ defmodule Pleroma.Web.StreamerTest do
CommonAPI.hide_reblogs(user1, user2) CommonAPI.hide_reblogs(user1, user2)
{:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"}) {:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"})
{:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, user2) {:ok, favorite_activity} = CommonAPI.favorite(user2, create_activity.id)
task = task =
Task.async(fn -> Task.async(fn ->