Allow fine-grained announce visibilities
Mastodon supports all standard visibilities except direct here, but until now we artificially limited this to either fully public or followers-only.
This commit is contained in:
parent
f452430acc
commit
954f6f7de0
4 changed files with 38 additions and 31 deletions
|
|
@ -316,21 +316,18 @@ def block(blocker, blocked) do
|
|||
|
||||
@spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()}
|
||||
def announce(actor, object, options \\ []) do
|
||||
public? = Keyword.get(options, :public, false)
|
||||
visibility = Keyword.get(options, :visibility, "public")
|
||||
|
||||
to =
|
||||
cond do
|
||||
actor.ap_id == Relay.ap_id() ->
|
||||
[actor.follower_address]
|
||||
|
||||
public? and Visibility.is_local_public?(object) ->
|
||||
[actor.follower_address, object.data["actor"], Utils.as_local_public()]
|
||||
|
||||
public? ->
|
||||
[actor.follower_address, object.data["actor"], Pleroma.Constants.as_public()]
|
||||
|
||||
true ->
|
||||
[actor.follower_address, object.data["actor"]]
|
||||
{to, cc} =
|
||||
if actor.ap_id == Relay.ap_id() do
|
||||
{[actor.follower_address], []}
|
||||
else
|
||||
Pleroma.Web.CommonAPI.Utils.get_to_and_cc_for_visibility(
|
||||
visibility,
|
||||
actor.follower_address,
|
||||
nil,
|
||||
[object.data["actor"]]
|
||||
)
|
||||
end
|
||||
|
||||
{:ok,
|
||||
|
|
@ -339,6 +336,7 @@ def announce(actor, object, options \\ []) do
|
|||
"actor" => actor.ap_id,
|
||||
"object" => object.data["id"],
|
||||
"to" => to,
|
||||
"cc" => cc,
|
||||
"context" => object.data["context"],
|
||||
"type" => "Announce",
|
||||
"published" => Utils.make_date()
|
||||
|
|
|
|||
|
|
@ -123,8 +123,8 @@ def repeat(id, user, params \\ %{}) do
|
|||
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id(id),
|
||||
object = %Object{} <- Object.normalize(activity, fetch: false),
|
||||
{_, nil} <- {:existing_announce, Utils.get_existing_announce(user.ap_id, object)},
|
||||
public = public_announce?(object, params),
|
||||
{:ok, announce, _} <- Builder.announce(user, object, public: public),
|
||||
visibility = announce_visibility(object, params),
|
||||
{:ok, announce, _} <- Builder.announce(user, object, visibility: visibility),
|
||||
{:ok, activity, _} <- Pipeline.common_pipeline(announce, local: true) do
|
||||
{:ok, activity}
|
||||
else
|
||||
|
|
@ -286,13 +286,11 @@ defp normalize_and_validate_choices(choices, object) do
|
|||
end
|
||||
end
|
||||
|
||||
def public_announce?(_, %{visibility: visibility})
|
||||
when visibility in ~w{public unlisted private direct},
|
||||
do: visibility in ~w(public unlisted)
|
||||
def announce_visibility(_, %{visibility: visibility})
|
||||
when visibility in ~w{public unlisted private direct local},
|
||||
do: visibility
|
||||
|
||||
def public_announce?(object, _) do
|
||||
Visibility.is_public?(object)
|
||||
end
|
||||
def announce_visibility(object, _), do: Visibility.get_visibility(object)
|
||||
|
||||
def get_visibility(_, _, %Participation{}), do: {"direct", "direct"}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,23 +86,32 @@ test "returns an error if the actor can't announce the object", %{
|
|||
object = Object.normalize(post_activity, fetch: false)
|
||||
|
||||
# Another user can't announce it
|
||||
{:ok, announce, []} = Builder.announce(announcer, object, public: false)
|
||||
{:ok, announce, []} = Builder.announce(announcer, object, visibility: "private")
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(announce, [])
|
||||
|
||||
assert {:actor, {"can not announce this object", []}} in cng.errors
|
||||
|
||||
# The actor of the object can announce it
|
||||
{:ok, announce, []} = Builder.announce(user, object, public: false)
|
||||
# The actor of the object can announce it with a restrictive scope
|
||||
{:ok, announce, []} = Builder.announce(user, object, visibility: "private")
|
||||
assert {:ok, _, _} = ObjectValidator.validate(announce, [])
|
||||
|
||||
{:ok, announce, []} = Builder.announce(user, object, visibility: "direct")
|
||||
assert {:ok, _, _} = ObjectValidator.validate(announce, [])
|
||||
|
||||
# The actor of the object can not announce it publicly
|
||||
{:ok, announce, []} = Builder.announce(user, object, public: true)
|
||||
{:ok, announce, []} = Builder.announce(user, object, visibility: "public")
|
||||
{:error, cng1} = ObjectValidator.validate(announce, [])
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(announce, [])
|
||||
{:ok, announce, []} = Builder.announce(user, object, visibility: "unlisted")
|
||||
{:error, cng2} = ObjectValidator.validate(announce, [])
|
||||
|
||||
{:ok, announce, []} = Builder.announce(user, object, visibility: "local")
|
||||
{:error, cng3} = ObjectValidator.validate(announce, [])
|
||||
|
||||
for cng <- [cng1, cng2, cng3] do
|
||||
assert {:actor, {"can not announce this object publicly", []}} in cng.errors
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -684,13 +684,15 @@ test "creates a notification", %{like: like, poster: poster} do
|
|||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
{:ok, private_post} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
|
||||
|
||||
{:ok, announce_data, _meta} = Builder.announce(user, post.object, public: true)
|
||||
{:ok, announce_data, _meta} = Builder.announce(user, post.object, visibility: "public")
|
||||
|
||||
{:ok, private_announce_data, _meta} =
|
||||
Builder.announce(user, private_post.object, public: false)
|
||||
Builder.announce(user, private_post.object, visibility: "private")
|
||||
|
||||
{:ok, relay_announce_data, _meta} =
|
||||
Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object, public: true)
|
||||
Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object,
|
||||
visibility: "public"
|
||||
)
|
||||
|
||||
{:ok, announce, _meta} = ActivityPub.persist(announce_data, local: true)
|
||||
{:ok, private_announce, _meta} = ActivityPub.persist(private_announce_data, local: true)
|
||||
|
|
|
|||
Loading…
Reference in a new issue