From e7edfd9fec88af24869c3805a404f2b0a20914de Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 29 May 2019 12:20:18 -0500 Subject: Permit fetching statuses from API with nickname or id --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 2110027c3..bc75ab35a 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -330,7 +330,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do - with %User{} = user <- User.get_cached_by_id(params["id"]) do + with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"]) do activities = ActivityPub.fetch_user_activities(user, reading_user, params) conn -- cgit v1.2.3 From 18234cc44e6bc989e3e3cf15714c54b4fa05b9dd Mon Sep 17 00:00:00 2001 From: Sachin Joshi Date: Tue, 16 Jul 2019 22:37:36 +0545 Subject: add the rich media ttl based on image exp time --- lib/pleroma/web/rich_media/parser.ex | 41 ++++++++++++++++ .../web/rich_media/parsers/ttl/aws_signed_url.ex | 54 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex (limited to 'lib') diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index 0d2523338..ba8dc6f2a 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -24,6 +24,7 @@ defmodule Pleroma.Web.RichMedia.Parser do Cachex.fetch!(:rich_media_cache, url, fn _ -> {:commit, parse_url(url)} end) + |> set_ttl_based_on_image(url) rescue e -> {:error, "Cachex error: #{inspect(e)}"} @@ -31,6 +32,46 @@ defmodule Pleroma.Web.RichMedia.Parser do end end + @doc """ + Set the rich media cache based on the expiration time of image. + + Define a module that has `run` function + + ## Example + + defmodule MyModule do + def run(data, url) do + image_url = Map.get(data, :image) + # do some parsing in the url and get the ttl of the image + # ttl is unix time + ttl = parse_ttl_from_url(image_url) + Cachex.expire_at(:rich_media_cache, url, ttl * 1000) + end + end + + Define the module in the config + + config :pleroma, :rich_media, + ttl_setters: [MyModule] + """ + def set_ttl_based_on_image({:ok, data}, url) do + case Cachex.ttl(:rich_media_cache, url) do + {:ok, nil} -> + modules = Pleroma.Config.get([:rich_media, :ttl_setters]) + + if Enum.count(modules) > 0 do + Enum.each(modules, & &1.run(data, url)) + end + + {:ok, data} + + _ -> + {:ok, data} + end + end + + def set_ttl_based_on_image(data, _url), do: data + defp parse_url(url) do try do {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options) diff --git a/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex b/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex new file mode 100644 index 000000000..d57107939 --- /dev/null +++ b/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex @@ -0,0 +1,54 @@ +defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl do + def run(data, url) do + image = Map.get(data, :image) + + if is_aws_signed_url(image) do + image + |> parse_query_params() + |> format_query_params() + |> get_expiration_timestamp() + |> set_ttl(url) + end + end + + defp is_aws_signed_url(""), do: nil + defp is_aws_signed_url(nil), do: nil + + defp is_aws_signed_url(image) when is_binary(image) do + %URI{host: host, query: query} = URI.parse(image) + + if String.contains?(host, "amazonaws.com") and + String.contains?(query, "X-Amz-Expires") do + image + else + nil + end + end + + defp is_aws_signed_url(_), do: nil + + defp parse_query_params(image) do + %URI{query: query} = URI.parse(image) + query + end + + defp format_query_params(query) do + query + |> String.split(~r/&|=/) + |> Enum.chunk_every(2) + |> Map.new(fn [k, v] -> {k, v} end) + end + + defp get_expiration_timestamp(params) when is_map(params) do + {:ok, date} = + params + |> Map.get("X-Amz-Date") + |> Timex.parse("{ISO:Basic:Z}") + + Timex.to_unix(date) + String.to_integer(Map.get(params, "X-Amz-Expires")) + end + + defp set_ttl(ttl, url) do + Cachex.expire_at(:rich_media_cache, url, ttl * 1000) + end +end -- cgit v1.2.3 From 88d064d80e4a3272a2a7101089b5f924fd175866 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 18 Jul 2019 15:06:58 +0000 Subject: http signature plug: remove redundant checks handled by HTTPSignatures library the redundant checks assumed a POST request, which will not work for signed GETs. this check was originally needed because the HTTPSignatures adapter assumed that the requests were also POST requests. but now, the adapter has been corrected. --- lib/pleroma/plugs/http_signature.ex | 49 +++++++++++++++---------------------- 1 file changed, 20 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/http_signature.ex b/lib/pleroma/plugs/http_signature.ex index e2874c469..d87fa52fa 100644 --- a/lib/pleroma/plugs/http_signature.ex +++ b/lib/pleroma/plugs/http_signature.ex @@ -3,7 +3,6 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do - alias Pleroma.Web.ActivityPub.Utils import Plug.Conn require Logger @@ -16,38 +15,30 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do end def call(conn, _opts) do - user = Utils.get_ap_id(conn.params["actor"]) - Logger.debug("Checking sig for #{user}") [signature | _] = get_req_header(conn, "signature") - 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( - "(request-target)", - 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)) + if signature do + # set (request-target) header to the appropriate value + # we also replace the digest header with the one we computed + conn = + conn + |> put_req_header( + "(request-target)", + String.downcase("#{conn.method}") <> " #{conn.request_path}" + ) - signature -> - Logger.debug("Signature not from actor") - assign(conn, :valid_signature, false) + conn = + if conn.assigns[:digest] do + conn + |> put_req_header("digest", conn.assigns[:digest]) + else + conn + end - true -> - Logger.debug("No signature header!") - conn + assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn)) + else + Logger.debug("No signature header!") + conn end end end -- cgit v1.2.3 From 18d8d12d53567b7c0c246bb793ee724d0d2e4c77 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 18 Jul 2019 15:35:42 +0000 Subject: signature: make key_id_to_actor_id() public --- lib/pleroma/signature.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex index a45c70a9d..2a0823ecf 100644 --- a/lib/pleroma/signature.ex +++ b/lib/pleroma/signature.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Signature do alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub - defp key_id_to_actor_id(key_id) do + def key_id_to_actor_id(key_id) do URI.parse(key_id) |> Map.put(:fragment, nil) |> URI.to_string() -- cgit v1.2.3 From 184fa61fb3a1bc8c5d5515bb7748c12816b11ebf Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 18 Jul 2019 15:38:45 +0000 Subject: plugs: add MappedSignatureToIdentityPlug --- .../plugs/mapped_signature_to_identity_plug.ex | 64 ++++++++++++++++++++++ lib/pleroma/web/router.ex | 1 + 2 files changed, 65 insertions(+) create mode 100644 lib/pleroma/plugs/mapped_signature_to_identity_plug.ex (limited to 'lib') diff --git a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex new file mode 100644 index 000000000..ae9339595 --- /dev/null +++ b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex @@ -0,0 +1,64 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do + alias Pleroma.Signature + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Utils + + import Plug.Conn + require Logger + + def init(options), do: options + + defp key_id_from_conn(conn) do + with %{"keyId" => key_id} <- HTTPSignatures.signature_for_conn(conn) do + Signature.key_id_to_actor_id(key_id) + else + _ -> + nil + end + end + + defp user_from_key_id(conn) do + with key_actor_id when is_binary(key_actor_id) <- key_id_from_conn(conn), + %User{} = user <- User.get_or_fetch_by_ap_id(key_actor_id) do + user + else + _ -> + nil + end + end + + def call(%{assigns: %{mapped_identity: _}} = conn, _opts), do: conn + + # if this has payload make sure it is signed by the same actor that made it + def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = conn, _opts) do + with actor_id <- Utils.get_ap_id(actor), + %User{} = user <- user_from_key_id(conn), + true <- user.ap_id == actor_id do + assign(conn, :mapped_identity, user) + else + _ -> + Logger.debug("Failed to map identity from signature (payload actor mismatch?)") + Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}") + conn + end + end + + # no payload, probably a signed fetch + def call(%{assigns: %{valid_signature: true}} = conn, _opts) do + with %User{} = user <- user_from_key_id(conn) do + assign(conn, :mapped_identity, user) + else + _ -> + Logger.debug("Failed to map identity from signature (no payload actor mismatch)") + Logger.debug("key_id=#{key_id_from_conn(conn)}") + conn + end + end + + # no signature at all + def call(conn, _opts), do: conn +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 8095ac4b1..518720d38 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -617,6 +617,7 @@ defmodule Pleroma.Web.Router do pipeline :activitypub do plug(:accepts, ["activity+json", "json"]) plug(Pleroma.Web.Plugs.HTTPSignaturePlug) + plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug) end scope "/", Pleroma.Web.ActivityPub do -- cgit v1.2.3 From 5ea0cd69f7457086fc486f13e072f13d2c1ef547 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 18 Jul 2019 16:01:21 +0000 Subject: mapped signature plug: don't invalidate in cases where a signature is actually not present (testsuite) --- lib/pleroma/plugs/mapped_signature_to_identity_plug.ex | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex index ae9339595..2a8ed4470 100644 --- a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex +++ b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex @@ -36,12 +36,18 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do # if this has payload make sure it is signed by the same actor that made it def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = conn, _opts) do with actor_id <- Utils.get_ap_id(actor), - %User{} = user <- user_from_key_id(conn), - true <- user.ap_id == actor_id do + {:user, %User{} = user} <- {:user, user_from_key_id(conn)}, + {:user_match, true} <- {:user_match, user.ap_id == actor_id} do assign(conn, :mapped_identity, user) else - _ -> - Logger.debug("Failed to map identity from signature (payload actor mismatch?)") + {:user_match, false} -> + Logger.debug("Failed to map identity from signature (payload actor mismatch)") + Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}") + assign(conn, :valid_signature, false) + + # remove me once testsuite uses mapped capabilities instead of what we do now + {:user, nil} -> + Logger.debug("Failed to map identity from signature (lookup failure)") Logger.debug("key_id=#{key_id_from_conn(conn)}, actor=#{actor}") conn end @@ -55,7 +61,7 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do _ -> Logger.debug("Failed to map identity from signature (no payload actor mismatch)") Logger.debug("key_id=#{key_id_from_conn(conn)}") - conn + assign(conn, :valid_signature, false) end end -- cgit v1.2.3 From a8af0ac053713102204418fe7a28d322f81eb3ea Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 18 Jul 2019 16:27:50 +0000 Subject: mapped signature plug: fix user lookup --- lib/pleroma/plugs/mapped_signature_to_identity_plug.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex index 2a8ed4470..1e7da4f50 100644 --- a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex +++ b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex @@ -23,7 +23,7 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do defp user_from_key_id(conn) do with key_actor_id when is_binary(key_actor_id) <- key_id_from_conn(conn), - %User{} = user <- User.get_or_fetch_by_ap_id(key_actor_id) do + {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(key_actor_id) do user else _ -> -- cgit v1.2.3 From c947cfec5ab49f90fb2de83f61bda77568298d6f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 18 Jul 2019 20:31:25 +0000 Subject: mapped signature plug: use `user` assign like authentication plug --- lib/pleroma/plugs/mapped_signature_to_identity_plug.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex index 1e7da4f50..ce8494b9d 100644 --- a/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex +++ b/lib/pleroma/plugs/mapped_signature_to_identity_plug.ex @@ -31,14 +31,14 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do end end - def call(%{assigns: %{mapped_identity: _}} = conn, _opts), do: conn + def call(%{assigns: %{user: _}} = conn, _opts), do: conn # if this has payload make sure it is signed by the same actor that made it def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = conn, _opts) do with actor_id <- Utils.get_ap_id(actor), {:user, %User{} = user} <- {:user, user_from_key_id(conn)}, {:user_match, true} <- {:user_match, user.ap_id == actor_id} do - assign(conn, :mapped_identity, user) + assign(conn, :user, user) else {:user_match, false} -> Logger.debug("Failed to map identity from signature (payload actor mismatch)") @@ -56,7 +56,7 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do # no payload, probably a signed fetch def call(%{assigns: %{valid_signature: true}} = conn, _opts) do with %User{} = user <- user_from_key_id(conn) do - assign(conn, :mapped_identity, user) + assign(conn, :user, user) else _ -> Logger.debug("Failed to map identity from signature (no payload actor mismatch)") -- cgit v1.2.3 From de9906ad56bd25d6c8c38bef1307192df2e95445 Mon Sep 17 00:00:00 2001 From: Sachin Joshi Date: Fri, 19 Jul 2019 11:43:42 +0545 Subject: change the structure of image ttl parsar --- lib/pleroma/web/rich_media/parser.ex | 36 ++++++++++++---------- .../web/rich_media/parsers/ttl/aws_signed_url.ex | 10 +++--- lib/pleroma/web/rich_media/parsers/ttl/ttl.ex | 3 ++ 3 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 lib/pleroma/web/rich_media/parsers/ttl/ttl.ex (limited to 'lib') diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index ba8dc6f2a..b69b2be61 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -35,17 +35,17 @@ defmodule Pleroma.Web.RichMedia.Parser do @doc """ Set the rich media cache based on the expiration time of image. - Define a module that has `run` function + Adopt behaviour `Pleroma.Web.RichMedia.Parser.TTL` ## Example defmodule MyModule do - def run(data, url) do + @behaviour Pleroma.Web.RichMedia.Parser.TTL + def ttl(data, url) do image_url = Map.get(data, :image) # do some parsing in the url and get the ttl of the image - # ttl is unix time - ttl = parse_ttl_from_url(image_url) - Cachex.expire_at(:rich_media_cache, url, ttl * 1000) + # and return ttl is unix time + parse_ttl_from_url(image_url) end end @@ -55,22 +55,26 @@ defmodule Pleroma.Web.RichMedia.Parser do ttl_setters: [MyModule] """ def set_ttl_based_on_image({:ok, data}, url) do - case Cachex.ttl(:rich_media_cache, url) do - {:ok, nil} -> - modules = Pleroma.Config.get([:rich_media, :ttl_setters]) - - if Enum.count(modules) > 0 do - Enum.each(modules, & &1.run(data, url)) - end - - {:ok, data} - + with {:ok, nil} <- Cachex.ttl(:rich_media_cache, url) do + ttl = get_ttl_from_image(data, url) + Cachex.expire_at(:rich_media_cache, url, ttl * 1000) + {:ok, data} + else _ -> {:ok, data} end end - def set_ttl_based_on_image(data, _url), do: data + defp get_ttl_from_image(data, url) do + Pleroma.Config.get([:rich_media, :ttl_setters]) + |> Enum.reduce({:ok, nil}, fn + module, {:ok, _ttl} -> + module.ttl(data, url) + + _, error -> + error + end) + end defp parse_url(url) do try do diff --git a/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex b/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex index d57107939..014c0935f 100644 --- a/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex +++ b/lib/pleroma/web/rich_media/parsers/ttl/aws_signed_url.ex @@ -1,5 +1,8 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl do - def run(data, url) do + @behaviour Pleroma.Web.RichMedia.Parser.TTL + + @impl Pleroma.Web.RichMedia.Parser.TTL + def ttl(data, _url) do image = Map.get(data, :image) if is_aws_signed_url(image) do @@ -7,7 +10,6 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl do |> parse_query_params() |> format_query_params() |> get_expiration_timestamp() - |> set_ttl(url) end end @@ -47,8 +49,4 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl do Timex.to_unix(date) + String.to_integer(Map.get(params, "X-Amz-Expires")) end - - defp set_ttl(ttl, url) do - Cachex.expire_at(:rich_media_cache, url, ttl * 1000) - end end diff --git a/lib/pleroma/web/rich_media/parsers/ttl/ttl.ex b/lib/pleroma/web/rich_media/parsers/ttl/ttl.ex new file mode 100644 index 000000000..6b3ec6d30 --- /dev/null +++ b/lib/pleroma/web/rich_media/parsers/ttl/ttl.ex @@ -0,0 +1,3 @@ +defmodule Pleroma.Web.RichMedia.Parser.TTL do + @callback ttl(Map.t(), String.t()) :: {:ok, Integer.t()} | {:error, String.t()} +end -- cgit v1.2.3 From c2e2aadc4254fe931ea519a9813854ccdac456b8 Mon Sep 17 00:00:00 2001 From: Maksim Date: Fri, 19 Jul 2019 16:20:23 +0000 Subject: #1110 fixed /api/pleroma/healthcheck --- .../web/twitter_api/controllers/util_controller.ex | 32 ++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index c10c66ff2..9e4da7dca 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -8,7 +8,9 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do require Logger alias Pleroma.Activity + alias Pleroma.Config alias Pleroma.Emoji + alias Pleroma.Healthcheck alias Pleroma.Notification alias Pleroma.Plugs.AuthenticationPlug alias Pleroma.User @@ -23,7 +25,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def remote_subscribe(conn, %{"nickname" => nick, "profile" => _}) do - with %User{} = user <- User.get_cached_by_nickname(nick), avatar = User.avatar_url(user) do + with %User{} = user <- User.get_cached_by_nickname(nick), + avatar = User.avatar_url(user) do conn |> render("subscribe.html", %{nickname: nick, avatar: avatar, error: false}) else @@ -338,20 +341,21 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def healthcheck(conn, _params) do - info = - if Pleroma.Config.get([:instance, :healthcheck]) do - Pleroma.Healthcheck.system_info() - else - %{} - end + with true <- Config.get([:instance, :healthcheck]), + %{healthy: true} = info <- Healthcheck.system_info() do + json(conn, info) + else + %{healthy: false} = info -> + service_unavailable(conn, info) - conn = - if info[:healthy] do - conn - else - Plug.Conn.put_status(conn, :service_unavailable) - end + _ -> + service_unavailable(conn, %{}) + end + end - json(conn, info) + defp service_unavailable(conn, info) do + conn + |> put_status(:service_unavailable) + |> json(info) end end -- cgit v1.2.3 From 9a8eb2c94d2243fadd69786eb74d94cc6116468f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 19 Jul 2019 19:11:04 +0000 Subject: mix: add pleroma.user unsubscribe_all_from_instance --- lib/mix/tasks/pleroma/user.ex | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 8a78b4fe6..c9b84b8f9 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -62,6 +62,10 @@ defmodule Mix.Tasks.Pleroma.User do mix pleroma.user unsubscribe NICKNAME + ## Unsubscribe local users from an entire instance and deactivate all accounts + + mix pleroma.user unsubscribe_all_from_instance INSTANCE + ## Create a password reset link. mix pleroma.user reset_password NICKNAME @@ -246,6 +250,20 @@ defmodule Mix.Tasks.Pleroma.User do end end + def run(["unsubscribe_all_from_instance", instance]) do + start_pleroma() + + Pleroma.User.Query.build(%{nickname: "@#{instance}"}) + |> Pleroma.RepoStreamer.chunk_stream(500) + |> Stream.each(fn users -> + users + |> Enum.each(fn user -> + run(["unsubscribe", user.nickname]) + end) + end) + |> Stream.run() + end + def run(["set", nickname | rest]) do start_pleroma() -- cgit v1.2.3 From d0198fe215a7542ce506e40e1e4860a27ee2d01e Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sat, 20 Jul 2019 13:03:34 +0300 Subject: [#1112] Preserving `id` on user insert conflict on order not to violate conversation_partipations_user_id_fkey constraint. --- lib/pleroma/user.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index c91fbb68a..5ea2b518b 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1211,7 +1211,7 @@ defmodule Pleroma.User do data |> Map.put(:name, blank?(data[:name]) || data[:nickname]) |> remote_user_creation() - |> Repo.insert(on_conflict: :replace_all, conflict_target: :nickname) + |> Repo.insert(on_conflict: :replace_all_except_primary_key, conflict_target: :nickname) |> set_cache() end -- cgit v1.2.3 From bc6c5c513ae69e7a868c63f878a009dce8dd8c63 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 21 Jul 2019 03:52:06 +0000 Subject: router: ensure the AP sharedinbox path is registered first --- lib/pleroma/web/router.ex | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 518720d38..a33b5ddd7 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -663,6 +663,12 @@ defmodule Pleroma.Web.Router do end end + scope "/", Pleroma.Web.ActivityPub do + pipe_through(:activitypub) + post("/inbox", ActivityPubController, :inbox) + post("/users/:nickname/inbox", ActivityPubController, :inbox) + end + scope "/relay", Pleroma.Web.ActivityPub do pipe_through(:ap_service_actor) @@ -677,12 +683,6 @@ defmodule Pleroma.Web.Router do post("/inbox", ActivityPubController, :inbox) end - scope "/", Pleroma.Web.ActivityPub do - pipe_through(:activitypub) - post("/inbox", ActivityPubController, :inbox) - post("/users/:nickname/inbox", ActivityPubController, :inbox) - end - scope "/.well-known", Pleroma.Web do pipe_through(:well_known) -- cgit v1.2.3 From 33681747857eec90ff56ea0342d2ea179c4f856e Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sun, 21 Jul 2019 18:22:22 +0300 Subject: Fix rich media parser failing when no TTL can be found by image TTL setters --- lib/pleroma/web/rich_media/parser.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index b69b2be61..185156375 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -55,8 +55,8 @@ defmodule Pleroma.Web.RichMedia.Parser do ttl_setters: [MyModule] """ def set_ttl_based_on_image({:ok, data}, url) do - with {:ok, nil} <- Cachex.ttl(:rich_media_cache, url) do - ttl = get_ttl_from_image(data, url) + with {:ok, nil} <- Cachex.ttl(:rich_media_cache, url), + ttl when is_number(ttl) <- get_ttl_from_image(data, url) do Cachex.expire_at(:rich_media_cache, url, ttl * 1000) {:ok, data} else -- cgit v1.2.3 From 56019d53a8fa0a37de4c342c74cc8c70bf1786e9 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 22 Jul 2019 02:18:45 +0000 Subject: activitypub: publisher: align sharedinbox usage with AP specification rules While debugging the follow breakage, I observed that our sharedInbox usage did not match the rules in the specification. Accordingly, I have better aligned our usage of sharedInbox with the rules outlined in the ActivityPub specification. --- lib/pleroma/web/activity_pub/publisher.ex | 43 +++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index c505223f7..f8a4a4420 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -112,6 +112,45 @@ defmodule Pleroma.Web.ActivityPub.Publisher do |> Enum.map(& &1.ap_id) end + @as_public "https://www.w3.org/ns/activitystreams#Public" + + defp maybe_use_sharedinbox(%User{info: %{source_data: data}}), + do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] + + @doc """ + Determine a user inbox to use based on heuristics. These heuristics + are based on an approximation of the ``sharedInbox`` rules in the + [ActivityPub specification][ap-sharedinbox]. + + Please do not edit this function (or its children) without reading + the spec, as editing the code is likely to introduce some breakage + without some familiarity. + + [ap-sharedinbox]: https://www.w3.org/TR/activitypub/#shared-inbox-delivery + """ + def determine_inbox( + %Activity{data: activity_data}, + %User{info: %{source_data: data}} = user + ) do + to = activity_data["to"] || [] + cc = activity_data["cc"] || [] + type = activity_data["type"] + + cond do + type == "Delete" -> + maybe_use_sharedinbox(user) + + @as_public in to || @as_public in cc -> + maybe_use_sharedinbox(user) + + length(to) + length(cc) > 1 -> + maybe_use_sharedinbox(user) + + true -> + data["inbox"] + end + end + @doc """ Publishes an activity with BCC to all relevant peers. """ @@ -166,8 +205,8 @@ defmodule Pleroma.Web.ActivityPub.Publisher do recipients(actor, activity) |> Enum.filter(fn user -> User.ap_enabled?(user) end) - |> Enum.map(fn %{info: %{source_data: data}} -> - (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] + |> Enum.map(fn %User{} = user -> + determine_inbox(activity, user) end) |> Enum.uniq() |> Enum.filter(fn inbox -> should_federate?(inbox, public) end) -- cgit v1.2.3 From a5d6287ba861b9b30edb2ac52584369b9c4665bc Mon Sep 17 00:00:00 2001 From: Sadposter Date: Mon, 22 Jul 2019 02:42:29 +0000 Subject: Hide blocked users from interactions --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (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 e8b43e475..d660f3f05 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -883,7 +883,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %Activity{data: %{"object" => object}} <- Activity.get_by_id(id), %Object{data: %{"likes" => likes}} <- Object.normalize(object) do q = from(u in User, where: u.ap_id in ^likes) - users = Repo.all(q) + + users = + Repo.all(q) + |> Enum.filter(&(not User.blocks?(user, &1))) conn |> put_view(AccountView) @@ -897,7 +900,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %Activity{data: %{"object" => object}} <- Activity.get_by_id(id), %Object{data: %{"announcements" => announces}} <- Object.normalize(object) do q = from(u in User, where: u.ap_id in ^announces) - users = Repo.all(q) + + users = + Repo.all(q) + |> Enum.filter(&(not User.blocks?(user, &1))) conn |> put_view(AccountView) -- cgit v1.2.3 From 05b5af8075621bfefb207ee84b54608f652fe757 Mon Sep 17 00:00:00 2001 From: Sergey Suprunenko Date: Mon, 22 Jul 2019 02:43:15 +0000 Subject: Add tests for users tasks and PleromaAuthenticator --- lib/pleroma/user_invite_token.ex | 2 +- lib/pleroma/web/admin_api/admin_api_controller.ex | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user_invite_token.ex b/lib/pleroma/user_invite_token.ex index fadc89891..b9e80acdd 100644 --- a/lib/pleroma/user_invite_token.ex +++ b/lib/pleroma/user_invite_token.ex @@ -74,7 +74,7 @@ defmodule Pleroma.UserInviteToken do @spec find_by_token(token()) :: {:ok, UserInviteToken.t()} | nil def find_by_token(token) do - with invite <- Repo.get_by(UserInviteToken, token: token) do + with %UserInviteToken{} = invite <- Repo.get_by(UserInviteToken, token: token) do {:ok, invite} end end diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 4a0bf4823..811be1eff 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -272,11 +272,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do @doc "Revokes invite by token" def revoke_invite(conn, %{"token" => token}) do - invite = UserInviteToken.find_by_token!(token) - {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) - - conn - |> json(AccountView.render("invite.json", %{invite: updated_invite})) + with {:ok, invite} <- UserInviteToken.find_by_token(token), + {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do + conn + |> json(AccountView.render("invite.json", %{invite: updated_invite})) + else + nil -> {:error, :not_found} + end end @doc "Get a password reset token (base64 string) for given nickname" -- cgit v1.2.3 From f712ee879ab771b5cb9591ae402f52e26a8bebf3 Mon Sep 17 00:00:00 2001 From: Sadposter Date: Mon, 22 Jul 2019 02:43:55 +0000 Subject: Bugfix: muted/blocked user notification streaming --- lib/pleroma/web/streamer.ex | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 4f325113a..86e2dc4dd 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.Streamer do alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Visibility + alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.NotificationView @keepalive_interval :timer.seconds(30) @@ -118,10 +119,14 @@ defmodule Pleroma.Web.Streamer do topics |> Map.get("#{topic}:#{item.user_id}", []) |> Enum.each(fn socket -> - send( - socket.transport_pid, - {:text, represent_notification(socket.assigns[:user], item)} - ) + with %User{} = user <- User.get_cached_by_ap_id(socket.assigns[:user].ap_id), + true <- should_send?(user, item), + false <- CommonAPI.thread_muted?(user, item.activity) do + send( + socket.transport_pid, + {:text, represent_notification(socket.assigns[:user], item)} + ) + end end) {:noreply, topics} @@ -225,19 +230,32 @@ defmodule Pleroma.Web.Streamer do |> Jason.encode!() end + defp should_send?(%User{} = user, %Activity{} = item) do + blocks = user.info.blocks || [] + mutes = user.info.mutes || [] + reblog_mutes = user.info.muted_reblogs || [] + + with parent when not is_nil(parent) <- Object.normalize(item), + true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), + true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), + true <- thread_containment(item, user) do + true + else + _ -> false + end + end + + defp should_send?(%User{} = user, %Notification{activity: activity}) do + should_send?(user, activity) + 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. if socket.assigns[:user] do user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id) - blocks = user.info.blocks || [] - mutes = user.info.mutes || [] - reblog_mutes = user.info.muted_reblogs || [] - with parent when not is_nil(parent) <- Object.normalize(item), - true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), - true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), - true <- thread_containment(item, user) do + if should_send?(user, item) do send(socket.transport_pid, {:text, represent_update(item, user)}) end else -- cgit v1.2.3 From b70e659304ba35f7afc598c3d3d1b96fa16f6cdf Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Mon, 22 Jul 2019 14:33:58 +0000 Subject: Feature/1087 wildcard option for blocks --- lib/pleroma/user.ex | 7 ++- lib/pleroma/web/activity_pub/mrf.ex | 10 +++++ lib/pleroma/web/activity_pub/mrf/simple_policy.ex | 55 +++++++++++++++++------ lib/pleroma/web/activity_pub/publisher.ex | 9 +++- 4 files changed, 63 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 5ea2b518b..a3f6add28 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -873,10 +873,13 @@ defmodule Pleroma.User do def blocks?(%User{info: info} = _user, %{ap_id: ap_id}) do blocks = info.blocks - domain_blocks = info.domain_blocks + + domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(info.domain_blocks) + %{host: host} = URI.parse(ap_id) - Enum.member?(blocks, ap_id) || Enum.any?(domain_blocks, &(&1 == host)) + Enum.member?(blocks, ap_id) || + Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host) end def subscribed_to?(user, %{ap_id: ap_id}) do diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex index 10ceef715..dd204b21c 100644 --- a/lib/pleroma/web/activity_pub/mrf.ex +++ b/lib/pleroma/web/activity_pub/mrf.ex @@ -25,4 +25,14 @@ defmodule Pleroma.Web.ActivityPub.MRF do defp get_policies(policy) when is_atom(policy), do: [policy] defp get_policies(policies) when is_list(policies), do: policies defp get_policies(_), do: [] + + @spec subdomains_regex([String.t()]) :: [Regex.t()] + def subdomains_regex(domains) when is_list(domains) do + for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$) + end + + @spec subdomain_match?([Regex.t()], String.t()) :: boolean() + def subdomain_match?(domains, host) do + Enum.any?(domains, fn domain -> Regex.match?(domain, host) end) + end end diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex index 433d23c5f..2cf63d3db 100644 --- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex @@ -4,22 +4,29 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do alias Pleroma.User + alias Pleroma.Web.ActivityPub.MRF @moduledoc "Filter activities depending on their origin instance" - @behaviour Pleroma.Web.ActivityPub.MRF + @behaviour MRF defp check_accept(%{host: actor_host} = _actor_info, object) do - accepts = Pleroma.Config.get([:mrf_simple, :accept]) + accepts = + Pleroma.Config.get([:mrf_simple, :accept]) + |> MRF.subdomains_regex() cond do accepts == [] -> {:ok, object} actor_host == Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object} - Enum.member?(accepts, actor_host) -> {:ok, object} + MRF.subdomain_match?(accepts, actor_host) -> {:ok, object} true -> {:reject, nil} end end defp check_reject(%{host: actor_host} = _actor_info, object) do - if Enum.member?(Pleroma.Config.get([:mrf_simple, :reject]), actor_host) do + rejects = + Pleroma.Config.get([:mrf_simple, :reject]) + |> MRF.subdomains_regex() + + if MRF.subdomain_match?(rejects, actor_host) do {:reject, nil} else {:ok, object} @@ -31,8 +38,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do %{"type" => "Create", "object" => %{"attachment" => child_attachment}} = object ) when length(child_attachment) > 0 do + media_removal = + Pleroma.Config.get([:mrf_simple, :media_removal]) + |> MRF.subdomains_regex() + object = - if Enum.member?(Pleroma.Config.get([:mrf_simple, :media_removal]), actor_host) do + if MRF.subdomain_match?(media_removal, actor_host) do child_object = Map.delete(object["object"], "attachment") Map.put(object, "object", child_object) else @@ -51,8 +62,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do "object" => child_object } = object ) do + media_nsfw = + Pleroma.Config.get([:mrf_simple, :media_nsfw]) + |> MRF.subdomains_regex() + object = - if Enum.member?(Pleroma.Config.get([:mrf_simple, :media_nsfw]), actor_host) do + if MRF.subdomain_match?(media_nsfw, actor_host) do tags = (child_object["tag"] || []) ++ ["nsfw"] child_object = Map.put(child_object, "tag", tags) child_object = Map.put(child_object, "sensitive", true) @@ -67,12 +82,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do defp check_media_nsfw(_actor_info, object), do: {:ok, object} defp check_ftl_removal(%{host: actor_host} = _actor_info, object) do + timeline_removal = + Pleroma.Config.get([:mrf_simple, :federated_timeline_removal]) + |> MRF.subdomains_regex() + object = - with true <- - Enum.member?( - Pleroma.Config.get([:mrf_simple, :federated_timeline_removal]), - actor_host - ), + with true <- MRF.subdomain_match?(timeline_removal, actor_host), user <- User.get_cached_by_ap_id(object["actor"]), true <- "https://www.w3.org/ns/activitystreams#Public" in object["to"] do to = @@ -94,7 +109,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do end defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = object) do - if actor_host in Pleroma.Config.get([:mrf_simple, :report_removal]) do + report_removal = + Pleroma.Config.get([:mrf_simple, :report_removal]) + |> MRF.subdomains_regex() + + if MRF.subdomain_match?(report_removal, actor_host) do {:reject, nil} else {:ok, object} @@ -104,7 +123,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do defp check_report_removal(_actor_info, object), do: {:ok, object} defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do - if actor_host in Pleroma.Config.get([:mrf_simple, :avatar_removal]) do + avatar_removal = + Pleroma.Config.get([:mrf_simple, :avatar_removal]) + |> MRF.subdomains_regex() + + if MRF.subdomain_match?(avatar_removal, actor_host) do {:ok, Map.delete(object, "icon")} else {:ok, object} @@ -114,7 +137,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do defp check_avatar_removal(_actor_info, object), do: {:ok, object} defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do - if actor_host in Pleroma.Config.get([:mrf_simple, :banner_removal]) do + banner_removal = + Pleroma.Config.get([:mrf_simple, :banner_removal]) + |> MRF.subdomains_regex() + + if MRF.subdomain_match?(banner_removal, actor_host) do {:ok, Map.delete(object, "image")} else {:ok, object} diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index f8a4a4420..0bbe6ee80 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -87,8 +87,13 @@ defmodule Pleroma.Web.ActivityPub.Publisher do if public do true else - inbox_info = URI.parse(inbox) - !Enum.member?(Config.get([:instance, :quarantined_instances], []), inbox_info.host) + %{host: host} = URI.parse(inbox) + + quarantined_instances = + Config.get([:instance, :quarantined_instances], []) + |> Pleroma.Web.ActivityPub.MRF.subdomains_regex() + + !Pleroma.Web.ActivityPub.MRF.subdomain_match?(quarantined_instances, host) end end -- cgit v1.2.3 From eacf61d823f8bc4398dee883aa86171ec4757fe9 Mon Sep 17 00:00:00 2001 From: Sadposter Date: Tue, 23 Jul 2019 15:02:18 +0100 Subject: fix unauthenticated req to favourited/rebloggd_by --- .../web/mastodon_api/mastodon_api_controller.ex | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (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 d660f3f05..ccebcd415 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -884,9 +884,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do %Object{data: %{"likes" => likes}} <- Object.normalize(object) do q = from(u in User, where: u.ap_id in ^likes) - users = - Repo.all(q) - |> Enum.filter(&(not User.blocks?(user, &1))) + users = Repo.all(q) + users = if is_nil(user) do + users + else + Enum.filter(users, &(not User.blocks?(user, &1))) + end conn |> put_view(AccountView) @@ -901,9 +904,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do %Object{data: %{"announcements" => announces}} <- Object.normalize(object) do q = from(u in User, where: u.ap_id in ^announces) - users = - Repo.all(q) - |> Enum.filter(&(not User.blocks?(user, &1))) + users = Repo.all(q) + users = if is_nil(user) do + users + else + Enum.filter(users, &(not User.blocks?(user, &1))) + end conn |> put_view(AccountView) -- cgit v1.2.3 From 452980652dc749d71e96b1cbb17d68d393121a78 Mon Sep 17 00:00:00 2001 From: Sadposter Date: Tue, 23 Jul 2019 15:13:05 +0100 Subject: Mix format --- .../web/mastodon_api/mastodon_api_controller.ex | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (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 ccebcd415..9269a5a29 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -885,11 +885,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do q = from(u in User, where: u.ap_id in ^likes) users = Repo.all(q) - users = if is_nil(user) do - users - else - Enum.filter(users, &(not User.blocks?(user, &1))) - end + + users = + if is_nil(user) do + users + else + Enum.filter(users, &(not User.blocks?(user, &1))) + end conn |> put_view(AccountView) @@ -905,11 +907,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do q = from(u in User, where: u.ap_id in ^announces) users = Repo.all(q) - users = if is_nil(user) do - users - else - Enum.filter(users, &(not User.blocks?(user, &1))) - end + + users = + if is_nil(user) do + users + else + Enum.filter(users, &(not User.blocks?(user, &1))) + end conn |> put_view(AccountView) -- cgit v1.2.3 From e7c64f106eb578f802d000ecd8dacbc00a357b66 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 23 Jul 2019 16:47:22 +0000 Subject: signature: properly deduce the actor from misskey key IDs --- lib/pleroma/signature.ex | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex index 2a0823ecf..0bf49fd7c 100644 --- a/lib/pleroma/signature.ex +++ b/lib/pleroma/signature.ex @@ -10,9 +10,18 @@ defmodule Pleroma.Signature do alias Pleroma.Web.ActivityPub.ActivityPub def key_id_to_actor_id(key_id) do - URI.parse(key_id) - |> Map.put(:fragment, nil) - |> URI.to_string() + uri = + URI.parse(key_id) + |> Map.put(:fragment, nil) + + uri = + if String.ends_with?(uri.path, "/publickey") do + Map.put(uri, :path, String.replace(uri.path, "/publickey", "")) + else + uri + end + + URI.to_string(uri) end def fetch_public_key(conn) do -- cgit v1.2.3 From fd287387a042b86a62d80c41b1dd282316b6609b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 23 Jul 2019 13:14:26 -0500 Subject: Do not notify subscribers for messages from users which are replies to others --- lib/pleroma/web/common_api/utils.ex | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index fcc000969..6f0f56d96 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -439,6 +439,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do def maybe_notify_mentioned_recipients(recipients, _), do: recipients + def maybe_notify_subscribers(_, %Activity{ + data: %{"object" => %Object{data: %{"inReplyTo" => _ap_id}}} + }) do + :nothing + end + def maybe_notify_subscribers( recipients, %Activity{data: %{"actor" => actor, "type" => type}} = activity -- cgit v1.2.3 From 54a161cb7ad58da05ced24daaf0c16964f76fa4c Mon Sep 17 00:00:00 2001 From: Sadposter Date: Tue, 23 Jul 2019 19:44:47 +0100 Subject: move unauth'd user blocks?/2 check --- lib/pleroma/user.ex | 2 ++ .../web/mastodon_api/mastodon_api_controller.ex | 18 ++++-------------- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index a3f6add28..e017efad6 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -882,6 +882,8 @@ defmodule Pleroma.User do Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host) end + def blocks?(nil, _), do: false + def subscribed_to?(user, %{ap_id: ap_id}) do with %User{} = target <- get_cached_by_ap_id(ap_id) do Enum.member?(target.info.subscribers, user.ap_id) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 9269a5a29..d660f3f05 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -884,14 +884,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do %Object{data: %{"likes" => likes}} <- Object.normalize(object) do q = from(u in User, where: u.ap_id in ^likes) - users = Repo.all(q) - users = - if is_nil(user) do - users - else - Enum.filter(users, &(not User.blocks?(user, &1))) - end + Repo.all(q) + |> Enum.filter(&(not User.blocks?(user, &1))) conn |> put_view(AccountView) @@ -906,14 +901,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do %Object{data: %{"announcements" => announces}} <- Object.normalize(object) do q = from(u in User, where: u.ap_id in ^announces) - users = Repo.all(q) - users = - if is_nil(user) do - users - else - Enum.filter(users, &(not User.blocks?(user, &1))) - end + Repo.all(q) + |> Enum.filter(&(not User.blocks?(user, &1))) conn |> put_view(AccountView) -- cgit v1.2.3 From 6a79bb12c38bce6287b29c79c1ad3b7f9b967b69 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 23 Jul 2019 13:53:05 -0500 Subject: Fix function --- lib/pleroma/web/common_api/utils.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 6f0f56d96..94462c3dd 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -439,10 +439,11 @@ defmodule Pleroma.Web.CommonAPI.Utils do def maybe_notify_mentioned_recipients(recipients, _), do: recipients - def maybe_notify_subscribers(_, %Activity{ - data: %{"object" => %Object{data: %{"inReplyTo" => _ap_id}}} + # Do not notify subscribers if author is making a reply + def maybe_notify_subscribers(recipients, %Activity{ + object: %Object{data: %{"inReplyTo" => _ap_id}} }) do - :nothing + recipients end def maybe_notify_subscribers( -- cgit v1.2.3 From c49a09ed88c3cef0f3df3e97cf4fa5367cd8f830 Mon Sep 17 00:00:00 2001 From: Maksim Date: Tue, 23 Jul 2019 19:15:48 +0000 Subject: tests for Pleroma.Web.ActivityPub.Publisher --- lib/pleroma/user.ex | 11 +++++++++++ lib/pleroma/web/activity_pub/publisher.ex | 8 ++++---- lib/pleroma/web/activity_pub/visibility.ex | 13 ++++++------- 3 files changed, 21 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index e017efad6..982ca8bc1 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -586,12 +586,23 @@ defmodule Pleroma.User do @spec get_followers_query(User.t()) :: Ecto.Query.t() def get_followers_query(user), do: get_followers_query(user, nil) + @spec get_followers(User.t(), pos_integer()) :: {:ok, list(User.t())} def get_followers(user, page \\ nil) do q = get_followers_query(user, page) {:ok, Repo.all(q)} end + @spec get_external_followers(User.t(), pos_integer()) :: {:ok, list(User.t())} + def get_external_followers(user, page \\ nil) do + q = + user + |> get_followers_query(page) + |> User.Query.build(%{external: true}) + + {:ok, Repo.all(q)} + end + def get_followers_ids(user, page \\ nil) do q = get_followers_query(user, page) diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index 0bbe6ee80..016d78216 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -97,13 +97,13 @@ defmodule Pleroma.Web.ActivityPub.Publisher do end end + @spec recipients(User.t(), Activity.t()) :: list(User.t()) | [] defp recipients(actor, activity) do - followers = + {:ok, followers} = if actor.follower_address in activity.recipients do - {:ok, followers} = User.get_followers(actor) - Enum.filter(followers, &(!&1.local)) + User.get_external_followers(actor) else - [] + {:ok, []} end Pleroma.Web.Salmon.remote_users(actor, activity) ++ followers diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex index 2666edc7c..097fceb08 100644 --- a/lib/pleroma/web/activity_pub/visibility.ex +++ b/lib/pleroma/web/activity_pub/visibility.ex @@ -8,14 +8,14 @@ defmodule Pleroma.Web.ActivityPub.Visibility do alias Pleroma.Repo alias Pleroma.User + @public "https://www.w3.org/ns/activitystreams#Public" + + @spec is_public?(Object.t() | Activity.t() | map()) :: boolean() def is_public?(%Object{data: %{"type" => "Tombstone"}}), do: false def is_public?(%Object{data: data}), do: is_public?(data) def is_public?(%Activity{data: data}), do: is_public?(data) def is_public?(%{"directMessage" => true}), do: false - - def is_public?(data) do - "https://www.w3.org/ns/activitystreams#Public" in (data["to"] ++ (data["cc"] || [])) - end + def is_public?(data), do: @public in (data["to"] ++ (data["cc"] || [])) def is_private?(activity) do with false <- is_public?(activity), @@ -69,15 +69,14 @@ defmodule Pleroma.Web.ActivityPub.Visibility do end def get_visibility(object) do - public = "https://www.w3.org/ns/activitystreams#Public" to = object.data["to"] || [] cc = object.data["cc"] || [] cond do - public in to -> + @public in to -> "public" - public in cc -> + @public in cc -> "unlisted" # this should use the sql for the object's activity -- cgit v1.2.3 From 5e72554f3c6490ebdaaa8238f34860fa362016fc Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Tue, 23 Jul 2019 19:17:00 +0000 Subject: Admin config fix --- lib/pleroma/web/admin_api/config.ex | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/config.ex b/lib/pleroma/web/admin_api/config.ex index b4eb8e002..dde05ea7b 100644 --- a/lib/pleroma/web/admin_api/config.ex +++ b/lib/pleroma/web/admin_api/config.ex @@ -84,6 +84,7 @@ defmodule Pleroma.Web.AdminAPI.Config do end defp do_convert({:dispatch, [entity]}), do: %{"tuple" => [":dispatch", [inspect(entity)]]} + defp do_convert({:partial_chain, entity}), do: %{"tuple" => [":partial_chain", inspect(entity)]} defp do_convert(entity) when is_tuple(entity), do: %{"tuple" => do_convert(Tuple.to_list(entity))} @@ -113,11 +114,15 @@ defmodule Pleroma.Web.AdminAPI.Config do defp do_transform(%Regex{} = entity) when is_map(entity), do: entity defp do_transform(%{"tuple" => [":dispatch", [entity]]}) do - cleaned_string = String.replace(entity, ~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "") - {dispatch_settings, []} = Code.eval_string(cleaned_string, [], requires: [], macros: []) + {dispatch_settings, []} = do_eval(entity) {:dispatch, [dispatch_settings]} end + defp do_transform(%{"tuple" => [":partial_chain", entity]}) do + {partial_chain, []} = do_eval(entity) + {:partial_chain, partial_chain} + end + defp do_transform(%{"tuple" => entity}) do Enum.reduce(entity, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end) end @@ -149,4 +154,9 @@ defmodule Pleroma.Web.AdminAPI.Config do do: String.to_existing_atom("Elixir." <> value), else: value end + + defp do_eval(entity) do + cleaned_string = String.replace(entity, ~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "") + Code.eval_string(cleaned_string, [], requires: [], macros: []) + end end -- cgit v1.2.3 From 90be91b0e091dabd6db36dff92b13ce9dc251c5c Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 22 Jul 2019 13:41:56 +0200 Subject: Router: Remove deprecated AdminAPI endpoints --- lib/pleroma/web/router.ex | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a33b5ddd7..d230788d0 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -154,22 +154,12 @@ defmodule Pleroma.Web.Router do post("/users/follow", AdminAPIController, :user_follow) post("/users/unfollow", AdminAPIController, :user_unfollow) - # TODO: to be removed at version 1.0 - delete("/user", AdminAPIController, :user_delete) - post("/user", AdminAPIController, :user_create) - delete("/users", AdminAPIController, :user_delete) post("/users", AdminAPIController, :user_create) patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation) put("/users/tag", AdminAPIController, :tag_users) delete("/users/tag", AdminAPIController, :untag_users) - # TODO: to be removed at version 1.0 - get("/permission_group/:nickname", AdminAPIController, :right_get) - get("/permission_group/:nickname/:permission_group", AdminAPIController, :right_get) - post("/permission_group/:nickname/:permission_group", AdminAPIController, :right_add) - delete("/permission_group/:nickname/:permission_group", AdminAPIController, :right_delete) - get("/users/:nickname/permission_group", AdminAPIController, :right_get) get("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_get) post("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_add) @@ -190,9 +180,6 @@ defmodule Pleroma.Web.Router do post("/users/revoke_invite", AdminAPIController, :revoke_invite) post("/users/email_invite", AdminAPIController, :email_invite) - # TODO: to be removed at version 1.0 - get("/password_reset", AdminAPIController, :get_password_reset) - get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset) get("/users", AdminAPIController, :list_users) -- cgit v1.2.3