From cb21bf5fc225899ad6cf87f5ab0253506cf0531e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Tue, 26 Jun 2018 13:45:47 -0700 Subject: [PATCH 01/56] filter exif data #187 --- config/config.exs | 4 +++- lib/pleroma/upload.ex | 8 ++++++++ mix.exs | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/config/config.exs b/config/config.exs index cf6cbaa9d..fd9662aea 100644 --- a/config/config.exs +++ b/config/config.exs @@ -10,7 +10,9 @@ config :pleroma, ecto_repos: [Pleroma.Repo] config :pleroma, Pleroma.Repo, types: Pleroma.PostgresTypes -config :pleroma, Pleroma.Upload, uploads: "uploads" +config :pleroma, Pleroma.Upload, + uploads: "uploads", + strip_exif: false # Configures the endpoint config :pleroma, Pleroma.Web.Endpoint, diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 43df0d418..dee281f5b 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -80,6 +80,14 @@ defmodule Pleroma.Upload do } end + def strip_exif_data(file) do + settings = Application.get_env(:pleroma, Pleroma.Upload) + @do_strip = Keyword.fetch!(settings, :strip_exif) + if @do_strip == true do + Mogrify.open(file) |> Mogrify.custom("strip") |> Mogrify.save(in_place: true) + end + end + def upload_path do settings = Application.get_env(:pleroma, Pleroma.Upload) Keyword.fetch!(settings, :uploads) diff --git a/mix.exs b/mix.exs index 281687294..cc279a7f9 100644 --- a/mix.exs +++ b/mix.exs @@ -47,7 +47,8 @@ defmodule Pleroma.Mixfile do {:jason, "~> 1.0"}, {:ex_machina, "~> 2.0", only: :test}, {:credo, "~> 0.7", only: [:dev, :test]}, - {:mock, "~> 0.3.0", only: :test} + {:mock, "~> 0.3.0", only: :test}, + {:mogrify, "~> 0.6.1"} ] end From c67cf8e9af3ab9b52f34387a686a68ee4e1554b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Tue, 26 Jun 2018 13:49:57 -0700 Subject: [PATCH 02/56] format... --- config/config.exs | 2 +- lib/pleroma/upload.ex | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/config.exs b/config/config.exs index fd9662aea..33b7f098e 100644 --- a/config/config.exs +++ b/config/config.exs @@ -10,7 +10,7 @@ config :pleroma, ecto_repos: [Pleroma.Repo] config :pleroma, Pleroma.Repo, types: Pleroma.PostgresTypes -config :pleroma, Pleroma.Upload, +config :pleroma, Pleroma.Upload, uploads: "uploads", strip_exif: false diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index dee281f5b..e412e43fa 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -83,8 +83,9 @@ defmodule Pleroma.Upload do def strip_exif_data(file) do settings = Application.get_env(:pleroma, Pleroma.Upload) @do_strip = Keyword.fetch!(settings, :strip_exif) + if @do_strip == true do - Mogrify.open(file) |> Mogrify.custom("strip") |> Mogrify.save(in_place: true) + Mogrify.open(file) |> Mogrify.custom("strip") |> Mogrify.save(in_place: true) end end From d8d43f1173aaea677a74aee6315d1195d59197e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Tue, 26 Jun 2018 14:03:23 -0700 Subject: [PATCH 03/56] do the filtering --- lib/pleroma/upload.ex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index e412e43fa..1640c1f9c 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -18,6 +18,8 @@ defmodule Pleroma.Upload do File.cp!(file.path, result_file) end + strip_exif_data(content_type, file.path) + %{ "type" => "Image", "url" => [ @@ -67,6 +69,8 @@ defmodule Pleroma.Upload do File.rename(uuidpath, result_file) end + strip_exif_data(content_type, uuidpath) + %{ "type" => "Image", "url" => [ @@ -80,11 +84,12 @@ defmodule Pleroma.Upload do } end - def strip_exif_data(file) do + def strip_exif_data(content_type, file) do settings = Application.get_env(:pleroma, Pleroma.Upload) @do_strip = Keyword.fetch!(settings, :strip_exif) + [filetype, ext] = String.split(content_type, "/") - if @do_strip == true do + if filetype == "image" and @do_strip == true do Mogrify.open(file) |> Mogrify.custom("strip") |> Mogrify.save(in_place: true) end end From 2df0fd1462c7fed0fe80bafecdfc72309025c943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Tue, 26 Jun 2018 14:16:28 -0700 Subject: [PATCH 04/56] mogrify mix.lock --- mix.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/mix.lock b/mix.lock index 2a826111c..9ae8fe0ac 100644 --- a/mix.lock +++ b/mix.lock @@ -25,6 +25,7 @@ "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, "mochiweb": {:hex, :mochiweb, "2.15.0", "e1daac474df07651e5d17cc1e642c4069c7850dc4508d3db7263a0651330aacc", [:rebar3], [], "hexpm"}, "mock": {:hex, :mock, "0.3.1", "994f00150f79a0ea50dc9d86134cd9ebd0d177ad60bd04d1e46336cdfdb98ff9", [:mix], [{:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, + "mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"}, "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"}, "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "hexpm"}, "phoenix": {:hex, :phoenix, "1.3.2", "2a00d751f51670ea6bc3f2ba4e6eb27ecb8a2c71e7978d9cd3e5de5ccf7378bd", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, From ca63585a329f0afa02f7d539328f5fb3485d2a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Tue, 26 Jun 2018 14:35:35 -0700 Subject: [PATCH 05/56] maybe I should learn proper elixir ;D --- lib/pleroma/upload.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 1640c1f9c..45fac9060 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -86,10 +86,10 @@ defmodule Pleroma.Upload do def strip_exif_data(content_type, file) do settings = Application.get_env(:pleroma, Pleroma.Upload) - @do_strip = Keyword.fetch!(settings, :strip_exif) + do_strip = Keyword.fetch!(settings, :strip_exif) [filetype, ext] = String.split(content_type, "/") - if filetype == "image" and @do_strip == true do + if filetype == "image" and do_strip == true do Mogrify.open(file) |> Mogrify.custom("strip") |> Mogrify.save(in_place: true) end end From dc8ace29d12e8022ef7381d273724d7e5e7e3a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Tue, 26 Jun 2018 15:09:45 -0700 Subject: [PATCH 06/56] use the correct end file --- lib/pleroma/upload.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 45fac9060..dd2bbab9f 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -18,7 +18,7 @@ defmodule Pleroma.Upload do File.cp!(file.path, result_file) end - strip_exif_data(content_type, file.path) + strip_exif_data(content_type, result_file) %{ "type" => "Image", @@ -69,7 +69,7 @@ defmodule Pleroma.Upload do File.rename(uuidpath, result_file) end - strip_exif_data(content_type, uuidpath) + strip_exif_data(content_type, result_file) %{ "type" => "Image", From a2009432408dd0e93c3eb9506ff37da788b50895 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 05:23:54 +0000 Subject: [PATCH 07/56] object: add helper functions to handle various forms of a given object and return a normalized one --- lib/pleroma/object.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index ff2af4a6f..1bcff5a7b 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -27,6 +27,10 @@ defmodule Pleroma.Object do Repo.one(from(object in Object, where: fragment("(?)->>'id' = ?", object.data, ^ap_id))) end + def normalize(obj) when is_map(obj), do: Object.get_by_ap_id(obj["id"]) + def normalize(ap_id) when is_binary(ap_id), do: Object.get_by_ap_id(ap_id) + def normalize(_), do: nil + def get_cached_by_ap_id(ap_id) do if Mix.env() == :test do get_by_ap_id(ap_id) From b036a19c213c2b3cc08c64a0d887d36b9386609d Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 20:54:59 +0000 Subject: [PATCH 08/56] activity: add normalize() to find a complete activity given either URI or partial structure --- lib/pleroma/activity.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index dd6805125..bed96861f 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -78,4 +78,8 @@ defmodule Pleroma.Activity do end def get_create_activity_by_object_ap_id(_), do: nil + + def normalize(obj) when is_map(obj), do: Activity.get_by_ap_id(obj["id"]) + def normalize(ap_id) when is_binary(ap_id), do: Activity.get_by_ap_id(ap_id) + def normalize(_), do: nil end From 47189531c55ac0c3f671298e6efa8c020ce5853a Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 20:57:38 +0000 Subject: [PATCH 09/56] user: use Object.normalize() instead of Object.get_by_ap_id() directly. --- lib/pleroma/user.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 94f16c3c0..df22d29a8 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -607,7 +607,7 @@ defmodule Pleroma.User do |> Enum.each(fn activity -> case activity.data["type"] do "Create" -> - ActivityPub.delete(Object.get_by_ap_id(activity.data["object"]["id"])) + ActivityPub.delete(Object.normalize(activity.data["object"])) # TODO: Do something with likes, follows, repeats. _ -> From fb04fecfb4791639369414a685be79bdd9d03309 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 20:58:09 +0000 Subject: [PATCH 10/56] streamer: use Object.normalize() instead of Object.get_by_ap_id() directly. --- lib/pleroma/web/streamer.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index ce38f3cc3..c61bad830 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -158,7 +158,7 @@ defmodule Pleroma.Web.Streamer do user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id) blocks = user.info["blocks"] || [] - parent = Object.get_by_ap_id(item.data["object"]) + parent = Object.normalize(item.data["object"]) unless is_nil(parent) or item.actor in blocks or parent.data["actor"] in blocks do send(socket.transport_pid, {:text, represent_update(item, user)}) From 15d624e07797719e9ec1cf112b8beaa08dad2562 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 21:01:33 +0000 Subject: [PATCH 11/56] activitypub: use Object.normalize() instead of Object.get_by_ap_id() directly. --- lib/pleroma/web/activity_pub/activity_pub.ex | 6 +++--- lib/pleroma/web/activity_pub/transmogrifier.ex | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 195679fad..93219d76a 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -670,7 +670,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do recv_timeout: 20000 ), {:ok, data} <- Jason.decode(body), - nil <- Object.get_by_ap_id(data["id"]), + nil <- Object.normalize(data), params <- %{ "type" => "Create", "to" => data["to"], @@ -679,7 +679,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do "object" => data }, {:ok, activity} <- Transmogrifier.handle_incoming(params) do - {:ok, Object.get_by_ap_id(activity.data["object"]["id"])} + {:ok, Object.normalize(activity.data["object"])} else object = %Object{} -> {:ok, object} @@ -688,7 +688,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do Logger.info("Couldn't get object via AP, trying out OStatus fetching...") case OStatus.fetch_activity_from_url(id) do - {:ok, [activity | _]} -> {:ok, Object.get_by_ap_id(activity.data["object"]["id"])} + {:ok, [activity | _]} -> {:ok, Object.normalize(activity.data["object"])} e -> e end end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 30cd70fb6..8b5c85f42 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -412,7 +412,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def handle_incoming(_), do: :error def get_obj_helper(id) do - if object = Object.get_by_ap_id(id), do: {:ok, object}, else: nil + if object = Object.normalize(id), do: {:ok, object}, else: nil end def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do From 49da04c5094e698dca4dbf5788127177702f288b Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 21:08:12 +0000 Subject: [PATCH 12/56] common api: use Object.normalize() instead of Object.get_by_ap_id() directly. --- lib/pleroma/web/common_api/common_api.ex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 8845419c2..3f18a68e8 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -7,7 +7,7 @@ defmodule Pleroma.Web.CommonAPI do def delete(activity_id, user) do with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id), - %Object{} = object <- Object.get_by_ap_id(object_id), + %Object{} = object <- Object.normalize(object_id), true <- user.info["is_moderator"] || user.ap_id == object.data["actor"], {:ok, delete} <- ActivityPub.delete(object) do {:ok, delete} @@ -16,7 +16,7 @@ defmodule Pleroma.Web.CommonAPI do def repeat(id_or_ap_id, user) do with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), - object <- Object.get_by_ap_id(activity.data["object"]["id"]) do + object <- Object.normalize(activity.data["object"]["id"]) do ActivityPub.announce(user, object) else _ -> @@ -26,7 +26,7 @@ defmodule Pleroma.Web.CommonAPI do def unrepeat(id_or_ap_id, user) do with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), - object <- Object.get_by_ap_id(activity.data["object"]["id"]) do + object <- Object.normalize(activity.data["object"]["id"]) do ActivityPub.unannounce(user, object) else _ -> @@ -37,7 +37,7 @@ defmodule Pleroma.Web.CommonAPI do def favorite(id_or_ap_id, user) do with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), false <- activity.data["actor"] == user.ap_id, - object <- Object.get_by_ap_id(activity.data["object"]["id"]) do + object <- Object.normalize(activity.data["object"]["id"]) do ActivityPub.like(user, object) else _ -> @@ -48,7 +48,7 @@ defmodule Pleroma.Web.CommonAPI do def unfavorite(id_or_ap_id, user) do with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), false <- activity.data["actor"] == user.ap_id, - object <- Object.get_by_ap_id(activity.data["object"]["id"]) do + object <- Object.normalize(activity.data["object"]["id"]) do ActivityPub.unlike(user, object) else _ -> From bc05548370862a2a5daba20d4577b56fabc169ea Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 21:08:37 +0000 Subject: [PATCH 13/56] ostatus: use Object.normalize() instead of Object.get_by_ap_id() directly. --- lib/pleroma/web/ostatus/handlers/delete_handler.ex | 2 +- lib/pleroma/web/ostatus/ostatus.ex | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/ostatus/handlers/delete_handler.ex b/lib/pleroma/web/ostatus/handlers/delete_handler.ex index 4f3016b65..6330d7f64 100644 --- a/lib/pleroma/web/ostatus/handlers/delete_handler.ex +++ b/lib/pleroma/web/ostatus/handlers/delete_handler.ex @@ -6,7 +6,7 @@ defmodule Pleroma.Web.OStatus.DeleteHandler do def handle_delete(entry, _doc \\ nil) do with id <- XML.string_from_xpath("//id", entry), - object when not is_nil(object) <- Object.get_by_ap_id(id), + %Object{} = object <- Object.normalize(id), {:ok, delete} <- ActivityPub.delete(object, false) do delete end diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index f0ff0624f..916c894eb 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -89,7 +89,7 @@ defmodule Pleroma.Web.OStatus do def make_share(entry, doc, retweeted_activity) do with {:ok, actor} <- find_make_or_update_user(doc), - %Object{} = object <- Object.get_by_ap_id(retweeted_activity.data["object"]["id"]), + %Object{} = object <- Object.normalize(retweeted_activity.data["object"]), id when not is_nil(id) <- string_from_xpath("/entry/id", entry), {:ok, activity, _object} = ActivityPub.announce(actor, object, id, false) do {:ok, activity} @@ -107,7 +107,7 @@ defmodule Pleroma.Web.OStatus do def make_favorite(entry, doc, favorited_activity) do with {:ok, actor} <- find_make_or_update_user(doc), - %Object{} = object <- Object.get_by_ap_id(favorited_activity.data["object"]["id"]), + %Object{} = object <- Object.normalize(favorited_activity.data["object"]), id when not is_nil(id) <- string_from_xpath("/entry/id", entry), {:ok, activity, _object} = ActivityPub.like(actor, object, id, false) do {:ok, activity} From 5b240c3b187260498cbebbd540872975fb30bafe Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 21:20:18 +0000 Subject: [PATCH 14/56] federator: use Activity.normalize() instead of directly using Activity.get_by_ap_id(). --- lib/pleroma/web/federator/federator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex index 8ca530031..ccefb0bdf 100644 --- a/lib/pleroma/web/federator/federator.ex +++ b/lib/pleroma/web/federator/federator.ex @@ -95,7 +95,7 @@ defmodule Pleroma.Web.Federator do params = Utils.normalize_params(params) with {:ok, _user} <- ap_enabled_actor(params["actor"]), - nil <- Activity.get_by_ap_id(params["id"]), + nil <- Activity.normalize(params["id"]), {:ok, _activity} <- Transmogrifier.handle_incoming(params) do else %Activity{} -> From 6f4ca7ddf7f70b219ef1223f6343707ff6910f90 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 21:20:44 +0000 Subject: [PATCH 15/56] ostatus: use Activity.normalize() instead of directly using Activity.get_by_ap_id(). --- lib/pleroma/web/ostatus/activity_representer.ex | 2 +- lib/pleroma/web/ostatus/ostatus_controller.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/ostatus/activity_representer.ex b/lib/pleroma/web/ostatus/activity_representer.ex index 4179d86c9..5d831459b 100644 --- a/lib/pleroma/web/ostatus/activity_representer.ex +++ b/lib/pleroma/web/ostatus/activity_representer.ex @@ -246,7 +246,7 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: [] mentions = (activity.recipients || []) |> get_mentions - follow_activity = Activity.get_by_ap_id(follow_activity["id"]) + follow_activity = Activity.normalize(follow_activity) [ {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']}, diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 2f72fdb16..00bffbd5d 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -107,7 +107,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do def activity(conn, %{"uuid" => uuid}) do with id <- o_status_url(conn, :activity, uuid), - {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(id)}, + {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, {_, true} <- {:public?, ActivityPub.is_public?(activity)}, %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do case get_format(conn) do From 7c63e70de1b92ab8119732fe92040dea7f545b3d Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Jun 2018 21:21:03 +0000 Subject: [PATCH 16/56] activitypub: use Activity.normalize() in several places instead of using Activity.get_by_ap_id() directly. --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 93219d76a..464832a1e 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end def insert(map, local \\ true) when is_map(map) do - with nil <- Activity.get_by_ap_id(map["id"]), + with nil <- Activity.normalize(map), map <- lazy_put_activity_defaults(map), :ok <- check_actor_is_active(map["actor"]), {:ok, map} <- MRF.filter(map), diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 8b5c85f42..9d7c64743 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -460,14 +460,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # Mastodon Accept/Reject requires a non-normalized object containing the actor URIs, # because of course it does. def prepare_outgoing(%{"type" => "Accept"} = data) do - follow_activity_id = - if is_binary(data["object"]) do - data["object"] - else - data["object"]["id"] - end - - with follow_activity <- Activity.get_by_ap_id(follow_activity_id) do + with follow_activity <- Activity.normalize(data["object"]) do object = %{ "actor" => follow_activity.actor, "object" => follow_activity.data["object"], @@ -485,14 +478,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def prepare_outgoing(%{"type" => "Reject"} = data) do - follow_activity_id = - if is_binary(data["object"]) do - data["object"] - else - data["object"]["id"] - end - - with follow_activity <- Activity.get_by_ap_id(follow_activity_id) do + with follow_activity <- Activity.normalize(data["object"]) do object = %{ "actor" => follow_activity.actor, "object" => follow_activity.data["object"], From 4f6de34f4f40d408fb9200a5c4c908aec3ed9e91 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 23 Jun 2018 06:53:29 +0000 Subject: [PATCH 17/56] mastodon api: use info["default_scope"] if available for post scope --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 9d3f526c9..09e6b0b59 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -873,7 +873,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do }, compose: %{ me: "#{user.id}", - default_privacy: "public", + default_privacy: user.info["default_scope"] || "public", default_sensitive: false }, media_attachments: %{ From dcdf7b6686fe3732ac8f9a93570dfa8a1412783a Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 23 Jun 2018 06:55:32 +0000 Subject: [PATCH 18/56] twitter api: user view: show default message scope if known --- lib/pleroma/web/twitter_api/views/user_view.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index 711008973..9c8460378 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -52,7 +52,8 @@ defmodule Pleroma.Web.TwitterAPI.UserView do "cover_photo" => User.banner_url(user) |> MediaProxy.url(), "background_image" => image_url(user.info["background"]) |> MediaProxy.url(), "is_local" => user.local, - "locked" => !!user.info["locked"] + "locked" => !!user.info["locked"], + "default_scope" => user.info["default_scope"] || "public" } if assigns[:token] do From 2f14996d9afedbc4dbd75a518cf191636f926f74 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 23 Jun 2018 07:02:49 +0000 Subject: [PATCH 19/56] twitter api: allow setting default_scope --- .../web/twitter_api/twitter_api_controller.ex | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 8f5b3c786..65e67396b 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -431,6 +431,19 @@ defmodule Pleroma.Web.TwitterAPI.Controller do user end + user = + if default_scope = params["default_scope"] do + with new_info <- Map.put(user.info, "default_scope", default_scope), + change <- User.info_changeset(user, %{info: new_info}), + {:ok, user} <- User.update_and_set_cache(change) do + user + else + _e -> user + end + else + user + end + with changeset <- User.update_changeset(user, params), {:ok, user} <- User.update_and_set_cache(changeset) do CommonAPI.update(user) From 32211c4ada3ea113fb4041ae28b884130b2f4342 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:31:09 +0000 Subject: [PATCH 20/56] tests: add default_scope where appropriate --- test/web/twitter_api/views/user_view_test.exs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/web/twitter_api/views/user_view_test.exs b/test/web/twitter_api/views/user_view_test.exs index eea743b32..49f73c2fe 100644 --- a/test/web/twitter_api/views/user_view_test.exs +++ b/test/web/twitter_api/views/user_view_test.exs @@ -60,7 +60,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do "cover_photo" => banner, "background_image" => nil, "is_local" => true, - "locked" => false + "locked" => false, + "default_scope" => "public" } assert represented == UserView.render("show.json", %{user: user}) @@ -96,7 +97,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do "cover_photo" => banner, "background_image" => nil, "is_local" => true, - "locked" => false + "locked" => false, + "default_scope" => "public" } assert represented == UserView.render("show.json", %{user: user, for: follower}) @@ -133,7 +135,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do "cover_photo" => banner, "background_image" => nil, "is_local" => true, - "locked" => false + "locked" => false, + "default_scope" => "public" } assert represented == UserView.render("show.json", %{user: follower, for: user}) @@ -177,7 +180,8 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do "cover_photo" => banner, "background_image" => nil, "is_local" => true, - "locked" => false + "locked" => false, + "default_scope" => "public" } blocker = Repo.get(User, blocker.id) From c42f28b82c01423d05b85514797bf3bce692628d Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 05:33:22 +0000 Subject: [PATCH 21/56] transmogrifier: accept Article activities --- lib/pleroma/web/activity_pub/transmogrifier.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 30cd70fb6..1b60170d9 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -122,7 +122,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # TODO: validate those with a Ecto scheme # - tags # - emoji - def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do + def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data) when objtype in ["Article", "Note"] do with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]), %User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do object = fix_object(data["object"]) From bd479606ba2b645db46ef5312f06323534cfd9c9 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:52:17 +0000 Subject: [PATCH 22/56] utils: make_create_data: add support for Article objects --- lib/pleroma/web/activity_pub/utils.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 64329b710..8b41a3bec 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -128,7 +128,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do Inserts a full object if it is contained in an activity. """ def insert_full_object(%{"object" => %{"type" => type} = object_data}) - when is_map(object_data) and type in ["Note"] do + when is_map(object_data) and type in ["Article", "Note"] do with {:ok, _} <- Object.create(object_data) do :ok end From 121c1f62306e416f1f6106d1751b55a5eb9f9075 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 05:33:34 +0000 Subject: [PATCH 23/56] twitter api: refactor activity html generation, add support for Articles --- .../web/twitter_api/views/activity_view.ex | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 62ce3b7b5..0779872fe 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -228,15 +228,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags - summary = activity.data["object"]["summary"] - content = object["content"] - - content = - if !!summary and summary != "" do - "#{activity.data["object"]["summary"]}
#{content}" - else - content - end + {summary, content} = render_content(object) html = HtmlSanitizeEx.basic_html(content) @@ -266,4 +258,35 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object) } end + + def render_content(%{"type" => "Note"} = object) do + summary = object["summary"] + content = + if !!summary and summary != "" do + "

