Merge branch 'fix/2927-disallow-unauthenticated-access' into 'develop'
/api/v1/statuses/:id/context: filter context activities using Visibility.visible_for_user?/2 See merge request pleroma/pleroma!3801
This commit is contained in:
commit
b08cbe76f1
3 changed files with 290 additions and 0 deletions
1
changelog.d/3801.fix
Normal file
1
changelog.d/3801.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Filter context activities using Visibility.visible_for_user?
|
|
@ -455,6 +455,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|> maybe_preload_objects(opts)
|
|> maybe_preload_objects(opts)
|
||||||
|> maybe_preload_bookmarks(opts)
|
|> maybe_preload_bookmarks(opts)
|
||||||
|> maybe_set_thread_muted_field(opts)
|
|> maybe_set_thread_muted_field(opts)
|
||||||
|
|> restrict_unauthenticated(opts[:user])
|
||||||
|> restrict_blocked(opts)
|
|> restrict_blocked(opts)
|
||||||
|> restrict_blockers_visibility(opts)
|
|> restrict_blockers_visibility(opts)
|
||||||
|> restrict_recipients(recipients, opts[:user])
|
|> restrict_recipients(recipients, opts[:user])
|
||||||
|
@ -1215,6 +1216,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|
|
||||||
defp restrict_filtered(query, _), do: query
|
defp restrict_filtered(query, _), do: query
|
||||||
|
|
||||||
|
defp restrict_unauthenticated(query, nil) do
|
||||||
|
local = Config.restrict_unauthenticated_access?(:activities, :local)
|
||||||
|
remote = Config.restrict_unauthenticated_access?(:activities, :remote)
|
||||||
|
|
||||||
|
cond do
|
||||||
|
local and remote ->
|
||||||
|
from(activity in query, where: false)
|
||||||
|
|
||||||
|
local ->
|
||||||
|
from(activity in query, where: activity.local == false)
|
||||||
|
|
||||||
|
remote ->
|
||||||
|
from(activity in query, where: activity.local == true)
|
||||||
|
|
||||||
|
true ->
|
||||||
|
query
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp restrict_unauthenticated(query, _), do: query
|
||||||
|
|
||||||
defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
|
defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
|
||||||
|
|
||||||
defp exclude_poll_votes(query, _) do
|
defp exclude_poll_votes(query, _) do
|
||||||
|
|
|
@ -771,6 +771,49 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
||||||
{:ok, local: local, remote: remote}
|
{:ok, local: local, remote: remote}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp local_and_remote_context_activities do
|
||||||
|
local_user_1 = insert(:user)
|
||||||
|
local_user_2 = insert(:user)
|
||||||
|
remote_user = insert(:user, local: false)
|
||||||
|
|
||||||
|
{:ok, %{id: id1, data: %{"context" => context}}} =
|
||||||
|
CommonAPI.post(local_user_1, %{status: "post"})
|
||||||
|
|
||||||
|
{:ok, %{id: id2} = post} =
|
||||||
|
CommonAPI.post(local_user_2, %{status: "local reply", in_reply_to_status_id: id1})
|
||||||
|
|
||||||
|
params = %{
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"actor" => remote_user.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"context" => context,
|
||||||
|
"id" => "#{remote_user.ap_id}/activities/1",
|
||||||
|
"inReplyTo" => post.data["id"],
|
||||||
|
"object" => %{
|
||||||
|
"type" => "Note",
|
||||||
|
"content" => "remote reply",
|
||||||
|
"context" => context,
|
||||||
|
"id" => "#{remote_user.ap_id}/objects/1",
|
||||||
|
"attributedTo" => remote_user.ap_id,
|
||||||
|
"to" => [
|
||||||
|
local_user_1.ap_id,
|
||||||
|
local_user_2.ap_id,
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"to" => [
|
||||||
|
local_user_1.ap_id,
|
||||||
|
local_user_2.ap_id,
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, job} = Pleroma.Web.Federator.incoming_ap_doc(params)
|
||||||
|
{:ok, remote_activity} = ObanHelpers.perform(job)
|
||||||
|
|
||||||
|
%{locals: [id1, id2], remote: remote_activity.id, context: context}
|
||||||
|
end
|
||||||
|
|
||||||
describe "status with restrict unauthenticated activities for local and remote" do
|
describe "status with restrict unauthenticated activities for local and remote" do
|
||||||
setup do: local_and_remote_activities()
|
setup do: local_and_remote_activities()
|
||||||
|
|
||||||
|
@ -957,6 +1000,230 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "getting status contexts restricted unauthenticated for local and remote" do
|
||||||
|
setup do: local_and_remote_context_activities()
|
||||||
|
|
||||||
|
setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
|
||||||
|
|
||||||
|
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
|
||||||
|
|
||||||
|
test "if user is unauthenticated", %{conn: conn, locals: [post_id, _]} do
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
|
||||||
|
|
||||||
|
assert json_response_and_validate_schema(res_conn, 200) == %{
|
||||||
|
"ancestors" => [],
|
||||||
|
"descendants" => []
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is unauthenticated reply", %{conn: conn, locals: [_, reply_id]} do
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
|
||||||
|
|
||||||
|
assert json_response_and_validate_schema(res_conn, 200) == %{
|
||||||
|
"ancestors" => [],
|
||||||
|
"descendants" => []
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is authenticated", %{locals: [post_id, reply_id], remote: remote_reply_id} do
|
||||||
|
%{conn: conn} = oauth_access(["read"])
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => [], "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert reply_id in descendant_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is authenticated reply", %{locals: [post_id, reply_id], remote: remote_reply_id} do
|
||||||
|
%{conn: conn} = oauth_access(["read"])
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => ancestors, "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
ancestor_ids =
|
||||||
|
ancestors
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert post_id in ancestor_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "getting status contexts restricted unauthenticated for local" do
|
||||||
|
setup do: local_and_remote_context_activities()
|
||||||
|
|
||||||
|
setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
|
||||||
|
|
||||||
|
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], false)
|
||||||
|
|
||||||
|
test "if user is unauthenticated", %{
|
||||||
|
conn: conn,
|
||||||
|
locals: [post_id, reply_id],
|
||||||
|
remote: remote_reply_id
|
||||||
|
} do
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => [], "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert reply_id not in descendant_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is unauthenticated reply", %{
|
||||||
|
conn: conn,
|
||||||
|
locals: [post_id, reply_id],
|
||||||
|
remote: remote_reply_id
|
||||||
|
} do
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => ancestors, "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
ancestor_ids =
|
||||||
|
ancestors
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert post_id not in ancestor_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is authenticated", %{locals: [post_id, reply_id], remote: remote_reply_id} do
|
||||||
|
%{conn: conn} = oauth_access(["read"])
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => [], "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert reply_id in descendant_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is authenticated reply", %{locals: [post_id, reply_id], remote: remote_reply_id} do
|
||||||
|
%{conn: conn} = oauth_access(["read"])
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => ancestors, "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
ancestor_ids =
|
||||||
|
ancestors
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert post_id in ancestor_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "getting status contexts restricted unauthenticated for remote" do
|
||||||
|
setup do: local_and_remote_context_activities()
|
||||||
|
|
||||||
|
setup do: clear_config([:restrict_unauthenticated, :activities, :local], false)
|
||||||
|
|
||||||
|
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
|
||||||
|
|
||||||
|
test "if user is unauthenticated", %{
|
||||||
|
conn: conn,
|
||||||
|
locals: [post_id, reply_id],
|
||||||
|
remote: remote_reply_id
|
||||||
|
} do
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => [], "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert reply_id in descendant_ids
|
||||||
|
assert remote_reply_id not in descendant_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is unauthenticated reply", %{
|
||||||
|
conn: conn,
|
||||||
|
locals: [post_id, reply_id],
|
||||||
|
remote: remote_reply_id
|
||||||
|
} do
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => ancestors, "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
ancestor_ids =
|
||||||
|
ancestors
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert post_id in ancestor_ids
|
||||||
|
assert remote_reply_id not in descendant_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is authenticated", %{locals: [post_id, reply_id], remote: remote_reply_id} do
|
||||||
|
%{conn: conn} = oauth_access(["read"])
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{post_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => [], "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
reply_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert reply_id in reply_ids
|
||||||
|
assert remote_reply_id in reply_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "if user is authenticated reply", %{locals: [post_id, reply_id], remote: remote_reply_id} do
|
||||||
|
%{conn: conn} = oauth_access(["read"])
|
||||||
|
res_conn = get(conn, "/api/v1/statuses/#{reply_id}/context")
|
||||||
|
|
||||||
|
%{"ancestors" => ancestors, "descendants" => descendants} =
|
||||||
|
json_response_and_validate_schema(res_conn, 200)
|
||||||
|
|
||||||
|
ancestor_ids =
|
||||||
|
ancestors
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
descendant_ids =
|
||||||
|
descendants
|
||||||
|
|> Enum.map(& &1["id"])
|
||||||
|
|
||||||
|
assert post_id in ancestor_ids
|
||||||
|
assert remote_reply_id in descendant_ids
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "deleting a status" do
|
describe "deleting a status" do
|
||||||
test "when you created it" do
|
test "when you created it" do
|
||||||
%{user: author, conn: conn} = oauth_access(["write:statuses"])
|
%{user: author, conn: conn} = oauth_access(["write:statuses"])
|
||||||
|
|
Loading…
Reference in a new issue