Skip to content

Commit

Permalink
Display information about "unpublish all" actions in the member manag…
Browse files Browse the repository at this point in the history
…er (forem#18576)

* Query audit_log + target records for display in the member manager

* Display information about logged unpublished articles and comments

* Display information if the post was republished

* Added specs for unpublish_log tab on user's page in the member manager

* Fixed specs

* Change the wording for displaying info about unpublish all actions
  • Loading branch information
lightalloy authored Oct 14, 2022
1 parent f839aca commit 9bb5b81
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 6 deletions.
9 changes: 8 additions & 1 deletion app/controllers/admin/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def edit
def show
@user = User.find(params[:id])
set_current_tab(params[:tab])
set_unpublish_all_log
set_banishable_user
set_feedback_messages
set_related_reactions
Expand Down Expand Up @@ -392,7 +393,7 @@ def credit_params
end

def set_current_tab(current_tab = "overview")
@current_tab = if current_tab.in? Constants::UserDetails::TAB_LIST.map(&:downcase)
@current_tab = if current_tab.in? Constants::UserDetails::TAB_LIST.map(&:underscore)
current_tab
else
"overview"
Expand All @@ -403,5 +404,11 @@ def set_banishable_user
@banishable_user = (@user.comments.where("created_at < ?", 100.days.ago).empty? &&
@user.created_at < 100.days.ago) || current_user.super_admin? || current_user.support_admin?
end

def set_unpublish_all_log
# in theory, there could be multiple "unpublish all" actions
# but let's query and display the last one for now, that should be enough for most cases
@unpublish_all_data = AuditLog::UnpublishAllsQuery.call(@user.id)
end
end
end
1 change: 1 addition & 0 deletions app/lib/constants/user_details.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module UserDetails
Emails
Reports
Flags
UnpublishLogs
].freeze
end
end
36 changes: 36 additions & 0 deletions app/queries/audit_log/unpublish_alls_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class AuditLog
class UnpublishAllsQuery
Result = Struct.new(:exists?, :audit_log, :target_articles, :target_comments, keyword_init: true)

def initialize(user_id)
@user_id = user_id
@target_articles = []
@target_comments = []
end

def self.call(...)
new(...).call
end

def call
audit_log = AuditLog.where(slug: %w[api_user_unpublish unpublish_all_articles])
.where("data @> '{\"target_user_id\": ?}'", user_id)
.includes(:user)
.order("created_at DESC")
.first
if audit_log
target_articles = Article.where(id: audit_log.data["target_article_ids"], user_id: user_id)
target_comments = Comment.where(id: audit_log.data["target_comment_ids"], user_id: user_id)
end
Result.new(
exists?: audit_log.present?,
audit_log: audit_log,
target_articles: target_articles,
target_comments: target_comments,
)
end

attr_reader :user_id
attr_accessor :target_comments, :target_articles
end
end
8 changes: 6 additions & 2 deletions app/views/admin/users/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%= render "admin/users/show/profile" %>
<%= render "admin/users/show/tabs" %>

<% if @current_tab == "overview" %>
<% if @current_tab == "overview" %>
<div class="crayons-card p-3 s:p-4 m:p-7">
<%= render "admin/users/show/overview/stats" if @user.registered %>