#{summary}

#{object["content"]}" + else + object["content"] + end + + {summary, content} + end + + def render_content(%{"type" => "Article"} = object) do + summary = object["name"] || object["summary"] + content = + if !!summary and summary != "" do + "

#{summary}

#{object["content"]}" + else + object["content"] + end + + {summary, content} + end + + def render_content(object) do + summary = object["summary"] || "Unhandled activity type: #{object["type"]}" + content = "

#{summary}

#{object["content"]}" + + {summary, content} + end end From ea982e7503767f645dc26235e04c541ce976de71 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:14:17 +0000 Subject: [PATCH 24/56] mastodon api: add interpreter for Article activity types --- .../web/mastodon_api/views/status_view.ex | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 59898457b..f7ad87bad 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -128,7 +128,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do in_reply_to_id: reply_to && to_string(reply_to.id), in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id), reblog: nil, - content: HtmlSanitizeEx.basic_html(object["content"]), + content: render_content(object), created_at: created_at, reblogs_count: announcement_count, favourites_count: like_count, @@ -207,4 +207,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do "direct" end end + + def render_content(%{"type" => "Article"} = object) do + summary = object["name"] + content = + if !!summary and summary != "" do + "

#{summary}

#{object["content"]}" + else + object["content"] + end + + HtmlSanitizeEx.basic_html(content) + end + + def render_content(object) do + HtmlSanitizeEx.basic_html(object["content"]) + end end From 66819ea784509fbed3f7db8056ececf150339b35 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:30:23 +0000 Subject: [PATCH 25/56] twitter api: use ActivityView.render_content() where appropriate instead of duplicating the logic --- .../twitter_api/representers/activity_representer.ex | 11 ++--------- .../representers/activity_representer_test.exs | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index 57837205e..bb77e61f3 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -4,7 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter alias Pleroma.{Activity, User} - alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView} + alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView} alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Formatter @@ -164,14 +164,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags - summary = activity.data["object"]["summary"] - - content = - if !!summary and summary != "" do - "#{activity.data["object"]["summary"]}
#{content}" - else - content - end + {summary, content} = ActivityView.render_content(object) html = HtmlSanitizeEx.basic_html(content) diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs index 16c6e7b0d..7505093dd 100644 --- a/test/web/twitter_api/representers/activity_representer_test.exs +++ b/test/web/twitter_api/representers/activity_representer_test.exs @@ -126,7 +126,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do } expected_html = - "2hu
alert('YAY')Some 2hu content mentioning 2hu

