Merge remote-tracking branch 'pleroma/develop' into feature/addressable-lists
This commit is contained in:
commit
cfa5572d28
|
@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
### Added
|
### Added
|
||||||
- Add a generic settings store for frontends / clients to use.
|
- 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).
|
- Optional SSH access mode. (Needs `erlang-ssh` package on some distributions).
|
||||||
- [MongooseIM](https://github.com/esl/MongooseIM) http authentication support.
|
- [MongooseIM](https://github.com/esl/MongooseIM) http authentication support.
|
||||||
- LDAP authentication
|
- LDAP authentication
|
||||||
|
|
|
@ -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.
|
- `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.
|
- `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.
|
||||||
- `visibility`: string, besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`.
|
- `visibility`: string, besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`.
|
||||||
|
|
||||||
## PATCH `/api/v1/update_credentials`
|
## PATCH `/api/v1/update_credentials`
|
||||||
|
|
|
@ -1441,4 +1441,12 @@ def ensure_keys_present(user) do
|
||||||
update_and_set_cache(cng)
|
update_and_set_cache(cng)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -209,8 +209,10 @@ def post(user, %{"status" => status} = data) do
|
||||||
data,
|
data,
|
||||||
visibility
|
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),
|
{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),
|
||||||
bcc <- bcc_for_list(user, visibility),
|
bcc <- bcc_for_list(user, visibility),
|
||||||
context <- make_context(in_reply_to),
|
context <- make_context(in_reply_to),
|
||||||
cw <- data["spoiler_text"] || "",
|
cw <- data["spoiler_text"] || "",
|
||||||
|
|
|
@ -61,9 +61,9 @@ def attachments_from_ids_descs(ids, descs_str) do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do
|
@spec get_to_and_cc(User.t(), list(String.t()), Activity.t() | nil, String.t()) ::
|
||||||
mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
|
{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 = ["https://www.w3.org/ns/activitystreams#Public" | mentioned_users]
|
||||||
cc = [user.follower_address]
|
cc = [user.follower_address]
|
||||||
|
|
||||||
|
@ -74,9 +74,7 @@ def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_for_user_and_mentions(user, mentions, inReplyTo, "unlisted") do
|
def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do
|
||||||
mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
|
|
||||||
|
|
||||||
to = [user.follower_address | mentioned_users]
|
to = [user.follower_address | mentioned_users]
|
||||||
cc = ["https://www.w3.org/ns/activitystreams#Public"]
|
cc = ["https://www.w3.org/ns/activitystreams#Public"]
|
||||||
|
|
||||||
|
@ -87,14 +85,12 @@ def to_for_user_and_mentions(user, mentions, inReplyTo, "unlisted") do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_for_user_and_mentions(user, mentions, inReplyTo, "private") do
|
def get_to_and_cc(user, mentioned_users, inReplyTo, "private") do
|
||||||
{to, cc} = to_for_user_and_mentions(user, mentions, inReplyTo, "direct")
|
{to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct")
|
||||||
{[user.follower_address | to], cc}
|
{[user.follower_address | to], cc}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do
|
def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do
|
||||||
mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
|
|
||||||
|
|
||||||
if inReplyTo do
|
if inReplyTo do
|
||||||
{Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []}
|
{Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []}
|
||||||
else
|
else
|
||||||
|
@ -102,7 +98,11 @@ def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_for_user_and_mentions(_user, _mentions, _inReplyTo, _), do: {[], []}
|
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 bcc_for_list(user, {:list, list_id}) do
|
def bcc_for_list(user, {:list, list_id}) do
|
||||||
list = Pleroma.List.get(list_id, user)
|
list = Pleroma.List.get(list_id, user)
|
||||||
|
|
|
@ -98,6 +98,7 @@ def raw_nodeinfo do
|
||||||
"mastodon_api",
|
"mastodon_api",
|
||||||
"mastodon_api_streaming",
|
"mastodon_api_streaming",
|
||||||
"polls",
|
"polls",
|
||||||
|
"pleroma_explicit_addressing",
|
||||||
if Config.get([:media_proxy, :enabled]) do
|
if Config.get([:media_proxy, :enabled]) do
|
||||||
"media_proxy"
|
"media_proxy"
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -1266,4 +1266,16 @@ test "it doesn't create keys if there already are some" do
|
||||||
assert user.info.keys == "xxx"
|
assert user.info.keys == "xxx"
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -56,6 +56,25 @@ test "it adds emoji when updating profiles" do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "posting" do
|
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
|
test "it filters out obviously bad tags when accepting a post as HTML" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,15 @@
|
||||||
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
||||||
alias Pleroma.Builders.UserBuilder
|
alias Pleroma.Builders.UserBuilder
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
use Pleroma.DataCase
|
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
|
test "it adds attachment links to a given text and attachment set" do
|
||||||
name =
|
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"
|
"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 @@ test "when date is nil" do
|
||||||
assert Utils.date_to_asctime(nil) == expected
|
assert Utils.date_to_asctime(nil) == expected
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
Loading…
Reference in New Issue