Merge pull request #336 from philomena-dev/more-reports

More reports cleanups
This commit is contained in:
liamwhite 2024-07-20 22:47:39 -04:00 committed by GitHub
commit 99958ee941
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 104 additions and 40 deletions

View file

@ -144,7 +144,7 @@ defmodule Philomena.Comments do
end end
def hide_comment(%Comment{} = comment, attrs, user) do def hide_comment(%Comment{} = comment, attrs, user) do
report_query = Reports.close_report_query("Comment", comment.id, user) report_query = Reports.close_report_query({"Comment", comment.id}, user)
comment = Comment.hide_changeset(comment, attrs, user) comment = Comment.hide_changeset(comment, attrs, user)
Multi.new() Multi.new()
@ -185,7 +185,7 @@ defmodule Philomena.Comments do
end end
def approve_comment(%Comment{} = comment, user) do def approve_comment(%Comment{} = comment, user) do
report_query = Reports.close_report_query("Comment", comment.id, user) report_query = Reports.close_report_query({"Comment", comment.id}, user)
comment = Comment.approve_changeset(comment) comment = Comment.approve_changeset(comment)
Multi.new() Multi.new()
@ -210,8 +210,7 @@ defmodule Philomena.Comments do
def report_non_approved(comment) do def report_non_approved(comment) do
Reports.create_system_report( Reports.create_system_report(
comment.id, {"Comment", comment.id},
"Comment",
"Approval", "Approval",
"Comment contains externally-embedded images and has been flagged for review." "Comment contains externally-embedded images and has been flagged for review."
) )

View file

@ -208,7 +208,7 @@ defmodule Philomena.Conversations do
end end
def approve_conversation_message(message, user) do def approve_conversation_message(message, user) do
reports_query = Reports.close_report_query("Conversation", message.conversation_id, user) reports_query = Reports.close_report_query({"Conversation", message.conversation_id}, user)
message_query = message_query =
message message
@ -236,8 +236,7 @@ defmodule Philomena.Conversations do
def report_non_approved(id) do def report_non_approved(id) do
Reports.create_system_report( Reports.create_system_report(
id, {"Conversation", id},
"Conversation",
"Approval", "Approval",
"PM contains externally-embedded images and has been flagged for review." "PM contains externally-embedded images and has been flagged for review."
) )

View file

@ -193,8 +193,7 @@ defmodule Philomena.Images do
defp maybe_suggest_user_verification(%User{id: id, uploads_count: 5, verified: false}) do defp maybe_suggest_user_verification(%User{id: id, uploads_count: 5, verified: false}) do
Reports.create_system_report( Reports.create_system_report(
id, {"User", id},
"User",
"Verification", "Verification",
"User has uploaded enough approved images to be considered for verification." "User has uploaded enough approved images to be considered for verification."
) )
@ -577,7 +576,7 @@ defmodule Philomena.Images do
end end
defp hide_image_multi(changeset, image, user, multi) do defp hide_image_multi(changeset, image, user, multi) do
report_query = Reports.close_report_query("Image", image.id, user) report_query = Reports.close_report_query({"Image", image.id}, user)
galleries = galleries =
Gallery Gallery

View file

@ -114,8 +114,7 @@ defmodule Philomena.Posts do
def report_non_approved(post) do def report_non_approved(post) do
Reports.create_system_report( Reports.create_system_report(
post.id, {"Post", post.id},
"Post",
"Approval", "Approval",
"Post contains externally-embedded images and has been flagged for review." "Post contains externally-embedded images and has been flagged for review."
) )
@ -203,7 +202,7 @@ defmodule Philomena.Posts do
end end
def hide_post(%Post{} = post, attrs, user) do def hide_post(%Post{} = post, attrs, user) do
report_query = Reports.close_report_query("Post", post.id, user) report_query = Reports.close_report_query({"Post", post.id}, user)
topics = topics =
Topic Topic
@ -250,7 +249,7 @@ defmodule Philomena.Posts do
end end
def approve_post(%Post{} = post, user) do def approve_post(%Post{} = post, user) do
report_query = Reports.close_report_query("Post", post.id, user) report_query = Reports.close_report_query({"Post", post.id}, user)
post = Post.approve_changeset(post) post = Post.approve_changeset(post)
Multi.new() Multi.new()