alert('YAY')Some 2hu content mentioning
@shp" From 971bb4f2bde125c1f8397c244a6fbdec0d26716b Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:34:44 +0000 Subject: [PATCH 26/56] activity interpretation: formatting --- lib/pleroma/web/activity_pub/transmogrifier.ex | 3 ++- lib/pleroma/web/mastodon_api/views/status_view.ex | 1 + lib/pleroma/web/twitter_api/views/activity_view.ex | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 1b60170d9..59c4b90e7 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -122,7 +122,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # TODO: validate those with a Ecto scheme # - tags # - emoji - def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data) when objtype in ["Article", "Note"] do + def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data) + when objtype in ["Article", "Note"] do with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]), %User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do object = fix_object(data["object"]) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index f7ad87bad..6b48c41c1 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -210,6 +210,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do def render_content(%{"type" => "Article"} = object) do summary = object["name"] + content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 0779872fe..f418249e2 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -261,6 +261,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do def render_content(%{"type" => "Note"} = object) do summary = object["summary"] + content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" @@ -273,6 +274,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do def render_content(%{"type" => "Article"} = object) do summary = object["name"] || object["summary"] + content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" From c06a5af386a3cdfeda0b2c21963d9200fb7d6c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Mah=C3=A9?= Date: Thu, 28 Jun 2018 10:49:44 -0700 Subject: [PATCH 27/56] CONFIGURATION.md: add doc about upload and strip_exif --- CONFIGURATION.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 3f0ecafb5..51a76d1b7 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -13,6 +13,21 @@ Instead, overload the settings by editing the following files: * `dev.secret.exs`: custom additional configuration for `MIX_ENV=dev` * `prod.secret.exs`: custom additional configuration for `MIX_ENV=prod` +## Uploads configuration + +To configure where to upload files, and wether or not +you want to remove automatically EXIF data from pictures +being uploaded. + + config :pleroma, Pleroma.Upload, + uploads: "uploads", + strip_exif: false + +* `uploads`: where to put the uploaded files, relative to pleroma's main directory. +* `strip_exif`: whether or not to remove EXIF data from uploaded pics automatically. + This needs Imagemagick installed on the system ( apt install imagemagick ). + + ## Block functionality config :pleroma, :activitypub, From 0bfbf15b379a95e7fad50e8f611cf6c5e67cfa9c Mon Sep 17 00:00:00 2001 From: Jorty Date: Sat, 30 Jun 2018 15:08:31 -0400 Subject: [PATCH 28/56] Allow emojis to be added automatically --- .../controllers/util_controller.ex | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 7a0c37ce9..db6142dc8 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -173,7 +173,25 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def emoji(conn, _params) do - json(conn, Enum.into(Formatter.get_custom_emoji(), %{})) + emoji_dir = Path.join(:code.priv_dir(:pleroma), "static/emoji") + + shortcode_emoji_glob = + Path.join( + emoji_dir, + Application.get_env(:pleroma, :emoji, []) |> + Keyword.get(:glob, "by-shortcode/**/*.png") + ) + shortcode_emoji = + Path.wildcard(shortcode_emoji_glob) |> + Enum.map(fn path -> + shortcode = Path.basename(path, ".png") + serve_path = Path.join("/emoji", Path.relative_to(path, emoji_dir)) + {shortcode, serve_path} + end) + + emoji = Enum.into(Formatter.get_custom_emoji(), shortcode_emoji) |> Enum.into(%{}) + + json(conn, emoji) end def follow_import(conn, %{"list" => %Plug.Upload{} = listfile}) do From c171f9790bc2d6a1b215792ade1b1cfc7e458ac4 Mon Sep 17 00:00:00 2001 From: Jorty Date: Sat, 30 Jun 2018 17:20:08 -0400 Subject: [PATCH 29/56] Move emoji glob setting to config.exs Also, a bit of formatting, and the glob includes an "/emoji/" prefix to make it more intuitive to users --- config/config.exs | 2 ++ .../controllers/util_controller.ex | 35 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/config/config.exs b/config/config.exs index cf6cbaa9d..96350d064 100644 --- a/config/config.exs +++ b/config/config.exs @@ -12,6 +12,8 @@ config :pleroma, Pleroma.Repo, types: Pleroma.PostgresTypes config :pleroma, Pleroma.Upload, uploads: "uploads" +config :pleroma, :emoji, shortcode_glob: "/emoji/by-shortcode/**/*.png" + # Configures the endpoint config :pleroma, Pleroma.Web.Endpoint, url: [host: "localhost"], diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index db6142dc8..73a46bb5e 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -173,23 +173,30 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def emoji(conn, _params) do - emoji_dir = Path.join(:code.priv_dir(:pleroma), "static/emoji") + static_dir = Path.join(:code.priv_dir(:pleroma), "static") + + emoji_shortcode_glob = + Application.get_env(:pleroma, :emoji, []) + |> Keyword.get(:shortcode_glob) - shortcode_emoji_glob = - Path.join( - emoji_dir, - Application.get_env(:pleroma, :emoji, []) |> - Keyword.get(:glob, "by-shortcode/**/*.png") - ) shortcode_emoji = - Path.wildcard(shortcode_emoji_glob) |> - Enum.map(fn path -> - shortcode = Path.basename(path, ".png") - serve_path = Path.join("/emoji", Path.relative_to(path, emoji_dir)) - {shortcode, serve_path} - end) + case emoji_shortcode_glob do + nil -> + [] - emoji = Enum.into(Formatter.get_custom_emoji(), shortcode_emoji) |> Enum.into(%{}) + glob -> + Path.join(static_dir, glob) + |> Path.wildcard() + |> Enum.map(fn path -> + shortcode = Path.basename(path, ".png") + serve_path = Path.join("/", Path.relative_to(path, static_dir)) + {shortcode, serve_path} + end) + end + + emoji = + Enum.into(Formatter.get_custom_emoji(), shortcode_emoji) + |> Enum.into(%{}) json(conn, emoji) end From 748fff6544cc70476bb0892a661d4d8c7f6ee295 Mon Sep 17 00:00:00 2001 From: Jorty Date: Sat, 30 Jun 2018 20:35:34 -0400 Subject: [PATCH 30/56] Fix auto-shortcode emoji Emoji were broken due to `Pleroma.Formatter` not knowing about the auto-shortcode emoji. This moves that logic from `Pleroma.Web.TwitterAPI.UtilController` to `Pleroma.Formatter`. Additionally, it's now possible to specify multiple shortcode globs, and the default globs were changed to `["/emoji/custom/**/*.png"]`, since that's in the .gitignore and the files there would have to be shortcode emoji anyway. --- config/config.exs | 2 +- lib/pleroma/formatter.ex | 23 +++++++++++++++- .../controllers/util_controller.ex | 27 +------------------ 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/config/config.exs b/config/config.exs index 96350d064..0616fe4fb 100644 --- a/config/config.exs +++ b/config/config.exs @@ -12,7 +12,7 @@ config :pleroma, Pleroma.Repo, types: Pleroma.PostgresTypes config :pleroma, Pleroma.Upload, uploads: "uploads" -config :pleroma, :emoji, shortcode_glob: "/emoji/by-shortcode/**/*.png" +config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"] # Configures the endpoint config :pleroma, Pleroma.Web.Endpoint, diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index df7ffbc41..0aaf21538 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -116,7 +116,28 @@ defmodule Pleroma.Formatter do _ -> [] end) - @emoji @finmoji_with_filenames ++ @emoji_from_file + @emoji_from_globs ( + static_path = Path.join(:code.priv_dir(:pleroma), "static") + + globs = + Application.get_env(:pleroma, :emoji, []) + |> Keyword.get(:shortcode_globs, []) + + paths = + Enum.map(globs, fn glob -> + Path.join(static_path, glob) + |> Path.wildcard() + end) + |> Enum.concat() + + Enum.map(paths, fn path -> + shortcode = Path.basename(path, Path.extname(path)) + external_path = Path.join("/", Path.relative_to(path, static_path)) + {shortcode, external_path} + end) + ) + + @emoji @finmoji_with_filenames ++ @emoji_from_globs ++ @emoji_from_file def emojify(text, emoji \\ @emoji) def emojify(text, nil), do: text diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 73a46bb5e..7a0c37ce9 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -173,32 +173,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def emoji(conn, _params) do - static_dir = Path.join(:code.priv_dir(:pleroma), "static") - - emoji_shortcode_glob = - Application.get_env(:pleroma, :emoji, []) - |> Keyword.get(:shortcode_glob) - - shortcode_emoji = - case emoji_shortcode_glob do - nil -> - [] - - glob -> - Path.join(static_dir, glob) - |> Path.wildcard() - |> Enum.map(fn path -> - shortcode = Path.basename(path, ".png") - serve_path = Path.join("/", Path.relative_to(path, static_dir)) - {shortcode, serve_path} - end) - end - - emoji = - Enum.into(Formatter.get_custom_emoji(), shortcode_emoji) - |> Enum.into(%{}) - - json(conn, emoji) + json(conn, Enum.into(Formatter.get_custom_emoji(), %{})) end def follow_import(conn, %{"list" => %Plug.Upload{} = listfile}) do From 7a351cb36f64ae98fa3d28d5133fa0a49d376659 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 2 Jul 2018 06:28:21 +0200 Subject: [PATCH 31/56] [Pleroma.Web.MastodonAPI.StatusView]: Fill the url field for statuses Closes: https://git.pleroma.social/pleroma/pleroma/issues/231 --- lib/pleroma/web/mastodon_api/views/status_view.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 59898457b..39abb4c6b 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -54,8 +54,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do %{ id: to_string(activity.id), uri: object, - # TODO: This might be wrong, check with mastodon. - url: nil, + url: object, account: AccountView.render("account.json", %{user: user}), in_reply_to_id: nil, in_reply_to_account_id: nil, From 4326cb992019f0a050cde3775a4d36219750dbbc Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 26 Jun 2018 13:51:35 +0200 Subject: [PATCH 32/56] [Pleroma.Web.Nodeinfo.NodeinfoController]: add mediaProxy metadata Closes: https://git.pleroma.social/pleroma/pleroma/issues/229 --- lib/pleroma/web/nodeinfo/nodeinfo_controller.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index aec77168a..e7e2794ae 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -4,8 +4,6 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do alias Pleroma.Stats alias Pleroma.Web - @instance Application.get_env(:pleroma, :instance) - def schemas(conn, _params) do response = %{ links: [ @@ -21,6 +19,8 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do # Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json def nodeinfo(conn, %{"version" => "2.0"}) do + @instance = Application.get_env(:pleroma, :instance) + @media_proxy = Application.get_env(:pleroma, :media_proxy) stats = Stats.get_stats() response = %{ @@ -42,7 +42,8 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do localPosts: stats.status_count || 0 }, metadata: %{ - nodeName: Keyword.get(@instance, :name) + nodeName: Keyword.get(@instance, :name), + mediaProxy: Keyword.get(@media_proxy, :enabled) } } From 85465512578d8113366e71d9122d336b8fd49fa4 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 12 Jul 2018 02:45:48 +0000 Subject: [PATCH 33/56] activitypub: switch to using x509 representation for public keys instead of pkcs#1 --- lib/pleroma/web/activity_pub/views/user_view.ex | 2 +- test/web/activity_pub/views/user_view_test.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index f4b2e0610..41bfe5048 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do def render("user.json", %{user: user}) do {:ok, user} = WebFinger.ensure_keys_present(user) {:ok, _, public_key} = Salmon.keys_from_pem(user.info["keys"]) - public_key = :public_key.pem_entry_encode(:RSAPublicKey, public_key) + public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) public_key = :public_key.pem_encode([public_key]) %{ diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index 0c64e62c3..7fc870e96 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -13,6 +13,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do assert result["id"] == user.ap_id assert result["preferredUsername"] == user.nickname - assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN RSA PUBLIC KEY") + assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN PUBLIC KEY") end end From b806aa36c89f2f7359580c716f98d41b58cb87f9 Mon Sep 17 00:00:00 2001 From: lambda Date: Thu, 12 Jul 2018 06:00:55 +0000 Subject: [PATCH 34/56] Update nodeinfo_controller.ex --- lib/pleroma/web/nodeinfo/nodeinfo_controller.ex | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index e7e2794ae..12aca4a10 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -19,22 +19,22 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do # Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json def nodeinfo(conn, %{"version" => "2.0"}) do - @instance = Application.get_env(:pleroma, :instance) - @media_proxy = Application.get_env(:pleroma, :media_proxy) + instance = Application.get_env(:pleroma, :instance) + media_proxy = Application.get_env(:pleroma, :media_proxy) stats = Stats.get_stats() response = %{ version: "2.0", software: %{ name: "pleroma", - version: Keyword.get(@instance, :version) + version: Keyword.get(instance, :version) }, protocols: ["ostatus", "activitypub"], services: %{ inbound: [], outbound: [] }, - openRegistrations: Keyword.get(@instance, :registrations_open), + openRegistrations: Keyword.get(instance, :registrations_open), usage: %{ users: %{ total: stats.user_count || 0 @@ -42,8 +42,8 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do localPosts: stats.status_count || 0 }, metadata: %{ - nodeName: Keyword.get(@instance, :name), - mediaProxy: Keyword.get(@media_proxy, :enabled) + nodeName: Keyword.get(instance, :name), + mediaProxy: Keyword.get(media_proxy, :enabled) } } From 3b799f22b7cd6afd9fb8bc8c7800ec770585a957 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 23 Jun 2018 06:08:09 +0000 Subject: [PATCH 35/56] twitterapi: activity view: expose message summary text --- lib/pleroma/web/twitter_api/views/activity_view.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index f418249e2..55b5287f5 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -255,7 +255,8 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do "tags" => tags, "activity_type" => "post", "possibly_sensitive" => possibly_sensitive, - "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object) + "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object), + "summary" => summary } end From 152a526237abb846b96a3c7b4001c8bd0c7409f9 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 05:33:34 +0000 Subject: [PATCH 36/56] twitter api: refactor activity html generation, add support for Articles --- lib/pleroma/web/twitter_api/views/activity_view.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 55b5287f5..cb7c4cb96 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -262,7 +262,6 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do def render_content(%{"type" => "Note"} = object) do summary = object["summary"] - content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" @@ -275,7 +274,6 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do def render_content(%{"type" => "Article"} = object) do summary = object["name"] || object["summary"] - content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" From f03e57f7647f4d302359680c7eb7fe48433c7beb Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:22:53 +0000 Subject: [PATCH 37/56] twitter api: activity representer: add summary field for testsuite --- .../web/twitter_api/representers/activity_representer.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index bb77e61f3..26bfb79af 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -191,7 +191,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "tags" => tags, "activity_type" => "post", "possibly_sensitive" => possibly_sensitive, - "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object) + "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object), + "summary" => object["summary"] } end From 4fb64c1d862692bb869dd735e9772195b7cf2705 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 24 Jun 2018 06:23:19 +0000 Subject: [PATCH 38/56] testsuite: twitter api: add summary where necessary --- .../web/twitter_api/representers/activity_representer_test.exs | 3 ++- test/web/twitter_api/views/activity_view_test.exs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs index 7505093dd..3f85e028b 100644 --- a/test/web/twitter_api/representers/activity_representer_test.exs +++ b/test/web/twitter_api/representers/activity_representer_test.exs @@ -155,7 +155,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do "activity_type" => "post", "possibly_sensitive" => true, "uri" => activity.data["object"]["id"], - "visibility" => "direct" + "visibility" => "direct", + "summary" => "2hu" } assert ActivityRepresenter.to_map(activity, %{ diff --git a/test/web/twitter_api/views/activity_view_test.exs b/test/web/twitter_api/views/activity_view_test.exs index 5b2a7466b..a101e4ae8 100644 --- a/test/web/twitter_api/views/activity_view_test.exs +++ b/test/web/twitter_api/views/activity_view_test.exs @@ -48,7 +48,8 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do "text" => "Hey @shp!", "uri" => activity.data["object"]["id"], "user" => UserView.render("show.json", %{user: user}), - "visibility" => "direct" + "visibility" => "direct", + "summary" => nil } assert result == expected From b832df1e158aa945a3c481804da0a839f18d46c5 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 12 Jul 2018 16:12:54 +0000 Subject: [PATCH 39/56] formatting --- lib/pleroma/web/twitter_api/views/activity_view.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index cb7c4cb96..55b5287f5 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -262,6 +262,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do def render_content(%{"type" => "Note"} = object) do summary = object["summary"] + content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" @@ -274,6 +275,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do def render_content(%{"type" => "Article"} = object) do summary = object["name"] || object["summary"] + content = if !!summary and summary != "" do "

