diff options
36 files changed, 862 insertions, 85 deletions
| diff --git a/lib/pleroma/object/containment.ex b/lib/pleroma/object/containment.ex index 9ae6a5600..99608b8a5 100644 --- a/lib/pleroma/object/containment.ex +++ b/lib/pleroma/object/containment.ex @@ -32,6 +32,18 @@ defmodule Pleroma.Object.Containment do      get_actor(%{"actor" => actor})    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    # objects being present in the test suite environment.  Once these objects are    # removed, please also remove this. diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index d9f74b6a4..d9f30e629 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -126,6 +126,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    def increase_poll_votes_if_vote(_create_data), do: :noop    @spec insert(map(), boolean(), boolean(), boolean()) :: {:ok, Activity.t()} | {:error, any()} +  # TODO rewrite in with style +  @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} +  def persist(object, meta) do +    local = Keyword.fetch!(meta, :local) +    {recipients, _, _} = get_recipients(object) + +    {:ok, activity} = +      Repo.insert(%Activity{ +        data: object, +        local: local, +        recipients: recipients, +        actor: object["actor"] +      }) + +    {:ok, activity, meta} +  end +    def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when is_map(map) do      with nil <- Activity.normalize(map),           map <- lazy_put_activity_defaults(map, fake), @@ -133,6 +150,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do           {_, true} <- {:remote_limit_error, check_remote_limit(map)},           {:ok, map} <- MRF.filter(map),           {recipients, _, _} = get_recipients(map), +         # ???           {:fake, false, map, recipients} <- {:fake, fake, map, recipients},           {:containment, :ok} <- {:containment, Containment.contain_child(map)},           {:ok, map, object} <- insert_full_object(map) do diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex new file mode 100644 index 000000000..429a510b8 --- /dev/null +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -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 diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex new file mode 100644 index 000000000..cff924047 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -0,0 +1,38 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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 +    |> Enum.map(fn {key, val} -> {to_string(key), val} end) +    |> Enum.into(%{}) +  end + +  def fetch_actor_and_object(object) do +    User.get_or_fetch_by_ap_id(object["actor"]) +    Object.normalize(object["object"]) +    :ok +  end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex new file mode 100644 index 000000000..db0e2072d --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -0,0 +1,32 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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, actor -> +      if Object.get_cached_by_ap_id(actor) do +        [] +      else +        [{field_name, "can't find user"}] +      end +    end) +  end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_validator.ex new file mode 100644 index 000000000..bd90f7250 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/create_validator.ex @@ -0,0 +1,31 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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.Types +  alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator + +  import Ecto.Changeset + +  @primary_key false + +  embedded_schema do +    field(:id, :string, 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 +    %__MODULE__{} +    |> cast(data, __schema__(:fields)) +  end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex new file mode 100644 index 000000000..ccbc7d071 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex @@ -0,0 +1,57 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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, :string, 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 diff --git a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex new file mode 100644 index 000000000..eea15ce1c --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex @@ -0,0 +1,63 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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, :string, 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 diff --git a/lib/pleroma/web/activity_pub/object_validators/types/date_time.ex b/lib/pleroma/web/activity_pub/object_validators/types/date_time.ex new file mode 100644 index 000000000..4f412fcde --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/types/date_time.ex @@ -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 diff --git a/lib/pleroma/web/activity_pub/object_validators/types/object.ex b/lib/pleroma/web/activity_pub/object_validators/types/object.ex new file mode 100644 index 000000000..92fc13ba8 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/types/object.ex @@ -0,0 +1,25 @@ +defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID do +  use Ecto.Type + +  def type, do: :string + +  def cast(object) when is_binary(object) do +    {:ok, object} +  end + +  def cast(%{"id" => object}) when is_binary(object) do +    {:ok, object} +  end + +  def cast(_) do +    :error +  end + +  def dump(data) do +    {:ok, data} +  end + +  def load(data) do +    {:ok, data} +  end +end diff --git a/lib/pleroma/web/activity_pub/pipeline.ex b/lib/pleroma/web/activity_pub/pipeline.ex new file mode 100644 index 000000000..cb3571917 --- /dev/null +++ b/lib/pleroma/web/activity_pub/pipeline.ex @@ -0,0 +1,41 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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 +      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, "local not set in meta"} +    end +  end +end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex new file mode 100644 index 000000000..666a4e310 --- /dev/null +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -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 diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 9cd3de705..dbb14e9aa 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -13,6 +13,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    alias Pleroma.Repo    alias Pleroma.User    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.Visibility    alias Pleroma.Web.Federator @@ -608,17 +611,21 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      |> handle_incoming(options)    end -  def handle_incoming( -        %{"type" => "Like", "object" => object_id, "actor" => _actor, "id" => id} = data, -        _options -      ) do -    with actor <- Containment.get_actor(data), -         {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor), -         {:ok, object} <- get_obj_helper(object_id), -         {:ok, activity, _object} <- ActivityPub.like(actor, object, id, false) do +  def handle_incoming(%{"type" => "Like"} = data, _options) do +    with {_, {:ok, cast_data_sym}} <- +           {:casting_data, +            data |> LikeValidator.cast_data() |> Ecto.Changeset.apply_action(:insert)}, +         {_, cast_data} <- +           {:stringify_keys, ObjectValidator.stringify_keys(cast_data_sym |> Map.from_struct())}, +         :ok <- ObjectValidator.fetch_actor_and_object(cast_data), +         {_, {:ok, cast_data}} <- {:maybe_add_context, maybe_add_context_from_object(cast_data)}, +         {_, {:ok, cast_data}} <- +           {:maybe_add_recipients, maybe_add_recipients_from_object(cast_data)}, +         {_, {:ok, activity, _meta}} <- +           {:common_pipeline, Pipeline.common_pipeline(cast_data, local: false)} do        {:ok, activity}      else -      _e -> :error +      e -> {:error, e}      end    end @@ -1244,4 +1251,47 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    def maybe_fix_user_url(data), do: data    def maybe_fix_user_object(data), do: maybe_fix_user_url(data) + +  defp maybe_add_context_from_object(%{"context" => context} = data) when is_binary(context), +    do: {:ok, data} + +  defp maybe_add_context_from_object(%{"object" => object} = data) when is_binary(object) do +    if object = Object.normalize(object) do +      data = +        data +        |> Map.put("context", object.data["context"]) + +      {:ok, data} +    else +      {:error, "No context on referenced object"} +    end +  end + +  defp maybe_add_context_from_object(_) do +    {:error, "No referenced object"} +  end + +  defp maybe_add_recipients_from_object(%{"object" => object} = data) do +    to = data["to"] || [] +    cc = data["cc"] || [] + +    if to == [] && cc == [] do +      if object = Object.normalize(object) do +        data = +          data +          |> Map.put("to", [object.data["actor"]]) +          |> Map.put("cc", cc) + +        {:ok, data} +      else +        {:error, "No actor on referenced object"} +      end +    else +      {:ok, data} +    end +  end + +  defp maybe_add_recipients_from_object(_) do +    {:error, "No referenced object"} +  end  end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 091011c6b..f882f9fcb 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -12,6 +12,8 @@ defmodule Pleroma.Web.CommonAPI do    alias Pleroma.User    alias Pleroma.UserRelationship    alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.Pipeline    alias Pleroma.Web.ActivityPub.Utils    alias Pleroma.Web.ActivityPub.Visibility @@ -19,6 +21,7 @@ defmodule Pleroma.Web.CommonAPI do    import Pleroma.Web.CommonAPI.Utils    require Pleroma.Constants +  require Logger    def follow(follower, followed) do      timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout]) @@ -109,18 +112,39 @@ defmodule Pleroma.Web.CommonAPI do      end    end -  def favorite(id_or_ap_id, user) do -    with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)}, -         object <- Object.normalize(activity), -         like_activity <- Utils.get_existing_like(user.ap_id, object) do -      if like_activity do -        {:ok, like_activity, object} -      else -        ActivityPub.like(user, object) -      end +  @spec favorite(User.t(), binary()) :: {:ok, Activity.t()} | {:error, any()} +  def favorite(%User{} = 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 -      {:find_activity, _} -> {:error, :not_found} -      _ -> {:error, dgettext("errors", "Could not favorite")} +      {:find_object, _} -> +        {: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 +          Logger.error("Could not favorite #{id}. Error: #{inspect(e, pretty: true)}") +          {:error, dgettext("errors", "Could not favorite"), e} +        end + +      e -> +        Logger.error("Could not favorite #{id}. Error: #{inspect(e, pretty: true)}") +        {:error, dgettext("errors", "Could not favorite"), e}      end    end diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 5c90065f6..83cd2c768 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -207,9 +207,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do    end    @doc "POST /api/v1/statuses/:id/favourite" -  def favourite(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do -    with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user), -         %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do +  def favourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do +    with {:ok, _fav} <- CommonAPI.favorite(user, activity_id), +         %Activity{} = activity <- Activity.get_by_id(activity_id) do        try_render(conn, "show.json", activity: activity, for: user, as: :activity)      end    end diff --git a/test/notification_test.exs b/test/notification_test.exs index 56a581810..81eb0e2f7 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -455,7 +455,7 @@ defmodule Pleroma.NotificationTest do            "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)        assert other_user not in Notification.get_notified_from_activity(activity_two)      end @@ -485,7 +485,7 @@ defmodule Pleroma.NotificationTest do        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 @@ -502,7 +502,7 @@ defmodule Pleroma.NotificationTest do        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 @@ -557,7 +557,7 @@ defmodule Pleroma.NotificationTest do        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))      end diff --git a/test/object_test.exs b/test/object_test.exs index 85b2a3f6d..703fd6e0f 100644 --- a/test/object_test.exs +++ b/test/object_test.exs @@ -380,7 +380,8 @@ defmodule Pleroma.ObjectTest do        user = insert(:user)        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 diff --git a/test/stat_test.exs b/test/stat_test.exs index 33b77e7e7..bccc1c8d0 100644 --- a/test/stat_test.exs +++ b/test/stat_test.exs @@ -60,7 +60,7 @@ defmodule Pleroma.StateTest do        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})        _ = CommonAPI.follow(user, other_user) -      CommonAPI.favorite(activity.id, other_user) +      CommonAPI.favorite(other_user, activity.id)        CommonAPI.repeat(activity.id, other_user)        assert %{direct: 0, private: 0, public: 1, unlisted: 0} = diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs index ed1c31d9c..7b05993d3 100644 --- a/test/tasks/database_test.exs +++ b/test/tasks/database_test.exs @@ -102,7 +102,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do        {:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})        {:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"}) -      CommonAPI.favorite(id, user2) +      CommonAPI.favorite(user2, id)        likes = %{          "first" => diff --git a/test/user_test.exs b/test/user_test.exs index b07fed42b..8dcac676d 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1146,8 +1146,8 @@ defmodule Pleroma.UserTest do        object_two = insert(:note, user: follower)        activity_two = insert(:note_activity, user: follower, note: object_two) -      {:ok, like, _} = CommonAPI.favorite(activity_two.id, user) -      {:ok, like_two, _} = CommonAPI.favorite(activity.id, follower) +      {:ok, like} = CommonAPI.favorite(user, activity_two.id) +      {:ok, like_two} = CommonAPI.favorite(follower, activity.id)        {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)        {:ok, job} = User.delete(user) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 3dd3dd04d..d5dd44cc3 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -1894,14 +1894,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "})        {:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "}) -      {:ok, _, _} = CommonAPI.favorite(a4.id, user) -      {:ok, _, _} = CommonAPI.favorite(a3.id, other_user) -      {:ok, _, _} = CommonAPI.favorite(a3.id, user) -      {:ok, _, _} = CommonAPI.favorite(a5.id, other_user) -      {:ok, _, _} = CommonAPI.favorite(a5.id, user) -      {:ok, _, _} = CommonAPI.favorite(a4.id, other_user) -      {:ok, _, _} = CommonAPI.favorite(a1.id, user) -      {:ok, _, _} = CommonAPI.favorite(a1.id, other_user) +      {:ok, _} = CommonAPI.favorite(user, a4.id) +      {:ok, _} = CommonAPI.favorite(other_user, a3.id) +      {:ok, _} = CommonAPI.favorite(user, a3.id) +      {:ok, _} = CommonAPI.favorite(other_user, a5.id) +      {:ok, _} = CommonAPI.favorite(user, a5.id) +      {:ok, _} = CommonAPI.favorite(other_user, a4.id) +      {:ok, _} = CommonAPI.favorite(user, a1.id) +      {:ok, _} = CommonAPI.favorite(other_user, a1.id)        result = ActivityPub.fetch_favourites(user)        assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id] diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs new file mode 100644 index 000000000..3c5c3696e --- /dev/null +++ b/test/web/activity_pub/object_validator_test.exs @@ -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 diff --git a/test/web/activity_pub/object_validators/note_validator_test.exs b/test/web/activity_pub/object_validators/note_validator_test.exs new file mode 100644 index 000000000..2bcd75e25 --- /dev/null +++ b/test/web/activity_pub/object_validators/note_validator_test.exs @@ -0,0 +1,35 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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 diff --git a/test/web/activity_pub/object_validators/types/date_time_test.exs b/test/web/activity_pub/object_validators/types/date_time_test.exs new file mode 100644 index 000000000..3e17a9497 --- /dev/null +++ b/test/web/activity_pub/object_validators/types/date_time_test.exs @@ -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 diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs new file mode 100644 index 000000000..318d306af --- /dev/null +++ b/test/web/activity_pub/pipeline_test.exs @@ -0,0 +1,87 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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 diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs new file mode 100644 index 000000000..ef91954ae --- /dev/null +++ b/test/web/activity_pub/side_effects_test.exs @@ -0,0 +1,34 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 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 diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index efbca82f6..83372ec7e 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -334,7 +334,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do          |> Poison.decode!()          |> 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["type"] == "Like" diff --git a/test/web/activity_pub/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs index 09866e99b..f6796ad4a 100644 --- a/test/web/activity_pub/views/object_view_test.exs +++ b/test/web/activity_pub/views/object_view_test.exs @@ -61,7 +61,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do      object = Object.normalize(note)      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}) diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index b80523160..c2ed1c789 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -284,9 +284,12 @@ defmodule Pleroma.Web.CommonAPITest do        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      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)      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)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) -      {:ok, %Activity{} = activity, object} = CommonAPI.favorite(activity.id, user) -      {:ok, ^activity, ^object} = CommonAPI.favorite(activity.id, user) +      {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id) +      assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)      end    end diff --git a/test/web/mastodon_api/controllers/notification_controller_test.exs b/test/web/mastodon_api/controllers/notification_controller_test.exs index d452ddbdd..3bc9aff16 100644 --- a/test/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/web/mastodon_api/controllers/notification_controller_test.exs @@ -194,10 +194,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do        {:ok, private_activity} =          CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"}) -      {:ok, _, _} = CommonAPI.favorite(public_activity.id, user) -      {:ok, _, _} = CommonAPI.favorite(direct_activity.id, user) -      {:ok, _, _} = CommonAPI.favorite(unlisted_activity.id, user) -      {:ok, _, _} = CommonAPI.favorite(private_activity.id, user) +      {:ok, _} = CommonAPI.favorite(user, public_activity.id) +      {:ok, _} = CommonAPI.favorite(user, direct_activity.id) +      {:ok, _} = CommonAPI.favorite(user, unlisted_activity.id) +      {:ok, _} = CommonAPI.favorite(user, private_activity.id)        activity_ids =          conn @@ -274,7 +274,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})      {: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, _, _, follow_activity} = CommonAPI.follow(other_user, user) diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index fbf63f608..f36552041 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -622,7 +622,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        user1 = insert(:user)        user2 = 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, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)        {:ok, _, _object} = CommonAPI.repeat(activity.id, user2) @@ -697,11 +697,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        activity = insert(:note_activity)        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      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"}      end @@ -713,7 +717,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "unfavorites a status and returns it", %{user: user, conn: conn} do        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") @@ -1025,7 +1029,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "returns users who have favorited the status", %{conn: conn, activity: activity} do        other_user = insert(:user) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        response =          conn @@ -1056,7 +1060,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        other_user = insert(:user)        {:ok, _user_relationship} = User.block(user, other_user) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        response =          conn @@ -1068,7 +1072,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "does not fail on an unauthenticated request", %{activity: activity} do        other_user = insert(:user) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        response =          build_conn() @@ -1088,7 +1092,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do            "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" @@ -1248,7 +1252,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})      {: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") @@ -1265,7 +1269,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do            "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"] diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index 4df9c3c03..779126556 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -42,7 +42,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do      user = insert(:user)      another_user = insert(:user)      {: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)      create_activity = Activity.get_by_id(create_activity.id) diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index 3b84358e4..ae99e37fe 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -138,7 +138,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        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" diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs index 245cc1579..3853a9bbb 100644 --- a/test/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/web/pleroma_api/controllers/account_controller_test.exs @@ -140,7 +140,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        user: user      } do        [activity | _] = insert_pair(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        response =          conn @@ -157,7 +157,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        user: user      } do        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        build_conn()        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") @@ -174,7 +174,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do            "visibility" => "direct"          }) -      CommonAPI.favorite(direct.id, user) +      CommonAPI.favorite(user, direct.id)        for u <- [user, current_user] do          response = @@ -204,7 +204,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do            "visibility" => "direct"          }) -      CommonAPI.favorite(direct.id, user) +      CommonAPI.favorite(user, direct.id)        response =          conn @@ -221,7 +221,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        activities = insert_list(10, :note_activity)        Enum.each(activities, fn activity -> -        CommonAPI.favorite(activity.id, user) +        CommonAPI.favorite(user, activity.id)        end)        third_activity = Enum.at(activities, 2) @@ -247,7 +247,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        7        |> insert_list(:note_activity)        |> Enum.each(fn activity -> -        CommonAPI.favorite(activity.id, user) +        CommonAPI.favorite(user, activity.id)        end)        response = @@ -279,7 +279,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      test "returns 403 error when user has hidden own favorites", %{conn: conn} do        user = insert(:user, hide_favorites: true)        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") @@ -289,7 +289,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      test "hides favorites for new users by default", %{conn: conn} do        user = insert(:user)        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        assert user.hide_favorites        conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index 089d55577..b90e31f94 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -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."        }) -    {:ok, activity, _} = CommonAPI.favorite(activity.id, user) +    {:ok, activity} = CommonAPI.favorite(user, activity.id)      object = Object.normalize(activity)      assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post" diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index 339f99bbf..f0bafc093 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -65,9 +65,6 @@ defmodule Pleroma.Web.StreamerTest do        blocked = insert(:user)        {: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)        Streamer.add_socket( @@ -75,6 +72,9 @@ defmodule Pleroma.Web.StreamerTest do          %{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)        Task.await(task)      end @@ -84,10 +84,6 @@ defmodule Pleroma.Web.StreamerTest do      } do        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)        Streamer.add_socket( @@ -95,6 +91,10 @@ defmodule Pleroma.Web.StreamerTest do          %{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)        Task.await(task)      end @@ -104,10 +104,6 @@ defmodule Pleroma.Web.StreamerTest do      } do        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)        Streamer.add_socket( @@ -115,6 +111,10 @@ defmodule Pleroma.Web.StreamerTest do          %{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)        Task.await(task)      end @@ -465,7 +465,7 @@ defmodule Pleroma.Web.StreamerTest do      CommonAPI.hide_reblogs(user1, user2)      {: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.async(fn -> | 
