forked from AkkomaGang/akkoma
Merge branch 'prevent-public-answers' into 'develop'
Prevent public answers to direct messages See merge request pleroma/pleroma!1159
This commit is contained in:
commit
18f2d2024d
6 changed files with 79 additions and 39 deletions
|
@ -58,4 +58,28 @@ def entire_thread_visible_for_user?(
|
||||||
visible_for_user?(tail, user)
|
visible_for_user?(tail, user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_visibility(object) do
|
||||||
|
public = "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
to = object.data["to"] || []
|
||||||
|
cc = object.data["cc"] || []
|
||||||
|
|
||||||
|
cond do
|
||||||
|
public in to ->
|
||||||
|
"public"
|
||||||
|
|
||||||
|
public in cc ->
|
||||||
|
"unlisted"
|
||||||
|
|
||||||
|
# this should use the sql for the object's activity
|
||||||
|
Enum.any?(to, &String.contains?(&1, "/followers")) ->
|
||||||
|
"private"
|
||||||
|
|
||||||
|
length(cc) > 0 ->
|
||||||
|
"private"
|
||||||
|
|
||||||
|
true ->
|
||||||
|
"direct"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,32 +116,34 @@ def unfavorite(id_or_ap_id, user) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_visibility(%{"visibility" => visibility})
|
def get_visibility(%{"visibility" => visibility}, in_reply_to)
|
||||||
when visibility in ~w{public unlisted private direct},
|
when visibility in ~w{public unlisted private direct},
|
||||||
do: visibility
|
do: {visibility, get_replied_to_visibility(in_reply_to)}
|
||||||
|
|
||||||
def get_visibility(%{"in_reply_to_status_id" => status_id}) when not is_nil(status_id) do
|
def get_visibility(_, in_reply_to) when not is_nil(in_reply_to) do
|
||||||
case get_replied_to_activity(status_id) do
|
visibility = get_replied_to_visibility(in_reply_to)
|
||||||
nil ->
|
{visibility, visibility}
|
||||||
"public"
|
end
|
||||||
|
|
||||||
in_reply_to ->
|
def get_visibility(_, in_reply_to), do: {"public", get_replied_to_visibility(in_reply_to)}
|
||||||
# XXX: these heuristics should be moved out of MastodonAPI.
|
|
||||||
with %Object{} = object <- Object.normalize(in_reply_to) do
|
def get_replied_to_visibility(nil), do: nil
|
||||||
Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)
|
|
||||||
end
|
def get_replied_to_visibility(activity) do
|
||||||
|
with %Object{} = object <- Object.normalize(activity) do
|
||||||
|
Pleroma.Web.ActivityPub.Visibility.get_visibility(object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_visibility(_), do: "public"
|
|
||||||
|
|
||||||
def post(user, %{"status" => status} = data) do
|
def post(user, %{"status" => status} = data) do
|
||||||
visibility = get_visibility(data)
|
|
||||||
limit = Pleroma.Config.get([:instance, :limit])
|
limit = Pleroma.Config.get([:instance, :limit])
|
||||||
|
|
||||||
with status <- String.trim(status),
|
with status <- String.trim(status),
|
||||||
attachments <- attachments_from_ids(data),
|
attachments <- attachments_from_ids(data),
|
||||||
in_reply_to <- get_replied_to_activity(data["in_reply_to_status_id"]),
|
in_reply_to <- get_replied_to_activity(data["in_reply_to_status_id"]),
|
||||||
|
{visibility, in_reply_to_visibility} <- get_visibility(data, in_reply_to),
|
||||||
|
{_, false} <-
|
||||||
|
{:private_to_public, in_reply_to_visibility == "direct" && visibility != "direct"},
|
||||||
{content_html, mentions, tags} <-
|
{content_html, mentions, tags} <-
|
||||||
make_content_html(
|
make_content_html(
|
||||||
status,
|
status,
|
||||||
|
@ -185,6 +187,8 @@ def post(user, %{"status" => status} = data) do
|
||||||
)
|
)
|
||||||
|
|
||||||
res
|
res
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
|
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1]
|
||||||
|
|
||||||
# TODO: Add cached version.
|
# TODO: Add cached version.
|
||||||
defp get_replied_to_activities(activities) do
|
defp get_replied_to_activities(activities) do
|
||||||
activities
|
activities
|
||||||
|
@ -340,30 +342,6 @@ def get_reply_to(%{data: %{"object" => _object}} = activity, _) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_visibility(object) do
|
|
||||||
public = "https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
to = object.data["to"] || []
|
|
||||||
cc = object.data["cc"] || []
|
|
||||||
|
|
||||||
cond do
|
|
||||||
public in to ->
|
|
||||||
"public"
|
|
||||||
|
|
||||||
public in cc ->
|
|
||||||
"unlisted"
|
|
||||||
|
|
||||||
# this should use the sql for the object's activity
|
|
||||||
Enum.any?(to, &String.contains?(&1, "/followers")) ->
|
|
||||||
"private"
|
|
||||||
|
|
||||||
length(cc) > 0 ->
|
|
||||||
"private"
|
|
||||||
|
|
||||||
true ->
|
|
||||||
"direct"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_content(%{data: %{"type" => "Video"}} = object) do
|
def render_content(%{data: %{"type" => "Video"}} = object) do
|
||||||
with name when not is_nil(name) and name != "" <- object.data["name"] do
|
with name when not is_nil(name) and name != "" <- object.data["name"] do
|
||||||
"<p><a href=\"#{object.data["id"]}\">#{name}</a></p>#{object.data["content"]}"
|
"<p><a href=\"#{object.data["id"]}\">#{name}</a></p>#{object.data["content"]}"
|
||||||
|
|
|
@ -310,7 +310,7 @@ def render(
|
||||||
"tags" => tags,
|
"tags" => tags,
|
||||||
"activity_type" => "post",
|
"activity_type" => "post",
|
||||||
"possibly_sensitive" => possibly_sensitive,
|
"possibly_sensitive" => possibly_sensitive,
|
||||||
"visibility" => StatusView.get_visibility(object),
|
"visibility" => Pleroma.Web.ActivityPub.Visibility.get_visibility(object),
|
||||||
"summary" => summary,
|
"summary" => summary,
|
||||||
"summary_html" => summary |> Formatter.emojify(object.data["emoji"]),
|
"summary_html" => summary |> Formatter.emojify(object.data["emoji"]),
|
||||||
"card" => card,
|
"card" => card,
|
||||||
|
|
|
@ -95,4 +95,16 @@ test "visible_for_user?", %{
|
||||||
refute Visibility.visible_for_user?(private, unrelated)
|
refute Visibility.visible_for_user?(private, unrelated)
|
||||||
refute Visibility.visible_for_user?(direct, unrelated)
|
refute Visibility.visible_for_user?(direct, unrelated)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "get_visibility", %{
|
||||||
|
public: public,
|
||||||
|
private: private,
|
||||||
|
direct: direct,
|
||||||
|
unlisted: unlisted
|
||||||
|
} do
|
||||||
|
assert Visibility.get_visibility(public) == "public"
|
||||||
|
assert Visibility.get_visibility(private) == "private"
|
||||||
|
assert Visibility.get_visibility(direct) == "direct"
|
||||||
|
assert Visibility.get_visibility(unlisted) == "unlisted"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -87,6 +87,28 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||||
|
|
||||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it does not allow replies to direct messages that are not direct messages themselves" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"})
|
||||||
|
|
||||||
|
assert {:ok, _} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "suya..",
|
||||||
|
"visibility" => "direct",
|
||||||
|
"in_reply_to_status_id" => activity.id
|
||||||
|
})
|
||||||
|
|
||||||
|
Enum.each(["public", "private", "unlisted"], fn visibility ->
|
||||||
|
assert {:error, {:private_to_public, _}} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "suya..",
|
||||||
|
"visibility" => visibility,
|
||||||
|
"in_reply_to_status_id" => activity.id
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "reactions" do
|
describe "reactions" do
|
||||||
|
|
Loading…
Reference in a new issue