#{summary}

#{object["content"]}" From 590d4df77c5b6b17b12e9692e77bb24c87ecc4a2 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 12 Jul 2018 16:37:42 +0000 Subject: [PATCH 40/56] activitypub: more robustly handle object-to-actor associations --- .../web/activity_pub/transmogrifier.ex | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 59c4b90e7..3dd3df553 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do """ def fix_object(object) do object - |> Map.put("actor", object["attributedTo"]) + |> fix_actor |> fix_attachments |> fix_context |> fix_in_reply_to @@ -27,6 +27,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> fix_content_map end + def fix_actor(%{"attributedTo" => actor} = object) do + # attributedTo can be a list in the case of peertube or plume + actor = + if is_list(actor) do + Enum.at(actor, 0) + else + actor + end + + object + |> Map.put("actor", actor) + end + def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object) when not is_nil(in_reply_to_id) do case ActivityPub.fetch_object_from_id(in_reply_to_id) do @@ -126,7 +139,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do when objtype in ["Article", "Note"] do with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]), %User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do - object = fix_object(data["object"]) + # prefer the activity's actor instead of attributedTo + object = + fix_object(data["object"]) + |> Map.put("actor", data["actor"]) params = %{ to: data["to"], From 0899588e4dfba7b7e65ee606378a1c1c710e4a82 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 12 Jul 2018 17:13:20 +0000 Subject: [PATCH 41/56] ostatus: return AS2 objects on /notice and /activities URLs like with /objects. --- lib/pleroma/web/ostatus/ostatus_controller.ex | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 00bffbd5d..09d1b1110 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Repo alias Pleroma.Web.{OStatus, Federator} alias Pleroma.Web.XML + alias Pleroma.Web.ActivityPub.ObjectView alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPub @@ -90,7 +91,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do case get_format(conn) do "html" -> redirect(conn, to: "/notice/#{activity.id}") - _ -> represent_activity(conn, activity, user) + _ -> represent_activity(conn, nil, activity, user) end else {:public?, false} -> @@ -110,9 +111,9 @@ defmodule Pleroma.Web.OStatus.OStatusController do {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, {_, true} <- {:public?, ActivityPub.is_public?(activity)}, %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do - case get_format(conn) do + case format = get_format(conn) do "html" -> redirect(conn, to: "/notice/#{activity.id}") - _ -> represent_activity(conn, activity, user) + _ -> represent_activity(conn, format, activity, user) end else {:public?, false} -> @@ -130,14 +131,14 @@ defmodule Pleroma.Web.OStatus.OStatusController do with {_, %Activity{} = activity} <- {:activity, Repo.get(Activity, id)}, {_, true} <- {:public?, ActivityPub.is_public?(activity)}, %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do - case get_format(conn) do + case format = get_format(conn) do "html" -> conn |> put_resp_content_type("text/html") |> send_file(200, "priv/static/index.html") _ -> - represent_activity(conn, activity, user) + represent_activity(conn, format, activity, user) end else {:public?, false} -> @@ -151,7 +152,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do end end - defp represent_activity(conn, activity, user) do + defp represent_activity(conn, "activity+json", activity, user) do + conn + |> put_resp_header("content-type", "application/activity+json") + |> json(ObjectView.render("object.json", %{object: activity})) + end + + defp represent_activity(conn, _, activity, user) do response = activity |> ActivityRepresenter.to_simple_form(user, true) From f1a29fc43c2ef47786ff932b7afb42825159a067 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 12 Jul 2018 20:32:05 +0000 Subject: [PATCH 42/56] test: ostatus controller: add AS2 fetching tests --- test/web/ostatus/ostatus_controller_test.exs | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index d5adf3bf3..c23b175e8 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -155,6 +155,31 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do assert response(conn, 200) end + test "gets a notice in AS2 format", %{conn: conn} do + note_activity = insert(:note_activity) + url = "/notice/#{note_activity.id}" + + conn = + conn + |> put_req_header("accept", "application/activity+json") + |> get(url) + + assert json_response(conn, 200) + end + + test "gets an activity in AS2 format", %{conn: conn} do + note_activity = insert(:note_activity) + [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"])) + url = "/activities/#{uuid}" + + conn = + conn + |> put_req_header("accept", "application/activity+json") + |> get(url) + + assert json_response(conn, 200) + end + test "404s a private notice", %{conn: conn} do note_activity = insert(:direct_note_activity) url = "/notice/#{note_activity.id}" From 24b5a75d096387ac63b30a09c1a6d8a986eceb61 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 12 Jul 2018 19:52:17 +0200 Subject: [PATCH 43/56] Add test for Plume Articles --- .../baptiste.gelex.xyz-article.json | 1 + .../httpoison_mock/baptiste.gelex.xyz-user.json | 1 + test/support/httpoison_mock.ex | 16 ++++++++++++++++ test/web/activity_pub/activity_pub_test.exs | 9 +++++++++ 4 files changed, 27 insertions(+) create mode 100644 test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json create mode 100644 test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json diff --git a/test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json b/test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json new file mode 100644 index 000000000..3f3f0f4fb --- /dev/null +++ b/test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json @@ -0,0 +1 @@ +{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"Emoji":"toot:Emoji","Hashtag":"as:Hashtag","atomUri":"ostatus:atomUri","conversation":"ostatus:conversation","featured":"toot:featured","focalPoint":{"@container":"@list","@id":"toot:focalPoint"},"inReplyToAtomUri":"ostatus:inReplyToAtomUri","manuallyApprovesFollowers":"as:manuallyApprovesFollowers","movedTo":"as:movedTo","ostatus":"http://ostatus.org#","sensitive":"as:sensitive","toot":"http://joinmastodon.org/ns#"}],"attributedTo":["https://baptiste.gelez.xyz/@/BaptisteGelez"],"cc":[],"content":"