View file

@ -12,6 +12,31 @@ defmodule Philomena.Reports do
alias Philomena.IndexWorker alias Philomena.IndexWorker
alias Philomena.Polymorphic alias Philomena.Polymorphic
@doc """
Returns the current number of open reports.
If the user is allowed to view reports, returns the current count.
If the user is not allowed to view reports, returns `nil`.
## Examples
iex> count_reports(%User{})
nil
iex> count_reports(%User{role: "admin"})
4
"""
def count_open_reports(user) do
if Canada.Can.can?(user, :index, Report) do
Report
|> where(open: true)
|> Repo.aggregate(:count)
else
nil
end
end
@doc """ @doc """
Returns the list of reports. Returns the list of reports.
@ -53,8 +78,8 @@ defmodule Philomena.Reports do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
def create_report(reportable_id, reportable_type, attribution, attrs \\ %{}) do def create_report({reportable_type, reportable_id} = _type_and_id, attribution, attrs \\ %{}) do
%Report{reportable_id: reportable_id, reportable_type: reportable_type} %Report{reportable_type: reportable_type, reportable_id: reportable_id}
|> Report.creation_changeset(attrs, attribution) |> Report.creation_changeset(attrs, attribution)
|> Repo.insert() |> Repo.insert()
|> reindex_after_update() |> reindex_after_update()
@ -67,7 +92,7 @@ defmodule Philomena.Reports do
Because this is only a query due to the limitations of `m:Ecto.Multi`, this must be Because this is only a query due to the limitations of `m:Ecto.Multi`, this must be
coupled with an associated call to `reindex_reports/1` to operate correctly, e.g.: coupled with an associated call to `reindex_reports/1` to operate correctly, e.g.:
report_query = Reports.close_system_report_query("Image", image.id, user) report_query = Reports.close_system_report_query({"Image", image.id}, user)
Multi.new() Multi.new()
|> Multi.update_all(:reports, report_query, []) |> Multi.update_all(:reports, report_query, [])
@ -88,14 +113,24 @@ defmodule Philomena.Reports do
#Ecto.Query<...> #Ecto.Query<...>
""" """
def close_report_query(reportable_type, reportable_id, closing_user) do def close_report_query({reportable_type, reportable_id} = _type_and_id, closing_user) do
from r in Report, from r in Report,
where: r.reportable_type == ^reportable_type and r.reportable_id == ^reportable_id, where: r.reportable_type == ^reportable_type and r.reportable_id == ^reportable_id,
select: r.id, select: r.id,
update: [set: [open: false, state: "closed", admin_id: ^closing_user.id]] update: [set: [open: false, state: "closed", admin_id: ^closing_user.id]]
end end
def create_system_report(reportable_id, reportable_type, category, reason) do @doc """
Automatically create a report with the given category and reason on the given
`reportable_id` and `reportable_type`.
## Examples
iex> create_system_report({"Comment", 1}, "Other", "Custom report reason")
{:ok, %Report{}}
"""
def create_system_report({reportable_type, reportable_id} = _type_and_id, category, reason) do
attrs = %{ attrs = %{
reason: reason, reason: reason,
category: category category: category
@ -109,7 +144,7 @@ defmodule Philomena.Reports do
"Mozilla/5.0 (X11; Philomena; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0" "Mozilla/5.0 (X11; Philomena; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0"
} }
%Report{reportable_id: reportable_id, reportable_type: reportable_type} %Report{reportable_type: reportable_type, reportable_id: reportable_id}
|> Report.creation_changeset(attrs, attributes) |> Report.creation_changeset(attrs, attributes)
|> Repo.insert() |> Repo.insert()
|> reindex_after_update() |> reindex_after_update()
@ -163,6 +198,15 @@ defmodule Philomena.Reports do
Report.changeset(report, %{}) Report.changeset(report, %{})
end end
@doc """
Marks the report as claimed by the given user.
## Example
iex> claim_report(%Report{}, %User{})
{:ok, %Report{}}
"""
def claim_report(%Report{} = report, user) do def claim_report(%Report{} = report, user) do
report report
|> Report.claim_changeset(user) |> Report.claim_changeset(user)
@ -170,6 +214,15 @@ defmodule Philomena.Reports do
|> reindex_after_update() |> reindex_after_update()
end end
@doc """
Marks the report as unclaimed.
## Example
iex> unclaim_report(%Report{})
{:ok, %Report{}}
"""
def unclaim_report(%Report{} = report) do def unclaim_report(%Report{} = report) do
report report
|> Report.unclaim_changeset() |> Report.unclaim_changeset()
@ -177,6 +230,15 @@ defmodule Philomena.Reports do
|> reindex_after_update() |> reindex_after_update()
end end
@doc """
Marks the report as closed by the given user.
## Example
iex> close_report(%Report{}, %User{})
{:ok, %Report{}}
"""
def close_report(%Report{} = report, user) do def close_report(%Report{} = report, user) do
report report
|> Report.close_changeset(user) |> Report.close_changeset(user)
@ -184,6 +246,15 @@ defmodule Philomena.Reports do
|> reindex_after_update() |> reindex_after_update()
end end
@doc """
Reindex all reports where the user or admin has `old_name`.
## Example
iex> user_name_reindex("Administrator", "Administrator2")
{:ok, %Req.Response{}}
"""
def user_name_reindex(old_name, new_name) do def user_name_reindex(old_name, new_name) do
data = ReportIndex.user_name_update_by_query(old_name, new_name) data = ReportIndex.user_name_update_by_query(old_name, new_name)
@ -200,18 +271,25 @@ defmodule Philomena.Reports do
result result
end end
@doc """
Callback for post-transaction update.
See `close_report_query/2` for more information and example.
"""
def reindex_reports(report_ids) do def reindex_reports(report_ids) do
Exq.enqueue(Exq, "indexing", IndexWorker, ["Reports", "id", report_ids]) Exq.enqueue(Exq, "indexing", IndexWorker, ["Reports", "id", report_ids])
report_ids report_ids
end end
@doc false
def reindex_report(%Report{} = report) do def reindex_report(%Report{} = report) do
Exq.enqueue(Exq, "indexing", IndexWorker, ["Reports", "id", [report.id]]) Exq.enqueue(Exq, "indexing", IndexWorker, ["Reports", "id", [report.id]])
report report
end end
@doc false
def perform_reindex(column, condition) do def perform_reindex(column, condition) do
Report Report
|> where([r], field(r, ^column) in ^condition) |> where([r], field(r, ^column) in ^condition)
@ -220,14 +298,4 @@ defmodule Philomena.Reports do
|> Polymorphic.load_polymorphic(reportable: [reportable_id: :reportable_type]) |> Polymorphic.load_polymorphic(reportable: [reportable_id: :reportable_type])
|> Enum.map(&Search.index_document(&1, Report)) |> Enum.map(&Search.index_document(&1, Report))
end end
def count_reports(user) do
if Canada.Can.can?(user, :index, Report) do
Report
|> where(open: true)
|> Repo.aggregate(:count, :id)
else
nil
end
end
end end

