forked from AkkomaGang/akkoma
Merge branch 'feature/store-statuses-data-inside-flag' into 'develop'
Store status data inside flag activity See merge request pleroma/pleroma!1849
This commit is contained in:
commit
556da92902
8 changed files with 176 additions and 38 deletions
|
@ -65,8 +65,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- OStatus: Extract RSS functionality
|
- OStatus: Extract RSS functionality
|
||||||
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
||||||
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
||||||
</details>
|
|
||||||
- Deprecated `User.Info` embedded schema (fields moved to `User`)
|
- Deprecated `User.Info` embedded schema (fields moved to `User`)
|
||||||
|
- Store status data inside Flag activity
|
||||||
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Report emails now include functional links to profiles of remote user accounts
|
- Report emails now include functional links to profiles of remote user accounts
|
||||||
|
|
|
@ -503,7 +503,8 @@ def flag(
|
||||||
|
|
||||||
with flag_data <- make_flag_data(params, additional),
|
with flag_data <- make_flag_data(params, additional),
|
||||||
{:ok, activity} <- insert(flag_data, local),
|
{:ok, activity} <- insert(flag_data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
{:ok, stripped_activity} <- strip_report_status_data(activity),
|
||||||
|
:ok <- maybe_federate(stripped_activity) do
|
||||||
Enum.each(User.all_superusers(), fn superuser ->
|
Enum.each(User.all_superusers(), fn superuser ->
|
||||||
superuser
|
superuser
|
||||||
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
|
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
|
||||||
|
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
alias Pleroma.Web.Router.Helpers
|
alias Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
||||||
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer", "Audio"]
|
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer", "Audio"]
|
||||||
|
@strip_status_report_states ~w(closed resolved)
|
||||||
@supported_report_states ~w(open closed resolved)
|
@supported_report_states ~w(open closed resolved)
|
||||||
@valid_visibilities ~w(public unlisted private direct)
|
@valid_visibilities ~w(public unlisted private direct)
|
||||||
|
|
||||||
|
@ -614,10 +616,24 @@ def make_flag_data(_, _), do: %{}
|
||||||
|
|
||||||
defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
||||||
[account.ap_id] ++
|
[account.ap_id] ++
|
||||||
Enum.map(statuses || [], fn
|
Enum.map(statuses || [], fn act ->
|
||||||
%Activity{} = act -> act.data["id"]
|
id =
|
||||||
act when is_map(act) -> act["id"]
|
case act do
|
||||||
act when is_binary(act) -> act
|
%Activity{} = act -> act.data["id"]
|
||||||
|
act when is_map(act) -> act["id"]
|
||||||
|
act when is_binary(act) -> act
|
||||||
|
end
|
||||||
|
|
||||||
|
activity = Activity.get_by_ap_id_with_object(id)
|
||||||
|
actor = User.get_by_ap_id(activity.object.data["actor"])
|
||||||
|
|
||||||
|
%{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity.data["id"],
|
||||||
|
"content" => activity.object.data["content"],
|
||||||
|
"published" => activity.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: actor})
|
||||||
|
}
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -664,6 +680,20 @@ def fetch_ordered_collection(from, pages_left, acc \\ []) do
|
||||||
|
|
||||||
#### Report-related helpers
|
#### Report-related helpers
|
||||||
|
|
||||||
|
def update_report_state(%Activity{} = activity, state)
|
||||||
|
when state in @strip_status_report_states do
|
||||||
|
{:ok, stripped_activity} = strip_report_status_data(activity)
|
||||||
|
|
||||||
|
new_data =
|
||||||
|
activity.data
|
||||||
|
|> Map.put("state", state)
|
||||||
|
|> Map.put("object", stripped_activity.data["object"])
|
||||||
|
|
||||||
|
activity
|
||||||
|
|> Changeset.change(data: new_data)
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do
|
def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do
|
||||||
new_data = Map.put(activity.data, "state", state)
|
new_data = Map.put(activity.data, "state", state)
|
||||||
|
|
||||||
|
@ -674,6 +704,14 @@ def update_report_state(%Activity{} = activity, state) when state in @supported_
|
||||||
|
|
||||||
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
||||||
|
|
||||||
|
def strip_report_status_data(activity) do
|
||||||
|
[actor | reported_activities] = activity.data["object"]
|
||||||
|
stripped_activities = Enum.map(reported_activities, & &1["id"])
|
||||||
|
new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
|
||||||
|
|
||||||
|
{:ok, %{activity | data: new_data}}
|
||||||
|
end
|
||||||
|
|
||||||
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
|
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
|
||||||
[to, cc, recipients] =
|
[to, cc, recipients] =
|
||||||
activity
|
activity
|
||||||
|
|
|
@ -13,8 +13,9 @@ def extract_report_info(
|
||||||
account = User.get_cached_by_ap_id(account_ap_id)
|
account = User.get_cached_by_ap_id(account_ap_id)
|
||||||
|
|
||||||
statuses =
|
statuses =
|
||||||
Enum.map(status_ap_ids, fn ap_id ->
|
Enum.map(status_ap_ids, fn
|
||||||
Activity.get_by_ap_id_with_object(ap_id)
|
act when is_map(act) -> Activity.get_by_ap_id_with_object(act["id"])
|
||||||
|
act when is_binary(act) -> Activity.get_by_ap_id_with_object(act)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
%{report: report, user: user, account: account, statuses: statuses}
|
%{report: report, user: user, account: account, statuses: statuses}
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -1281,35 +1282,99 @@ test "returned pinned statuses" do
|
||||||
assert 3 = length(activities)
|
assert 3 = length(activities)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it can create a Flag activity" do
|
describe "flag/1" do
|
||||||
reporter = insert(:user)
|
setup do
|
||||||
target_account = insert(:user)
|
reporter = insert(:user)
|
||||||
{:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
|
target_account = insert(:user)
|
||||||
context = Utils.generate_context_id()
|
content = "foobar"
|
||||||
content = "foobar"
|
{:ok, activity} = CommonAPI.post(target_account, %{"status" => content})
|
||||||
|
context = Utils.generate_context_id()
|
||||||
|
|
||||||
reporter_ap_id = reporter.ap_id
|
reporter_ap_id = reporter.ap_id
|
||||||
target_ap_id = target_account.ap_id
|
target_ap_id = target_account.ap_id
|
||||||
activity_ap_id = activity.data["id"]
|
activity_ap_id = activity.data["id"]
|
||||||
|
|
||||||
assert {:ok, activity} =
|
activity_with_object = Activity.get_by_ap_id_with_object(activity_ap_id)
|
||||||
ActivityPub.flag(%{
|
|
||||||
actor: reporter,
|
|
||||||
context: context,
|
|
||||||
account: target_account,
|
|
||||||
statuses: [activity],
|
|
||||||
content: content
|
|
||||||
})
|
|
||||||
|
|
||||||
assert %Activity{
|
{:ok,
|
||||||
actor: ^reporter_ap_id,
|
%{
|
||||||
data: %{
|
reporter: reporter,
|
||||||
"type" => "Flag",
|
context: context,
|
||||||
"content" => ^content,
|
target_account: target_account,
|
||||||
"context" => ^context,
|
reported_activity: activity,
|
||||||
"object" => [^target_ap_id, ^activity_ap_id]
|
content: content,
|
||||||
}
|
activity_ap_id: activity_ap_id,
|
||||||
} = activity
|
activity_with_object: activity_with_object,
|
||||||
|
reporter_ap_id: reporter_ap_id,
|
||||||
|
target_ap_id: target_ap_id
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it can create a Flag activity",
|
||||||
|
%{
|
||||||
|
reporter: reporter,
|
||||||
|
context: context,
|
||||||
|
target_account: target_account,
|
||||||
|
reported_activity: reported_activity,
|
||||||
|
content: content,
|
||||||
|
activity_ap_id: activity_ap_id,
|
||||||
|
activity_with_object: activity_with_object,
|
||||||
|
reporter_ap_id: reporter_ap_id,
|
||||||
|
target_ap_id: target_ap_id
|
||||||
|
} do
|
||||||
|
assert {:ok, activity} =
|
||||||
|
ActivityPub.flag(%{
|
||||||
|
actor: reporter,
|
||||||
|
context: context,
|
||||||
|
account: target_account,
|
||||||
|
statuses: [reported_activity],
|
||||||
|
content: content
|
||||||
|
})
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity_ap_id,
|
||||||
|
"content" => content,
|
||||||
|
"published" => activity_with_object.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: target_account})
|
||||||
|
}
|
||||||
|
|
||||||
|
assert %Activity{
|
||||||
|
actor: ^reporter_ap_id,
|
||||||
|
data: %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"content" => ^content,
|
||||||
|
"context" => ^context,
|
||||||
|
"object" => [^target_ap_id, ^note_obj]
|
||||||
|
}
|
||||||
|
} = activity
|
||||||
|
end
|
||||||
|
|
||||||
|
test_with_mock "strips status data from Flag, before federating it",
|
||||||
|
%{
|
||||||
|
reporter: reporter,
|
||||||
|
context: context,
|
||||||
|
target_account: target_account,
|
||||||
|
reported_activity: reported_activity,
|
||||||
|
content: content
|
||||||
|
},
|
||||||
|
Utils,
|
||||||
|
[:passthrough],
|
||||||
|
[] do
|
||||||
|
{:ok, activity} =
|
||||||
|
ActivityPub.flag(%{
|
||||||
|
actor: reporter,
|
||||||
|
context: context,
|
||||||
|
account: target_account,
|
||||||
|
statuses: [reported_activity],
|
||||||
|
content: content
|
||||||
|
})
|
||||||
|
|
||||||
|
new_data =
|
||||||
|
put_in(activity.data, ["object"], [target_account.ap_id, reported_activity.data["id"]])
|
||||||
|
|
||||||
|
assert_called(Utils.maybe_federate(%{activity | data: new_data}))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fetch_activities/2 returns activities addressed to a list " do
|
test "fetch_activities/2 returns activities addressed to a list " do
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Mock
|
import Mock
|
||||||
|
@ -1109,10 +1110,18 @@ test "it accepts Flag activities" do
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity.data["id"],
|
||||||
|
"content" => "test post",
|
||||||
|
"published" => object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: user})
|
||||||
|
}
|
||||||
|
|
||||||
message = %{
|
message = %{
|
||||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
"cc" => [user.ap_id],
|
"cc" => [user.ap_id],
|
||||||
"object" => [user.ap_id, object.data["id"]],
|
"object" => [user.ap_id, activity.data["id"]],
|
||||||
"type" => "Flag",
|
"type" => "Flag",
|
||||||
"content" => "blocked AND reported!!!",
|
"content" => "blocked AND reported!!!",
|
||||||
"actor" => other_user.ap_id
|
"actor" => other_user.ap_id
|
||||||
|
@ -1120,7 +1129,7 @@ test "it accepts Flag activities" do
|
||||||
|
|
||||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||||
|
|
||||||
assert activity.data["object"] == [user.ap_id, object.data["id"]]
|
assert activity.data["object"] == [user.ap_id, note_obj]
|
||||||
assert activity.data["content"] == "blocked AND reported!!!"
|
assert activity.data["content"] == "blocked AND reported!!!"
|
||||||
assert activity.data["actor"] == other_user.ap_id
|
assert activity.data["actor"] == other_user.ap_id
|
||||||
assert activity.data["cc"] == [user.ap_id]
|
assert activity.data["cc"] == [user.ap_id]
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -581,11 +582,19 @@ test "returns map with Flag object" do
|
||||||
%{}
|
%{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity_ap_id,
|
||||||
|
"content" => content,
|
||||||
|
"published" => activity.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: target_account})
|
||||||
|
}
|
||||||
|
|
||||||
assert %{
|
assert %{
|
||||||
"type" => "Flag",
|
"type" => "Flag",
|
||||||
"content" => ^content,
|
"content" => ^content,
|
||||||
"context" => ^context,
|
"context" => ^context,
|
||||||
"object" => [^target_ap_id, ^activity_ap_id],
|
"object" => [^target_ap_id, ^note_obj],
|
||||||
"state" => "open"
|
"state" => "open"
|
||||||
} = res
|
} = res
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -385,6 +386,14 @@ test "creates a report" do
|
||||||
"status_ids" => [activity.id]
|
"status_ids" => [activity.id]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity_ap_id,
|
||||||
|
"content" => "foobar",
|
||||||
|
"published" => activity.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: target_user})
|
||||||
|
}
|
||||||
|
|
||||||
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
|
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
|
||||||
|
|
||||||
assert %Activity{
|
assert %Activity{
|
||||||
|
@ -392,7 +401,7 @@ test "creates a report" do
|
||||||
data: %{
|
data: %{
|
||||||
"type" => "Flag",
|
"type" => "Flag",
|
||||||
"content" => ^comment,
|
"content" => ^comment,
|
||||||
"object" => [^target_ap_id, ^activity_ap_id],
|
"object" => [^target_ap_id, ^note_obj],
|
||||||
"state" => "open"
|
"state" => "open"
|
||||||
}
|
}
|
||||||
} = flag_activity
|
} = flag_activity
|
||||||
|
@ -412,6 +421,11 @@ test "updates report state" do
|
||||||
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
||||||
|
|
||||||
assert report.data["state"] == "resolved"
|
assert report.data["state"] == "resolved"
|
||||||
|
|
||||||
|
[reported_user, activity_id] = report.data["object"]
|
||||||
|
|
||||||
|
assert reported_user == target_user.ap_id
|
||||||
|
assert activity_id == activity.data["id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not update report state when state is unsupported" do
|
test "does not update report state when state is unsupported" do
|
||||||
|
|
Loading…
Reference in a new issue