It has been one month since the last \"This Month in Plume\" article, so it is time for another edition of our monthly changelog!

\n

Bug Fixes and Security

\n

Let's start with the hidden, but still (very) important changes: bug fixes and security patches.

\n

First of all, @Trinity protected us against two major security flaws, called XSS and CSRF. The first one allows the attacker to run malicious code if you visit a Plume page where some of their personal data is present. The second one lets them post data with your Plume account by visiting one of their own website. It is two very common attack, and it is great we are now protected against them!

\n

The other big change in this area, is that we are now validating the data you are sending before doing anything with it. It means that, for instance, you will no longer be able to register with an empty username and to break everything.

\n

On the federation side, many issues were reported by @kaniini and redmatrix (respectively contributing to Pleroma and Hubzilla). By fixing some of them, we made it possible to federate Plume articles to Pleroma!

\n

@Trinity hopefully noticed that there was a bug in our password check code: we were not checking that your password was correct, but only that the verification process went without errors. Concretely, it means that you could login to any account with any password. I wrote this part of the code when I was still the only contributor to the project, so nobody could review my work. We will now be trying to check every change, especially when it deals with critical parts of Plume, to avoid similar issues in the future, and we I'm really sorry this happened (even if I think nobody exploited it).

\n

Zanfib and stephenburgess8 also commited some small bugfixes, improving the general experience.