View file

@ -42,6 +42,6 @@ defmodule PhilomenaWeb.Conversation.ReportController do
conversation = conn.assigns.conversation conversation = conn.assigns.conversation
action = ~p"/conversations/#{conversation}/reports" action = ~p"/conversations/#{conversation}/reports"
ReportController.create(conn, action, conversation, "Conversation", params) ReportController.create(conn, action, "Conversation", conversation, params)
end end
end end

View file

@ -41,6 +41,6 @@ defmodule PhilomenaWeb.Gallery.ReportController do
gallery = conn.assigns.gallery gallery = conn.assigns.gallery
action = ~p"/galleries/#{gallery}/reports" action = ~p"/galleries/#{gallery}/reports"
ReportController.create(conn, action, gallery, "Gallery", params) ReportController.create(conn, action, "Gallery", gallery, params)
end end
end end

View file

@ -44,6 +44,6 @@ defmodule PhilomenaWeb.Image.Comment.ReportController do
comment = conn.assigns.comment comment = conn.assigns.comment
action = ~p"/images/#{comment.image}/comments/#{comment}/reports" action = ~p"/images/#{comment.image}/comments/#{comment}/reports"
ReportController.create(conn, action, comment, "Comment", params) ReportController.create(conn, action, "Comment", comment, params)
end end
end end

