fix(moderation): expose reported parent actions
This commit is contained in:
parent
504c0af867
commit
50be881601
|
|
@ -78,6 +78,15 @@ defmodule WhoNeedHelp.Activities.Activity do
|
|||
activity
|
||||
|> cast(attrs, [:hidden_at, :hidden_reason])
|
||||
|> validate_length(:hidden_reason, max: 1_000)
|
||||
|> require_hidden_reason()
|
||||
end
|
||||
|
||||
defp require_hidden_reason(changeset) do
|
||||
if get_field(changeset, :hidden_at) do
|
||||
validate_required(changeset, :hidden_reason)
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
def public_coordinates(%__MODULE__{
|
||||
|
|
|
|||
|
|
@ -87,6 +87,15 @@ defmodule WhoNeedHelp.Help.HelpRequest do
|
|||
request
|
||||
|> cast(attrs, [:hidden_at, :hidden_reason])
|
||||
|> validate_length(:hidden_reason, max: 1_000)
|
||||
|> require_hidden_reason()
|
||||
end
|
||||
|
||||
defp require_hidden_reason(changeset) do
|
||||
if get_field(changeset, :hidden_at) do
|
||||
validate_required(changeset, :hidden_reason)
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
def cancellation_changeset(request, attrs) do
|
||||
|
|
|
|||
|
|
@ -345,10 +345,10 @@ defmodule WhoNeedHelp.Trust do
|
|||
:reporter,
|
||||
:reviewed_by,
|
||||
request: :requester,
|
||||
assignment: :helper,
|
||||
message: :sender,
|
||||
assignment: [:helper, :request],
|
||||
message: [:sender, assignment: :request],
|
||||
activity: :creator,
|
||||
activity_message: :sender
|
||||
activity_message: [:sender, :activity]
|
||||
])
|
||||
|> Repo.all()
|
||||
|> Pagination.page(limit, &{&1.inserted_at, &1.id})
|
||||
|
|
|
|||
|
|
@ -284,6 +284,38 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
defp signal_label(:manual), do: gettext("Manual review")
|
||||
defp signal_label(value), do: to_string(value)
|
||||
|
||||
defp report_request(%{request: %WhoNeedHelp.Help.HelpRequest{} = request}), do: request
|
||||
|
||||
defp report_request(%{
|
||||
assignment: %WhoNeedHelp.Help.Assignment{
|
||||
request: %WhoNeedHelp.Help.HelpRequest{} = request
|
||||
}
|
||||
}),
|
||||
do: request
|
||||
|
||||
defp report_request(%{
|
||||
message: %WhoNeedHelp.Messaging.Message{
|
||||
assignment: %WhoNeedHelp.Help.Assignment{
|
||||
request: %WhoNeedHelp.Help.HelpRequest{} = request
|
||||
}
|
||||
}
|
||||
}),
|
||||
do: request
|
||||
|
||||
defp report_request(_report), do: nil
|
||||
|
||||
defp report_activity(%{activity: %WhoNeedHelp.Activities.Activity{} = activity}),
|
||||
do: activity
|
||||
|
||||
defp report_activity(%{
|
||||
activity_message: %WhoNeedHelp.Activities.Message{
|
||||
activity: %WhoNeedHelp.Activities.Activity{} = activity
|
||||
}
|
||||
}),
|
||||
do: activity
|
||||
|
||||
defp report_activity(_report), do: nil
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
|
|
@ -309,6 +341,8 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
<div class="mt-4 space-y-4">
|
||||
<article :for={report <- @reports} class="rounded-2xl border border-base-300 p-5">
|
||||
<% hide_form = scoped_form(%{"note" => ""}, :moderation, "report-hide-#{report.id}") %>
|
||||
<% reported_request = report_request(report) %>
|
||||
<% reported_activity = report_activity(report) %>
|
||||
<% report_form =
|
||||
scoped_form(
|
||||
%{"status" => to_string(report.status), "resolution_note" => ""},
|
||||
|
|
@ -324,6 +358,12 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
<span :if={report.activity_message_id} class="badge badge-info badge-outline">
|
||||
{gettext("activity message")}
|
||||
</span>
|
||||
<span :if={report.message_id} class="badge badge-info badge-outline">
|
||||
{gettext("matched chat message")}
|
||||
</span>
|
||||
<span :if={report.assignment_id} class="badge badge-info badge-outline">
|
||||
{gettext("matched conversation")}
|
||||
</span>
|
||||
<span class="text-xs text-base-content/50">
|
||||
{gettext("by %{name}", name: report.reporter.display_name)}
|
||||
</span>
|
||||
|
|
@ -338,29 +378,55 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
{gettext("View scoped evidence")}
|
||||
</button>
|
||||
<.form
|
||||
:if={report.request_id}
|
||||
:if={reported_request && is_nil(reported_request.hidden_at)}
|
||||
for={hide_form}
|
||||
phx-submit="hide-request"
|
||||
phx-value-id={report.request_id}
|
||||
phx-value-id={reported_request.id}
|
||||
class="flex gap-2"
|
||||
>
|
||||
<.input field={hide_form[:note]} placeholder={gettext("Hide reason")} />
|
||||
<.input
|
||||
field={hide_form[:note]}
|
||||
placeholder={gettext("Required reason for hiding")}
|
||||
required
|
||||
/>
|
||||
<.button class="btn btn-sm btn-error self-end">
|
||||
{gettext("Hide request")}
|
||||
</.button>
|
||||
</.form>
|
||||
<button
|
||||
:if={reported_request && reported_request.hidden_at}
|
||||
type="button"
|
||||
phx-click="restore-request"
|
||||
phx-value-id={reported_request.id}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
{gettext("Restore request")}
|
||||
</button>
|
||||
<.form
|
||||
:if={report.activity_id}
|
||||
:if={reported_activity && is_nil(reported_activity.hidden_at)}
|
||||
for={hide_form}
|
||||
phx-submit="hide-activity"
|
||||
phx-value-id={report.activity_id}
|
||||
phx-value-id={reported_activity.id}
|
||||
class="flex gap-2"
|
||||
>
|
||||
<.input field={hide_form[:note]} placeholder={gettext("Hide reason")} />
|
||||
<.input
|
||||
field={hide_form[:note]}
|
||||
placeholder={gettext("Required reason for hiding")}
|
||||
required
|
||||
/>
|
||||
<.button class="btn btn-sm btn-error self-end">
|
||||
{gettext("Hide activity")}
|
||||
</.button>
|
||||
</.form>
|
||||
<button
|
||||
:if={reported_activity && reported_activity.hidden_at}
|
||||
type="button"
|
||||
phx-click="restore-activity"
|
||||
phx-value-id={reported_activity.id}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
{gettext("Restore activity")}
|
||||
</button>
|
||||
</div>
|
||||
<.form
|
||||
for={report_form}
|
||||
|
|
|
|||
|
|
@ -153,6 +153,21 @@ defmodule WhoNeedHelp.TrustSafetyTest do
|
|||
)
|
||||
end
|
||||
|
||||
test "hiding a request requires a moderation reason", context do
|
||||
moderator =
|
||||
user_fixture(display_name: "Reason moderator")
|
||||
|> Ecto.Changeset.change(role: :moderator)
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, request} = Help.create_request(context.requester_scope, context.attrs)
|
||||
|
||||
assert {:error, %Ecto.Changeset{} = changeset} =
|
||||
Trust.hide_request(user_scope_fixture(moderator), request.id, "")
|
||||
|
||||
assert "can't be blank" in errors_on(changeset).hidden_reason
|
||||
refute Repo.get!(WhoNeedHelp.Help.HelpRequest, request.id).hidden_at
|
||||
end
|
||||
|
||||
test "category moderation cannot cross help and activity taxonomies", context do
|
||||
moderator =
|
||||
user_fixture(display_name: "Category moderator")
|
||||
|
|
|
|||
|
|
@ -1113,7 +1113,7 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
|
|||
{:ok, request} = Help.create_request(user_scope_fixture(requester), attrs)
|
||||
{:ok, assignment} = Help.accept_request(user_scope_fixture(helper), request.id)
|
||||
|
||||
{:ok, _message} =
|
||||
{:ok, message} =
|
||||
Messaging.send_message(user_scope_fixture(helper), assignment, %{
|
||||
"body" => "Evidence message"
|
||||
})
|
||||
|
|
@ -1122,7 +1122,7 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
|
|||
Trust.report(user_scope_fixture(requester), %{
|
||||
"reason" => "harassment",
|
||||
"details" => "Please review the matched conversation.",
|
||||
"assignment_id" => assignment.id
|
||||
"message_id" => message.id
|
||||
})
|
||||
|
||||
{:ok, _proposal} =
|
||||
|
|
@ -1140,6 +1140,11 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
|
|||
assert html =~ "Please review the matched conversation."
|
||||
assert html =~ "Bicycle repair"
|
||||
|
||||
assert has_element?(
|
||||
view,
|
||||
"form[phx-submit='hide-request'][phx-value-id='#{request.id}']"
|
||||
)
|
||||
|
||||
evidence_html =
|
||||
view
|
||||
|> element("button[phx-click='view-evidence']")
|
||||
|
|
@ -1148,6 +1153,60 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
|
|||
assert evidence_html =~ "Evidence message"
|
||||
end
|
||||
|
||||
test "message reports expose parent activity moderation and switch to restore", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
scope: participant_scope
|
||||
} do
|
||||
user |> Ecto.Changeset.change(role: :moderator) |> Repo.update!()
|
||||
organizer = user_fixture(display_name: "Activity organizer")
|
||||
Catalog.seed_defaults()
|
||||
activity_category = Catalog.list_categories(:activity) |> List.first()
|
||||
|
||||
{:ok, activity} =
|
||||
Activities.create_activity(
|
||||
user_scope_fixture(organizer),
|
||||
activity_attrs(activity_category)
|
||||
)
|
||||
|
||||
{:ok, join_request} = Activities.request_to_join(participant_scope, activity.id)
|
||||
|
||||
{:ok, _approved} =
|
||||
Activities.approve_participant(user_scope_fixture(organizer), join_request.id)
|
||||
|
||||
{:ok, message} =
|
||||
Activities.send_message(user_scope_fixture(organizer), activity.id, %{
|
||||
"body" => "Reported activity message"
|
||||
})
|
||||
|
||||
{:ok, _report} =
|
||||
Trust.report(participant_scope, %{
|
||||
"reason" => "harassment",
|
||||
"details" => "Please review this activity message.",
|
||||
"activity_message_id" => message.id
|
||||
})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/moderation")
|
||||
|
||||
assert has_element?(
|
||||
view,
|
||||
"form[phx-submit='hide-activity'][phx-value-id='#{activity.id}']"
|
||||
)
|
||||
|
||||
view
|
||||
|> form("form[phx-submit='hide-activity'][phx-value-id='#{activity.id}']", %{
|
||||
"moderation" => %{"note" => "Unsafe public activity details"}
|
||||
})
|
||||
|> render_submit()
|
||||
|
||||
assert has_element?(
|
||||
view,
|
||||
"button[phx-click='restore-activity'][phx-value-id='#{activity.id}']"
|
||||
)
|
||||
|
||||
assert Repo.get!(WhoNeedHelp.Activities.Activity, activity.id).hidden_at
|
||||
end
|
||||
|
||||
test "abuse-signal pagination stays available without opening report evidence", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user