\n

New Features

\n

Let's now talk about the features that we introduced during this month.

\n

One of the most easy to spot is the redesign of Plume, made by @Madeorsk. I personaly love what he did, it really improved the readability and gave Plume a bit more of identity than the previous design. And he is still improving it.

\n

We also enabled Mardown in comment, to let you write more structured and nicely formatted responses.

\n

As you may have noticed, I have used mentions in this post. Indeed, it is now possible to mention someone in your articles or in comments. It works exactly the same way as in other apps, and you should receive a notification if someone mentionned you.

\n

A dashboard to manage your blogs has also been introduced. In the future it may be used to manage your drafts, and eventually to show some statistics. The goal is to have a more specific homepage for authors.

\n

The federation with other ActivityPub softwares, like Mastodon or Pleroma is starting to work quite well, but the federation between Plume instances is far from being complete. However, we started to work on it, and it is now possible to view a distant user profile or blog from your instance, even if only basic informations are fetched yet (the articles are not loaded for instance).

\n

Another new feature that may not be visible for everyone, is the new NodeInfo endpoint. NodeInfo is a protocol allowing to get informations about a specific federated instance (whatever software it runs). It means that Plume instances can now be listed on sites like fediverse.network.

\n

Maybe you wanted to host a Plume instance, but you don't like long install process during which you are just copy/pasting commands that you don't really understand from the documentation. That's why we introduced a setup script: the first you'll launch Plume, it will ask you a few questions and automatically setup your instance in a few minutes. We hope that this feature will help to host small instances, run by non-professional adminsys. You can see a demo of this tool on asciinema.

\n

Last but not least, Plume is now translatable! It is already available in English, French, Polish (thanks to @m4sk1n)) and German (thanks to bitkeks). If your browser is configured to display pages in these languages, you should normally see the interface in your language. And if your language is not present yet, feel free to add your translation.

\n

Other Changes

\n

