From 7c8abbcb1ccafa79372fd75fdec87db2207b61ec Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Fri, 26 Jul 2019 15:33:25 +0200
Subject: [PATCH 01/16] CHANGELOG.md: Add entry for !1484
Related to: https://git.pleroma.social/pleroma/pleroma/merge_requests/1484
[ci skip]
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3f54d19e..bd3048b19 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Changed
- **Breaking:** Configuration: A setting to explicitly disable the mailer was added, defaulting to true, if you are using a mailer add `config :pleroma, Pleroma.Emails.Mailer, enabled: true` to your config
+- **Breaking:** Configuration: `/media/` is now removed when `base_url` is configured, append `/media/` to your `base_url` config to keep the old behaviour if desired
- Configuration: OpenGraph and TwitterCard providers enabled by default
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
- Federation: Return 403 errors when trying to request pages from a user's follower/following collections if they have `hide_followers`/`hide_follows` set
From 6b77a88365f3a58cf8d1f9c00ed04532f706b87c Mon Sep 17 00:00:00 2001
From: Maksim
Date: Fri, 26 Jul 2019 20:27:38 +0000
Subject: [PATCH 02/16] [#1097] added redirect: /pleroma/admin ->
/pleroma/admin/
---
.../web/fallback_redirect_controller.ex | 77 +++++++++++++++++++
lib/pleroma/web/router.ex | 65 ----------------
test/web/fallback_test.exs | 4 +
3 files changed, 81 insertions(+), 65 deletions(-)
create mode 100644 lib/pleroma/web/fallback_redirect_controller.ex
diff --git a/lib/pleroma/web/fallback_redirect_controller.ex b/lib/pleroma/web/fallback_redirect_controller.ex
new file mode 100644
index 000000000..5fbf3695f
--- /dev/null
+++ b/lib/pleroma/web/fallback_redirect_controller.ex
@@ -0,0 +1,77 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Fallback.RedirectController do
+ use Pleroma.Web, :controller
+ require Logger
+ alias Pleroma.User
+ alias Pleroma.Web.Metadata
+
+ def api_not_implemented(conn, _params) do
+ conn
+ |> put_status(404)
+ |> json(%{error: "Not implemented"})
+ end
+
+ def redirector(conn, _params, code \\ 200)
+
+ # redirect to admin section
+ # /pleroma/admin -> /pleroma/admin/
+ #
+ def redirector(conn, %{"path" => ["pleroma", "admin"]} = _, _code) do
+ redirect(conn, to: "/pleroma/admin/")
+ end
+
+ def redirector(conn, _params, code) do
+ conn
+ |> put_resp_content_type("text/html")
+ |> send_file(code, index_file_path())
+ end
+
+ def redirector_with_meta(conn, %{"maybe_nickname_or_id" => maybe_nickname_or_id} = params) do
+ with %User{} = user <- User.get_cached_by_nickname_or_id(maybe_nickname_or_id) do
+ redirector_with_meta(conn, %{user: user})
+ else
+ nil ->
+ redirector(conn, params)
+ end
+ end
+
+ def redirector_with_meta(conn, params) do
+ {:ok, index_content} = File.read(index_file_path())
+
+ tags =
+ try do
+ Metadata.build_tags(params)
+ rescue
+ e ->
+ Logger.error(
+ "Metadata rendering for #{conn.request_path} failed.\n" <>
+ Exception.format(:error, e, __STACKTRACE__)
+ )
+
+ ""
+ end
+
+ response = String.replace(index_content, "", tags)
+
+ conn
+ |> put_resp_content_type("text/html")
+ |> send_resp(200, response)
+ end
+
+ def index_file_path do
+ Pleroma.Plugs.InstanceStatic.file_path("index.html")
+ end
+
+ def registration_page(conn, params) do
+ redirector(conn, params)
+ end
+
+ def empty(conn, _params) do
+ conn
+ |> put_status(204)
+ |> text("")
+ end
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index a9f3826fc..47ee762dc 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -729,68 +729,3 @@ defmodule Pleroma.Web.Router do
options("/*path", RedirectController, :empty)
end
end
-
-defmodule Fallback.RedirectController do
- use Pleroma.Web, :controller
- require Logger
- alias Pleroma.User
- alias Pleroma.Web.Metadata
-
- def api_not_implemented(conn, _params) do
- conn
- |> put_status(404)
- |> json(%{error: "Not implemented"})
- end
-
- def redirector(conn, _params, code \\ 200) do
- conn
- |> put_resp_content_type("text/html")
- |> send_file(code, index_file_path())
- end
-
- def redirector_with_meta(conn, %{"maybe_nickname_or_id" => maybe_nickname_or_id} = params) do
- with %User{} = user <- User.get_cached_by_nickname_or_id(maybe_nickname_or_id) do
- redirector_with_meta(conn, %{user: user})
- else
- nil ->
- redirector(conn, params)
- end
- end
-
- def redirector_with_meta(conn, params) do
- {:ok, index_content} = File.read(index_file_path())
-
- tags =
- try do
- Metadata.build_tags(params)
- rescue
- e ->
- Logger.error(
- "Metadata rendering for #{conn.request_path} failed.\n" <>
- Exception.format(:error, e, __STACKTRACE__)
- )
-
- ""
- end
-
- response = String.replace(index_content, "", tags)
-
- conn
- |> put_resp_content_type("text/html")
- |> send_resp(200, response)
- end
-
- def index_file_path do
- Pleroma.Plugs.InstanceStatic.file_path("index.html")
- end
-
- def registration_page(conn, params) do
- redirector(conn, params)
- end
-
- def empty(conn, _params) do
- conn
- |> put_status(204)
- |> text("")
- end
-end
diff --git a/test/web/fallback_test.exs b/test/web/fallback_test.exs
index cc78b3ae1..c13db9526 100644
--- a/test/web/fallback_test.exs
+++ b/test/web/fallback_test.exs
@@ -30,6 +30,10 @@ test "GET /api*path", %{conn: conn} do
|> json_response(404) == %{"error" => "Not implemented"}
end
+ test "GET /pleroma/admin -> /pleroma/admin/", %{conn: conn} do
+ assert redirected_to(get(conn, "/pleroma/admin")) =~ "/pleroma/admin/"
+ end
+
test "GET /*path", %{conn: conn} do
assert conn
|> get("/foo")
From 961e7785314688b9e2445649c71e12023a982165 Mon Sep 17 00:00:00 2001
From: Thomas Sileo
Date: Sun, 28 Jul 2019 14:17:56 +0200
Subject: [PATCH 03/16] Fix HTTP sig tweak on KeyId
---
lib/pleroma/signature.ex | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex
index 0bf49fd7c..15bf3c317 100644
--- a/lib/pleroma/signature.ex
+++ b/lib/pleroma/signature.ex
@@ -15,7 +15,7 @@ def key_id_to_actor_id(key_id) do
|> Map.put(:fragment, nil)
uri =
- if String.ends_with?(uri.path, "/publickey") do
+ if not is_nil(uri.path) and String.ends_with?(uri.path, "/publickey") do
Map.put(uri, :path, String.replace(uri.path, "/publickey", ""))
else
uri
From 02dc651828af00ba88a687570833333d4b939c7e Mon Sep 17 00:00:00 2001
From: Sergey Suprunenko
Date: Sun, 28 Jul 2019 20:24:39 +0000
Subject: [PATCH 04/16] Handle 303 redirects
---
lib/pleroma/http/connection.ex | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/pleroma/http/connection.ex b/lib/pleroma/http/connection.ex
index a1460d303..7e2c6f5e8 100644
--- a/lib/pleroma/http/connection.ex
+++ b/lib/pleroma/http/connection.ex
@@ -11,6 +11,7 @@ defmodule Pleroma.HTTP.Connection do
connect_timeout: 10_000,
recv_timeout: 20_000,
follow_redirect: true,
+ force_redirect: true,
pool: :federation
]
@adapter Application.get_env(:tesla, :adapter)
From 6a4b8b2681023dc355331999aeac6c24c5a21f7f Mon Sep 17 00:00:00 2001
From: Maksim
Date: Sun, 28 Jul 2019 20:29:26 +0000
Subject: [PATCH 05/16] fixed User.update_and_set_cache for stale user
---
lib/pleroma/user.ex | 2 +-
test/user_test.exs | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 974f6df18..6e2fd3af8 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -471,7 +471,7 @@ def set_cache(%User{} = user) do
end
def update_and_set_cache(changeset) do
- with {:ok, user} <- Repo.update(changeset) do
+ with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
set_cache(user)
else
e -> e
diff --git a/test/user_test.exs b/test/user_test.exs
index 8a7b7537f..556df45fd 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1369,4 +1369,28 @@ test "user with internal-prefixed nickname returns true" do
assert User.is_internal_user?(user)
end
end
+
+ describe "update_and_set_cache/1" do
+ test "returns error when user is stale instead Ecto.StaleEntryError" do
+ user = insert(:user)
+
+ changeset = Ecto.Changeset.change(user, bio: "test")
+
+ Repo.delete(user)
+
+ assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
+ User.update_and_set_cache(changeset)
+ end
+
+ test "performs update cache if user updated" do
+ user = insert(:user)
+ assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
+
+ changeset = Ecto.Changeset.change(user, bio: "test-bio")
+
+ assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
+ assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
+ assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
+ end
+ end
end
From 242f5c585ed797917ba8c61ceb5d266f4c670c90 Mon Sep 17 00:00:00 2001
From: Sachin Joshi
Date: Sun, 28 Jul 2019 20:30:10 +0000
Subject: [PATCH 06/16] add account confirmation email resend in mastodon api
---
CHANGELOG.md | 1 +
config/config.exs | 3 +-
docs/api/pleroma_api.md | 8 ++++
.../mastodon_api/mastodon_api_controller.ex | 14 +++++++
lib/pleroma/web/router.ex | 6 +++
.../mastodon_api_controller_test.exs | 41 +++++++++++++++++++
6 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd3048b19..20f4eea41 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- ActivityPub: Add an internal service actor for fetching ActivityPub objects.
- ActivityPub: Optional signing of ActivityPub object fetches.
- Admin API: Endpoint for fetching latest user's statuses
+- Pleroma API: Add `/api/v1/pleroma/accounts/confirmation_resend?email=` for resending account confirmation.
### Changed
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
diff --git a/config/config.exs b/config/config.exs
index 569411866..17770640a 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -534,7 +534,8 @@
relation_id_action: {60_000, 2},
statuses_actions: {10_000, 15},
status_id_action: {60_000, 3},
- password_reset: {1_800_000, 5}
+ password_reset: {1_800_000, 5},
+ account_confirmation_resend: {8_640_000, 5}
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
diff --git a/docs/api/pleroma_api.md b/docs/api/pleroma_api.md
index d83ebd734..5698e88ac 100644
--- a/docs/api/pleroma_api.md
+++ b/docs/api/pleroma_api.md
@@ -245,6 +245,14 @@ See [Admin-API](Admin-API.md)
- PATCH `/api/v1/pleroma/accounts/update_banner`: Set/clear user banner image
- PATCH `/api/v1/pleroma/accounts/update_background`: Set/clear user background image
+## `/api/v1/pleroma/accounts/confirmation_resend`
+### Resend confirmation email
+* Method `POST`
+* Params:
+ * `email`: email of that needs to be verified
+* Authentication: not required
+* Response: 204 No Content
+
## `/api/v1/pleroma/mascot`
### Gets user mascot image
* Method `GET`
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index d660f3f05..5bdbb709b 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -4,6 +4,9 @@
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper, only: [json_response: 3]
+
alias Ecto.Changeset
alias Pleroma.Activity
alias Pleroma.Bookmark
@@ -74,6 +77,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
plug(RateLimiter, :app_account_creation when action == :account_register)
plug(RateLimiter, :search when action in [:search, :search2, :account_search])
plug(RateLimiter, :password_reset when action == :password_reset)
+ plug(RateLimiter, :account_confirmation_resend when action == :account_confirmation_resend)
@local_mastodon_name "Mastodon-Local"
@@ -1839,6 +1843,16 @@ def password_reset(conn, params) do
end
end
+ def account_confirmation_resend(conn, params) do
+ nickname_or_email = params["email"] || params["nickname"]
+
+ with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
+ {:ok, _} <- User.try_send_confirmation_email(user) do
+ conn
+ |> json_response(:no_content, "")
+ end
+ end
+
def try_render(conn, target, params)
when is_binary(target) do
case render(conn, target, params) do
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 47ee762dc..4e1ab6c33 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -412,6 +412,12 @@ defmodule Pleroma.Web.Router do
get("/accounts/search", SearchController, :account_search)
+ post(
+ "/pleroma/accounts/confirmation_resend",
+ MastodonAPIController,
+ :account_confirmation_resend
+ )
+
scope [] do
pipe_through(:oauth_read_or_public)
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index ce2e44499..d7f92fac2 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -3923,4 +3923,45 @@ test "it returns 400 when user is not local", %{conn: conn, user: user} do
assert conn.resp_body == ""
end
end
+
+ describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
+ setup do
+ setting = Pleroma.Config.get([:instance, :account_activation_required])
+
+ unless setting do
+ Pleroma.Config.put([:instance, :account_activation_required], true)
+ on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
+ end
+
+ user = insert(:user)
+ info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
+
+ {:ok, user} =
+ user
+ |> Changeset.change()
+ |> Changeset.put_embed(:info, info_change)
+ |> Repo.update()
+
+ assert user.info.confirmation_pending
+
+ [user: user]
+ end
+
+ test "resend account confirmation email", %{conn: conn, user: user} do
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
+ |> json_response(:no_content)
+
+ email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
+ notify_email = Pleroma.Config.get([:instance, :notify_email])
+ instance_name = Pleroma.Config.get([:instance, :name])
+
+ assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {user.name, user.email},
+ html_body: email.html_body
+ )
+ end
+ end
end
From 492d854e7aa29a2438dbbe2f95e509e43328eb7f Mon Sep 17 00:00:00 2001
From: Ariadne Conill
Date: Sun, 28 Jul 2019 21:29:10 +0000
Subject: [PATCH 07/16] transmogrifier: use User.delete() instead of handrolled
user deletion code for remote users
Closes #1104
---
CHANGELOG.md | 1 +
.../web/activity_pub/transmogrifier.ex | 15 +----
test/notification_test.exs | 58 +++++++++++++++++++
3 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20f4eea41..48379b757 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Rich Media: Parser failing when no TTL can be found by image TTL setters
- Rich Media: The crawled URL is now spliced into the rich media data.
- ActivityPub S2S: sharedInbox usage has been mostly aligned with the rules in the AP specification.
+- ActivityPub S2S: remote user deletions now work the same as local user deletions.
### Added
- MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 602ae48e1..7f06e6edd 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -656,20 +656,7 @@ def handle_incoming(
nil ->
case User.get_cached_by_ap_id(object_id) do
%User{ap_id: ^actor} = user ->
- {:ok, followers} = User.get_followers(user)
-
- Enum.each(followers, fn follower ->
- User.unfollow(follower, user)
- end)
-
- {:ok, friends} = User.get_friends(user)
-
- Enum.each(friends, fn followed ->
- User.unfollow(user, followed)
- end)
-
- User.invalidate_cache(user)
- Repo.delete(user)
+ User.delete(user)
nil ->
:error
diff --git a/test/notification_test.exs b/test/notification_test.exs
index 28f8df49d..c88ac54bd 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -564,6 +564,64 @@ test "replying to a deleted post without tagging does not generate a notificatio
assert Enum.empty?(Notification.for_user(user))
end
+
+ test "notifications are deleted if a local user is deleted" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}", "visibility" => "direct"})
+
+ refute Enum.empty?(Notification.for_user(other_user))
+
+ User.delete(user)
+
+ assert Enum.empty?(Notification.for_user(other_user))
+ end
+
+ test "notifications are deleted if a remote user is deleted" do
+ remote_user = insert(:user)
+ local_user = insert(:user)
+
+ dm_message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "type" => "Create",
+ "actor" => remote_user.ap_id,
+ "id" => remote_user.ap_id <> "/activities/test",
+ "to" => [local_user.ap_id],
+ "cc" => [],
+ "object" => %{
+ "type" => "Note",
+ "content" => "Hello!",
+ "tag" => [
+ %{
+ "type" => "Mention",
+ "href" => local_user.ap_id,
+ "name" => "@#{local_user.nickname}"
+ }
+ ],
+ "to" => [local_user.ap_id],
+ "cc" => [],
+ "attributedTo" => remote_user.ap_id
+ }
+ }
+
+ {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
+
+ refute Enum.empty?(Notification.for_user(local_user))
+
+ delete_user_message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "id" => remote_user.ap_id <> "/activities/delete",
+ "actor" => remote_user.ap_id,
+ "type" => "Delete",
+ "object" => remote_user.ap_id
+ }
+
+ {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
+
+ assert Enum.empty?(Notification.for_user(local_user))
+ end
end
describe "for_user" do
From 9d78b3b281ff7f758d4e0dce19fd74d938e47ccc Mon Sep 17 00:00:00 2001
From: Ariadne Conill
Date: Mon, 29 Jul 2019 02:12:35 +0000
Subject: [PATCH 08/16] mix: add ex_const dependency
---
mix.exs | 1 +
mix.lock | 1 +
2 files changed, 2 insertions(+)
diff --git a/mix.exs b/mix.exs
index e69940c5d..2a8fe2e9d 100644
--- a/mix.exs
+++ b/mix.exs
@@ -150,6 +150,7 @@ defp deps do
{:benchee, "~> 1.0"},
{:esshd, "~> 0.1.0", runtime: Application.get_env(:esshd, :enabled, false)},
{:ex_rated, "~> 1.3"},
+ {:ex_const, "~> 0.2"},
{:plug_static_index_html, "~> 1.0.0"},
{:excoveralls, "~> 0.11.1", only: :test},
{:mox, "~> 0.5", only: :test}
diff --git a/mix.lock b/mix.lock
index 5f20878d3..65da7be8b 100644
--- a/mix.lock
+++ b/mix.lock
@@ -27,6 +27,7 @@
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
"ex_aws": {:hex, :ex_aws, "2.1.0", "b92651527d6c09c479f9013caa9c7331f19cba38a650590d82ebf2c6c16a1d8a", [:mix], [{:configparser_ex, "~> 2.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:xml_builder, "~> 0.1.0", [hex: :xml_builder, repo: "hexpm", optional: true]}], "hexpm"},
"ex_aws_s3": {:hex, :ex_aws_s3, "2.0.1", "9e09366e77f25d3d88c5393824e613344631be8db0d1839faca49686e99b6704", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm"},
+ "ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
"ex_rated": {:hex, :ex_rated, "1.3.3", "30ecbdabe91f7eaa9d37fa4e81c85ba420f371babeb9d1910adbcd79ec798d27", [:mix], [{:ex2ms, "~> 1.5", [hex: :ex2ms, repo: "hexpm", optional: false]}], "hexpm"},
From b93498eb5289dc92587b77c316ed9f697bb9e5c8 Mon Sep 17 00:00:00 2001
From: Ariadne Conill
Date: Mon, 29 Jul 2019 02:43:19 +0000
Subject: [PATCH 09/16] constants: add as_public constant and use it everywhere
---
lib/mix/tasks/pleroma/database.ex | 12 ++++++---
lib/pleroma/activity/search.ex | 4 ++-
lib/pleroma/constants.ex | 9 +++++++
lib/pleroma/web/activity_pub/activity_pub.ex | 27 +++++++------------
.../web/activity_pub/mrf/hellthread_policy.ex | 11 +++++---
.../web/activity_pub/mrf/keyword_policy.ex | 8 +++---
.../web/activity_pub/mrf/reject_non_public.ex | 6 ++---
.../web/activity_pub/mrf/simple_policy.ex | 12 ++++-----
.../web/activity_pub/mrf/tag_policy.ex | 15 ++++++-----
lib/pleroma/web/activity_pub/publisher.ex | 6 ++---
.../web/activity_pub/transmogrifier.ex | 11 ++++----
lib/pleroma/web/activity_pub/utils.ex | 13 ++++-----
lib/pleroma/web/activity_pub/visibility.ex | 8 +++---
lib/pleroma/web/auth/authenticator.ex | 3 +--
lib/pleroma/web/common_api/common_api.ex | 3 +--
lib/pleroma/web/common_api/utils.ex | 5 ++--
.../mastodon_api/mastodon_api_controller.ex | 6 ++---
lib/pleroma/web/oauth/oauth_controller.ex | 3 +--
lib/pleroma/web/oauth/token.ex | 3 +--
.../web/ostatus/activity_representer.ex | 3 ++-
.../web/ostatus/handlers/note_handler.ex | 5 ++--
.../rich_media/parsers/ttl/aws_signed_url.ex | 3 +--
lib/pleroma/web/twitter_api/twitter_api.ex | 4 ++-
.../web/twitter_api/views/activity_view.ex | 3 ++-
.../twitter_api/views/notification_view.ex | 4 ++-
test/web/push/impl_test.exs | 6 ++---
26 files changed, 104 insertions(+), 89 deletions(-)
create mode 100644 lib/pleroma/constants.ex
diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex
index e91fb31d1..8547a329a 100644
--- a/lib/mix/tasks/pleroma/database.ex
+++ b/lib/mix/tasks/pleroma/database.ex
@@ -8,6 +8,7 @@ defmodule Mix.Tasks.Pleroma.Database do
alias Pleroma.Repo
alias Pleroma.User
require Logger
+ require Pleroma.Constants
import Mix.Pleroma
use Mix.Task
@@ -99,10 +100,15 @@ def run(["prune_objects" | args]) do
NaiveDateTime.utc_now()
|> NaiveDateTime.add(-(deadline * 86_400))
- public = "https://www.w3.org/ns/activitystreams#Public"
-
from(o in Object,
- where: fragment("?->'to' \\? ? OR ?->'cc' \\? ?", o.data, ^public, o.data, ^public),
+ where:
+ fragment(
+ "?->'to' \\? ? OR ?->'cc' \\? ?",
+ o.data,
+ ^Pleroma.Constants.as_public(),
+ o.data,
+ ^Pleroma.Constants.as_public()
+ ),
where: o.inserted_at < ^time_deadline,
where:
fragment("split_part(?->>'actor', '/', 3) != ?", o.data, ^Pleroma.Web.Endpoint.host())
diff --git a/lib/pleroma/activity/search.ex b/lib/pleroma/activity/search.ex
index 0cc3770a7..f847ac238 100644
--- a/lib/pleroma/activity/search.ex
+++ b/lib/pleroma/activity/search.ex
@@ -9,6 +9,8 @@ defmodule Pleroma.Activity.Search do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Visibility
+ require Pleroma.Constants
+
import Ecto.Query
def search(user, search_query, options \\ []) do
@@ -39,7 +41,7 @@ def maybe_restrict_author(query, _), do: query
defp restrict_public(q) do
from([a, o] in q,
where: fragment("?->>'type' = 'Create'", a.data),
- where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients
+ where: ^Pleroma.Constants.as_public() in a.recipients
)
end
diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex
new file mode 100644
index 000000000..ef1418543
--- /dev/null
+++ b/lib/pleroma/constants.ex
@@ -0,0 +1,9 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Constants do
+ use Const
+
+ const(as_public, do: "https://www.w3.org/ns/activitystreams#Public")
+end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index a42c50875..6fd7fef92 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -23,6 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
import Pleroma.Web.ActivityPub.Visibility
require Logger
+ require Pleroma.Constants
# For Announce activities, we filter the recipients based on following status for any actors
# that match actual users. See issue #164 for more information about why this is necessary.
@@ -207,8 +208,6 @@ def stream_out_participations(%Object{data: %{"context" => context}}, user) do
def stream_out_participations(_, _), do: :noop
def stream_out(activity) do
- public = "https://www.w3.org/ns/activitystreams#Public"
-
if activity.data["type"] in ["Create", "Announce", "Delete"] do
object = Object.normalize(activity)
# Do not stream out poll replies
@@ -216,7 +215,7 @@ def stream_out(activity) do
Pleroma.Web.Streamer.stream("user", activity)
Pleroma.Web.Streamer.stream("list", activity)
- if Enum.member?(activity.data["to"], public) do
+ if get_visibility(activity) == "public" do
Pleroma.Web.Streamer.stream("public", activity)
if activity.local do
@@ -238,13 +237,8 @@ def stream_out(activity) do
end
end
else
- # TODO: Write test, replace with visibility test
- if !Enum.member?(activity.data["cc"] || [], public) &&
- !Enum.member?(
- activity.data["to"],
- User.get_cached_by_ap_id(activity.data["actor"]).follower_address
- ),
- do: Pleroma.Web.Streamer.stream("direct", activity)
+ if get_visibility(activity) == "direct",
+ do: Pleroma.Web.Streamer.stream("direct", activity)
end
end
end
@@ -514,7 +508,7 @@ def flag(
end
defp fetch_activities_for_context_query(context, opts) do
- public = ["https://www.w3.org/ns/activitystreams#Public"]
+ public = [Pleroma.Constants.as_public()]
recipients =
if opts["user"], do: [opts["user"].ap_id | opts["user"].following] ++ public, else: public
@@ -555,7 +549,7 @@ def fetch_latest_activity_id_for_context(context, opts \\ %{}) do
end
def fetch_public_activities(opts \\ %{}) do
- q = fetch_activities_query(["https://www.w3.org/ns/activitystreams#Public"], opts)
+ q = fetch_activities_query([Pleroma.Constants.as_public()], opts)
q
|> restrict_unlisted()
@@ -646,10 +640,9 @@ defp user_activities_recipients(%{"godmode" => true}) do
defp user_activities_recipients(%{"reading_user" => reading_user}) do
if reading_user do
- ["https://www.w3.org/ns/activitystreams#Public"] ++
- [reading_user.ap_id | reading_user.following]
+ [Pleroma.Constants.as_public()] ++ [reading_user.ap_id | reading_user.following]
else
- ["https://www.w3.org/ns/activitystreams#Public"]
+ [Pleroma.Constants.as_public()]
end
end
@@ -834,7 +827,7 @@ defp restrict_unlisted(query) do
fragment(
"not (coalesce(?->'cc', '{}'::jsonb) \\?| ?)",
activity.data,
- ^["https://www.w3.org/ns/activitystreams#Public"]
+ ^[Pleroma.Constants.as_public()]
)
)
end
@@ -971,7 +964,7 @@ def fetch_activities_bounded_query(query, recipients, recipients_with_public) do
where:
fragment("? && ?", activity.recipients, ^recipients) or
(fragment("? && ?", activity.recipients, ^recipients_with_public) and
- "https://www.w3.org/ns/activitystreams#Public" in activity.recipients)
+ ^Pleroma.Constants.as_public() in activity.recipients)
)
end
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index a699f6a7e..377987cf2 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -4,6 +4,9 @@
defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
alias Pleroma.User
+
+ require Pleroma.Constants
+
@moduledoc "Block messages with too much mentions (configurable)"
@behaviour Pleroma.Web.ActivityPub.MRF
@@ -19,12 +22,12 @@ defp delist_message(message, threshold) when threshold > 0 do
when follower_collection? and recipients > threshold ->
message
|> Map.put("to", [follower_collection])
- |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+ |> Map.put("cc", [Pleroma.Constants.as_public()])
{:public, recipients} when recipients > threshold ->
message
|> Map.put("to", [])
- |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+ |> Map.put("cc", [Pleroma.Constants.as_public()])
_ ->
message
@@ -51,10 +54,10 @@ defp get_recipient_count(message) do
recipients = (message["to"] || []) ++ (message["cc"] || [])
follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
- if Enum.member?(recipients, "https://www.w3.org/ns/activitystreams#Public") do
+ if Enum.member?(recipients, Pleroma.Constants.as_public()) do
recipients =
recipients
- |> List.delete("https://www.w3.org/ns/activitystreams#Public")
+ |> List.delete(Pleroma.Constants.as_public())
|> List.delete(follower_collection)
{:public, length(recipients)}
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index d5c341433..4eec8b916 100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -3,6 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
+ require Pleroma.Constants
+
@moduledoc "Reject or Word-Replace messages with a keyword or regex"
@behaviour Pleroma.Web.ActivityPub.MRF
@@ -31,12 +33,12 @@ defp check_reject(%{"object" => %{"content" => content, "summary" => summary}} =
defp check_ftl_removal(
%{"to" => to, "object" => %{"content" => content, "summary" => summary}} = message
) do
- if "https://www.w3.org/ns/activitystreams#Public" in to and
+ if Pleroma.Constants.as_public() in to and
Enum.any?(Pleroma.Config.get([:mrf_keyword, :federated_timeline_removal]), fn pattern ->
string_matches?(content, pattern) or string_matches?(summary, pattern)
end) do
- to = List.delete(to, "https://www.w3.org/ns/activitystreams#Public")
- cc = ["https://www.w3.org/ns/activitystreams#Public" | message["cc"] || []]
+ to = List.delete(to, Pleroma.Constants.as_public())
+ cc = [Pleroma.Constants.as_public() | message["cc"] || []]
message =
message
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 da13fd7c7..457b6ee10 100644
--- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
+++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
@@ -10,7 +10,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
@behaviour Pleroma.Web.ActivityPub.MRF
- @public "https://www.w3.org/ns/activitystreams#Public"
+ require Pleroma.Constants
@impl true
def filter(%{"type" => "Create"} = object) do
@@ -19,8 +19,8 @@ def filter(%{"type" => "Create"} = object) do
# Determine visibility
visibility =
cond do
- @public in object["to"] -> "public"
- @public in object["cc"] -> "unlisted"
+ Pleroma.Constants.as_public() in object["to"] -> "public"
+ Pleroma.Constants.as_public() in object["cc"] -> "unlisted"
user.follower_address in object["to"] -> "followers"
true -> "direct"
end
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index 2cf63d3db..f266457e3 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -8,6 +8,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
@moduledoc "Filter activities depending on their origin instance"
@behaviour MRF
+ require Pleroma.Constants
+
defp check_accept(%{host: actor_host} = _actor_info, object) do
accepts =
Pleroma.Config.get([:mrf_simple, :accept])
@@ -89,14 +91,10 @@ defp check_ftl_removal(%{host: actor_host} = _actor_info, object) do
object =
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 =
- List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++
- [user.follower_address]
+ true <- Pleroma.Constants.as_public() in object["to"] do
+ to = List.delete(object["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
- cc =
- List.delete(object["cc"], user.follower_address) ++
- ["https://www.w3.org/ns/activitystreams#Public"]
+ cc = List.delete(object["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
object
|> Map.put("to", to)
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index b42c4ed76..70edf4f7f 100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
- `mrf_tag:disable-any-subscription`: Reject any follow requests
"""
- @public "https://www.w3.org/ns/activitystreams#Public"
+ require Pleroma.Constants
defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
defp get_tags(_), do: []
@@ -70,9 +70,9 @@ defp process_tag(
) do
user = User.get_cached_by_ap_id(actor)
- if Enum.member?(to, @public) do
- to = List.delete(to, @public) ++ [user.follower_address]
- cc = List.delete(cc, user.follower_address) ++ [@public]
+ if Enum.member?(to, Pleroma.Constants.as_public()) do
+ to = List.delete(to, Pleroma.Constants.as_public()) ++ [user.follower_address]
+ cc = List.delete(cc, user.follower_address) ++ [Pleroma.Constants.as_public()]
object =
object
@@ -103,9 +103,10 @@ defp process_tag(
) do
user = User.get_cached_by_ap_id(actor)
- if Enum.member?(to, @public) or Enum.member?(cc, @public) do
- to = List.delete(to, @public) ++ [user.follower_address]
- cc = List.delete(cc, @public)
+ if Enum.member?(to, Pleroma.Constants.as_public()) or
+ Enum.member?(cc, Pleroma.Constants.as_public()) do
+ to = List.delete(to, Pleroma.Constants.as_public()) ++ [user.follower_address]
+ cc = List.delete(cc, Pleroma.Constants.as_public())
object =
object
diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex
index 016d78216..46edab0bd 100644
--- a/lib/pleroma/web/activity_pub/publisher.ex
+++ b/lib/pleroma/web/activity_pub/publisher.ex
@@ -11,6 +11,8 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier
+ require Pleroma.Constants
+
import Pleroma.Web.ActivityPub.Visibility
@behaviour Pleroma.Web.Federator.Publisher
@@ -117,8 +119,6 @@ defp get_cc_ap_ids(ap_id, recipients) 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"]
@@ -145,7 +145,7 @@ def determine_inbox(
type == "Delete" ->
maybe_use_sharedinbox(user)
- @as_public in to || @as_public in cc ->
+ Pleroma.Constants.as_public() in to || Pleroma.Constants.as_public() in cc ->
maybe_use_sharedinbox(user)
length(to) + length(cc) > 1 ->
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 7f06e6edd..44bb1cb9a 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -19,6 +19,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
import Ecto.Query
require Logger
+ require Pleroma.Constants
@doc """
Modifies an incoming AP object (mastodon format) to our internal format.
@@ -102,8 +103,7 @@ def fix_explicit_addressing(object) do
follower_collection = User.get_cached_by_ap_id(Containment.get_actor(object)).follower_address
- explicit_mentions =
- explicit_mentions ++ ["https://www.w3.org/ns/activitystreams#Public", follower_collection]
+ explicit_mentions = explicit_mentions ++ [Pleroma.Constants.as_public(), follower_collection]
fix_explicit_addressing(object, explicit_mentions, follower_collection)
end
@@ -115,11 +115,11 @@ def fix_implicit_addressing(%{"to" => to, "cc" => cc} = object, followers_collec
if followers_collection not in recipients do
cond do
- "https://www.w3.org/ns/activitystreams#Public" in cc ->
+ Pleroma.Constants.as_public() in cc ->
to = to ++ [followers_collection]
Map.put(object, "to", to)
- "https://www.w3.org/ns/activitystreams#Public" in to ->
+ Pleroma.Constants.as_public() in to ->
cc = cc ++ [followers_collection]
Map.put(object, "cc", cc)
@@ -480,8 +480,7 @@ def handle_incoming(
{:ok, %User{} = follower} <- User.get_or_fetch_by_ap_id(follower),
{:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do
with deny_follow_blocked <- Pleroma.Config.get([:user, :deny_follow_blocked]),
- {_, false} <-
- {:user_blocked, User.blocks?(followed, follower) && deny_follow_blocked},
+ {_, false} <- {:user_blocked, User.blocks?(followed, follower) && deny_follow_blocked},
{_, false} <- {:user_locked, User.locked?(followed)},
{_, {:ok, follower}} <- {:follow, User.follow(follower, followed)},
{_, {:ok, _}} <-
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index c146f59d4..39074888b 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -18,6 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
import Ecto.Query
require Logger
+ require Pleroma.Constants
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer"]
@supported_report_states ~w(open closed resolved)
@@ -418,7 +419,7 @@ def make_follow_data(
"type" => "Follow",
"actor" => follower_id,
"to" => [followed_id],
- "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [Pleroma.Constants.as_public()],
"object" => followed_id,
"state" => "pending"
}
@@ -510,7 +511,7 @@ def make_announce_data(
"actor" => ap_id,
"object" => id,
"to" => [user.follower_address, object.data["actor"]],
- "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [Pleroma.Constants.as_public()],
"context" => object.data["context"]
}
@@ -530,7 +531,7 @@ def make_unannounce_data(
"actor" => ap_id,
"object" => activity.data,
"to" => [user.follower_address, activity.data["actor"]],
- "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [Pleroma.Constants.as_public()],
"context" => context
}
@@ -547,7 +548,7 @@ def make_unlike_data(
"actor" => ap_id,
"object" => activity.data,
"to" => [user.follower_address, activity.data["actor"]],
- "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [Pleroma.Constants.as_public()],
"context" => context
}
@@ -556,7 +557,7 @@ def make_unlike_data(
def add_announce_to_object(
%Activity{
- data: %{"actor" => actor, "cc" => ["https://www.w3.org/ns/activitystreams#Public"]}
+ data: %{"actor" => actor, "cc" => [Pleroma.Constants.as_public()]}
},
object
) do
@@ -765,7 +766,7 @@ defp get_updated_targets(
) do
cc = Map.get(data, "cc", [])
follower_address = User.get_cached_by_ap_id(data["actor"]).follower_address
- public = "https://www.w3.org/ns/activitystreams#Public"
+ public = Pleroma.Constants.as_public()
case visibility do
"public" ->
diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex
index 097fceb08..dfb166b65 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"
+ require Pleroma.Constants
@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: @public in (data["to"] ++ (data["cc"] || []))
+ def is_public?(data), do: Pleroma.Constants.as_public() in (data["to"] ++ (data["cc"] || []))
def is_private?(activity) do
with false <- is_public?(activity),
@@ -73,10 +73,10 @@ def get_visibility(object) do
cc = object.data["cc"] || []
cond do
- @public in to ->
+ Pleroma.Constants.as_public() in to ->
"public"
- @public in cc ->
+ Pleroma.Constants.as_public() in cc ->
"unlisted"
# this should use the sql for the object's activity
diff --git a/lib/pleroma/web/auth/authenticator.ex b/lib/pleroma/web/auth/authenticator.ex
index d4e0ffa80..dd49987f7 100644
--- a/lib/pleroma/web/auth/authenticator.ex
+++ b/lib/pleroma/web/auth/authenticator.ex
@@ -21,8 +21,7 @@ def get_user(plug), do: implementation().get_user(plug)
def create_from_registration(plug, registration),
do: implementation().create_from_registration(plug, registration)
- @callback get_registration(Plug.Conn.t()) ::
- {:ok, Registration.t()} | {:error, any()}
+ @callback get_registration(Plug.Conn.t()) :: {:ok, Registration.t()} | {:error, any()}
def get_registration(plug), do: implementation().get_registration(plug)
@callback handle_error(Plug.Conn.t(), any()) :: any()
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index 44af6a773..2db58324b 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -300,8 +300,7 @@ def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do
}
} = activity <- get_by_id_or_ap_id(id_or_ap_id),
true <- Visibility.is_public?(activity),
- %{valid?: true} = info_changeset <-
- User.Info.add_pinnned_activity(user.info, activity),
+ %{valid?: true} = info_changeset <- User.Info.add_pinnned_activity(user.info, activity),
changeset <-
Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset),
{:ok, _user} <- User.update_and_set_cache(changeset) do
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 94462c3dd..d80fffa26 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -19,6 +19,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.Web.MediaProxy
require Logger
+ require Pleroma.Constants
# This is a hack for twidere.
def get_by_id_or_ap_id(id) do
@@ -66,7 +67,7 @@ def attachments_from_ids_descs(ids, descs_str) do
@spec get_to_and_cc(User.t(), list(String.t()), Activity.t() | nil, String.t()) ::
{list(String.t()), list(String.t())}
def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do
- to = ["https://www.w3.org/ns/activitystreams#Public" | mentioned_users]
+ to = [Pleroma.Constants.as_public() | mentioned_users]
cc = [user.follower_address]
if inReplyTo do
@@ -78,7 +79,7 @@ def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do
def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do
to = [user.follower_address | mentioned_users]
- cc = ["https://www.w3.org/ns/activitystreams#Public"]
+ cc = [Pleroma.Constants.as_public()]
if inReplyTo do
{Enum.uniq([inReplyTo.data["actor"] | to]), cc}
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 5bdbb709b..174e93468 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -49,6 +49,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
import Ecto.Query
require Logger
+ require Pleroma.Constants
@rate_limited_relations_actions ~w(follow unfollow)a
@@ -1224,10 +1225,9 @@ def user_favourites(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params
recipients =
if for_user do
- ["https://www.w3.org/ns/activitystreams#Public"] ++
- [for_user.ap_id | for_user.following]
+ [Pleroma.Constants.as_public()] ++ [for_user.ap_id | for_user.following]
else
- ["https://www.w3.org/ns/activitystreams#Public"]
+ [Pleroma.Constants.as_public()]
end
activities =
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index ef53b7ae3..81eae2c8b 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -365,8 +365,7 @@ def registration_details(%Plug.Conn{} = conn, %{"authorization" => auth_attrs})
def register(%Plug.Conn{} = conn, %{"authorization" => _, "op" => "connect"} = params) do
with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn),
%Registration{} = registration <- Repo.get(Registration, registration_id),
- {_, {:ok, auth}} <-
- {:create_authorization, do_create_authorization(conn, params)},
+ {_, {:ok, auth}} <- {:create_authorization, do_create_authorization(conn, params)},
%User{} = user <- Repo.preload(auth, :user).user,
{:ok, _updated_registration} <- Registration.bind_to_user(registration, user) do
conn
diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex
index 90c304487..40f131b57 100644
--- a/lib/pleroma/web/oauth/token.ex
+++ b/lib/pleroma/web/oauth/token.ex
@@ -44,8 +44,7 @@ def get_by_refresh_token(%App{id: app_id} = _app, token) do
|> Repo.find_resource()
end
- @spec exchange_token(App.t(), Authorization.t()) ::
- {:ok, Token.t()} | {:error, Changeset.t()}
+ @spec exchange_token(App.t(), Authorization.t()) :: {:ok, Token.t()} | {:error, Changeset.t()}
def exchange_token(app, auth) do
with {:ok, auth} <- Authorization.use_token(auth),
true <- auth.app_id == app.id do
diff --git a/lib/pleroma/web/ostatus/activity_representer.ex b/lib/pleroma/web/ostatus/activity_representer.ex
index 95037125d..760345301 100644
--- a/lib/pleroma/web/ostatus/activity_representer.ex
+++ b/lib/pleroma/web/ostatus/activity_representer.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
alias Pleroma.Web.OStatus.UserRepresenter
require Logger
+ require Pleroma.Constants
defp get_href(id) do
with %Object{data: %{"external_url" => external_url}} <- Object.get_cached_by_ap_id(id) do
@@ -34,7 +35,7 @@ defp get_mentions(to) do
Enum.map(to, fn id ->
cond do
# Special handling for the AP/Ostatus public collections
- "https://www.w3.org/ns/activitystreams#Public" == id ->
+ Pleroma.Constants.as_public() == id ->
{:link,
[
rel: "mentioned",
diff --git a/lib/pleroma/web/ostatus/handlers/note_handler.ex b/lib/pleroma/web/ostatus/handlers/note_handler.ex
index 8e0adad91..3005e8f57 100644
--- a/lib/pleroma/web/ostatus/handlers/note_handler.ex
+++ b/lib/pleroma/web/ostatus/handlers/note_handler.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.OStatus.NoteHandler do
require Logger
+ require Pleroma.Constants
alias Pleroma.Activity
alias Pleroma.Object
@@ -49,7 +50,7 @@ def get_people_mentions(entry) do
def get_collection_mentions(entry) do
transmogrify = fn
"http://activityschema.org/collection/public" ->
- "https://www.w3.org/ns/activitystreams#Public"
+ Pleroma.Constants.as_public()
group ->
group
@@ -126,7 +127,7 @@ def handle_note(entry, doc \\ nil, options \\ []) do
to <- make_to_list(actor, mentions),
date <- XML.string_from_xpath("//published", entry),
unlisted <- XML.string_from_xpath("//mastodon:scope", entry) == "unlisted",
- cc <- if(unlisted, do: ["https://www.w3.org/ns/activitystreams#Public"], else: []),
+ cc <- if(unlisted, do: [Pleroma.Constants.as_public()], else: []),
note <-
CommonAPI.Utils.make_note_data(
actor.ap_id,
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 014c0935f..0dc1efdaf 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
@@ -19,8 +19,7 @@ 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
+ if String.contains?(host, "amazonaws.com") and String.contains?(query, "X-Amz-Expires") do
image
else
nil
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index bb5dda204..80082ea84 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -15,6 +15,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
import Ecto.Query
+ require Pleroma.Constants
+
def create_status(%User{} = user, %{"status" => _} = data) do
CommonAPI.post(user, data)
end
@@ -286,7 +288,7 @@ def search(_user, %{"q" => query} = params) do
from(
[a, o] in Activity.with_preloaded_object(Activity),
where: fragment("?->>'type' = 'Create'", a.data),
- where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients,
+ where: ^Pleroma.Constants.as_public() in a.recipients,
where:
fragment(
"to_tsvector('english', ?->>'content') @@ plainto_tsquery('english', ?)",
diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex
index e84af84dc..abae63877 100644
--- a/lib/pleroma/web/twitter_api/views/activity_view.ex
+++ b/lib/pleroma/web/twitter_api/views/activity_view.ex
@@ -19,6 +19,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
import Ecto.Query
require Logger
+ require Pleroma.Constants
defp query_context_ids([]), do: []
@@ -91,7 +92,7 @@ defp get_user(ap_id, opts) do
String.ends_with?(ap_id, "/followers") ->
nil
- ap_id == "https://www.w3.org/ns/activitystreams#Public" ->
+ ap_id == Pleroma.Constants.as_public() ->
nil
user = User.get_cached_by_ap_id(ap_id) ->
diff --git a/lib/pleroma/web/twitter_api/views/notification_view.ex b/lib/pleroma/web/twitter_api/views/notification_view.ex
index e7c7a7496..085cd5aa3 100644
--- a/lib/pleroma/web/twitter_api/views/notification_view.ex
+++ b/lib/pleroma/web/twitter_api/views/notification_view.ex
@@ -10,6 +10,8 @@ defmodule Pleroma.Web.TwitterAPI.NotificationView do
alias Pleroma.Web.TwitterAPI.ActivityView
alias Pleroma.Web.TwitterAPI.UserView
+ require Pleroma.Constants
+
defp get_user(ap_id, opts) do
cond do
user = opts[:users][ap_id] ->
@@ -18,7 +20,7 @@ defp get_user(ap_id, opts) do
String.ends_with?(ap_id, "/followers") ->
nil
- ap_id == "https://www.w3.org/ns/activitystreams#Public" ->
+ ap_id == Pleroma.Constants.as_public() ->
nil
true ->
diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs
index 1e948086a..e2f89f40a 100644
--- a/test/web/push/impl_test.exs
+++ b/test/web/push/impl_test.exs
@@ -124,8 +124,7 @@ test "renders body for follow activity" do
{:ok, _, _, activity} = CommonAPI.follow(user, other_user)
object = Object.normalize(activity)
- assert Impl.format_body(%{activity: activity}, user, object) ==
- "@Bob has followed you"
+ assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has followed you"
end
test "renders body for announce activity" do
@@ -156,7 +155,6 @@ test "renders body for like activity" do
{:ok, activity, _} = CommonAPI.favorite(activity.id, user)
object = Object.normalize(activity)
- assert Impl.format_body(%{activity: activity}, user, object) ==
- "@Bob has favorited your post"
+ assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post"
end
end
From 159bbec570c308bf3d71487726737a91eb569178 Mon Sep 17 00:00:00 2001
From: Maksim
Date: Mon, 29 Jul 2019 05:02:20 +0000
Subject: [PATCH 10/16] added tests for OstatusController
---
lib/pleroma/web/ostatus/ostatus_controller.ex | 170 +++--
test/web/ostatus/ostatus_controller_test.exs | 630 ++++++++++++++----
2 files changed, 585 insertions(+), 215 deletions(-)
diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex
index 372d52899..c70063b84 100644
--- a/lib/pleroma/web/ostatus/ostatus_controller.ex
+++ b/lib/pleroma/web/ostatus/ostatus_controller.ex
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.OStatus.OStatusController do
use Pleroma.Web, :controller
+ alias Fallback.RedirectController
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.User
@@ -12,42 +13,44 @@ defmodule Pleroma.Web.OStatus.OStatusController do
alias Pleroma.Web.ActivityPub.ActivityPubController
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Visibility
+ alias Pleroma.Web.Endpoint
alias Pleroma.Web.Federator
+ alias Pleroma.Web.Metadata.PlayerView
alias Pleroma.Web.OStatus
alias Pleroma.Web.OStatus.ActivityRepresenter
alias Pleroma.Web.OStatus.FeedRepresenter
+ alias Pleroma.Web.Router
alias Pleroma.Web.XML
plug(Pleroma.Web.FederatingPlug when action in [:salmon_incoming])
+ plug(
+ Pleroma.Plugs.SetFormatPlug
+ when action in [:feed_redirect, :object, :activity, :notice]
+ )
+
action_fallback(:errors)
+ def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
+ with {_, %User{} = user} <-
+ {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
+ RedirectController.redirector_with_meta(conn, %{user: user})
+ end
+ end
+
+ def feed_redirect(%{assigns: %{format: format}} = conn, _params)
+ when format in ["json", "activity+json"] do
+ ActivityPubController.call(conn, :user)
+ end
+
def feed_redirect(conn, %{"nickname" => nickname}) do
- case get_format(conn) do
- "html" ->
- with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
- Fallback.RedirectController.redirector_with_meta(conn, %{user: user})
- else
- nil -> {:error, :not_found}
- end
-
- "activity+json" ->
- ActivityPubController.call(conn, :user)
-
- "json" ->
- ActivityPubController.call(conn, :user)
-
- _ ->
- with %User{} = user <- User.get_cached_by_nickname(nickname) do
- redirect(conn, external: OStatus.feed_path(user))
- else
- nil -> {:error, :not_found}
- end
+ with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
+ redirect(conn, external: OStatus.feed_path(user))
end
end
def feed(conn, %{"nickname" => nickname} = params) do
- with %User{} = user <- User.get_cached_by_nickname(nickname) do
+ with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
query_params =
Map.take(params, ["max_id"])
|> Map.merge(%{"whole_db" => true, "actor_id" => user.ap_id})
@@ -65,8 +68,6 @@ def feed(conn, %{"nickname" => nickname} = params) do
conn
|> put_resp_content_type("application/atom+xml")
|> send_resp(200, response)
- else
- nil -> {:error, :not_found}
end
end
@@ -97,93 +98,82 @@ def salmon_incoming(conn, _) do
|> send_resp(200, "")
end
- def object(conn, %{"uuid" => uuid}) do
- if get_format(conn) in ["activity+json", "json"] do
- ActivityPubController.call(conn, :object)
- else
- with id <- o_status_url(conn, :object, uuid),
- {_, %Activity{} = activity} <-
- {:activity, Activity.get_create_by_object_ap_id_with_object(id)},
- {_, true} <- {:public?, Visibility.is_public?(activity)},
- %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
- case get_format(conn) do
- "html" -> redirect(conn, to: "/notice/#{activity.id}")
- _ -> represent_activity(conn, nil, activity, user)
- end
- else
- {:public?, false} ->
- {:error, :not_found}
+ def object(%{assigns: %{format: format}} = conn, %{"uuid" => _uuid})
+ when format in ["json", "activity+json"] do
+ ActivityPubController.call(conn, :object)
+ end
- {:activity, nil} ->
- {:error, :not_found}
-
- e ->
- e
+ def object(%{assigns: %{format: format}} = conn, %{"uuid" => uuid}) do
+ with id <- o_status_url(conn, :object, uuid),
+ {_, %Activity{} = activity} <-
+ {:activity, Activity.get_create_by_object_ap_id_with_object(id)},
+ {_, true} <- {:public?, Visibility.is_public?(activity)},
+ %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
+ case format do
+ "html" -> redirect(conn, to: "/notice/#{activity.id}")
+ _ -> represent_activity(conn, nil, activity, user)
end
+ else
+ reason when reason in [{:public?, false}, {:activity, nil}] ->
+ {:error, :not_found}
+
+ e ->
+ e
end
end
- def activity(conn, %{"uuid" => uuid}) do
- if get_format(conn) in ["activity+json", "json"] do
- ActivityPubController.call(conn, :activity)
- else
- with id <- o_status_url(conn, :activity, uuid),
- {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
- {_, true} <- {:public?, Visibility.is_public?(activity)},
- %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
- case format = get_format(conn) do
- "html" -> redirect(conn, to: "/notice/#{activity.id}")
- _ -> represent_activity(conn, format, activity, user)
- end
- else
- {:public?, false} ->
- {:error, :not_found}
+ def activity(%{assigns: %{format: format}} = conn, %{"uuid" => _uuid})
+ when format in ["json", "activity+json"] do
+ ActivityPubController.call(conn, :activity)
+ end
- {:activity, nil} ->
- {:error, :not_found}
-
- e ->
- e
+ def activity(%{assigns: %{format: format}} = conn, %{"uuid" => uuid}) do
+ with id <- o_status_url(conn, :activity, uuid),
+ {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
+ {_, true} <- {:public?, Visibility.is_public?(activity)},
+ %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
+ case format do
+ "html" -> redirect(conn, to: "/notice/#{activity.id}")
+ _ -> represent_activity(conn, format, activity, user)
end
+ else
+ reason when reason in [{:public?, false}, {:activity, nil}] ->
+ {:error, :not_found}
+
+ e ->
+ e
end
end
- def notice(conn, %{"id" => id}) do
+ def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do
with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)},
{_, true} <- {:public?, Visibility.is_public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
- case format = get_format(conn) do
- "html" ->
- if activity.data["type"] == "Create" do
- %Object{} = object = Object.normalize(activity)
+ cond do
+ format == "html" && activity.data["type"] == "Create" ->
+ %Object{} = object = Object.normalize(activity)
- Fallback.RedirectController.redirector_with_meta(conn, %{
+ RedirectController.redirector_with_meta(
+ conn,
+ %{
activity_id: activity.id,
object: object,
- url:
- Pleroma.Web.Router.Helpers.o_status_url(
- Pleroma.Web.Endpoint,
- :notice,
- activity.id
- ),
+ url: Router.Helpers.o_status_url(Endpoint, :notice, activity.id),
user: user
- })
- else
- Fallback.RedirectController.redirector(conn, nil)
- end
+ }
+ )
- _ ->
+ format == "html" ->
+ RedirectController.redirector(conn, nil)
+
+ true ->
represent_activity(conn, format, activity, user)
end
else
- {:public?, false} ->
+ reason when reason in [{:public?, false}, {:activity, nil}] ->
conn
|> put_status(404)
- |> Fallback.RedirectController.redirector(nil, 404)
-
- {:activity, nil} ->
- conn
- |> Fallback.RedirectController.redirector(nil, 404)
+ |> RedirectController.redirector(nil, 404)
e ->
e
@@ -204,13 +194,13 @@ def notice_player(conn, %{"id" => id}) do
"content-security-policy",
"default-src 'none';style-src 'self' 'unsafe-inline';img-src 'self' data: https:; media-src 'self' https:;"
)
- |> put_view(Pleroma.Web.Metadata.PlayerView)
+ |> put_view(PlayerView)
|> render("player.html", url)
else
_error ->
conn
|> put_status(404)
- |> Fallback.RedirectController.redirector(nil, 404)
+ |> RedirectController.redirector(nil, 404)
end
end
@@ -248,6 +238,8 @@ def errors(conn, {:error, :not_found}) do
render_error(conn, :not_found, "Not found")
end
+ def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
+
def errors(conn, _) do
render_error(conn, :internal_server_error, "Something went wrong")
end
diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs
index bb7648bdd..9f756effb 100644
--- a/test/web/ostatus/ostatus_controller_test.exs
+++ b/test/web/ostatus/ostatus_controller_test.exs
@@ -101,160 +101,538 @@ test "returns 404 for a missing feed", %{conn: conn} do
assert response(conn, 404)
end
- test "gets an object", %{conn: conn} do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = User.get_cached_by_ap_id(note_activity.data["actor"])
- [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
- url = "/objects/#{uuid}"
+ describe "GET object/2" do
+ test "gets an object", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
+ url = "/objects/#{uuid}"
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/xml")
+ |> get(url)
+
+ expected =
+ ActivityRepresenter.to_simple_form(note_activity, user, true)
+ |> ActivityRepresenter.wrap_with_entry()
+ |> :xmerl.export_simple(:xmerl_xml)
+ |> to_string
+
+ assert response(conn, 200) == expected
+ end
+
+ test "redirects to /notice/id for html format", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
+ url = "/objects/#{uuid}"
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get(url)
+
+ assert redirected_to(conn) == "/notice/#{note_activity.id}"
+ end
+
+ test "500s when user not found", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+ User.invalidate_cache(user)
+ Pleroma.Repo.delete(user)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
+ url = "/objects/#{uuid}"
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/xml")
+ |> get(url)
+
+ assert response(conn, 500) == ~S({"error":"Something went wrong"})
+ end
+
+ test "404s on private objects", %{conn: conn} do
+ note_activity = insert(:direct_note_activity)
+ object = Object.normalize(note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
+
+ conn
+ |> get("/objects/#{uuid}")
+ |> response(404)
+ end
+
+ test "404s on nonexisting objects", %{conn: conn} do
+ conn
+ |> get("/objects/123")
+ |> response(404)
+ end
+ end
+
+ describe "GET activity/2" do
+ test "gets an activity in xml format", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
- conn =
conn
|> put_req_header("accept", "application/xml")
- |> get(url)
+ |> get("/activities/#{uuid}")
+ |> response(200)
+ end
- expected =
- ActivityRepresenter.to_simple_form(note_activity, user, true)
- |> ActivityRepresenter.wrap_with_entry()
- |> :xmerl.export_simple(:xmerl_xml)
- |> to_string
+ test "redirects to /notice/id for html format", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
- assert response(conn, 200) == expected
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/activities/#{uuid}")
+
+ assert redirected_to(conn) == "/notice/#{note_activity.id}"
+ end
+
+ test "505s when user not found", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+ User.invalidate_cache(user)
+ Pleroma.Repo.delete(user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/activities/#{uuid}")
+
+ assert response(conn, 500) == ~S({"error":"Something went wrong"})
+ end
+
+ test "404s on deleted objects", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
+
+ conn
+ |> put_req_header("accept", "application/xml")
+ |> get("/objects/#{uuid}")
+ |> response(200)
+
+ Object.delete(object)
+
+ conn
+ |> put_req_header("accept", "application/xml")
+ |> get("/objects/#{uuid}")
+ |> response(404)
+ end
+
+ test "404s on private activities", %{conn: conn} do
+ note_activity = insert(:direct_note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
+
+ conn
+ |> get("/activities/#{uuid}")
+ |> response(404)
+ end
+
+ test "404s on nonexistent activities", %{conn: conn} do
+ conn
+ |> get("/activities/123")
+ |> response(404)
+ end
+
+ test "gets an activity in AS2 format", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
+ url = "/activities/#{uuid}"
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get(url)
+
+ assert json_response(conn, 200)
+ end
end
- test "404s on private objects", %{conn: conn} do
- note_activity = insert(:direct_note_activity)
- object = Object.normalize(note_activity)
- [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
+ describe "GET notice/2" do
+ test "gets a notice in xml format", %{conn: conn} do
+ note_activity = insert(:note_activity)
- conn
- |> get("/objects/#{uuid}")
- |> response(404)
- end
+ conn
+ |> get("/notice/#{note_activity.id}")
+ |> response(200)
+ end
- test "404s on nonexisting objects", %{conn: conn} do
- conn
- |> get("/objects/123")
- |> response(404)
- end
+ test "gets a notice in AS2 format", %{conn: conn} do
+ note_activity = insert(:note_activity)
- test "gets an activity in xml format", %{conn: conn} do
- note_activity = insert(:note_activity)
- [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
-
- conn
- |> put_req_header("accept", "application/xml")
- |> get("/activities/#{uuid}")
- |> response(200)
- end
-
- test "404s on deleted objects", %{conn: conn} do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
-
- conn
- |> put_req_header("accept", "application/xml")
- |> get("/objects/#{uuid}")
- |> response(200)
-
- Object.delete(object)
-
- conn
- |> put_req_header("accept", "application/xml")
- |> get("/objects/#{uuid}")
- |> response(404)
- end
-
- test "404s on private activities", %{conn: conn} do
- note_activity = insert(:direct_note_activity)
- [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
-
- conn
- |> get("/activities/#{uuid}")
- |> response(404)
- end
-
- test "404s on nonexistent activities", %{conn: conn} do
- conn
- |> get("/activities/123")
- |> response(404)
- end
-
- test "gets a notice in xml format", %{conn: conn} do
- note_activity = insert(:note_activity)
-
- conn
- |> get("/notice/#{note_activity.id}")
- |> response(200)
- end
-
- test "gets a notice in AS2 format", %{conn: conn} do
- note_activity = insert(:note_activity)
-
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/notice/#{note_activity.id}")
- |> json_response(200)
- end
-
- test "only gets a notice in AS2 format for Create messages", %{conn: conn} do
- note_activity = insert(:note_activity)
- url = "/notice/#{note_activity.id}"
-
- conn =
conn
|> put_req_header("accept", "application/activity+json")
- |> get(url)
+ |> get("/notice/#{note_activity.id}")
+ |> json_response(200)
+ end
- assert json_response(conn, 200)
+ test "500s when actor not found", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+ User.invalidate_cache(user)
+ Pleroma.Repo.delete(user)
- user = insert(:user)
+ conn =
+ conn
+ |> get("/notice/#{note_activity.id}")
- {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
- url = "/notice/#{like_activity.id}"
+ assert response(conn, 500) == ~S({"error":"Something went wrong"})
+ end
- assert like_activity.data["type"] == "Like"
+ test "only gets a notice in AS2 format for Create messages", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ url = "/notice/#{note_activity.id}"
- conn =
- build_conn()
- |> put_req_header("accept", "application/activity+json")
- |> get(url)
+ conn =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get(url)
- assert response(conn, 404)
+ assert json_response(conn, 200)
+
+ user = insert(:user)
+
+ {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
+ url = "/notice/#{like_activity.id}"
+
+ assert like_activity.data["type"] == "Like"
+
+ conn =
+ build_conn()
+ |> put_req_header("accept", "application/activity+json")
+ |> get(url)
+
+ assert response(conn, 404)
+ end
+
+ test "render html for redirect for html format", %{conn: conn} do
+ note_activity = insert(:note_activity)
+
+ resp =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/#{note_activity.id}")
+ |> response(200)
+
+ assert resp =~
+ " "
+
+ user = insert(:user)
+
+ {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
+
+ assert like_activity.data["type"] == "Like"
+
+ resp =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/#{like_activity.id}")
+ |> response(200)
+
+ assert resp =~ ""
+ end
+
+ test "404s a private notice", %{conn: conn} do
+ note_activity = insert(:direct_note_activity)
+ url = "/notice/#{note_activity.id}"
+
+ conn =
+ conn
+ |> get(url)
+
+ assert response(conn, 404)
+ end
+
+ test "404s a nonexisting notice", %{conn: conn} do
+ url = "/notice/123"
+
+ conn =
+ conn
+ |> get(url)
+
+ assert response(conn, 404)
+ end
end
- test "gets an activity in AS2 format", %{conn: conn} do
- note_activity = insert(:note_activity)
- [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
- url = "/activities/#{uuid}"
+ describe "feed_redirect" do
+ test "undefined format. it redirects to feed", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get(url)
+ response =
+ conn
+ |> put_req_header("accept", "application/xml")
+ |> get("/users/#{user.nickname}")
+ |> response(302)
- assert json_response(conn, 200)
+ assert response ==
+ "You are being redirected ."
+ end
+
+ test "undefined format. it returns error when user not found", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("accept", "application/xml")
+ |> get("/users/jimm")
+ |> response(404)
+
+ assert response == ~S({"error":"Not found"})
+ end
+
+ test "activity+json format. it redirects on actual feed of user", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+ response =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get("/users/#{user.nickname}")
+ |> json_response(200)
+
+ assert response["endpoints"] == %{
+ "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
+ "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
+ "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
+ "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox"
+ }
+
+ assert response["@context"] == [
+ "https://www.w3.org/ns/activitystreams",
+ "http://localhost:4001/schemas/litepub-0.1.jsonld",
+ %{"@language" => "und"}
+ ]
+
+ assert Map.take(response, [
+ "followers",
+ "following",
+ "id",
+ "inbox",
+ "manuallyApprovesFollowers",
+ "name",
+ "outbox",
+ "preferredUsername",
+ "summary",
+ "tag",
+ "type",
+ "url"
+ ]) == %{
+ "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
+ "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
+ "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
+ "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
+ "manuallyApprovesFollowers" => false,
+ "name" => user.name,
+ "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
+ "preferredUsername" => user.nickname,
+ "summary" => user.bio,
+ "tag" => [],
+ "type" => "Person",
+ "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
+ }
+ end
+
+ test "activity+json format. it returns error whe use not found", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get("/users/jimm")
+ |> json_response(404)
+
+ assert response == "Not found"
+ end
+
+ test "json format. it redirects on actual feed of user", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+ response =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/#{user.nickname}")
+ |> json_response(200)
+
+ assert response["endpoints"] == %{
+ "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
+ "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
+ "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
+ "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox"
+ }
+
+ assert response["@context"] == [
+ "https://www.w3.org/ns/activitystreams",
+ "http://localhost:4001/schemas/litepub-0.1.jsonld",
+ %{"@language" => "und"}
+ ]
+
+ assert Map.take(response, [
+ "followers",
+ "following",
+ "id",
+ "inbox",
+ "manuallyApprovesFollowers",
+ "name",
+ "outbox",
+ "preferredUsername",
+ "summary",
+ "tag",
+ "type",
+ "url"
+ ]) == %{
+ "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
+ "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
+ "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
+ "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
+ "manuallyApprovesFollowers" => false,
+ "name" => user.name,
+ "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
+ "preferredUsername" => user.nickname,
+ "summary" => user.bio,
+ "tag" => [],
+ "type" => "Person",
+ "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
+ }
+ end
+
+ test "json format. it returns error whe use not found", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/jimm")
+ |> json_response(404)
+
+ assert response == "Not found"
+ end
+
+ test "html format. it redirects on actual feed of user", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+ response =
+ conn
+ |> get("/users/#{user.nickname}")
+ |> response(200)
+
+ assert response ==
+ Fallback.RedirectController.redirector_with_meta(
+ conn,
+ %{user: user}
+ ).resp_body
+ end
+
+ test "html format. it returns error when user not found", %{conn: conn} do
+ response =
+ conn
+ |> get("/users/jimm")
+ |> json_response(404)
+
+ assert response == %{"error" => "Not found"}
+ end
end
- test "404s a private notice", %{conn: conn} do
- note_activity = insert(:direct_note_activity)
- url = "/notice/#{note_activity.id}"
+ describe "GET /notice/:id/embed_player" do
+ test "render embed player", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Pleroma.Object.normalize(note_activity)
- conn =
- conn
- |> get(url)
+ object_data =
+ Map.put(object.data, "attachment", [
+ %{
+ "url" => [
+ %{
+ "href" =>
+ "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
+ ]
+ }
+ ])
- assert response(conn, 404)
- end
+ object
+ |> Ecto.Changeset.change(data: object_data)
+ |> Pleroma.Repo.update()
- test "404s a nonexisting notice", %{conn: conn} do
- url = "/notice/123"
+ conn =
+ conn
+ |> get("/notice/#{note_activity.id}/embed_player")
- conn =
- conn
- |> get(url)
+ assert Plug.Conn.get_resp_header(conn, "x-frame-options") == ["ALLOW"]
- assert response(conn, 404)
+ assert Plug.Conn.get_resp_header(
+ conn,
+ "content-security-policy"
+ ) == [
+ "default-src 'none';style-src 'self' 'unsafe-inline';img-src 'self' data: https:; media-src 'self' https:;"
+ ]
+
+ assert response(conn, 200) =~
+ "Your browser does not support video/mp4 playback. "
+ end
+
+ test "404s when activity isn't create", %{conn: conn} do
+ note_activity = insert(:note_activity, data_attrs: %{"type" => "Like"})
+
+ assert conn
+ |> get("/notice/#{note_activity.id}/embed_player")
+ |> response(404)
+ end
+
+ test "404s when activity is direct message", %{conn: conn} do
+ note_activity = insert(:note_activity, data_attrs: %{"directMessage" => true})
+
+ assert conn
+ |> get("/notice/#{note_activity.id}/embed_player")
+ |> response(404)
+ end
+
+ test "404s when attachment is empty", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Pleroma.Object.normalize(note_activity)
+ object_data = Map.put(object.data, "attachment", [])
+
+ object
+ |> Ecto.Changeset.change(data: object_data)
+ |> Pleroma.Repo.update()
+
+ assert conn
+ |> get("/notice/#{note_activity.id}/embed_player")
+ |> response(404)
+ end
+
+ test "404s when attachment isn't audio or video", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ object = Pleroma.Object.normalize(note_activity)
+
+ object_data =
+ Map.put(object.data, "attachment", [
+ %{
+ "url" => [
+ %{
+ "href" => "https://peertube.moe/static/webseed/480.jpg",
+ "mediaType" => "image/jpg",
+ "type" => "Link"
+ }
+ ]
+ }
+ ])
+
+ object
+ |> Ecto.Changeset.change(data: object_data)
+ |> Pleroma.Repo.update()
+
+ assert conn
+ |> get("/notice/#{note_activity.id}/embed_player")
+ |> response(404)
+ end
end
end
From c0e258cf21395fa2d5338ee238e4fcf4f3b3bf30 Mon Sep 17 00:00:00 2001
From: Sergey Suprunenko
Date: Mon, 29 Jul 2019 16:17:22 +0000
Subject: [PATCH 11/16] Redirect not logged-in users to the MastoFE login page
on private instances
---
CHANGELOG.md | 1 +
lib/pleroma/web/router.ex | 2 +-
.../mastodon_api/mastodon_api_controller_test.exs | 15 +++++++++++++++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48379b757..5416d452e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Rich Media: The crawled URL is now spliced into the rich media data.
- ActivityPub S2S: sharedInbox usage has been mostly aligned with the rules in the AP specification.
- ActivityPub S2S: remote user deletions now work the same as local user deletions.
+- Not being able to access the Mastodon FE login page on private instances
### Added
- MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 4e1ab6c33..0689d69fb 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -698,7 +698,7 @@ defmodule Pleroma.Web.Router do
post("/auth/password", MastodonAPIController, :password_reset)
scope [] do
- pipe_through(:oauth_read_or_public)
+ pipe_through(:oauth_read)
get("/web/*path", MastodonAPIController, :index)
end
end
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index d7f92fac2..66016c886 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -3154,6 +3154,21 @@ test "redirects not logged-in users to the login page", %{conn: conn, path: path
assert redirected_to(conn) == "/web/login"
end
+ test "redirects not logged-in users to the login page on private instances", %{
+ conn: conn,
+ path: path
+ } do
+ is_public = Pleroma.Config.get([:instance, :public])
+ Pleroma.Config.put([:instance, :public], false)
+
+ conn = get(conn, path)
+
+ assert conn.status == 302
+ assert redirected_to(conn) == "/web/login"
+
+ Pleroma.Config.put([:instance, :public], is_public)
+ end
+
test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
token = insert(:oauth_token)
From 0bee2131ce55ffd702ddc92800499b01b86d3765 Mon Sep 17 00:00:00 2001
From: Eugenij
Date: Mon, 29 Jul 2019 16:17:40 +0000
Subject: [PATCH 12/16] Add `mailerEnabled` to the NodeInfo metadata
---
CHANGELOG.md | 1 +
lib/pleroma/web/nodeinfo/nodeinfo_controller.ex | 1 +
2 files changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5416d452e..e77fe4f3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
- Federation: Return 403 errors when trying to request pages from a user's follower/following collections if they have `hide_followers`/`hide_follows` set
- NodeInfo: Return `skipThreadContainment` in `metadata` for the `skip_thread_containment` option
+- NodeInfo: Return `mailerEnabled` in `metadata`
- Mastodon API: Unsubscribe followers when they unfollow a user
- AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses)
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index a1d7fcc7d..54f89e65c 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -165,6 +165,7 @@ def raw_nodeinfo do
},
accountActivationRequired: Config.get([:instance, :account_activation_required], false),
invitesEnabled: Config.get([:instance, :invites_enabled], false),
+ mailerEnabled: Config.get([Pleroma.Emails.Mailer, :enabled], false),
features: features,
restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames]),
skipThreadContainment: Config.get([:instance, :skip_thread_containment], false)
From 5795a890e9d14a9e51e2613d26620899b2171623 Mon Sep 17 00:00:00 2001
From: Ariadne Conill
Date: Mon, 29 Jul 2019 19:09:58 +0000
Subject: [PATCH 13/16] markdown: clean up html generated by earmark
---
lib/pleroma/web/common_api/utils.ex | 3 +++
test/web/common_api/common_api_utils_test.exs | 10 +++++-----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index d80fffa26..6d42ae8ae 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -300,6 +300,9 @@ def format_input(text, "text/markdown", options) do
|> Earmark.as_html!()
|> Formatter.linkify(options)
|> Formatter.html_escape("text/html")
+ |> (fn {text, mentions, tags} ->
+ {String.replace(text, ~r/\r?\n/, ""), mentions, tags}
+ end).()
end
def make_note_data(
diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs
index af320f31f..38b2319ac 100644
--- a/test/web/common_api/common_api_utils_test.exs
+++ b/test/web/common_api/common_api_utils_test.exs
@@ -99,14 +99,14 @@ test "works for bare text/html" do
test "works for bare text/markdown" do
text = "**hello world**"
- expected = "hello world
\n"
+ expected = "hello world
"
{output, [], []} = Utils.format_input(text, "text/markdown")
assert output == expected
text = "**hello world**\n\n*another paragraph*"
- expected = "hello world
\nanother paragraph
\n"
+ expected = "hello world
another paragraph
"
{output, [], []} = Utils.format_input(text, "text/markdown")
@@ -118,7 +118,7 @@ test "works for bare text/markdown" do
by someone
"""
- expected = "cool quote
\n \nby someone
\n"
+ expected = "cool quote
by someone
"
{output, [], []} = Utils.format_input(text, "text/markdown")
@@ -157,11 +157,11 @@ test "works for text/markdown with mentions" do
text = "**hello world**\n\n*another @user__test and @user__test google.com paragraph*"
expected =
- "hello world
\nanother hello world
another @user__test and @user__test google.com paragraph
\n"
+ }\" class=\"u-url mention\" href=\"http://foo.com/user__test\">@user__test google.com paragraph
"
{output, _, _} = Utils.format_input(text, "text/markdown")
From 5835069215b880ad261a006cf310da624a82ca4a Mon Sep 17 00:00:00 2001
From: kaniini
Date: Mon, 29 Jul 2019 19:42:26 +0000
Subject: [PATCH 14/16] Revert "Merge branch
'bugfix/clean-up-markdown-rendering' into 'develop'"
This reverts merge request !1504
---
lib/pleroma/web/common_api/utils.ex | 3 ---
test/web/common_api/common_api_utils_test.exs | 10 +++++-----
2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 6d42ae8ae..d80fffa26 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -300,9 +300,6 @@ def format_input(text, "text/markdown", options) do
|> Earmark.as_html!()
|> Formatter.linkify(options)
|> Formatter.html_escape("text/html")
- |> (fn {text, mentions, tags} ->
- {String.replace(text, ~r/\r?\n/, ""), mentions, tags}
- end).()
end
def make_note_data(
diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs
index 38b2319ac..af320f31f 100644
--- a/test/web/common_api/common_api_utils_test.exs
+++ b/test/web/common_api/common_api_utils_test.exs
@@ -99,14 +99,14 @@ test "works for bare text/html" do
test "works for bare text/markdown" do
text = "**hello world**"
- expected = "hello world
"
+ expected = "hello world
\n"
{output, [], []} = Utils.format_input(text, "text/markdown")
assert output == expected
text = "**hello world**\n\n*another paragraph*"
- expected = "hello world
another paragraph
"
+ expected = "hello world
\nanother paragraph
\n"
{output, [], []} = Utils.format_input(text, "text/markdown")
@@ -118,7 +118,7 @@ test "works for bare text/markdown" do
by someone
"""
- expected = "cool quote
by someone
"
+ expected = "cool quote
\n \nby someone
\n"
{output, [], []} = Utils.format_input(text, "text/markdown")
@@ -157,11 +157,11 @@ test "works for text/markdown with mentions" do
text = "**hello world**\n\n*another @user__test and @user__test google.com paragraph*"
expected =
- "hello world
another hello world
\nanother @user__test and @user__test google.com paragraph
"
+ }\" class=\"u-url mention\" href=\"http://foo.com/user__test\">@user__test google.com paragraph\n"
{output, _, _} = Utils.format_input(text, "text/markdown")
From 3850812503ebfe0e1eaf84a4067e11e052a8206e Mon Sep 17 00:00:00 2001
From: Ariadne Conill
Date: Mon, 29 Jul 2019 20:00:57 +0000
Subject: [PATCH 15/16] twitter api: utils: rework do_remote_follow() to use
CommonAPI
Closes #1138
---
lib/pleroma/web/twitter_api/controllers/util_controller.ex | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 39bc6147c..5c73a615d 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -15,7 +15,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Pleroma.Plugs.AuthenticationPlug
alias Pleroma.User
alias Pleroma.Web
- alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.WebFinger
@@ -100,8 +99,7 @@ def do_remote_follow(conn, %{
with %User{} = user <- User.get_cached_by_nickname(username),
true <- AuthenticationPlug.checkpw(password, user.password_hash),
%User{} = _followed <- User.get_cached_by_id(id),
- {:ok, follower} <- User.follow(user, followee),
- {:ok, _activity} <- ActivityPub.follow(follower, followee) do
+ {:ok, _follower, _followee, _activity} <- CommonAPI.follow(user, followee) do
conn
|> render("followed.html", %{error: false})
else
@@ -122,8 +120,7 @@ def do_remote_follow(conn, %{
def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}}) do
with %User{} = followee <- User.get_cached_by_id(id),
- {:ok, follower} <- User.follow(user, followee),
- {:ok, _activity} <- ActivityPub.follow(follower, followee) do
+ {:ok, _follower, _followee, _activity} <- CommonAPI.follow(user, followee) do
conn
|> render("followed.html", %{error: false})
else
From 51b3b6d8164de9196159dc7de8d5abf0c4fa1bce Mon Sep 17 00:00:00 2001
From: Alexander Strizhakov
Date: Tue, 30 Jul 2019 16:36:05 +0000
Subject: [PATCH 16/16] Admin changes
---
CHANGELOG.md | 1 +
docs/api/admin_api.md | 23 ++++++++++++
lib/mix/tasks/pleroma/config.ex | 2 +-
.../web/admin_api/admin_api_controller.ex | 10 +++++
lib/pleroma/web/router.ex | 2 +
.../admin_api/admin_api_controller_test.exs | 37 +++++++++++++++++++
6 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e77fe4f3d..acd55362d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,6 +53,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Admin API: Return avatar and display name when querying users
- Admin API: Allow querying user by ID
- Admin API: Added support for `tuples`.
+- Admin API: Added endpoints to run mix tasks pleroma.config migrate_to_db & pleroma.config migrate_from_db
- Added synchronization of following/followers counters for external users
- Configuration: `enabled` option for `Pleroma.Emails.Mailer`, defaulting to `false`.
- Configuration: Pleroma.Plugs.RateLimiter `bucket_name`, `params` options.
diff --git a/docs/api/admin_api.md b/docs/api/admin_api.md
index ca9303227..22873dde9 100644
--- a/docs/api/admin_api.md
+++ b/docs/api/admin_api.md
@@ -575,6 +575,29 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
- 404 Not Found `"Not found"`
- On success: 200 OK `{}`
+
+## `/api/pleroma/admin/config/migrate_to_db`
+### Run mix task pleroma.config migrate_to_db
+Copy settings on key `:pleroma` to DB.
+- Method `GET`
+- Params: none
+- Response:
+
+```json
+{}
+```
+
+## `/api/pleroma/admin/config/migrate_from_db`
+### Run mix task pleroma.config migrate_from_db
+Copy all settings from DB to `config/prod.exported_from_db.secret.exs` with deletion from DB.
+- Method `GET`
+- Params: none
+- Response:
+
+```json
+{}
+```
+
## `/api/pleroma/admin/config`
### List config settings
List config settings only works with `:pleroma => :instance => :dynamic_configuration` setting to `true`.
diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex
index a7d0fac5d..462940e7e 100644
--- a/lib/mix/tasks/pleroma/config.ex
+++ b/lib/mix/tasks/pleroma/config.ex
@@ -15,7 +15,7 @@ defmodule Mix.Tasks.Pleroma.Config do
mix pleroma.config migrate_to_db
- ## Transfers config from DB to file.
+ ## Transfers config from DB to file `config/env.exported_from_db.secret.exs`
mix pleroma.config migrate_from_db ENV
"""
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 1ae5acd91..fcda57b3e 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -379,6 +379,16 @@ def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
end
end
+ def migrate_to_db(conn, _params) do
+ Mix.Tasks.Pleroma.Config.run(["migrate_to_db"])
+ json(conn, %{})
+ end
+
+ def migrate_from_db(conn, _params) do
+ Mix.Tasks.Pleroma.Config.run(["migrate_from_db", Pleroma.Config.get(:env), "true"])
+ json(conn, %{})
+ end
+
def config_show(conn, _params) do
configs = Pleroma.Repo.all(Config)
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 0689d69fb..d475fc973 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -196,6 +196,8 @@ defmodule Pleroma.Web.Router do
get("/config", AdminAPIController, :config_show)
post("/config", AdminAPIController, :config_update)
+ get("/config/migrate_to_db", AdminAPIController, :migrate_to_db)
+ get("/config/migrate_from_db", AdminAPIController, :migrate_from_db)
end
scope "/", Pleroma.Web.TwitterAPI do
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 6dda4ae51..824ad23e6 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -1916,6 +1916,43 @@ test "queues key as atom", %{conn: conn} do
end
end
+ describe "config mix tasks run" do
+ setup %{conn: conn} do
+ admin = insert(:user, info: %{is_admin: true})
+
+ temp_file = "config/test.exported_from_db.secret.exs"
+
+ on_exit(fn ->
+ :ok = File.rm(temp_file)
+ end)
+
+ dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
+
+ Pleroma.Config.put([:instance, :dynamic_configuration], true)
+
+ on_exit(fn ->
+ Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
+ end)
+
+ %{conn: assign(conn, :user, admin), admin: admin}
+ end
+
+ test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
+ assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
+ conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
+ assert json_response(conn, 200) == %{}
+ assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> get("/api/pleroma/admin/config/migrate_from_db")
+
+ assert json_response(conn, 200) == %{}
+ assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
+ end
+ end
+
describe "GET /api/pleroma/admin/users/:nickname/statuses" do
setup do
admin = insert(:user, info: %{is_admin: true})