View file

@ -41,6 +41,6 @@ defmodule PhilomenaWeb.Image.ReportController do
image = conn.assigns.image image = conn.assigns.image
action = ~p"/images/#{image}/reports" action = ~p"/images/#{image}/reports"
ReportController.create(conn, action, image, "Image", params) ReportController.create(conn, action, "Image", image, params)
end end
end end

View file

@ -53,7 +53,7 @@ defmodule PhilomenaWeb.Profile.Commission.ReportController do
commission = conn.assigns.user.commission commission = conn.assigns.user.commission
action = ~p"/profiles/#{user}/commission/reports" action = ~p"/profiles/#{user}/commission/reports"
ReportController.create(conn, action, commission, "Commission", params) ReportController.create(conn, action, "Commission", commission, params)
end end
defp ensure_commission(conn, _opts) do defp ensure_commission(conn, _opts) do

View file

@ -41,6 +41,6 @@ defmodule PhilomenaWeb.Profile.ReportController do
user = conn.assigns.user user = conn.assigns.user
action = ~p"/profiles/#{user}/reports" action = ~p"/profiles/#{user}/reports"
ReportController.create(conn, action, user, "User", params) ReportController.create(conn, action, "User", user, params)
end end
end end

View file

@ -33,7 +33,7 @@ defmodule PhilomenaWeb.ReportController do
# plug PhilomenaWeb.CheckCaptchaPlug when action in [:create] # plug PhilomenaWeb.CheckCaptchaPlug when action in [:create]
# plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true # plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
def create(conn, action, reportable, reportable_type, %{"report" => report_params}) do def create(conn, action, reportable_type, reportable, %{"report" => report_params}) do
attribution = conn.assigns.attributes attribution = conn.assigns.attributes
case too_many_reports?(conn) do case too_many_reports?(conn) do
@ -46,7 +46,7 @@ defmodule PhilomenaWeb.ReportController do
|> redirect(to: "/") |> redirect(to: "/")
_falsy -> _falsy ->
case Reports.create_report(reportable.id, reportable_type, attribution, report_params) do case Reports.create_report({reportable_type, reportable.id}, attribution, report_params) do
{:ok, _report} -> {:ok, _report} ->
conn conn
|> put_flash( |> put_flash(

View file

@ -42,6 +42,6 @@ defmodule PhilomenaWeb.Topic.Post.ReportController do
post = conn.assigns.post post = conn.assigns.post
action = ~p"/forums/#{topic.forum}/topics/#{topic}/posts/#{post}/reports" action = ~p"/forums/#{topic.forum}/topics/#{topic}/posts/#{post}/reports"
ReportController.create(conn, action, post, "Post", params) ReportController.create(conn, action, "Post", post, params)
end end
end end

View file

@ -34,7 +34,7 @@ defmodule PhilomenaWeb.AdminCountersPlug do
defp maybe_assign_admin_metrics(conn, user, true) do defp maybe_assign_admin_metrics(conn, user, true) do
pending_approvals = Images.count_pending_approvals(user) pending_approvals = Images.count_pending_approvals(user)
duplicate_reports = DuplicateReports.count_duplicate_reports(user) duplicate_reports = DuplicateReports.count_duplicate_reports(user)
reports = Reports.count_reports(user) reports = Reports.count_open_reports(user)
artist_links = ArtistLinks.count_artist_links(user) artist_links = ArtistLinks.count_artist_links(user)
dnps = DnpEntries.count_dnp_entries(user) dnps = DnpEntries.count_dnp_entries(user)