We also improved the code a lot. We tried to separate each part as much as possible, making it easier to re-use for other projects. For instance, our database code is now isolated from the rest of the app, which means it will be easier to make import tools from other blogging engines. Some parts of the code are even shared with another project, Aardwolf a federated Facebook alternative. For instance, both of our projects use the same internationalization code, and once Aardwolf will implement federation, this part of the code will probably be shared too. Since the WebFinger module (used to find new users and blogs) and the CSRF protection code (see the \"Bug fixes and Security\" section) have been isolated in their own modules, they may be shared by both projects too.

\n

We also worked a lot on documentation. We now have articles explaining how to setup your Plume instance on various operating systems, but also documenting the translation process. I want to thank BanjoFox (who imported some documentation from their project, Aardwolf, as the setup is quite similar), Kushal and @gled@plume.mastodon.host for working on this.

\n

As you can see, there were many changes this month, but there still a lot to do. Your help will of course be welcome. If you want to contribute to the code, translate Plume in your language, write some documentation, or anything else (or even if you're just curious about the project), feel free to join our Matrix room: #plume:disroot.org. Otherwise, as BanjoFox said on the Aardwolf Team Mastodon account, talking about the project around you is one of the easiest way to help.

\n","id":"https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/","likes":null,"name":"This Month in Plume: June 2018","published":"2018-07-10T20:16:24.087622Z","shares":null,"source":null,"tag":[{"href":"https://baptiste.gelez.xyz/@/Trinity","name":"@Trinity","type":"Mention"},{"href":"https://baptiste.gelez.xyz/@/kaniini/","name":"@kaniini","type":"Mention"},{"href":"https://baptiste.gelez.xyz/@/Trinity","name":"@Trinity","type":"Mention"}],"to":["https://unixcorn.xyz/users/Bat","https://mastodon.host/users/federationbot","https://social.tcit.fr/users/tcit","https://framapiaf.org/users/qwerty","https://mastodon.social/users/lthms","https://eldritch.cafe/users/Nausicaa","https://imaginair.es/users/Elanndelh","https://framapiaf.org/users/Drulac","https://mastodon.partipirate.org/users/NicolasConstant","https://aleph.land/users/Madeorsk","https://maly.io/users/Troll","https://hostux.social/users/superjey","https://mamot.fr/users/Phigger","https://mastodon.social/users/wakest","https://social.coop/users/wakest","https://unixcorn.xyz/users/Ce_lo","https://social.art-software.fr/users/Electron","https://framapiaf.org/users/Quenti","https://toot.plus.yt/users/Djyp","https://mastodon.social/users/brainblasted","https://social.mochi.academy/users/Ambraven","https://social.hacktivis.me/users/lanodan","https://mastodon.eliotberriot.com/users/eliotberriot","https://edolas.world/users/0x1C3B00DA","https://toot.cafe/users/zack","https://manowar.social/users/zatnosk","https://eldritch.cafe/users/fluffy","https://mastodon.social/users/david_ross","https://kosmos.social/users/xiroux","https://mastodon.art/users/EmergencyBattle","https://mastodon.social/users/trwnh","https://octodon.social/users/pybyte","https://anticapitalist.party/users/Trinity","https://mstdn.mx/users/xavavu","https://baptiste.gelez.xyz/@/m4sk1n","https://eldritch.cafe/users/milia","https://mastodon.zaclys.com/users/arx","https://toot.cafe/users/sivy","https://mastodon.social/users/ortegacmanuel","https://mastodon.observer/users/stephen","https://octodon.social/users/chloe","https://unixcorn.xyz/users/AmauryPi","https://cybre.space/users/rick_777","https://mastodon.social/users/wezm","https://baptiste.gelez.xyz/@/idlesong","https://mamot.fr/users/dr4Ke","https://imaginair.es/users/Phigger","https://mamot.fr/users/dlink","https://anticapitalist.party/users/a000d4f7a91939d0e71df1646d7a48","https://framapiaf.org/users/PhieLaidMignon","https://mastodon.social/users/y6nH","https://crazynoisybizarre.town/users/FederationBot","https://social.weho.st/users/dvn","https://mastodon.art/users/Wolthera","https://diaspodon.fr/users/dada","https://pachyder.me/users/Lanza","https://mastodon.xyz/users/ag","https://aleph.land/users/yahananxie","https://mstdn.io/users/chablis_social","https://mastodon.gougere.fr/users/fabien","https://functional.cafe/users/otini","https://social.coop/users/bhaugen","https://octodon.social/users/donblanco","https://chaos.social/users/astro","https://pachyder.me/users/sibear","https://mamot.fr/users/yohann","https://social.wxcafe.net/users/Bat","https://mastodon.social/users/dansup","https://chaos.social/users/juh","https://scifi.fyi/users/paeneultima","https://hostux.social/users/Deuchnord","https://mstdn.fr/users/taziden","https://mamot.fr/users/PifyZ","https://mastodon.social/users/plantabaja","https://mastodon.social/users/gitzgrog","https://mastodon.social/users/Syluban","https://masto.pt/users/eloisa","https://pleroma.soykaf.com/users/notclacke","https://mastodon.social/users/SiegfriedEhret","https://writing.exchange/users/write_as","https://mstdn.io/users/shellkr","https://mastodon.uy/users/jorge","https://mastodon.technology/users/bobstechsite","https://mastodon.social/users/hinterwaeldler","https://mastodon.xyz/users/mgdelacroix","https://mastodon.cloud/users/jjatria","https://baptiste.gelez.xyz/@/Jade/","https://edolas.world/users/pfm","https://mstdn.io/users/jort","https://mastodon.social/users/andreipetcu","https://mastodon.technology/users/0xf00fc7c8","https://mastodon.social/users/khanate","https://mastodon.technology/users/francois","https://mastodon.social/users/glherrmann","https://mastodon.host/users/gled","https://social.holdmybeer.solutions/users/kemonine","https://scholar.social/users/bgcarlisle","https://mastodon.social/users/oldgun","https://baptiste.gelez.xyz/@/snoe/","https://mastodon.at/users/switchingsocial","https://scifi.fyi/users/BrokenBiscuit","https://dev.glitch.social/users/hoodie","https://todon.nl/users/paulfree14","https://mastodon.social/users/aadilayub","https://social.fsck.club/users/anarchosaurus","https://mastodonten.de/users/GiantG","https://mastodon.technology/users/cj","https://cybre.space/users/sam","https://layer8.space/users/silkevicious","https://mastodon.xyz/users/Jimmyrwx","https://fosstodon.org/users/danyspin97","https://mstdn.io/users/cristhyano","https://mastodon.social/users/vanyok","https://hulvr.com/users/rook","https://niu.moe/users/Lucifer","https://mamot.fr/users/Thibaut","https://mastodont.cat/users/bgta","https://mstdn.io/users/hontoni","https://niu.moe/users/lionirdeadman","https://functional.cafe/users/phoe","https://mastodon.social/users/toontoet","https://mastodon.social/users/danipozo","https://scholar.social/users/robertson","https://mastodon.social/users/aldatsa","https://elekk.xyz/users/maloki","https://kitty.town/users/nursemchurt","https://neigh.horse/users/commagray","https://mastodon.social/users/hirojin","https://mastodon.xyz/users/mareklach","https://chaos.social/users/benthor","https://mastodon.social/users/djperreault","https://mastodon.art/users/eylul","https://mastodon.opportunis.me/users/bob","https://tootplanet.space/users/Shutsumon","https://toot.cat/users/woozle","https://mastodon.social/users/StephenLB","https://sleeping.town/users/oct2pus","https://mastodon.indie.host/users/stragu","https://social.coop/users/gilscottfitzgerald","https://icosahedron.website/users/joeld","https://mastodon.social/users/hellion","https://cybre.space/users/cooler_ranch","https://mastodon.social/users/kelsonv","https://mastodon.lat/users/scalpol","https://writing.exchange/users/hnb","https://hex.bz/users/Horst","https://mastodon.social/users/weddle","https://maly.io/users/sonya","https://social.coop/users/medusa","https://mastodon.social/users/DystopianK","https://mstdn.io/users/d_io","https://fosstodon.org/users/brandon","https://fosstodon.org/users/Cando","https://mastodon.host/users/panina","https://floss.social/users/tuxether","https://social.tchncs.de/users/suitbertmonz","https://mastodon.social/users/jrt","https://mastodon.social/users/sirikon","https://mstdn.io/users/yabirgb","https://mastodon.cloud/users/FerdiZ","https://mastodon.social/users/carlchenet","https://social.polonkai.eu/users/calendar_social","https://social.polonkai.eu/users/gergely","https://mastodon.social/users/Jelv","https://mastodon.social/users/srinicame","https://cybre.space/users/mastoabed","https://mastodon.social/users/tagomago","https://lgbt.io/users/bootblackCub","https://niu.moe/users/Nopplyy","https://mastodon.social/users/bpugh","https://www.w3.org/ns/activitystreams#Public"],"type":"Article","uploadMedia":null,"url":"https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"} \ No newline at end of file diff --git a/test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json b/test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json new file mode 100644 index 000000000..b226204ba --- /dev/null +++ b/test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json @@ -0,0 +1 @@ +{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"Emoji":"toot:Emoji","Hashtag":"as:Hashtag","atomUri":"ostatus:atomUri","conversation":"ostatus:conversation","featured":"toot:featured","focalPoint":{"@container":"@list","@id":"toot:focalPoint"},"inReplyToAtomUri":"ostatus:inReplyToAtomUri","manuallyApprovesFollowers":"as:manuallyApprovesFollowers","movedTo":"as:movedTo","ostatus":"http://ostatus.org#","sensitive":"as:sensitive","toot":"http://joinmastodon.org/ns#"}],"endpoints":{"oauthAuthorizationEndpoint":null,"oauthTokenEndpoint":null,"provideClientKey":null,"proxyUrl":null,"sharedInbox":"https://baptiste.gelez.xyz/inbox/","signClientKey":null},"followers":null,"following":null,"id":"https://baptiste.gelez.xyz/@/BaptisteGelez","inbox":"https://baptiste.gelez.xyz/@/BaptisteGelez/inbox","liked":null,"likes":null,"name":"Baptiste Gelez","outbox":"https://baptiste.gelez.xyz/@/BaptisteGelez/outbox","preferredUsername":"BaptisteGelez","publicKey":{"id":"https://baptiste.gelez.xyz/@/BaptisteGelez#main-key","owner":"https://baptiste.gelez.xyz/@/BaptisteGelez","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA56vPlCAyxZDDy8hNiT1p\n0cdFKnUK/51LiP4nTAxGf5Eb8NmsB2ftDgiDWZfg3LiHkjNcfTDpmN0aZyRxnTg9\nZ4JiQagfynVEbMkcOQhO64OFZpB47GpLtxrb49IcUes/p4ngp/Wkp+arYZSpoSs6\n3I995mZp3ZJ78pNQf1/lV0VIdDe6SqvRj1GmBDXXcecxF0O7rN/WYNO7Jag4i/XA\nU1ToDAMeUFeijRioSNoD3CHkMIu7AN+gqAWzZ21H/ZUvmfxh3WqQi/MDNcUhhA+0\nXv7/dv4S20EGnHadtE7OrBC1IwiHEuRM41zZq0ze9cKpoXg3VK2fiSNrCHlYrA18\n2wIDAQAB\n-----END PUBLIC KEY-----\n"},"shares":null,"source":null,"streams":null,"summary":"Main Plume developer","type":"Person","uploadMedia":null,"url":"https://baptiste.gelez.xyz/@/BaptisteGelez"} \ No newline at end of file diff --git a/test/support/httpoison_mock.ex b/test/support/httpoison_mock.ex index befebad8a..a52d44ed6 100644 --- a/test/support/httpoison_mock.ex +++ b/test/support/httpoison_mock.ex @@ -736,6 +736,22 @@ defmodule HTTPoisonMock do }} end + def get("https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/", _, _) do + {:ok, + %Response{ + status_code: 200, + body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json") + }} + end + + def get("https://baptiste.gelez.xyz/@/BaptisteGelez", _, _) do + {:ok, + %Response{ + status_code: 200, + body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json") + }} + end + def get(url, body, headers) do {:error, "Not implemented the mock response for get #{inspect(url)}, #{inspect(body)}, #{ diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index bc33b4dfc..90c0bd768 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -476,6 +476,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end end + test "it can fetch plume articles" do + {:ok, object} = + ActivityPub.fetch_object_from_id( + "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" + ) + + assert object + end + describe "update" do test "it creates an update activity with the new user data" do user = insert(:user) From 8472fba2a729f7764ffaf2a4744533c8a95adadb Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 12 Jul 2018 23:09:42 +0200 Subject: [PATCH 44/56] [Pleroma.Web.ActivityPub.Transmogrifier]: Fix actor key outside of object The code here is copied from feature/peertube by lain. Co-authored-by: lain --- .../web/activity_pub/transmogrifier.ex | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 0d2166196..6080303b6 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -13,6 +13,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do require Logger + def get_actor(%{"actor" => actor}) when is_binary(actor) do + actor + end + + def get_actor(%{"actor" => actor}) when is_list(actor) do + Enum.at(actor, 0) + end + @doc """ Modifies an incoming AP object (mastodon format) to our internal format. """ @@ -28,16 +36,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def fix_actor(%{"attributedTo" => actor} = object) do - # attributedTo can be a list in the case of peertube or plume - actor = - if is_list(actor) do - Enum.at(actor, 0) - else - actor - end - object - |> Map.put("actor", actor) + |> Map.put("actor", get_actor(%{"actor" => actor})) end def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object) @@ -137,12 +137,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # - emoji def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data) when objtype in ["Article", "Note"] do + actor = get_actor(data) + data = Map.put(data, "actor", actor) + with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]), %User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do - # prefer the activity's actor instead of attributedTo - object = - fix_object(data["object"]) - |> Map.put("actor", data["actor"]) + object = fix_object(data["object"]) params = %{ to: data["to"], From 7501481db4be56cf7b5babeeebeb7b96273ae4db Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 12 Jul 2018 23:25:44 +0200 Subject: [PATCH 45/56] [Pleroma.Web.ActivityPub.Transmogrifier] Add Person finding --- lib/pleroma/web/activity_pub/transmogrifier.ex | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 6080303b6..2ebc526df 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -21,6 +21,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Enum.at(actor, 0) end + def get_actor(%{"actor" => actor_list}) do + Enum.find(actor_list, fn %{"type" => type} -> type == "Person" end) + |> Map.get("id") + end + @doc """ Modifies an incoming AP object (mastodon format) to our internal format. """ From f10291a1d322eed22ae594024c9d3d9011a7d5fe Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 03:35:08 +0000 Subject: [PATCH 46/56] upload: use generic Document object type instead of Image (mastodon compatibility) Mastodon does not use the object name as alt text when the object is an Image. --- lib/pleroma/upload.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 43df0d418..92a89e296 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Upload do end %{ - "type" => "Image", + "type" => "Document", "url" => [ %{ "type" => "Link", From cd19d37a90cfceb8bafb380fd8ff8e5a765b7e3d Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 03:36:11 +0000 Subject: [PATCH 47/56] mastodon api: use object name as alt text --- lib/pleroma/web/mastodon_api/views/status_view.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 4c20581d6..5dbd59dd9 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -169,7 +169,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do remote_url: href, preview_url: MediaProxy.url(href), text_url: href, - type: type + type: type, + description: attachment["name"] } end From 99c0252314fc3391e6fae58bdad8110d0a053fb9 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 03:36:50 +0000 Subject: [PATCH 48/56] mastodon api: support descriptions in media api, add PUT endpoint for updating metadata about a media upload --- .../mastodon_api/mastodon_api_controller.ex | 35 ++++++++++++++++--- lib/pleroma/web/router.ex | 1 + 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 09e6b0b59..f270e1146 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1,6 +1,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller - alias Pleroma.{Repo, Activity, User, Notification, Stats} + alias Pleroma.{Repo, Object, Activity, User, Notification, Stats} alias Pleroma.Web alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView} alias Pleroma.Web.ActivityPub.ActivityPub @@ -428,16 +428,43 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do render(conn, AccountView, "relationships.json", %{user: user, targets: targets}) end - def upload(%{assigns: %{user: _}} = conn, %{"file" => file}) do - with {:ok, object} <- ActivityPub.upload(file) do + def update_media(%{assigns: %{user: _}} = conn, data) do + with %Object{} = object <- Repo.get(Object, data["id"]), + true <- is_binary(data["description"]), + description <- data["description"] do + new_data = %{object.data | "name" => description} + + change = Object.change(object, %{data: new_data}) + {:ok, media_obj} = Repo.update(change) + data = - object.data + new_data |> Map.put("id", object.id) render(conn, StatusView, "attachment.json", %{attachment: data}) end end + def upload(%{assigns: %{user: _}} = conn, %{"file" => file} = data) do + with {:ok, object} <- ActivityPub.upload(file) do + objdata = + if Map.has_key?(data, "description") do + Map.put(object.data, "name", data["description"]) + else + object.data + end + + change = Object.change(object, %{data: objdata}) + {:ok, object} = Repo.update(change) + + objdata = + objdata + |> Map.put("id", object.id) + + render(conn, StatusView, "attachment.json", %{attachment: objdata}) + end + end + def favourited_by(conn, %{"id" => id}) do with %Activity{data: %{"object" => %{"likes" => likes}}} <- Repo.get(Activity, id) do q = from(u in User, where: u.ap_id in ^likes) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 34652cdde..fc7a947aa 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -127,6 +127,7 @@ defmodule Pleroma.Web.Router do get("/notifications/:id", MastodonAPIController, :get_notification) post("/media", MastodonAPIController, :upload) + put("/media/:id", MastodonAPIController, :update_media) get("/lists", MastodonAPIController, :get_lists) get("/lists/:id", MastodonAPIController, :get_list) From 489453c2467b12970258927015209c9895d5cf6e Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 03:37:26 +0000 Subject: [PATCH 49/56] tests: verify media description api support is working --- test/web/mastodon_api/mastodon_api_controller_test.exs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index d1812457d..9e33c1d04 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -736,16 +736,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do filename: "an_image.jpg" } + desc = "Description of the image" + user = insert(:user) conn = conn |> assign(:user, user) - |> post("/api/v1/media", %{"file" => file}) + |> post("/api/v1/media", %{"file" => file, "description" => desc}) assert media = json_response(conn, 200) assert media["type"] == "image" + assert media["description"] == desc end test "hashtag timeline", %{conn: conn} do From 18cac1e36bd91e1554de1f495a7f178b27b2fbc3 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 03:37:40 +0000 Subject: [PATCH 50/56] test: mastodon attachments: update for added description field --- test/web/mastodon_api/status_view_test.exs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/web/mastodon_api/status_view_test.exs b/test/web/mastodon_api/status_view_test.exs index d28c3cbad..03c798bef 100644 --- a/test/web/mastodon_api/status_view_test.exs +++ b/test/web/mastodon_api/status_view_test.exs @@ -102,7 +102,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do url: "someurl", remote_url: "someurl", preview_url: "someurl", - text_url: "someurl" + text_url: "someurl", + description: nil } assert expected == StatusView.render("attachment.json", %{attachment: object}) From cf219b6addab9fffca0b2e996fa8de1d7fbcd198 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 15:10:14 +0000 Subject: [PATCH 51/56] config: make instance description configurable --- config/config.exs | 1 + lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- lib/pleroma/web/nodeinfo/nodeinfo_controller.ex | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config/config.exs b/config/config.exs index 0616fe4fb..51b953a94 100644 --- a/config/config.exs +++ b/config/config.exs @@ -52,6 +52,7 @@ config :pleroma, :instance, version: version, name: "Pleroma", email: "example@example.com", + description: "A Pleroma instance, an alternative fediverse server", limit: 5000, upload_limit: 16_000_000, registrations_open: true, diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 09e6b0b59..f521960c2 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -125,7 +125,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do response = %{ uri: Web.base_url(), title: Keyword.get(@instance, :name), - description: "A Pleroma instance, an alternative fediverse server", + description: Keyword.get(@instance, :description), version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})", email: Keyword.get(@instance, :email), urls: %{ diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index 12aca4a10..7c67bbf1c 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -43,7 +43,9 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do }, metadata: %{ nodeName: Keyword.get(instance, :name), - mediaProxy: Keyword.get(media_proxy, :enabled) + nodeDescription: Keyword.get(instance, :description), + mediaProxy: Keyword.get(media_proxy, :enabled), + private: !Keyword.get(instance, :public, true) } } From b23630076f8d1597c417e98dfc702c972b29a82c Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 17 Jul 2018 15:20:39 +0000 Subject: [PATCH 52/56] TwitterAPI: present pleroma frontend config in API --- config/config.exs | 12 ++++++++++++ .../controllers/util_controller.ex | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/config/config.exs b/config/config.exs index 51b953a94..9e2a66620 100644 --- a/config/config.exs +++ b/config/config.exs @@ -61,6 +61,18 @@ config :pleroma, :instance, public: true, quarantined_instances: [] +config :pleroma, :fe, + theme: "pleroma-dark", + logo: "/static/logo.png", + background: "/static/aurora_borealis.jpg", + redirect_root_no_login: "/main/all", + redirect_root_login: "/main/friends", + show_instance_panel: true, + show_who_to_follow_panel: false, + who_to_follow_provider: "https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-osa-api.cgi?{{host}}+{{user}}", + who_to_follow_link: "https://vinayaka.distsn.org/?{{host}}+{{user}}", + scope_options_enabled: false + config :pleroma, :activitypub, accept_blocks: true, unfollow_blocked: true, diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 7a0c37ce9..47fc79350 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -126,6 +126,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end @instance Application.get_env(:pleroma, :instance) + @instance_fe Application.get_env(:pleroma, :fe) + @instance_chat Application.get_env(:pleroma, :chat) def config(conn, _params) do case get_format(conn) do "xml" -> @@ -148,9 +150,24 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do json(conn, %{ site: %{ name: Keyword.get(@instance, :name), + description: Keyword.get(@instance, :description), server: Web.base_url(), textlimit: to_string(Keyword.get(@instance, :limit)), - closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1") + closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1"), + private: if(Keyword.get(@instance, :public, true), do: "0", else: "1"), + pleromafe: %{ + theme: Keyword.get(@instance_fe, :theme), + background: Keyword.get(@instance_fe, :background), + logo: Keyword.get(@instance_fe, :logo), + redirectRootNoLogin: Keyword.get(@instance_fe, :redirect_root_no_login), + redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login), + chatDisabled: !Keyword.get(@instance_chat, :enabled), + showInstanceSpecificPanel: Keyword.get(@instance_fe, :show_instance_panel), + showWhoToFollowPanel: Keyword.get(@instance_fe, :show_who_to_follow_panel), + scopeOptionsEnabled: Keyword.get(@instance_fe, :scope_options_enabled), + whoToFollowProvider: Keyword.get(@instance_fe, :who_to_follow_provider), + whoToFollowLink: Keyword.get(@instance_fe, :who_to_follow_link) + } } }) end From 2b3f049b06aa2d248028890bd8fdfbeb9e1e279e Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 18 Jul 2018 00:05:36 +0000 Subject: [PATCH 53/56] config: formatting --- config/config.exs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/config.exs b/config/config.exs index 9e2a66620..922acea4b 100644 --- a/config/config.exs +++ b/config/config.exs @@ -69,7 +69,8 @@ config :pleroma, :fe, redirect_root_login: "/main/friends", show_instance_panel: true, show_who_to_follow_panel: false, - who_to_follow_provider: "https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-osa-api.cgi?{{host}}+{{user}}", + who_to_follow_provider: + "https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-osa-api.cgi?{{host}}+{{user}}", who_to_follow_link: "https://vinayaka.distsn.org/?{{host}}+{{user}}", scope_options_enabled: false From 2890aef9e8924a6ddc170034679b7313372b3567 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 31 Jul 2018 21:41:18 +0000 Subject: [PATCH 54/56] activitypub: add digest header to outbound messages and sign it --- lib/pleroma/web/activity_pub/activity_pub.ex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 464832a1e..90a39ce69 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -641,8 +641,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do Logger.info("Federating #{id} to #{inbox}") host = URI.parse(inbox).host + digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64()) + signature = - Pleroma.Web.HTTPSignatures.sign(actor, %{host: host, "content-length": byte_size(json)}) + Pleroma.Web.HTTPSignatures.sign(actor, %{ + host: host, + "content-length": byte_size(json), + digest: digest + }) @httpoison.post( inbox, From 8da406afa2a53f1769e2a1a3a5e99571f30f8dea Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 31 Jul 2018 23:17:47 +0000 Subject: [PATCH 55/56] activitypub: verify remote http signature digests by recomputing the digest and replacing the digest header --- lib/pleroma/plugs/digest.ex | 10 ++++++++++ lib/pleroma/plugs/http_signature.ex | 10 ++++++++++ lib/pleroma/web/endpoint.ex | 3 ++- 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 lib/pleroma/plugs/digest.ex diff --git a/lib/pleroma/plugs/digest.ex b/lib/pleroma/plugs/digest.ex new file mode 100644 index 000000000..9d6bbb085 --- /dev/null +++ b/lib/pleroma/plugs/digest.ex @@ -0,0 +1,10 @@ +defmodule Pleroma.Web.Plugs.DigestPlug do + alias Plug.Conn + require Logger + + def read_body(conn, opts) do + {:ok, body, conn} = Conn.read_body(conn, opts) + digest = "SHA-256=" <> (:crypto.hash(:sha256, body) |> Base.encode64()) + {:ok, body, Conn.assign(conn, :digest, digest)} + end +end diff --git a/lib/pleroma/plugs/http_signature.ex b/lib/pleroma/plugs/http_signature.ex index 38bcd3a78..9e53371b7 100644 --- a/lib/pleroma/plugs/http_signature.ex +++ b/lib/pleroma/plugs/http_signature.ex @@ -19,6 +19,8 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do cond do signature && String.contains?(signature, user) -> + # set (request-target) header to the appropriate value + # we also replace the digest header with the one we computed conn = conn |> put_req_header( @@ -26,6 +28,14 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do String.downcase("#{conn.method}") <> " #{conn.request_path}" ) + conn = + if conn.assigns[:digest] do + conn + |> put_req_header("digest", conn.assigns[:digest]) + else + conn + end + assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn)) signature -> diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 1a012c1b4..cbedca004 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -35,7 +35,8 @@ defmodule Pleroma.Web.Endpoint do parsers: [:urlencoded, :multipart, :json], pass: ["*/*"], json_decoder: Jason, - length: Application.get_env(:pleroma, :instance) |> Keyword.get(:upload_limit) + length: Application.get_env(:pleroma, :instance) |> Keyword.get(:upload_limit), + body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []} ) plug(Plug.MethodOverride) From 3be58ad34ea69b1764245546c4d67a92e4d70328 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 1 Aug 2018 10:22:03 +0000 Subject: [PATCH 56/56] activitypub: actually send digest header when federating this is needed for backwards compatibility with non-digest pleroma instances --- lib/pleroma/web/activity_pub/activity_pub.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 90a39ce69..ec605b694 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -653,7 +653,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do @httpoison.post( inbox, json, - [{"Content-Type", "application/activity+json"}, {"signature", signature}], + [ + {"Content-Type", "application/activity+json"}, + {"signature", signature}, + {"digest", digest} + ], hackney: [pool: :default] ) end