Expand Down Expand Up @@ -50,8 +50,12 @@
<section class="crayons-card p-3 s:p-4 m:p-7">
<%= render "admin/users/show/reports/index" %>
</section>
<% else @current_tab == "flags" %>
<% elsif @current_tab == "flags" %>
<section class="crayons-card p-3 s:p-4 m:p-7">
<%= render "admin/users/show/flags/index" %>
</section>
<% elsif @current_tab == "unpublish_logs" %>
<section class="crayons-card p-3 s:p-4 m:p-7">
<%= render "admin/users/show/unpublish_logs/index" %>
</section>
<% end %>
3 changes: 3 additions & 0 deletions app/views/admin/users/show/_tabs.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
<li><%= link_to "Emails", admin_user_path(@user.id, tab: :emails), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'emails'}", aria: @current_tab == "emails" ? { current: "page" } : {} %></li></li>
<li><%= link_to "Reports", admin_user_path(@user.id, tab: :reports), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'reports'}", aria: @current_tab == "reports" ? { current: "page" } : {} %></li></li>
<li><%= link_to "Flags", admin_user_path(@user.id, tab: :flags), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'flags'}", aria: @current_tab == "flags" ? { current: "page" } : {} %></li></li>
<% if @unpublish_all_data.exists? %>
<li><%= link_to "Unpublish All History", admin_user_path(@user.id, tab: :unpublish_logs), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'unpublish_logs'}", aria: @current_tab == "flags" ? { current: "page" } : {} %></li>
<% end %>
</ul>
</nav>
29 changes: 29 additions & 0 deletions app/views/admin/users/show/unpublish_logs/_index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<% if @unpublish_all_data.exists? %>
<h2 class="fs-xl fw-normal mb-5">Unpublished by <%= link_to @unpublish_all_data.audit_log.user.username, @unpublish_all_data.audit_log.user.path %> on <%= @unpublish_all_data.audit_log.created_at.strftime("%Y-%m-%d, %H:%M") %></h3>
<div class="crayons-card p-6 mb-5">
<h4 class="mb-2">Posts:</h4>
<% @unpublish_all_data.target_articles.each do |article| %>
<div class="mb-1">
<%= link_to article.title, article.current_state_path %>
<a href="<%= article.path %>/edit" target="_blank" rel="noopener" class="c-link">Edit</a>
<% if article.published %>
<span class="color-base-60">(was republished)</span>
<% end %>
</div>
<% end %>
</div>
<div class="crayons-card p-6">
<h4 class="mb-2">Comments:</h4>
<% @unpublish_all_data.target_comments.each do |comment| %>
<div class="crayons-card p-3 mb-3">
<div class="color-base-80">
<%= truncate(strip_tags(comment.processed_html), length: 250).html_safe %>
</div>
<%= link_to "commentable", comment.commentable.current_state_path %>
<p class="fs-s">
Created at: <%= comment.created_at.strftime("%Y-%m-%d, %H:%M") %>
</p>
</div>
<% end %>
</div>
<% end %>
32 changes: 32 additions & 0 deletions spec/queries/audit_log/unpublish_alls_query_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require "rails_helper"

RSpec.describe AuditLog::UnpublishAllsQuery, type: :query do
let(:user) { create(:user) }
let!(:article) { create(:article, user: user) }

describe "::call" do
context "when audit_log exists" do
let!(:audit_log) do
create(:audit_log, slug: "unpublish_all_articles",
data: { target_user_id: user.id, target_article_ids: [article.id] })
end

it "has articles and audit_log in the result" do
res = described_class.call(user.id)
expect(res.target_articles).to eq([article])
expect(res.target_comments).to eq([])
expect(res.audit_log).to eq(audit_log)
end

it "exists?" do
res = described_class.call(user.id)
expect(res.exists?).to be true
end
end

it "doesn't exist when there is no related audit_log" do
res = described_class.call(user.id)
expect(res.exists?).to be false
end
end
end
32 changes: 29 additions & 3 deletions spec/requests/admin/users_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,30 @@
get admin_user_path(user.id)
expect(response.body).to include(report.feedback_type)
end

it "displays unpublish all data from logs when it exists on unpublish_alls tab" do
article = create(:article, user: user, published: false)
create(:audit_log, user: admin, slug: "unpublish_all_articles",
data: { target_article_ids: [article.id], target_user_id: user.id })
get "#{admin_user_path(user.id)}?tab=unpublish_logs"
expect(response.body).to include("Unpublished by")
expect(response.body).to include(CGI.escapeHTML(article.title))
end

it "displays a label if an unpublished post was republished" do
article = create(:article, user: user, published: true)
create(:audit_log, user: admin, slug: "unpublish_all_articles",
data: { target_article_ids: [article.id], target_user_id: user.id })
get "#{admin_user_path(user.id)}?tab=unpublish_logs"
expect(response.body).to include(CGI.escapeHTML(article.title))
expect(response.body).to include("(was republished)")
end

it "displays nothing on unpublish_alls tab if it the log doesn't exist" do
get "#{admin_user_path(user.id)}?tab=unpublish_logs"
expect(response).to be_successful
expect(response.body).not_to include("Unpublished by")
end
end

describe "POST /admin/member_manager/users/:id/banish" do
Expand Down Expand Up @@ -341,9 +365,11 @@
create(:article, user: target_user, published: false)
create(:comment, user: target_user, deleted: true)

sidekiq_perform_enqueued_jobs(only: Moderator::UnpublishAllArticlesWorker) do
post unpublish_all_articles_admin_user_path(target_user.id)
end
expect do
sidekiq_perform_enqueued_jobs(only: Moderator::UnpublishAllArticlesWorker) do
post unpublish_all_articles_admin_user_path(target_user.id)
end
end.to change(AuditLog, :count).by(1)

log = AuditLog.last
expect(log.category).to eq(AuditLog::MODERATOR_AUDIT_LOG_CATEGORY)
Expand Down

0 comments on commit 9bb5b81

Please sign in to comment.