diff options
-rw-r--r-- | lib/pleroma/activity.ex | 1 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 8 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/ostatus.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/ostatus_controller.ex | 21 | ||||
-rw-r--r-- | priv/repo/migrations/20171109091239_add_actor_to_activity.exs | 20 | ||||
-rw-r--r-- | priv/repo/migrations/20171109114020_fill_actor_field.exs | 26 | ||||
-rw-r--r-- | priv/repo/migrations/20171109141309_add_sort_index_to_activities.exs | 8 | ||||
-rw-r--r-- | test/support/factory.ex | 3 | ||||
-rw-r--r-- | test/web/activity_pub/activity_pub_test.exs | 1 | ||||
-rw-r--r-- | test/web/ostatus/ostatus_controller_test.exs | 41 |
10 files changed, 124 insertions, 10 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index f43b32b56..a35ccc9b4 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Activity do schema "activities" do field :data, :map field :local, :boolean, default: true + field :actor, :string has_many :notifications, Notification timestamps() diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index e7d4c48bd..1624c6545 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do with nil <- Activity.get_by_ap_id(map["id"]), map <- lazy_put_activity_defaults(map), :ok <- insert_full_object(map) do - {:ok, activity} = Repo.insert(%Activity{data: map, local: local}) + {:ok, activity} = Repo.insert(%Activity{data: map, local: local, actor: map["actor"]}) Notification.create_notifications(activity) {:ok, activity} else @@ -137,7 +137,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_actor(query, %{"actor_id" => actor_id}) do from activity in query, - where: fragment("?->>'actor' = ?", activity.data, ^actor_id) + where: activity.actor == ^actor_id end defp restrict_actor(query, _), do: query @@ -168,14 +168,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do blocks = info["blocks"] || [] from activity in query, - where: fragment("not (?->>'actor' = ANY(?))", activity.data, ^blocks) + where: fragment("not (? = ANY(?))", activity.actor, ^blocks) end defp restrict_blocked(query, _), do: query def fetch_activities(recipients, opts \\ %{}) do base_query = from activity in Activity, limit: 20, - order_by: [desc: :id] + order_by: [fragment("? desc nulls last", activity.id)] base_query |> restrict_recipients(recipients) diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 308e206c5..b0d2dda5d 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -221,7 +221,7 @@ defmodule Pleroma.Web.OStatus do Repo.insert(cs, on_conflict: :replace_all, conflict_target: :nickname) end - def make_user(uri) do + def make_user(uri, update \\ false) do with {:ok, info} <- gather_user_info(uri) do data = %{ name: info["name"], @@ -231,7 +231,8 @@ defmodule Pleroma.Web.OStatus do avatar: info["avatar"], bio: info["bio"] } - with %User{} = user <- User.get_by_ap_id(data.ap_id) do + with false <- update, + %User{} = user <- User.get_by_ap_id(data.ap_id) do {:ok, user} else _e -> insert_or_update_user(data) end diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 4e3fbb4f6..67688ace4 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Web.OStatus.{FeedRepresenter, ActivityRepresenter} alias Pleroma.Repo alias Pleroma.Web.{OStatus, Federator} + alias Pleroma.Web.XML import Ecto.Query def feed_redirect(conn, %{"nickname" => nickname}) do @@ -36,10 +37,26 @@ defmodule Pleroma.Web.OStatus.OStatusController do |> send_resp(200, response) end + defp decode_or_retry(body) do + with {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body), + {:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do + {:ok, doc} + else + _e -> + with [decoded | _] <- Pleroma.Web.Salmon.decode(body), + doc <- XML.parse_document(decoded), + uri when not is_nil(uri) <- XML.string_from_xpath("/entry/author[1]/uri", doc), + {:ok, user} <- Pleroma.Web.OStatus.make_user(uri, true), + {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body), + {:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do + {:ok, doc} + end + end + end + def salmon_incoming(conn, params) do {:ok, body, _conn} = read_body(conn) - {:ok, magic_key} = Pleroma.Web.Salmon.fetch_magic_key(body) - {:ok, doc} = Pleroma.Web.Salmon.decode_and_validate(magic_key, body) + {:ok, doc} = decode_or_retry(body) Federator.enqueue(:incoming_doc, doc) diff --git a/priv/repo/migrations/20171109091239_add_actor_to_activity.exs b/priv/repo/migrations/20171109091239_add_actor_to_activity.exs new file mode 100644 index 000000000..2d8b60a91 --- /dev/null +++ b/priv/repo/migrations/20171109091239_add_actor_to_activity.exs @@ -0,0 +1,20 @@ +defmodule Pleroma.Repo.Migrations.AddActorToActivity do + use Ecto.Migration + + @disable_ddl_transaction true + + def up do + alter table(:activities) do + add :actor, :string + end + + create index(:activities, [:actor, "id DESC NULLS LAST"], concurrently: true) + end + + def down do + drop index(:activities, [:actor, "id DESC NULLS LAST"]) + alter table(:activities) do + remove :actor + end + end +end diff --git a/priv/repo/migrations/20171109114020_fill_actor_field.exs b/priv/repo/migrations/20171109114020_fill_actor_field.exs new file mode 100644 index 000000000..255ca46d5 --- /dev/null +++ b/priv/repo/migrations/20171109114020_fill_actor_field.exs @@ -0,0 +1,26 @@ +defmodule Pleroma.Repo.Migrations.FillActorField do + use Ecto.Migration + + alias Pleroma.{Repo, Activity} + + def up do + max = Repo.aggregate(Activity, :max, :id) + if max do + IO.puts("#{max} activities") + chunks = 0..(round(max / 10_000)) + + Enum.each(chunks, fn (i) -> + min = i * 10_000 + max = min + 10_000 + execute(""" + update activities set actor = data->>'actor' where id > #{min} and id <= #{max}; + """) + |> IO.inspect + end) + end + end + + def down do + end +end + diff --git a/priv/repo/migrations/20171109141309_add_sort_index_to_activities.exs b/priv/repo/migrations/20171109141309_add_sort_index_to_activities.exs new file mode 100644 index 000000000..2d21c56ca --- /dev/null +++ b/priv/repo/migrations/20171109141309_add_sort_index_to_activities.exs @@ -0,0 +1,8 @@ +defmodule Pleroma.Repo.Migrations.AddSortIndexToActivities do + use Ecto.Migration + @disable_ddl_transaction true + + def change do + create index(:activities, ["id desc nulls last"], concurrently: true) + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index dabb95141..9bbf11f08 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -51,7 +51,8 @@ defmodule Pleroma.Factory do } %Pleroma.Activity{ - data: data + data: data, + actor: data["actor"] } end diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 2cd33d623..f50509b63 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -52,6 +52,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "removes doubled 'to' recipients" do {:ok, activity} = ActivityPub.create(["user1", "user1", "user2"], %User{ap_id: "1"}, "", %{}) assert activity.data["to"] == ["user1", "user2"] + assert activity.actor == "1" end end diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index 77bc202fe..20d17d41f 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -1,9 +1,41 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do use Pleroma.Web.ConnCase import Pleroma.Factory - alias Pleroma.User + alias Pleroma.{User, Repo} alias Pleroma.Web.OStatus.ActivityRepresenter + test "decodes a salmon", %{conn: conn} do + user = insert(:user) + salmon = File.read!("test/fixtures/salmon.xml") + conn = conn + |> put_req_header("content-type", "application/atom+xml") + |> post("/users/#{user.nickname}/salmon", salmon) + + assert response(conn, 200) + end + + test "decodes a salmon with a changed magic key", %{conn: conn} do + user = insert(:user) + salmon = File.read!("test/fixtures/salmon.xml") + conn = conn + |> put_req_header("content-type", "application/atom+xml") + |> post("/users/#{user.nickname}/salmon", salmon) + + assert response(conn, 200) + + # Set a wrong magic-key for a user so it has to refetch + salmon_user = User.get_by_ap_id("http://gs.example.org:4040/index.php/user/1") + info = salmon_user.info + |> Map.put("magic_key", "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB") # Wrong key + Repo.update(User.info_changeset(salmon_user, %{info: info})) + + conn = build_conn() + |> put_req_header("content-type", "application/atom+xml") + |> post("/users/#{user.nickname}/salmon", salmon) + + assert response(conn, 200) + end + test "gets a feed", %{conn: conn} do note_activity = insert(:note_activity) user = User.get_cached_by_ap_id(note_activity.data["actor"]) @@ -42,3 +74,10 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do assert response(conn, 200) end end + +defmodule Pleroma.Web.OStatusMock do + import Pleroma.Factory + def handle_incoming(_doc) do + insert(:note_activity) + end +end |