aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web/activity_pub
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/activity_pub')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex9
-rw-r--r--lib/pleroma/web/activity_pub/builder.ex2
-rw-r--r--lib/pleroma/web/activity_pub/object_validator.ex17
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex42
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/audio_validator.ex18
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex11
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/event_validator.ex96
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/note_validator.ex13
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/question_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/relay.ex56
-rw-r--r--lib/pleroma/web/activity_pub/side_effects.ex2
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex9
12 files changed, 206 insertions, 71 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index bde1fe708..624a508ae 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -85,7 +85,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp increase_replies_count_if_reply(_create_data), do: :noop
- @object_types ["ChatMessage", "Question", "Answer"]
+ @object_types ~w[ChatMessage Question Answer Audio Event]
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
def persist(%{"type" => type} = object, meta) when type in @object_types do
with {:ok, object} <- Object.create(object) do
@@ -1344,9 +1344,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
def maybe_handle_clashing_nickname(data) do
- nickname = data[:nickname]
-
- with %User{} = old_user <- User.get_by_nickname(nickname),
+ with nickname when is_binary(nickname) <- data[:nickname],
+ %User{} = old_user <- User.get_by_nickname(nickname),
{_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do
Logger.info(
"Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{
@@ -1360,7 +1359,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
else
{:ap_id_comparison, true} ->
Logger.info(
- "Found an old user for #{nickname}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
+ "Found an old user for #{data[:nickname]}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
)
_ ->
diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex
index f2392ce79..9a7b7d9de 100644
--- a/lib/pleroma/web/activity_pub/builder.ex
+++ b/lib/pleroma/web/activity_pub/builder.ex
@@ -215,7 +215,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
to =
cond do
- actor.ap_id == Relay.relay_ap_id() ->
+ actor.ap_id == Relay.ap_id() ->
[actor.follower_address]
public? ->
diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex
index d770ce1be..b77c06395 100644
--- a/lib/pleroma/web/activity_pub/object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validator.ex
@@ -23,6 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator
+ alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
@@ -43,6 +44,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
end
end
+ def validate(%{"type" => "Event"} = object, meta) do
+ with {:ok, object} <-
+ object
+ |> EventValidator.cast_and_validate()
+ |> Ecto.Changeset.apply_action(:insert) do
+ object = stringify_keys(object)
+ {:ok, object, meta}
+ end
+ end
+
def validate(%{"type" => "Follow"} = object, meta) do
with {:ok, object} <-
object
@@ -187,7 +198,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
%{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity,
meta
)
- when objtype in ~w[Question Answer Audio] do
+ when objtype in ~w[Question Answer Audio Event] do
with {:ok, object_data} <- cast_and_apply(object),
meta = Keyword.put(meta, :object_data, object_data |> stringify_keys),
{:ok, create_activity} <-
@@ -225,6 +236,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
AudioValidator.cast_and_apply(object)
end
+ def cast_and_apply(%{"type" => "Event"} = object) do
+ EventValidator.cast_and_apply(object)
+ end
+
def cast_and_apply(o), do: {:error, {:validator_not_set, o}}
# is_struct/1 isn't present in Elixir 1.8.x
diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
index f53bb02be..c8b148280 100644
--- a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
@@ -41,34 +41,34 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
end
def fix_media_type(data) do
- data =
- data
- |> Map.put_new("mediaType", data["mimeType"])
+ data = Map.put_new(data, "mediaType", data["mimeType"])
if MIME.valid?(data["mediaType"]) do
data
else
- data
- |> Map.put("mediaType", "application/octet-stream")
+ Map.put(data, "mediaType", "application/octet-stream")
end
end
- def fix_url(data) do
- case data["url"] do
- url when is_binary(url) ->
- data
- |> Map.put(
- "url",
- [
- %{
- "href" => url,
- "type" => "Link",
- "mediaType" => data["mediaType"]
- }
- ]
- )
-
- _ ->
+ defp handle_href(href, mediaType) do
+ [
+ %{
+ "href" => href,
+ "type" => "Link",
+ "mediaType" => mediaType
+ }
+ ]
+ end
+
+ defp fix_url(data) do
+ cond do
+ is_binary(data["url"]) ->
+ Map.put(data, "url", handle_href(data["url"], data["mediaType"]))
+
+ is_binary(data["href"]) and data["url"] == nil ->
+ Map.put(data, "url", handle_href(data["href"], data["mediaType"]))
+
+ true ->
data
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex
index 5d9bf345f..d1869f188 100644
--- a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex
@@ -41,7 +41,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, :string)
- field(:uri, ObjectValidators.Uri)
+ field(:url, ObjectValidators.Uri)
# short identifier for PleromaFE to group statuses by context
field(:context_id, :integer)
@@ -66,10 +66,24 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
|> changeset(data)
end
+ defp fix_url(%{"url" => url} = data) when is_list(url) do
+ attachment =
+ Enum.find(url, fn x -> is_map(x) and String.starts_with?(x["mimeType"], "audio/") end)
+
+ link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
+
+ data
+ |> Map.put("attachment", [attachment])
+ |> Map.put("url", link_element["href"])
+ end
+
+ defp fix_url(data), do: data
+
defp fix(data) do
data
|> CommonFixes.fix_defaults()
|> CommonFixes.fix_attribution()
+ |> fix_url()
end
def changeset(struct, data) do
@@ -83,7 +97,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Audio"])
- |> validate_required([:id, :actor, :attributedTo, :type, :context])
+ |> validate_required([:id, :actor, :attributedTo, :type, :context, :attachment])
|> CommonValidations.validate_any_presence([:cc, :to])
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|> CommonValidations.validate_actor_presence()
diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex
index 60868eae0..b3dbeea57 100644
--- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex
@@ -61,9 +61,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
end
end
+ defp fix_addressing(data, meta) do
+ if object = meta[:object_data] do
+ data
+ |> Map.put_new("to", object["to"] || [])
+ |> Map.put_new("cc", object["cc"] || [])
+ else
+ data
+ end
+ end
+
defp fix(data, meta) do
data
|> fix_context(meta)
+ |> fix_addressing(meta)
end
def validate_data(cng, meta \\ []) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex
new file mode 100644
index 000000000..07e4821a4
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex
@@ -0,0 +1,96 @@
+# 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.EventValidator do
+ use Ecto.Schema
+
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators
+ alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
+ alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
+ alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
+
+ import Ecto.Changeset
+
+ @primary_key false
+ @derive Jason.Encoder
+
+ # Extends from NoteValidator
+ embedded_schema do
+ field(:id, ObjectValidators.ObjectID, primary_key: true)
+ field(:to, ObjectValidators.Recipients, default: [])
+ field(:cc, ObjectValidators.Recipients, default: [])
+ field(:bto, ObjectValidators.Recipients, default: [])
+ field(:bcc, ObjectValidators.Recipients, default: [])
+ # TODO: Write type
+ field(:tag, {:array, :map}, default: [])
+ field(:type, :string)
+
+ field(:name, :string)
+ field(:summary, :string)
+ field(:content, :string)
+
+ field(:context, :string)
+ # short identifier for PleromaFE to group statuses by context
+ field(:context_id, :integer)
+
+ # TODO: Remove actor on objects
+ field(:actor, ObjectValidators.ObjectID)
+
+ field(:attributedTo, ObjectValidators.ObjectID)
+ field(:published, ObjectValidators.DateTime)
+ # TODO: Write type
+ field(:emoji, :map, default: %{})
+ field(:sensitive, :boolean, default: false)
+ embeds_many(:attachment, AttachmentValidator)
+ field(:replies_count, :integer, default: 0)
+ field(:like_count, :integer, default: 0)
+ field(:announcement_count, :integer, default: 0)
+ field(:inReplyTo, ObjectValidators.ObjectID)
+ field(:url, ObjectValidators.Uri)
+
+ field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
+ field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
+ end
+
+ def cast_and_apply(data) do
+ data
+ |> cast_data
+ |> apply_action(:insert)
+ end
+
+ def cast_and_validate(data) do
+ data
+ |> cast_data()
+ |> validate_data()
+ end
+
+ def cast_data(data) do
+ %__MODULE__{}
+ |> changeset(data)
+ end
+
+ defp fix(data) do
+ data
+ |> CommonFixes.fix_defaults()
+ |> CommonFixes.fix_attribution()
+ end
+
+ def changeset(struct, data) do
+ data = fix(data)
+
+ struct
+ |> cast(data, __schema__(:fields) -- [:attachment])
+ |> cast_embed(:attachment)
+ end
+
+ def validate_data(data_cng) do
+ data_cng
+ |> validate_inclusion(:type, ["Event"])
+ |> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id])
+ |> CommonValidations.validate_any_presence([:cc, :to])
+ |> CommonValidations.validate_fields_match([:actor, :attributedTo])
+ |> CommonValidations.validate_actor_presence()
+ |> CommonValidations.validate_host_match()
+ end
+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
index 14ae29cb6..20e735619 100644
--- a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex
@@ -20,11 +20,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
# TODO: Write type
field(:tag, {:array, :map}, default: [])
field(:type, :string)
+
+ field(:name, :string)
+ field(:summary, :string)
field(:content, :string)
+
field(:context, :string)
+ # short identifier for PleromaFE to group statuses by context
+ field(:context_id, :integer)
+
field(:actor, ObjectValidators.ObjectID)
field(:attributedTo, ObjectValidators.ObjectID)
- field(:summary, :string)
field(:published, ObjectValidators.DateTime)
# TODO: Write type
field(:emoji, :map, default: %{})
@@ -35,13 +41,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
- field(:uri, ObjectValidators.Uri)
+ field(:url, ObjectValidators.Uri)
field(:likes, {:array, :string}, default: [])
field(:announcements, {:array, :string}, default: [])
-
- # see if needed
- field(:context_id, :string)
end
def cast_and_validate(data) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex
index a7ca42b2f..712047424 100644
--- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex
@@ -43,7 +43,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
- field(:uri, ObjectValidators.Uri)
+ field(:url, ObjectValidators.Uri)
# short identifier for PleromaFE to group statuses by context
field(:context_id, :integer)
diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex
index b09764d2b..b65710a94 100644
--- a/lib/pleroma/web/activity_pub/relay.ex
+++ b/lib/pleroma/web/activity_pub/relay.ex
@@ -10,19 +10,13 @@ defmodule Pleroma.Web.ActivityPub.Relay do
alias Pleroma.Web.CommonAPI
require Logger
- @relay_nickname "relay"
+ @nickname "relay"
- def get_actor do
- actor =
- relay_ap_id()
- |> User.get_or_create_service_actor_by_ap_id(@relay_nickname)
+ @spec ap_id() :: String.t()
+ def ap_id, do: "#{Pleroma.Web.Endpoint.url()}/#{@nickname}"
- actor
- end
-
- def relay_ap_id do
- "#{Pleroma.Web.Endpoint.url()}/relay"
- end
+ @spec get_actor() :: User.t() | nil
+ def get_actor, do: User.get_or_create_service_actor_by_ap_id(ap_id(), @nickname)
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
def follow(target_instance) do
@@ -61,34 +55,38 @@ defmodule Pleroma.Web.ActivityPub.Relay do
def publish(_), do: {:error, "Not implemented"}
- @spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()}
- def list(with_not_accepted \\ false) do
+ @spec list() :: {:ok, [%{actor: String.t(), followed_back: boolean()}]} | {:error, any()}
+ def list do
with %User{} = user <- get_actor() do
accepted =
user
- |> User.following()
- |> Enum.map(fn entry -> URI.parse(entry).host end)
- |> Enum.uniq()
-
- list =
- if with_not_accepted do
- without_accept =
- user
- |> Pleroma.Activity.following_requests_for_actor()
- |> Enum.map(fn a -> URI.parse(a.data["object"]).host <> " (no Accept received)" end)
- |> Enum.uniq()
+ |> following()
+ |> Enum.map(fn actor -> %{actor: actor, followed_back: true} end)
- accepted ++ without_accept
- else
- accepted
- end
+ without_accept =
+ user
+ |> Pleroma.Activity.following_requests_for_actor()
+ |> Enum.map(fn activity -> %{actor: activity.data["object"], followed_back: false} end)
+ |> Enum.uniq()
- {:ok, list}
+ {:ok, accepted ++ without_accept}
else
error -> format_error(error)
end
end
+ @spec following() :: [String.t()]
+ def following do
+ get_actor()
+ |> following()
+ end
+
+ defp following(user) do
+ user
+ |> User.following_ap_ids()
+ |> Enum.uniq()
+ end
+
defp format_error({:error, error}), do: format_error(error)
defp format_error(error) do
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index 3dc66c60b..a5e2323bd 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -341,7 +341,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end
def handle_object_creation(%{"type" => objtype} = object, meta)
- when objtype in ~w[Audio Question] do
+ when objtype in ~w[Audio Question Event] do
with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
{:ok, object, meta}
end
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 6be17e0ed..76298c4a0 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -276,13 +276,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
Map.put(object, "url", url["href"])
end
- def fix_url(%{"type" => object_type, "url" => url} = object)
- when object_type in ["Video", "Audio"] and is_list(url) do
+ def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do
attachment =
Enum.find(url, fn x ->
media_type = x["mediaType"] || x["mimeType"] || ""
- is_map(x) and String.starts_with?(media_type, ["audio/", "video/"])
+ is_map(x) and String.starts_with?(media_type, "video/")
end)
link_element =
@@ -461,7 +460,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Create", "object" => %{"type" => objtype} = object} = data,
options
)
- when objtype in ~w{Article Event Note Video Page} do
+ when objtype in ~w{Article Note Video Page} do
actor = Containment.get_actor(data)
with nil <- Activity.get_create_by_object_ap_id(object["id"]),
@@ -555,7 +554,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Create", "object" => %{"type" => objtype}} = data,
_options
)
- when objtype in ~w{Question Answer ChatMessage Audio} do
+ when objtype in ~w{Question Answer ChatMessage Audio Event} do
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
{:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}