From 5d3fdbc08223a1b8b6f36f2621214285c383b840 Mon Sep 17 00:00:00 2001 From: eal Date: Wed, 30 May 2018 16:33:37 +0300 Subject: MastoAPI: Add streaming for lists. --- lib/pleroma/list.ex | 15 ++++++++++++++- lib/pleroma/web/activity_pub/activity_pub.ex | 1 + lib/pleroma/web/mastodon_api/mastodon_socket.ex | 7 +++++-- lib/pleroma/web/streamer.ex | 13 +++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/list.ex b/lib/pleroma/list.ex index 9d0b9285b..53d98665b 100644 --- a/lib/pleroma/list.ex +++ b/lib/pleroma/list.ex @@ -1,7 +1,7 @@ defmodule Pleroma.List do use Ecto.Schema import Ecto.{Changeset, Query} - alias Pleroma.{User, Repo} + alias Pleroma.{User, Repo, Activity} schema "lists" do belongs_to(:user, Pleroma.User) @@ -56,6 +56,19 @@ defmodule Pleroma.List do {:ok, Repo.all(q)} end + # Get lists the activity should be streamed to. + def get_lists_from_activity(%Activity{actor: ap_id}) do + actor = User.get_cached_by_ap_id(ap_id) + + query = + from( + l in Pleroma.List, + where: fragment("? && ?", l.following, ^[actor.follower_address]) + ) + + Repo.all(query) + end + def rename(%Pleroma.List{} = list, title) do list |> title_changeset(%{title: title}) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4e0be5ba2..91e851d54 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -57,6 +57,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do if activity.data["type"] in ["Create", "Announce"] do Pleroma.Web.Streamer.stream("user", activity) + Pleroma.Web.Streamer.stream("list", activity) if Enum.member?(activity.data["to"], public) do Pleroma.Web.Streamer.stream("public", activity) diff --git a/lib/pleroma/web/mastodon_api/mastodon_socket.ex b/lib/pleroma/web/mastodon_api/mastodon_socket.ex index 080f62b31..46648c366 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_socket.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_socket.ex @@ -15,10 +15,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonSocket do with token when not is_nil(token) <- params["access_token"], %Token{user_id: user_id} <- Repo.get_by(Token, token: token), %User{} = user <- Repo.get(User, user_id), - stream when stream in ["public", "public:local", "user", "direct"] <- params["stream"] do + stream when stream in ["public", "public:local", "user", "direct", "list"] <- + params["stream"] do + topic = if stream == "list", do: "list:#{params["list"]}", else: stream + socket = socket - |> assign(:topic, params["stream"]) + |> assign(:topic, topic) |> assign(:user, user) Pleroma.Web.Streamer.add_socket(params["stream"], socket) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 6ed9035fb..0c9e95485 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -59,6 +59,19 @@ defmodule Pleroma.Web.Streamer do {:noreply, topics} end + def handle_cast(%{action: :stream, topic: "list", item: item}, topics) do + recipient_topics = + Pleroma.List.get_lists_from_activity(item) + |> Enum.map(fn %{id: id} -> "list:#{id}" end) + + Enum.each(recipient_topics || [], fn list_topic -> + Logger.debug("Trying to push message to #{list_topic}\n\n") + push_to_socket(topics, list_topic, item) + end) + + {:noreply, topics} + end + def handle_cast(%{action: :stream, topic: "user", item: %Notification{} = item}, topics) do topic = "user:#{item.user_id}" -- cgit v1.2.3 From 87566b6e2f48ee2b82d4af7ccb6200ff8bc721d1 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 3 Jun 2018 22:01:37 +0300 Subject: user.ex: add domain blocks. --- lib/pleroma/user.ex | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index b1b935a0f..c8e61f8a9 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -479,7 +479,29 @@ defmodule Pleroma.User do def blocks?(user, %{ap_id: ap_id}) do blocks = user.info["blocks"] || [] - Enum.member?(blocks, ap_id) + domain_blocks = user.info["domain_blocks"] || [] + %{host: host} = URI.parse(ap_id) + Enum.member?(blocks, ap_id) || Enum.any?(domain_blocks, fn domain -> + host == domain + end) + end + + def block_domain(user, domain) do + domain_blocks = user.info["domain_blocks"] || [] + new_blocks = Enum.uniq([domain | domain_blocks]) + new_info = Map.put(user.info, "domain_blocks", new_blocks) + + cs = User.info_changeset(user, %{info: new_info}) + update_and_set_cache(cs) + end + + def unblock_domain(user, domain) do + blocks = user.info["domain_blocks"] || [] + new_blocks = List.delete(blocks, domain) + new_info = Map.put(user.info, "domain_blocks", new_blocks) + + cs = User.info_changeset(user, %{info: new_info}) + update_and_set_cache(cs) end def local_user_query() do -- cgit v1.2.3 From 4856962434ffd36826a4fc3052b867e751efc828 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 3 Jun 2018 22:21:23 +0300 Subject: MastoAPI: add domain blocking. --- lib/pleroma/user.ex | 8 +++++--- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 14 ++++++++++++++ lib/pleroma/web/router.ex | 5 ++++- 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index c8e61f8a9..aecf96c36 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -481,9 +481,11 @@ defmodule Pleroma.User do blocks = user.info["blocks"] || [] domain_blocks = user.info["domain_blocks"] || [] %{host: host} = URI.parse(ap_id) - Enum.member?(blocks, ap_id) || Enum.any?(domain_blocks, fn domain -> - host == domain - end) + + Enum.member?(blocks, ap_id) || + Enum.any?(domain_blocks, fn domain -> + host == domain + end) end def block_domain(user, domain) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 5fb51e8fa..12f9b5f7c 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -533,6 +533,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + def domain_blocks(%{assigns: %{user: %{info: info}}} = conn, _) do + json(conn, info["domain_blocks"] || []) + end + + def block_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do + User.block_domain(blocker, domain) + json(conn, %{}) + end + + def unblock_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do + User.unblock_domain(blocker, domain) + json(conn, %{}) + end + def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do accounts = User.search(query, params["resolve"] == "true") diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 924254895..57b10bff1 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -101,7 +101,6 @@ defmodule Pleroma.Web.Router do get("/blocks", MastodonAPIController, :blocks) - get("/domain_blocks", MastodonAPIController, :empty_array) get("/follow_requests", MastodonAPIController, :empty_array) get("/mutes", MastodonAPIController, :empty_array) @@ -134,6 +133,10 @@ defmodule Pleroma.Web.Router do get("/lists/:id/accounts", MastodonAPIController, :list_accounts) post("/lists/:id/accounts", MastodonAPIController, :add_to_list) delete("/lists/:id/accounts", MastodonAPIController, :remove_from_list) + + get("/domain_blocks", MastodonAPIController, :domain_blocks) + post("/domain_blocks", MastodonAPIController, :block_domain) + delete("/domain_blocks", MastodonAPIController, :unblock_domain) end scope "/api/web", Pleroma.Web.MastodonAPI do -- cgit v1.2.3 From 9075b6d25b4b136bb8d8ae888bd52996a9f302e2 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 3 Jun 2018 23:33:33 +0300 Subject: ActivityPub.ex: filter domain blocked activities. --- lib/pleroma/web/activity_pub/activity_pub.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4e0be5ba2..5c61920e5 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -439,11 +439,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do blocks = info["blocks"] || [] + domain_blocks = info["domain_blocks"] || [] from( activity in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocks), - where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks) + where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks), + where: fragment("not (? ~ ANY(?))", activity.actor, ^domain_blocks) ) end -- cgit v1.2.3 From 29c9c8d93b263e57915158d09761bc6586826798 Mon Sep 17 00:00:00 2001 From: eal Date: Wed, 6 Jun 2018 21:13:40 +0300 Subject: Extract host from ap_id, add index --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 5c61920e5..a5e42d9d0 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -445,7 +445,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do activity in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocks), where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks), - where: fragment("not (? ~ ANY(?))", activity.actor, ^domain_blocks) + where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks) ) end -- cgit v1.2.3 From 3f0440ac3c38b88fe449da9b8281d1dbadfa36d1 Mon Sep 17 00:00:00 2001 From: Sir_Boops Date: Sun, 15 Apr 2018 17:37:51 -0600 Subject: Dedupe uploads --- lib/mix/tasks/sample_config.eex | 3 +- lib/pleroma/upload.ex | 114 +++++++++++++++++++++------ lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- 3 files changed, 91 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index e37c864c0..d57591d53 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -8,7 +8,8 @@ config :pleroma, :instance, name: "<%= name %>", email: "<%= email %>", limit: 5000, - registrations_open: true + registrations_open: true, + dedupe_media: true config :pleroma, :media_proxy, enabled: false, diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index e5df94009..ab4bd16f0 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -2,20 +2,21 @@ defmodule Pleroma.Upload do alias Ecto.UUID alias Pleroma.Web - def store(%Plug.Upload{} = file) do - uuid = UUID.generate() - upload_folder = Path.join(upload_path(), uuid) + def store(%Plug.Upload{} = file, should_dedupe) do + content_type = get_content_type(file.path) + uuid = get_uuid(file, should_dedupe) + name = get_name(file, uuid, content_type, should_dedupe) + upload_folder = get_upload_path(uuid, should_dedupe) + url_path = get_url(name, uuid, should_dedupe) + File.mkdir_p!(upload_folder) - result_file = Path.join(upload_folder, file.filename) - File.cp!(file.path, result_file) + result_file = Path.join(upload_folder, name) - # fix content type on some image uploads - content_type = - if file.content_type in [nil, "application/octet-stream"] do - get_content_type(file.path) - else - file.content_type - end + if File.exists?(result_file) do + File.rm!(file.path) + else + File.cp!(file.path, result_file) + end %{ "type" => "Image", @@ -23,26 +24,48 @@ defmodule Pleroma.Upload do %{ "type" => "Link", "mediaType" => content_type, - "href" => url_for(Path.join(uuid, :cow_uri.urlencode(file.filename))) + "href" => url_path } ], - "name" => file.filename, - "uuid" => uuid + "name" => name } end - def store(%{"img" => "data:image/" <> image_data}) do + def store(%{"img" => "data:image/" <> image_data}, should_dedupe) do parsed = Regex.named_captures(~r/(?jpeg|png|gif);base64,(?.*)/, image_data) - data = Base.decode64!(parsed["data"]) + data = Base.decode64!(parsed["data"], ignore: :whitespace) uuid = UUID.generate() - upload_folder = Path.join(upload_path(), uuid) - File.mkdir_p!(upload_folder) - filename = Base.encode16(:crypto.hash(:sha256, data)) <> ".#{parsed["filetype"]}" - result_file = Path.join(upload_folder, filename) + uuidpath = Path.join(upload_path(), uuid) + uuid = UUID.generate() + + File.mkdir_p!(upload_path()) - File.write!(result_file, data) + File.write!(uuidpath, data) - content_type = "image/#{parsed["filetype"]}" + content_type = get_content_type(uuidpath) + + name = + create_name( + String.downcase(Base.encode16(:crypto.hash(:sha256, data))), + parsed["filetype"], + content_type + ) + + upload_folder = get_upload_path(uuid, should_dedupe) + url_path = get_url(name, uuid, should_dedupe) + + File.mkdir_p!(upload_folder) + result_file = Path.join(upload_folder, name) + + if should_dedupe do + if !File.exists?(result_file) do + File.rename(uuidpath, result_file) + else + File.rm!(uuidpath) + end + else + File.rename(uuidpath, result_file) + end %{ "type" => "Image", @@ -50,11 +73,10 @@ defmodule Pleroma.Upload do %{ "type" => "Link", "mediaType" => content_type, - "href" => url_for(Path.join(uuid, :cow_uri.urlencode(filename))) + "href" => url_path } ], - "name" => filename, - "uuid" => uuid + "name" => name } end @@ -63,6 +85,46 @@ defmodule Pleroma.Upload do Keyword.fetch!(settings, :uploads) end + defp create_name(uuid, ext, type) do + if type == "application/octet-stream" do + String.downcase(Enum.join([uuid, ext], ".")) + else + String.downcase(Enum.join([uuid, List.last(String.split(type, "/"))], ".")) + end + end + + defp get_uuid(file, should_dedupe) do + if should_dedupe do + Base.encode16(:crypto.hash(:sha256, File.read!(file.path))) + else + UUID.generate() + end + end + + defp get_name(file, uuid, type, should_dedupe) do + if should_dedupe do + create_name(uuid, List.last(String.split(file.filename, ".")), type) + else + file.filename + end + end + + defp get_upload_path(uuid, should_dedupe) do + if should_dedupe do + upload_path() + else + Path.join(upload_path(), uuid) + end + end + + defp get_url(name, uuid, should_dedupe) do + if should_dedupe do + url_for(:cow_uri.urlencode(name)) + else + url_for(Path.join(uuid, :cow_uri.urlencode(name))) + end + end + defp url_for(file) do "#{Web.base_url()}/media/#{file}" end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4e0be5ba2..3a03f5fe4 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -492,7 +492,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end def upload(file) do - data = Upload.store(file) + data = Upload.store(file, Application.get_env(:pleroma, :instance)[:dedupe_media]) Repo.insert(%Object{data: data}) end -- cgit v1.2.3 From 07f0cfa53f43954eadba9ca87398f12663b33d93 Mon Sep 17 00:00:00 2001 From: squidboi Date: Sun, 10 Jun 2018 16:40:51 -0700 Subject: add allow_followersonly and allow_direct options for configuring mrf_rejectnonpublic --- .../web/activity_pub/mrf/reject_non_public.ex | 26 +++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex index 879cbe6de..b6936fe90 100644 --- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex +++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex @@ -2,6 +2,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do alias Pleroma.User @behaviour Pleroma.Web.ActivityPub.MRF + @mrf_rejectnonpublic Application.get_env(:pleroma, :mrf_rejectnonpublic) + @allow_followersonly Keyword.get(@mrf_rejectnonpublic, :allow_followersonly) + @allow_direct Keyword.get(@mrf_rejectnonpublic, :allow_direct) + @impl true def filter(object) do if object["type"] == "Create" do @@ -18,9 +22,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do end case visibility do - "public" -> {:ok, object} - "unlisted" -> {:ok, object} - _ -> {:reject, nil} + "public" -> + {:ok, object} + + "unlisted" -> + {:ok, object} + + "followers" -> + with true <- @allow_followersonly do + {:ok, object} + else + _e -> {:reject, nil} + end + + "direct" -> + with true <- @allow_direct do + {:ok, object} + else + _e -> {:reject, nil} + end end else {:ok, object} -- cgit v1.2.3 From 18837c2fedfc5dc79e78751d5b1b16ea1f0dce87 Mon Sep 17 00:00:00 2001 From: eal Date: Mon, 11 Jun 2018 22:53:38 +0300 Subject: make_moderator.ex: set cache on update --- lib/mix/tasks/make_moderator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/make_moderator.ex b/lib/mix/tasks/make_moderator.ex index 20f04c54c..4d427cfd8 100644 --- a/lib/mix/tasks/make_moderator.ex +++ b/lib/mix/tasks/make_moderator.ex @@ -19,7 +19,7 @@ defmodule Mix.Tasks.SetModerator do |> Map.put("is_moderator", !!moderator) cng = User.info_changeset(user, %{info: info}) - user = Repo.update!(cng) + {:ok, user} = User.update_and_set_cache(cng) IO.puts("Moderator status of #{nickname}: #{user.info["is_moderator"]}") else -- cgit v1.2.3 From 3208611bfc9c8edfeab3ab4bbce5b6e0ad0bf9e6 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 26 May 2018 14:45:41 +0000 Subject: mix: add task for setting an account as locked or not --- lib/mix/tasks/set_locked.ex | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/mix/tasks/set_locked.ex (limited to 'lib') diff --git a/lib/mix/tasks/set_locked.ex b/lib/mix/tasks/set_locked.ex new file mode 100644 index 000000000..2b3b18b09 --- /dev/null +++ b/lib/mix/tasks/set_locked.ex @@ -0,0 +1,30 @@ +defmodule Mix.Tasks.SetLocked do + use Mix.Task + import Mix.Ecto + alias Pleroma.{Repo, User} + + @shortdoc "Set locked status" + def run([nickname | rest]) do + ensure_started(Repo, []) + + locked = + case rest do + [locked] -> locked == "true" + _ -> true + end + + with %User{local: true} = user <- User.get_by_nickname(nickname) do + info = + user.info + |> Map.put("locked", !!locked) + + cng = User.info_changeset(user, %{info: info}) + user = Repo.update!(cng) + + IO.puts("locked status of #{nickname}: #{user.info["locked"]}") + else + _ -> + IO.puts("No local user #{nickname}") + end + end +end -- cgit v1.2.3 From e5206752e163affc3c0b7bca506e89a6249f5702 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 26 May 2018 14:55:16 +0000 Subject: activitypub: only send accept back automatically if the account is not locked --- lib/pleroma/user.ex | 4 ++++ lib/pleroma/web/activity_pub/transmogrifier.ex | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 00cac153d..c7b7b4f0a 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -252,6 +252,10 @@ defmodule Pleroma.User do Enum.member?(follower.following, followed.follower_address) end + def locked?(%User{} = user) do + user.info["locked"] || false + end + def get_by_ap_id(ap_id) do Repo.get_by(User, ap_id: ap_id) end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 75ba36729..7b0d124b2 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -137,9 +137,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do with %User{local: true} = followed <- User.get_cached_by_ap_id(followed), %User{} = follower <- User.get_or_fetch_by_ap_id(follower), {:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do - ActivityPub.accept(%{to: [follower.ap_id], actor: followed.ap_id, object: data, local: true}) + if not User.locked?(followed) do + ActivityPub.accept(%{to: [follower.ap_id], actor: followed.ap_id, object: data, local: true}) + User.follow(follower, followed) + end - User.follow(follower, followed) {:ok, activity} else _e -> :error -- cgit v1.2.3 From 6041380774605dd17d7effd3d127dd756c087413 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 26 May 2018 15:03:32 +0000 Subject: activitypub transmogrifier: learn locked state in Update messages --- lib/pleroma/web/activity_pub/transmogrifier.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 7b0d124b2..ab744f6a2 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -254,7 +254,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) banner = new_user_data[:info]["banner"] - locked = new_user_data[:info]["locked"] + locked = new_user_data[:info]["locked"] || false update_data = new_user_data -- cgit v1.2.3 From 9c889334220487c4e370333a13908639b984bc19 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 26 May 2018 16:03:32 +0000 Subject: implement tracking of follow requests --- lib/pleroma/user.ex | 30 ++++++++++++++++++++++ lib/pleroma/web/activity_pub/utils.ex | 3 ++- .../web/mastodon_api/mastodon_api_controller.ex | 6 +++++ lib/pleroma/web/router.ex | 4 ++- 4 files changed, 41 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index c7b7b4f0a..35f3371ba 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -353,6 +353,36 @@ defmodule Pleroma.User do {:ok, Repo.all(q)} end + def get_follow_requests_query(%User{} = user) do + from( + a in Activity, + where: fragment( + "? ->> 'type' = 'Follow'", + a.data + ), + where: fragment( + "? ->> 'state' = 'pending'", + a.data + ), + where: fragment( + "? @> ?", + a.data, + ^%{"object" => user.ap_id} + ) + ) + end + + def get_follow_requests(%User{} = user) do + q = get_follow_requests_query(user) + reqs = Repo.all(q) + + users = + Enum.map(reqs, fn (req) -> req.actor end) + |> Enum.map(fn (ap_id) -> get_by_ap_id(ap_id) end) + + {:ok, users} + end + def increase_note_count(%User{} = user) do note_count = (user.info["note_count"] || 0) + 1 new_info = Map.put(user.info, "note_count", note_count) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 56b80a8db..3229949c0 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -219,7 +219,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do @doc """ Makes a follow activity data for the given follower and followed """ - def make_follow_data(%User{ap_id: follower_id}, %User{ap_id: followed_id}, activity_id) do + def make_follow_data(%User{ap_id: follower_id}, %User{ap_id: followed_id} = followed, activity_id) do data = %{ "type" => "Follow", "actor" => follower_id, @@ -229,6 +229,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do } if activity_id, do: Map.put(data, "id", activity_id), else: data + if User.locked?(followed), do: Map.put(data, "state", "pending"), else: data end def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 0f7d4bb6d..e92c6277b 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -476,6 +476,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + def follow_requests(%{assigns: %{user: followed}} = conn, _params) do + with {:ok, follow_requests} <- User.get_follow_requests(followed) do + render(conn, AccountView, "accounts.json", %{users: follow_requests, as: :user}) + end + end + def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do with %User{} = followed <- Repo.get(User, id), {:ok, follower} <- User.maybe_direct_follow(follower, followed), diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 57b10bff1..e517510b8 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -97,11 +97,13 @@ defmodule Pleroma.Web.Router do post("/accounts/:id/mute", MastodonAPIController, :relationship_noop) post("/accounts/:id/unmute", MastodonAPIController, :relationship_noop) + get("/follow_requests", MastodonAPIController, :follow_requests) + post("/follows", MastodonAPIController, :follow) get("/blocks", MastodonAPIController, :blocks) - get("/follow_requests", MastodonAPIController, :empty_array) + get("/domain_blocks", MastodonAPIController, :empty_array) get("/mutes", MastodonAPIController, :empty_array) get("/timelines/home", MastodonAPIController, :home_timeline) -- cgit v1.2.3 From 6f89d2d583c76d9a2c9908f560902bc75609c8ab Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 26 May 2018 16:16:20 +0000 Subject: stash api controller --- .../web/mastodon_api/mastodon_api_controller.ex | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index e92c6277b..90b0da8da 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Web alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView} alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.{CommonAPI, OStatus} alias Pleroma.Web.OAuth.{Authorization, Token, App} alias Comeonin.Pbkdf2 @@ -482,6 +483,29 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + def authorize_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do + with %User{} = follower <- Repo.get(User, id), + {:ok, follower} <- User.follow(follower, followed), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, _activity} <- + ActivityPub.accept(%{ + to: follower.ap_id, + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Accept" + }) do + render(conn, AccountView, "relationship.json", %{user: followed, target: follower}) + else + {:error, message} -> + conn + |> put_resp_content_type("application/json") + |> send_resp(403, Jason.encode!(%{"error" => message})) + end + end + + # def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do + # end + def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do with %User{} = followed <- Repo.get(User, id), {:ok, follower} <- User.maybe_direct_follow(follower, followed), -- cgit v1.2.3 From 760eb72a382b36d37e8fed3a9c0e48360ec65f8d Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 26 May 2018 18:03:23 +0000 Subject: add a bunch of stuff --- lib/pleroma/web/activity_pub/transmogrifier.ex | 21 +++++++++++++++++++ lib/pleroma/web/activity_pub/utils.ex | 20 ++++++++++++++++-- .../web/mastodon_api/mastodon_api_controller.ex | 24 +++++++++++++++++++--- lib/pleroma/web/router.ex | 2 ++ 4 files changed, 62 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index ab744f6a2..0ebb49dc0 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -434,6 +434,27 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, data} end + # Mastodon Accept/Reject requires a non-normalized object containing the actor URIs, + # because of course it does. + def prepare_outgoing(%{"type" => "Accept"} = data) do + with follow_activity <- Activity.get_by_ap_id(data["object"]) do + object = %{ + "actor" => follow_activity.actor, + "object" => follow_activity.data["object"], + "id" => follow_activity.data["id"], + "type" => "Follow" + } + + data = + data + |> Map.put("object", object) + + IO.inspect(data) + + {:ok, data} + end + end + def prepare_outgoing(%{"type" => _type} = data) do data = data diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 3229949c0..6ce954cd0 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do alias Pleroma.Web.Endpoint alias Ecto.{Changeset, UUID} import Ecto.Query + require Logger # Some implementations send the actor URI as the actor field, others send the entire actor object, # so figure out what the actor's URI is based on what we have. @@ -216,6 +217,19 @@ defmodule Pleroma.Web.ActivityPub.Utils do #### Follow-related helpers + @doc """ + Updates a follow activity's state (for locked accounts). + """ + def update_follow_state(%Activity{} = activity, state) do + with new_data <- + activity.data + |> Map.put("state", state), + changeset <- Changeset.change(activity, data: new_data), + {:ok, activity} <- Repo.update(changeset) do + {:ok, activity} + end + end + @doc """ Makes a follow activity data for the given follower and followed """ @@ -228,8 +242,10 @@ defmodule Pleroma.Web.ActivityPub.Utils do "object" => followed_id } - if activity_id, do: Map.put(data, "id", activity_id), else: data - if User.locked?(followed), do: Map.put(data, "state", "pending"), else: data + data = if activity_id, do: Map.put(data, "id", activity_id), else: data + data = if User.locked?(followed), do: Map.put(data, "state", "pending"), else: data + + data end def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 90b0da8da..cae81c43d 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -487,9 +487,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %User{} = follower <- Repo.get(User, id), {:ok, follower} <- User.follow(follower, followed), %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), {:ok, _activity} <- ActivityPub.accept(%{ - to: follower.ap_id, + to: [follower.ap_id], actor: followed.ap_id, object: follow_activity.data["id"], type: "Accept" @@ -503,8 +504,25 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - # def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do - # end + def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do + with %User{} = follower <- Repo.get(User, id), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), + {:ok, _activity} <- + ActivityPub.reject(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Reject" + }) do + render(conn, AccountView, "relationship.json", %{user: followed, target: follower}) + else + {:error, message} -> + conn + |> put_resp_content_type("application/json") + |> send_resp(403, Jason.encode!(%{"error" => message})) + end + end def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do with %User{} = followed <- Repo.get(User, id), diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index e517510b8..b37c8168f 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -98,6 +98,8 @@ defmodule Pleroma.Web.Router do post("/accounts/:id/unmute", MastodonAPIController, :relationship_noop) get("/follow_requests", MastodonAPIController, :follow_requests) + post("/follow_requests/:id/authorize", MastodonAPIController, :authorize_follow_request) + post("/follow_requests/:id/reject", MastodonAPIController, :reject_follow_request) post("/follows", MastodonAPIController, :follow) -- cgit v1.2.3 From 876ad6aa380dcc7ef4888fe31f3b7da567d6f490 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 27 May 2018 09:09:35 +0000 Subject: activitypub transmogrifier: send @context on accept activities --- lib/pleroma/web/activity_pub/transmogrifier.ex | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 0ebb49dc0..5f5ed7b8e 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -448,6 +448,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do data = data |> Map.put("object", object) + |> Map.put("@context", "https://www.w3.org/ns/activitystreams") IO.inspect(data) -- cgit v1.2.3 From f328de8eb77ced729a46e12cbcf898bcfaec78c1 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 27 May 2018 09:10:46 +0000 Subject: activitypub transmogrifier: send Rejects in the format Mastodon wants --- lib/pleroma/web/activity_pub/transmogrifier.ex | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 5f5ed7b8e..170bfbc03 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -456,6 +456,26 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end + def prepare_outgoing(%{"type" => "Reject"} = data) do + with follow_activity <- Activity.get_by_ap_id(data["object"]) do + object = %{ + "actor" => follow_activity.actor, + "object" => follow_activity.data["object"], + "id" => follow_activity.data["id"], + "type" => "Follow" + } + + data = + data + |> Map.put("object", object) + |> Map.put("@context", "https://www.w3.org/ns/activitystreams") + + IO.inspect(data) + + {:ok, data} + end + end + def prepare_outgoing(%{"type" => _type} = data) do data = data -- cgit v1.2.3 From ad7188fe920c5eaa21c38b5f7781a7ba22173b91 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 27 May 2018 09:45:12 +0000 Subject: user: use Enum.uniq on the follow request query --- lib/pleroma/user.ex | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 35f3371ba..9c0cc7455 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -378,6 +378,7 @@ defmodule Pleroma.User do users = Enum.map(reqs, fn (req) -> req.actor end) + |> Enum.uniq |> Enum.map(fn (ap_id) -> get_by_ap_id(ap_id) end) {:ok, users} -- cgit v1.2.3 From a2c4a5a75bc22653553fdf2f3ec25e2c9dd7c66a Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 27 May 2018 10:03:53 +0000 Subject: mastodon api: allow setting an account locked or not --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index cae81c43d..caff4ad86 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -72,6 +72,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do user end + user = + if locked = params["locked"] do + with locked <- locked == "true", + new_info <- Map.put(user.info, "locked", locked), + 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 if original_user != user do -- cgit v1.2.3 From 76f80ba8c23798d69ecc6b89d6fd42a1d37adeed Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 27 May 2018 13:51:13 +0000 Subject: activitypub: when unfollowing, update the follow activity's disposition to 'cancelled' so it cannot be reused --- lib/pleroma/web/activity_pub/activity_pub.ex | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 43e96fe37..3c2875548 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -214,6 +214,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def unfollow(follower, followed, activity_id \\ nil, local \\ true) do with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"), unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id), {:ok, activity} <- insert(unfollow_data, local), :ok <- maybe_federate(activity) do -- cgit v1.2.3 From 1452b2823fbd858f2b818c35ca1faedb0d222690 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 28 May 2018 16:42:18 +0000 Subject: user: add a workaround for situations where Pleroma may believe a followee is followed this was caused by lack of Undo follows in the early days, and can likely be eventually removed --- lib/pleroma/user.ex | 8 ++++++++ lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 9c0cc7455..1dcb68470 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -197,6 +197,14 @@ defmodule Pleroma.User do end end + def maybe_follow(%User{} = follower, %User{info: info} = followed) do + if not following?(follower, followed) do + follow(follower, followed) + else + {:ok, follower} + end + end + def follow(%User{} = follower, %User{info: info} = followed) do ap_followers = followed.follower_address diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index caff4ad86..922b83ed0 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -499,7 +499,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def authorize_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do with %User{} = follower <- Repo.get(User, id), - {:ok, follower} <- User.follow(follower, followed), + {:ok, follower} <- User.maybe_follow(follower, followed), %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), {:ok, _activity} <- -- cgit v1.2.3 From 4084889a2d2a00828b2909ee5356f86b42d747e8 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 28 May 2018 17:42:58 +0000 Subject: activitypub transmogrifier: remove debug code --- lib/pleroma/web/activity_pub/transmogrifier.ex | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 170bfbc03..dffe2f159 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -450,8 +450,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("object", object) |> Map.put("@context", "https://www.w3.org/ns/activitystreams") - IO.inspect(data) - {:ok, data} end end @@ -470,8 +468,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("object", object) |> Map.put("@context", "https://www.w3.org/ns/activitystreams") - IO.inspect(data) - {:ok, data} end end -- cgit v1.2.3 From 993312cdb3ec219f1cf29e14be97f2b98bc90a9c Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 28 May 2018 18:19:20 +0000 Subject: twitterapi: add profile setting for locked/unlocked accounts --- lib/pleroma/web/twitter_api/twitter_api_controller.ex | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index d53dd0c44..b078c447e 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -357,6 +357,20 @@ defmodule Pleroma.Web.TwitterAPI.Controller do params end + user = + if locked = params["locked"] do + with locked <- locked == "true", + new_info <- Map.put(user.info, "locked", locked), + 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) -- cgit v1.2.3 From 5eed1ea18145b16999b29f0a4c2313784c8cff0e Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 28 May 2018 18:31:48 +0000 Subject: run mix format --- lib/pleroma/user.ex | 35 ++++++++++++++------------ lib/pleroma/web/activity_pub/transmogrifier.ex | 8 +++++- lib/pleroma/web/activity_pub/utils.ex | 6 ++++- 3 files changed, 31 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 1dcb68470..b27397e13 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -364,19 +364,22 @@ defmodule Pleroma.User do def get_follow_requests_query(%User{} = user) do from( a in Activity, - where: fragment( - "? ->> 'type' = 'Follow'", - a.data - ), - where: fragment( - "? ->> 'state' = 'pending'", - a.data - ), - where: fragment( - "? @> ?", - a.data, - ^%{"object" => user.ap_id} - ) + where: + fragment( + "? ->> 'type' = 'Follow'", + a.data + ), + where: + fragment( + "? ->> 'state' = 'pending'", + a.data + ), + where: + fragment( + "? @> ?", + a.data, + ^%{"object" => user.ap_id} + ) ) end @@ -385,9 +388,9 @@ defmodule Pleroma.User do reqs = Repo.all(q) users = - Enum.map(reqs, fn (req) -> req.actor end) - |> Enum.uniq - |> Enum.map(fn (ap_id) -> get_by_ap_id(ap_id) end) + Enum.map(reqs, fn req -> req.actor end) + |> Enum.uniq() + |> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end) {:ok, users} end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index dffe2f159..08173f78d 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -138,7 +138,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %User{} = follower <- User.get_or_fetch_by_ap_id(follower), {:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do if not User.locked?(followed) do - ActivityPub.accept(%{to: [follower.ap_id], actor: followed.ap_id, object: data, local: true}) + ActivityPub.accept(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: data, + local: true + }) + User.follow(follower, followed) end diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6ce954cd0..64329b710 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -233,7 +233,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do @doc """ Makes a follow activity data for the given follower and followed """ - def make_follow_data(%User{ap_id: follower_id}, %User{ap_id: followed_id} = followed, activity_id) do + def make_follow_data( + %User{ap_id: follower_id}, + %User{ap_id: followed_id} = followed, + activity_id + ) do data = %{ "type" => "Follow", "actor" => follower_id, -- cgit v1.2.3 From d96377f3590c08a2c38941299aedb977b1b5a8e5 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 29 May 2018 10:18:23 +0000 Subject: activitypub transmogrifier: accept/reject outgoing: we might send the actual object instead of the URI in some cases, handle it --- lib/pleroma/web/activity_pub/transmogrifier.ex | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 08173f78d..e7a3420d2 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -443,7 +443,14 @@ 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 - with follow_activity <- Activity.get_by_ap_id(data["object"]) 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 object = %{ "actor" => follow_activity.actor, "object" => follow_activity.data["object"], @@ -461,7 +468,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def prepare_outgoing(%{"type" => "Reject"} = data) do - with follow_activity <- Activity.get_by_ap_id(data["object"]) 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 object = %{ "actor" => follow_activity.actor, "object" => follow_activity.data["object"], -- cgit v1.2.3 From ba8dab75426fbd881c7b8fd814934d46fc48e9ba Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 29 May 2018 14:13:34 +0000 Subject: twitterapi: user view: return if an account is locked or not --- lib/pleroma/web/twitter_api/views/user_view.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index 31527caae..711008973 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -51,7 +51,8 @@ defmodule Pleroma.Web.TwitterAPI.UserView do "statusnet_profile_url" => user.ap_id, "cover_photo" => User.banner_url(user) |> MediaProxy.url(), "background_image" => image_url(user.info["background"]) |> MediaProxy.url(), - "is_local" => user.local + "is_local" => user.local, + "locked" => !!user.info["locked"] } if assigns[:token] do -- cgit v1.2.3 From e08cf21e5b45f263d7f75641f3a91a5329488f82 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 29 May 2018 15:30:06 +0000 Subject: twitter api: add friend requests list api --- lib/pleroma/web/router.ex | 2 ++ lib/pleroma/web/twitter_api/twitter_api_controller.ex | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index b37c8168f..ea134bbff 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -247,6 +247,8 @@ defmodule Pleroma.Web.Router do post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet) post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post) + get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests) + post("/friendships/create", TwitterAPI.Controller, :follow) post("/friendships/destroy", TwitterAPI.Controller, :unfollow) post("/blocks/create", TwitterAPI.Controller, :block) diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index b078c447e..123d20177 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -331,6 +331,15 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end end + def friend_requests(conn, params) do + with {:ok, user} <- TwitterAPI.get_user(conn.assigns.user, params), + {:ok, friend_requests} <- User.get_follow_requests(user) do + render(conn, UserView, "index.json", %{users: friend_requests, for: user}) + else + _e -> bad_request_reply(conn, "Can't get friend requests") + end + end + def friends_ids(%{assigns: %{user: user}} = conn, _params) do with {:ok, friends} <- User.get_friends(user) do ids = -- cgit v1.2.3 From f8e0942745636f0f51e5ff57d1b40f79ee82f87b Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 7 Jun 2018 00:04:03 +0000 Subject: twitter api: add approve/deny endpoints --- lib/pleroma/web/router.ex | 2 + .../web/twitter_api/twitter_api_controller.ex | 44 +++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index ea134bbff..6f8b427b5 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -248,6 +248,8 @@ defmodule Pleroma.Web.Router do post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post) get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests) + post("/pleroma/friendships/approve", TwitterAPI.Controller, :approve_friend_request) + post("/pleroma/friendships/deny", TwitterAPI.Controller, :deny_friend_request) post("/friendships/create", TwitterAPI.Controller, :follow) post("/friendships/destroy", TwitterAPI.Controller, :unfollow) diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 123d20177..b29687df5 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do alias Pleroma.Web.CommonAPI alias Pleroma.{Repo, Activity, User, Notification} alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Utils alias Ecto.Changeset require Logger @@ -332,14 +333,53 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end def friend_requests(conn, params) do - with {:ok, user} <- TwitterAPI.get_user(conn.assigns.user, params), + with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params), {:ok, friend_requests} <- User.get_follow_requests(user) do - render(conn, UserView, "index.json", %{users: friend_requests, for: user}) + render(conn, UserView, "index.json", %{users: friend_requests, for: conn.assigns[:user]}) else _e -> bad_request_reply(conn, "Can't get friend requests") end end + def approve_friend_request(conn, %{"user_id" => uid} = params) do + with followed <- conn.assigns[:user], + uid when is_number(uid) <- String.to_integer(uid), + %User{} = follower <- Repo.get(User, uid), + {:ok, follower} <- User.maybe_follow(follower, followed), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), + {:ok, _activity} <- + ActivityPub.accept(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Accept" + }) do + render(conn, UserView, "show.json", %{user: follower, for: followed}) + else + e -> bad_request_reply(conn, "Can't approve user: #{inspect(e)}") + end + end + + def deny_friend_request(conn, %{"user_id" => uid} = params) do + with followed <- conn.assigns[:user], + uid when is_number(uid) <- String.to_integer(uid), + %User{} = follower <- Repo.get(User, uid), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), + {:ok, _activity} <- + ActivityPub.reject(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Reject" + }) do + render(conn, UserView, "show.json", %{user: follower, for: followed}) + else + e -> bad_request_reply(conn, "Can't deny user: #{inspect(e)}") + end + end + def friends_ids(%{assigns: %{user: user}} = conn, _params) do with {:ok, friends} <- User.get_friends(user) do ids = -- cgit v1.2.3 From 98104712379f4d001fc633eed7cfab69224816bc Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 11 Jun 2018 23:40:19 +0000 Subject: router: remove stub /domain_blocks entry --- lib/pleroma/web/router.ex | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 6f8b427b5..ee6a373d3 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -105,7 +105,6 @@ defmodule Pleroma.Web.Router do get("/blocks", MastodonAPIController, :blocks) - get("/domain_blocks", MastodonAPIController, :empty_array) get("/mutes", MastodonAPIController, :empty_array) get("/timelines/home", MastodonAPIController, :home_timeline) -- cgit v1.2.3 From f34232da86ff051d7b1e5a9e6d8ff32ff54dbfcb Mon Sep 17 00:00:00 2001 From: lambda Date: Tue, 12 Jun 2018 07:23:45 +0000 Subject: Update sample_config.eex --- lib/mix/tasks/sample_config.eex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index d57591d53..6db36fa09 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -9,7 +9,7 @@ config :pleroma, :instance, email: "<%= email %>", limit: 5000, registrations_open: true, - dedupe_media: true + dedupe_media: false config :pleroma, :media_proxy, enabled: false, -- cgit v1.2.3 From 3326205f95106e7ebabc544c704f28ca2e12f4b2 Mon Sep 17 00:00:00 2001 From: eal Date: Tue, 12 Jun 2018 15:42:40 +0300 Subject: set_moderator: ensureall applications are started. --- lib/mix/tasks/make_moderator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/make_moderator.ex b/lib/mix/tasks/make_moderator.ex index 4d427cfd8..a454a958e 100644 --- a/lib/mix/tasks/make_moderator.ex +++ b/lib/mix/tasks/make_moderator.ex @@ -5,7 +5,7 @@ defmodule Mix.Tasks.SetModerator do @shortdoc "Set moderator status" def run([nickname | rest]) do - ensure_started(Repo, []) + Application.ensure_all_started(:pleroma) moderator = case rest do -- cgit v1.2.3 From 59f95a7095f7f066f4f787f8fa1d04ceca4a3148 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 13 Jun 2018 06:37:02 +0000 Subject: webfinger: refactor webfinger() functions - remove code duplication - move user lookup to parent with statement - tighten both user lookup by nickname and activitypub URI with a type constraint --- lib/pleroma/web/web_finger/web_finger.ex | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index e7ee810f9..9f554d286 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -25,35 +25,17 @@ defmodule Pleroma.Web.WebFinger do |> XmlBuilder.to_doc() end - def webfinger(resource, "JSON") do + def webfinger(resource, fmt) when fmt in ["XML", "JSON"] do host = Pleroma.Web.Endpoint.host() regex = ~r/(acct:)?(?\w+)@#{host}/ - with %{"username" => username} <- Regex.named_captures(regex, resource) do - user = User.get_by_nickname(username) - {:ok, represent_user(user, "JSON")} + with %{"username" => username} <- Regex.named_captures(regex, resource), + %User{} = user <- User.get_by_nickname(username) do + {:ok, represent_user(user, fmt)} else _e -> - with user when not is_nil(user) <- User.get_cached_by_ap_id(resource) do - {:ok, represent_user(user, "JSON")} - else - _e -> - {:error, "Couldn't find user"} - end - end - end - - def webfinger(resource, "XML") do - host = Pleroma.Web.Endpoint.host() - regex = ~r/(acct:)?(?\w+)@#{host}/ - - with %{"username" => username} <- Regex.named_captures(regex, resource) do - user = User.get_by_nickname(username) - {:ok, represent_user(user, "XML")} - else - _e -> - with user when not is_nil(user) <- User.get_cached_by_ap_id(resource) do - {:ok, represent_user(user, "XML")} + with %User{} = user <- User.get_cached_by_ap_id(resource) do + {:ok, represent_user(user, fmt)} else _e -> {:error, "Couldn't find user"} -- cgit v1.2.3 From 3d402a9e2070c38c578d3bc64aed2b9361a4bcf0 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 13 Jun 2018 06:56:14 +0000 Subject: webfinger: send JRD by default instead of XRD JRD being the default representation for WebFinger responses was standardized 5 years ago in RFC 7033. --- lib/pleroma/web/router.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index ee6a373d3..0e6369147 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -41,7 +41,7 @@ defmodule Pleroma.Web.Router do end pipeline :well_known do - plug(:accepts, ["xml", "xrd+xml", "json", "jrd+json"]) + plug(:accepts, ["json", "jrd+json", "xml", "xml+xrd"]) end pipeline :config do -- cgit v1.2.3 From b5bc08fac3c38fd60232bce23f337c4616fbca1b Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 13 Jun 2018 21:57:14 +0000 Subject: streamer: don't relay boosts of messages which would otherwise be blocked --- lib/pleroma/web/streamer.ex | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 0c9e95485..ce38f3cc3 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Web.Streamer do use GenServer require Logger - alias Pleroma.{User, Notification} + alias Pleroma.{User, Notification, Activity, Object} def init(args) do {:ok, args} @@ -138,6 +138,34 @@ defmodule Pleroma.Web.Streamer do {:noreply, state} end + defp represent_update(%Activity{} = activity, %User{} = user) do + %{ + event: "update", + payload: + Pleroma.Web.MastodonAPI.StatusView.render( + "status.json", + activity: activity, + for: user + ) + |> Jason.encode!() + } + |> Jason.encode!() + end + + def push_to_socket(topics, topic, %Activity{data: %{"type" => "Announce"}} = item) do + Enum.each(topics[topic] || [], fn socket -> + # Get the current user so we have up-to-date blocks etc. + 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"]) + + 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)}) + end + end) + end + def push_to_socket(topics, topic, item) do Enum.each(topics[topic] || [], fn socket -> # Get the current user so we have up-to-date blocks etc. @@ -145,20 +173,7 @@ defmodule Pleroma.Web.Streamer do blocks = user.info["blocks"] || [] unless item.actor in blocks do - json = - %{ - event: "update", - payload: - Pleroma.Web.MastodonAPI.StatusView.render( - "status.json", - activity: item, - for: user - ) - |> Jason.encode!() - } - |> Jason.encode!() - - send(socket.transport_pid, {:text, json}) + send(socket.transport_pid, {:text, represent_update(item, user)}) end end) end -- cgit v1.2.3 From 401e8af9437f8a53540b93fc80d659c15f06e137 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 13 Jun 2018 22:14:53 +0000 Subject: activitypub transmogrifier: handle activity lookup failure with the introduction of MRF, it is possible that an activity may be orphaned from it's parent, if an activity in the chain was rejected by the active MRF policies. accordingly, handle this in the same way as any other orphaned activity. closes #156 --- lib/pleroma/web/activity_pub/transmogrifier.ex | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index e7a3420d2..4c27a5704 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -30,14 +30,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do when not is_nil(in_reply_to_id) do case ActivityPub.fetch_object_from_id(in_reply_to_id) do {:ok, replied_object} -> - activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) - - object - |> Map.put("inReplyTo", replied_object.data["id"]) - |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) - |> Map.put("inReplyToStatusId", activity.id) - |> Map.put("conversation", replied_object.data["context"] || object["conversation"]) - |> Map.put("context", replied_object.data["context"] || object["conversation"]) + with %Activity{} = activity <- + Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) do + object + |> Map.put("inReplyTo", replied_object.data["id"]) + |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) + |> Map.put("inReplyToStatusId", activity.id) + |> Map.put("conversation", replied_object.data["context"] || object["conversation"]) + |> Map.put("context", replied_object.data["context"] || object["conversation"]) + else + e -> + Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}") + object + end e -> Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}") -- cgit v1.2.3 From 1555c66650967c5023b2a4f7a44a683d803091c6 Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Wed, 13 Jun 2018 21:29:55 -0400 Subject: Add unretweet TwAPI endpoint and cleanup AP.unannounce --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 2 +- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- lib/pleroma/web/router.ex | 1 + lib/pleroma/web/twitter_api/twitter_api.ex | 16 ++++++---------- lib/pleroma/web/twitter_api/twitter_api_controller.ex | 7 +++++++ 6 files changed, 17 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4e0be5ba2..70e8dfd92 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -198,7 +198,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do :ok <- maybe_federate(unannounce_activity), {:ok, _activity} <- Repo.delete(announce_activity), {:ok, object} <- remove_announce_from_object(announce_activity, object) do - {:ok, unannounce_activity, announce_activity, object} + {:ok, unannounce_activity, object} else _e -> {:ok, object} end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 3c9377be9..053484f6f 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -303,7 +303,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), {:ok, object} <- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), - {:ok, activity, _, _} <- ActivityPub.unannounce(actor, object, id, false) do + {:ok, activity, _} <- ActivityPub.unannounce(actor, object, id, false) do {:ok, activity} else _e -> :error diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 4252ac2fe..60f67a8c1 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -336,7 +336,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do - with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), + with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 924254895..95627f8fd 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -238,6 +238,7 @@ defmodule Pleroma.Web.Router do post("/statuses/update", TwitterAPI.Controller, :status_update) post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet) + post("/statuses/unretweet/:id", TwitterAPI.Controller, :unretweet) post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post) post("/friendships/create", TwitterAPI.Controller, :follow) diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index ccc6fe8e7..c23b3c2c4 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -12,14 +12,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do end def delete(%User{} = user, id) do - # TwitterAPI does not have an "unretweet" endpoint; instead this is done - # via the "destroy" endpoint. Therefore, we need to handle - # when the status to "delete" is actually an Announce (repeat) object. - with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id) do - case type do - "Announce" -> unrepeat(user, id) - _ -> CommonAPI.delete(id, user) - end + with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id), + {:ok, activity} <- CommonAPI.delete(id, user) do + {:ok, activity} end end @@ -70,8 +65,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do end end - defp unrepeat(%User{} = user, ap_id_or_id) do - with {:ok, _unannounce, activity, _object} <- CommonAPI.unrepeat(ap_id_or_id, user) do + def unrepeat(%User{} = user, ap_id_or_id) do + with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), + %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do {:ok, activity} end end diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index d53dd0c44..56690cd6b 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -240,6 +240,13 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end end + def unretweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)}, + {:ok, activity} <- TwitterAPI.unrepeat(user, id) do + render(conn, ActivityView, "activity.json", %{activity: activity, for: user}) + end + end + def register(conn, params) do with {:ok, user} <- TwitterAPI.register_user(params) do render(conn, UserView, "show.json", %{user: user}) -- cgit v1.2.3 From 4894b88b1b40705e8d5236d4b417ce2791e3b8fd Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 14 Jun 2018 01:45:10 +0000 Subject: oauth: support either name or username parameter with grant_type=password closes #180 --- lib/pleroma/web/oauth/oauth_controller.ex | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 3dd87d0ab..cdfae8b6a 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -81,7 +81,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do # - investigate a way to verify the user wants to grant read/write/follow once scope handling is done def token_exchange( conn, - %{"grant_type" => "password", "name" => name, "password" => password} = params + %{"grant_type" => "password", "username" => name, "password" => password} = params ) do with %App{} = app <- get_app_from_request(conn, params), %User{} = user <- User.get_cached_by_nickname(name), @@ -104,6 +104,18 @@ defmodule Pleroma.Web.OAuth.OAuthController do end end + def token_exchange( + conn, + %{"grant_type" => "password", "name" => name, "password" => password} = params + ) do + params = + params + |> Map.delete("name") + |> Map.put("username", name) + + token_exchange(conn, params) + end + defp fix_padding(token) do token |> Base.url_decode64!(padding: false) -- cgit v1.2.3 From 544246656906714b895e077f940900fb0cd07068 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 14 Jun 2018 02:29:52 +0000 Subject: oauth: fix password-based login when username is email address closes #199 --- lib/pleroma/web/oauth/oauth_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 3dd87d0ab..47962bbf8 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -84,7 +84,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do %{"grant_type" => "password", "name" => name, "password" => password} = params ) do with %App{} = app <- get_app_from_request(conn, params), - %User{} = user <- User.get_cached_by_nickname(name), + %User{} = user <- User.get_by_nickname_or_email(name), true <- Pbkdf2.checkpw(password, user.password_hash), {:ok, auth} <- Authorization.create_authorization(app, user), {:ok, token} <- Token.exchange_token(app, auth) do -- cgit v1.2.3 From 12c7a023decac20ca563c25faa4031c1b3cc56ca Mon Sep 17 00:00:00 2001 From: eal Date: Thu, 14 Jun 2018 16:41:08 +0300 Subject: upload.ex: add MPEG Layer 3 file header. --- lib/pleroma/upload.ex | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index ab4bd16f0..c7f11f380 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -151,6 +151,9 @@ defmodule Pleroma.Upload do <<0x49, 0x44, 0x33, _, _, _, _, _>> -> "audio/mpeg" + <<255, 251, _, 68, 0, 0, 0, 0>> -> + "audio/mpeg" + <<0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00>> -> "audio/ogg" -- cgit v1.2.3 From 0a95b5594b654dbec73a9e50e340f4975aa3e8e5 Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Thu, 14 Jun 2018 12:12:38 -0400 Subject: Add missing file extension if file does not have one --- lib/pleroma/upload.ex | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index ab4bd16f0..e62ab820a 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -86,10 +86,15 @@ defmodule Pleroma.Upload do end defp create_name(uuid, ext, type) do - if type == "application/octet-stream" do - String.downcase(Enum.join([uuid, ext], ".")) - else - String.downcase(Enum.join([uuid, List.last(String.split(type, "/"))], ".")) + case type do + "application/octet-stream" -> + String.downcase(Enum.join([uuid, ext], ".")) + + "audio/mpeg" -> + String.downcase(Enum.join([uuid, "mp3"], ".")) + + _ -> + String.downcase(Enum.join([uuid, List.last(String.split(type, "/"))], ".")) end end @@ -105,7 +110,21 @@ defmodule Pleroma.Upload do if should_dedupe do create_name(uuid, List.last(String.split(file.filename, ".")), type) else - file.filename + unless String.contains?(file.filename, ".") do + case type do + "image/png" -> file.filename <> ".png" + "image/jpeg" -> file.filename <> ".jpg" + "image/gif" -> file.filename <> ".gif" + "video/webm" -> file.filename <> ".webm" + "video/mp4" -> file.filename <> ".mp4" + "audio/mpeg" -> file.filename <> ".mp3" + "audio/ogg" -> file.filename <> ".ogg" + "audio/wav" -> file.filename <> ".wav" + _ -> file.filename + end + else + file.filename + end end end -- cgit v1.2.3 From 00d7d109efd3315cff7e73dfb5b3064bf0dbe25c Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 15 Jun 2018 22:01:17 +0200 Subject: Fix typo --- lib/pleroma/web/router.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 1c1c26c56..13bd393ab 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -41,7 +41,7 @@ defmodule Pleroma.Web.Router do end pipeline :well_known do - plug(:accepts, ["json", "jrd+json", "xml", "xml+xrd"]) + plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"]) end pipeline :config do -- cgit v1.2.3 From 72c2915ecd0b6578d72b3c9796f4adc8cce83d86 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 15 Jun 2018 21:37:29 +0200 Subject: Pleroma.Web.MastodonAPI.StatusView: Fix status.json so it renders threads --- lib/pleroma/web/mastodon_api/views/status_view.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index d1d48cd0a..59898457b 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -125,8 +125,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do uri: object["id"], url: object["external_url"] || object["id"], account: AccountView.render("account.json", %{user: user}), - in_reply_to_id: reply_to && reply_to.id, - in_reply_to_account_id: reply_to_user && reply_to_user.id, + 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"]), created_at: created_at, -- cgit v1.2.3