aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaniini <nenolod@gmail.com>2019-06-05 08:28:20 +0000
committerkaniini <nenolod@gmail.com>2019-06-05 08:28:20 +0000
commite4babb1c9ff4c28ff08888736cc330a48b19b396 (patch)
tree3599c305e129871247fb97cf3923b8b96159856c
parent5188add534a1532ef323a0fec3503f8e96dfe762 (diff)
parent18c35d84fd732a6d55c9d3174fcbb837e098ea0a (diff)
downloadpleroma-e4babb1c9ff4c28ff08888736cc330a48b19b396.tar.gz
Merge branch 'explicit-addressing' into 'develop'
Explicit addressing See merge request pleroma/pleroma!1239
-rw-r--r--CHANGELOG.md1
-rw-r--r--docs/api/differences_in_mastoapi_responses.md1
-rw-r--r--lib/pleroma/user.ex8
-rw-r--r--lib/pleroma/web/common_api/common_api.ex4
-rw-r--r--lib/pleroma/web/common_api/utils.ex24
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo_controller.ex1
-rw-r--r--test/user_test.exs12
-rw-r--r--test/web/common_api/common_api_test.exs19
-rw-r--r--test/web/common_api/common_api_utils_test.exs133
9 files changed, 191 insertions, 12 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2fa9bd1e7..d1d87238c 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]
### Added
- Add a generic settings store for frontends / clients to use.
+- Explicit addressing option for posting.
- Optional SSH access mode. (Needs `erlang-ssh` package on some distributions).
- [MongooseIM](https://github.com/esl/MongooseIM) http authentication support.
- LDAP authentication
diff --git a/docs/api/differences_in_mastoapi_responses.md b/docs/api/differences_in_mastoapi_responses.md
index 623d4fbf5..f5766c2d9 100644
--- a/docs/api/differences_in_mastoapi_responses.md
+++ b/docs/api/differences_in_mastoapi_responses.md
@@ -70,6 +70,7 @@ Additional parameters can be added to the JSON body/Form data:
- `preview`: boolean, if set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example.
- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
+- `to`: A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply.
## PATCH `/api/v1/update_credentials`
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 474cd8c1a..dc534b05c 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1441,4 +1441,12 @@ defmodule Pleroma.User do
update_and_set_cache(cng)
end
end
+
+ def get_ap_ids_by_nicknames(nicknames) do
+ from(u in User,
+ where: u.nickname in ^nicknames,
+ select: u.ap_id
+ )
+ |> Repo.all()
+ end
end
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index ad3c03c55..2b3ae3de5 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -204,8 +204,10 @@ defmodule Pleroma.Web.CommonAPI do
data,
visibility
),
+ mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.ap_id),
+ addressed_users <- get_addressed_users(mentioned_users, data["to"]),
{poll, poll_emoji} <- make_poll_data(data),
- {to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility),
+ {to, cc} <- get_to_and_cc(user, addressed_users, in_reply_to, visibility),
context <- make_context(in_reply_to),
cw <- data["spoiler_text"] || "",
sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}),
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index f35ed36ab..6d82c0bd2 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -61,9 +61,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end)
end
- def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do
- mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
-
+ @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]
cc = [user.follower_address]
@@ -74,9 +74,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
end
- def to_for_user_and_mentions(user, mentions, inReplyTo, "unlisted") do
- mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
-
+ 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"]
@@ -87,14 +85,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
end
- def to_for_user_and_mentions(user, mentions, inReplyTo, "private") do
- {to, cc} = to_for_user_and_mentions(user, mentions, inReplyTo, "direct")
+ def get_to_and_cc(user, mentioned_users, inReplyTo, "private") do
+ {to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct")
{[user.follower_address | to], cc}
end
- def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do
- mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
-
+ def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do
if inReplyTo do
{Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []}
else
@@ -102,6 +98,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
end
+ def get_addressed_users(_, to) when is_list(to) do
+ User.get_ap_ids_by_nicknames(to)
+ end
+
+ def get_addressed_users(mentioned_users, _), do: mentioned_users
+
def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_in}} = data)
when is_list(options) do
%{max_expiration: max_expiration, min_expiration: min_expiration} =
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index 57f5b61bb..32be430b7 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -98,6 +98,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
"mastodon_api",
"mastodon_api_streaming",
"polls",
+ "pleroma_explicit_addressing",
if Config.get([:media_proxy, :enabled]) do
"media_proxy"
end,
diff --git a/test/user_test.exs b/test/user_test.exs
index 019f2b56d..d7473ef43 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1266,4 +1266,16 @@ defmodule Pleroma.UserTest do
assert user.info.keys == "xxx"
end
end
+
+ describe "get_ap_ids_by_nicknames" do
+ test "it returns a list of AP ids for a given set of nicknames" do
+ user = insert(:user)
+ user_two = insert(:user)
+
+ ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
+ assert length(ap_ids) == 2
+ assert user.ap_id in ap_ids
+ assert user_two.ap_id in ap_ids
+ end
+ end
end
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index 696060fb1..26efe6140 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -56,6 +56,25 @@ defmodule Pleroma.Web.CommonAPITest do
end
describe "posting" do
+ test "it supports explicit addressing" do
+ user = insert(:user)
+ user_two = insert(:user)
+ user_three = insert(:user)
+ user_four = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" =>
+ "Hey, I think @#{user_three.nickname} is ugly. @#{user_four.nickname} is alright though.",
+ "to" => [user_two.nickname, user_four.nickname, "nonexistent"]
+ })
+
+ assert user.ap_id in activity.recipients
+ assert user_two.ap_id in activity.recipients
+ assert user_four.ap_id in activity.recipients
+ refute user_three.ap_id in activity.recipients
+ end
+
test "it filters out obviously bad tags when accepting a post as HTML" do
user = insert(:user)
diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs
index ab4c62b35..b3a334d50 100644
--- a/test/web/common_api/common_api_utils_test.exs
+++ b/test/web/common_api/common_api_utils_test.exs
@@ -5,10 +5,15 @@
defmodule Pleroma.Web.CommonAPI.UtilsTest do
alias Pleroma.Builders.UserBuilder
alias Pleroma.Object
+ alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.Endpoint
use Pleroma.DataCase
+ import Pleroma.Factory
+
+ @public_address "https://www.w3.org/ns/activitystreams#Public"
+
test "it adds attachment links to a given text and attachment set" do
name =
"Sakura%20Mana%20%E2%80%93%20Turned%20on%20by%20a%20Senior%20OL%20with%20a%20Temptating%20Tight%20Skirt-s%20Full%20Hipline%20and%20Panty%20Shot-%20Beautiful%20Thick%20Thighs-%20and%20Erotic%20Ass-%20-2015-%20--%20Oppaitime%208-28-2017%206-50-33%20PM.png"
@@ -214,4 +219,132 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
assert Utils.date_to_asctime(nil) == expected
end
end
+
+ describe "get_to_and_cc" do
+ test "for public posts, not a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public")
+
+ assert length(to) == 2
+ assert length(cc) == 1
+
+ assert @public_address in to
+ assert mentioned_user.ap_id in to
+ assert user.follower_address in cc
+ end
+
+ test "for public posts, a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ third_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public")
+
+ assert length(to) == 3
+ assert length(cc) == 1
+
+ assert @public_address in to
+ assert mentioned_user.ap_id in to
+ assert third_user.ap_id in to
+ assert user.follower_address in cc
+ end
+
+ test "for unlisted posts, not a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted")
+
+ assert length(to) == 2
+ assert length(cc) == 1
+
+ assert @public_address in cc
+ assert mentioned_user.ap_id in to
+ assert user.follower_address in to
+ end
+
+ test "for unlisted posts, a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ third_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted")
+
+ assert length(to) == 3
+ assert length(cc) == 1
+
+ assert @public_address in cc
+ assert mentioned_user.ap_id in to
+ assert third_user.ap_id in to
+ assert user.follower_address in to
+ end
+
+ test "for private posts, not a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private")
+
+ assert length(to) == 2
+ assert length(cc) == 0
+
+ assert mentioned_user.ap_id in to
+ assert user.follower_address in to
+ end
+
+ test "for private posts, a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ third_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private")
+
+ assert length(to) == 3
+ assert length(cc) == 0
+
+ assert mentioned_user.ap_id in to
+ assert third_user.ap_id in to
+ assert user.follower_address in to
+ end
+
+ test "for direct posts, not a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct")
+
+ assert length(to) == 1
+ assert length(cc) == 0
+
+ assert mentioned_user.ap_id in to
+ end
+
+ test "for direct posts, a reply" do
+ user = insert(:user)
+ mentioned_user = insert(:user)
+ third_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ mentions = [mentioned_user.ap_id]
+
+ {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct")
+
+ assert length(to) == 2
+ assert length(cc) == 0
+
+ assert mentioned_user.ap_id in to
+ assert third_user.ap_id in to
+ end
+ end
end