Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement bulk actions for global moderations #13678

Merged
merged 55 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
c81157c
add action button and checkbox to index
ElviaBth Nov 19, 2024
69c2d97
add actions list
ElviaBth Nov 19, 2024
a44b158
add JS file
ElviaBth Nov 20, 2024
3cd5c1e
add bulk-actions files
ElviaBth Nov 20, 2024
a55cc35
Merge branch 'develop' into feature/implement_bulk_actions_moderations
ElviaBth Nov 20, 2024
b85b88e
add bulk_action method to controller
ElviaBth Nov 21, 2024
1ba30b4
add moderated users bulk actions
ElviaBth Nov 21, 2024
d207c3e
add moderated_users JS file
ElviaBth Nov 21, 2024
4e98231
add bulk_actions command and routes
ElviaBth Nov 21, 2024
00b1235
refactor ko
ElviaBth Nov 22, 2024
8f2eae9
refactor bulk action method on command
ElviaBth Nov 22, 2024
9747beb
add conditions for dropdown
ElviaBth Nov 24, 2024
820a0f1
refactor index view
ElviaBth Nov 25, 2024
3b1ab30
fix specs error
ElviaBth Nov 25, 2024
884dcbd
fix iniciatives spec
ElviaBth Nov 26, 2024
12da3ef
add more checks to admin_manages_global_moderations spec
ElviaBth Nov 26, 2024
e54ac18
add bulk_action to moderated_users controller
ElviaBth Nov 26, 2024
009fc3b
hide and show dropdown actions
ElviaBth Nov 27, 2024
ce0e015
add bulk_unreported
ElviaBth Nov 27, 2024
84cc468
add bulk_new, bulk_create and bulk_destroy
ElviaBth Nov 27, 2024
b8d919b
fix spec error
ElviaBth Nov 28, 2024
f91c4fc
fix user_id bug
ElviaBth Nov 28, 2024
647467e
add bulk_unblock command
ElviaBth Nov 28, 2024
3f8f732
refactor bulk_block command
ElviaBth Nov 28, 2024
45b3c38
refactor bulk_unblock
ElviaBth Nov 29, 2024
413784d
refactor bulk_unreport_user
ElviaBth Nov 29, 2024
657e4a1
refacrot bulk_unreport_user
ElviaBth Nov 29, 2024
5fe1eee
refactor bulk_unhide_content and bulk_unreport_content
ElviaBth Nov 29, 2024
95c770f
update presenter
Nov 29, 2024
56d7def
add admin logs action info
ElviaBth Nov 29, 2024
b62172f
refactor changeset method in UserPresenter
ElviaBth Dec 2, 2024
394fcdf
fix spelling error
ElviaBth Dec 2, 2024
3089f83
add bulk_hide_content
ElviaBth Dec 2, 2024
3ca8977
Update decidim-admin/app/commands/decidim/admin/bulk_action.rb
ElviaBth Dec 3, 2024
90e97ab
apply feedback suggestions
ElviaBth Dec 3, 2024
4230138
refactor bulk_action file
ElviaBth Dec 3, 2024
c2e45d0
refactor bulk actions
ElviaBth Dec 4, 2024
7d20185
add changeset_config method to moderations_presenter
ElviaBth Dec 4, 2024
3030241
ignore unused locales
ElviaBth Dec 4, 2024
66eb8a8
refactor changeset method
ElviaBth Dec 4, 2024
bdb6665
add more checks to admin_log_presenter
ElviaBth Dec 5, 2024
5cc9c87
Merge branch 'develop' into feature/implement_bulk_actions_moderations
ElviaBth Dec 5, 2024
640cd0a
fix spec
ElviaBth Dec 5, 2024
3e024e0
add more checks to moderation spec
ElviaBth Dec 5, 2024
67bf2d4
fix date_picker spec
ElviaBth Dec 5, 2024
999429d
apply feedback changes
ElviaBth Dec 12, 2024
86b15d0
add new class base_user_presenter
ElviaBth Dec 13, 2024
131f395
add perform_action_without_log method
ElviaBth Dec 13, 2024
b9c40d8
fix unreport_resource and unhide_resource specs
ElviaBth Dec 13, 2024
e29030c
Merge branch 'develop' into feature/implement_bulk_actions_moderations
ElviaBth Dec 16, 2024
6b00294
apply feedback suggestions
ElviaBth Dec 17, 2024
22eb588
Update decidim-admin/app/commands/decidim/admin/bulk_unblock_users.rb
ElviaBth Dec 17, 2024
a45dc47
Update decidim-admin/app/commands/decidim/admin/bulk_block_users.rb
ElviaBth Dec 17, 2024
599acb3
fix lint errors
ElviaBth Dec 17, 2024
6424648
remove trailing whitespace
ElviaBth Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/i18n-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ ignore_unused:
- '{date,time.formats}.*'
- datetime.distance_in_words.*
- decidim.admin.participatory_process_steps.default_title
- decidim.admin.admin_log.changeset.*
- decidim.authorization_handlers.{direct,multistep}
- decidim.admin.models.assembly_member.positions.*
- decidim.application.documents.component_documents.*
Expand Down
92 changes: 92 additions & 0 deletions decidim-admin/app/commands/decidim/admin/bulk_action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# frozen_string_literal: true

module Decidim
module Admin
class BulkAction < Decidim::Command
# Public: Initializes the command.
#
# current_user - the user that performs the action
# action - can be hide, unhide and unreport resources
# selected_moderations - all resources selected by current_user
def initialize(current_user, action, selected_moderations)
@current_user = current_user
@action = action
@selected_moderations = selected_moderations
@result = { ok: [], ko: [] }
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid, together with the resource.
# - :invalid if the resource is not reported
#
# Returns nothing.
def call
return broadcast(:invalid) if selected_moderations.blank?

process_reportables
create_action_log if selected_moderations.first.reportable

broadcast(:ok, **result)
end

private

attr_reader :action, :selected_moderations, :current_user, :result, :with_admin_log

def create_action_log
action_log_type = "bulk_#{action}"

Decidim::ActionLogger.log(
action_log_type,
current_user,
selected_moderations.first,
nil,
extra: {
reported_content:,
reported_count: result[:ok].count
}
)
end

def reported_content
@reported_content ||= result[:ok].group_by(&:decidim_reportable_type).to_h do |klass, moderations|
[
klass.split("::").last.downcase.pluralize,
moderations.to_h { |moderation| [moderation.reportable.id, moderation.title] }
]
end
end

def process_reportables
selected_moderations.each do |moderation|
next unless moderation

if moderation.respond_to?(:organization) && moderation.organization != current_user.organization
result[:ko] << moderation
next
end
command.call(moderation.reportable, current_user, with_admin_log: false) do
on(:ok) do
result[:ok] << moderation
end
on(:invalid) do
result[:ko] << moderation
end
end
end
end

def command
case action
when "hide"
Admin::HideResource
when "unreport"
Admin::UnreportResource
when "unhide"
Admin::UnhideResource
end
end
end
end
end
75 changes: 75 additions & 0 deletions decidim-admin/app/commands/decidim/admin/bulk_block_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

module Decidim
module Admin
class BulkBlockUsers < Decidim::Command
# Public: Initializes the command.
def initialize(form)
@form = form
@result = { ok: [], ko: [] }
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid, together with the resource.
# - :invalid if the resource is not reported
#
# Returns nothing.
def call
return broadcast(:invalid) unless form.valid?

block_all_users!
create_action_log if first_blocked

broadcast(:ok, **result)
end

private

attr_reader :form, :result, :first_blocked

def create_action_log
Decidim::ActionLogger.log(
"bulk_block",
form.current_user,
first_blocked,
nil,
extra: {
blocked:,
reportable_type: first_blocked.class.name,
current_justification: form.justification
}
)
end

def blocked
@blocked ||= result[:ok].to_h { |user| [user.id, user.extended_data["user_name"]] }
end

def block_all_users!
form.users.each do |user|
transaction do
Decidim::UserModeration.find_or_create_by!(user:)

@current_blocking = UserBlock.create!(
justification: form.justification,
user:,
blocking_user: form.current_user
)

user.blocked = true
user.blocked_at = Time.current
user.block_id = @current_blocking.id
user.extended_data["user_name"] = user.name
user.name = "Blocked user"
user.save!
end
result[:ok] << user
@first_blocked ||= user
rescue ActiveRecord::RecordInvalid
result[:ko] << user
end
end
end
end
end
66 changes: 66 additions & 0 deletions decidim-admin/app/commands/decidim/admin/bulk_unblock_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# frozen_string_literal: true

module Decidim
module Admin
class BulkUnblockUsers < Decidim::Command
# Public: Initializes the command.
def initialize(blocked_users, current_user)
@blocked_users = blocked_users
@current_user = current_user
@result = { ok: [], ko: [] }
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid, together with the resource.
# - :invalid if the resource is not reported
#
# Returns nothing.
def call
return broadcast(:invalid) if blocked_users.blank?

unblock_users!
create_action_log if first_unblocked

broadcast(:ok, **result)
end

private

attr_reader :current_user, :blocked_users, :result, :first_unblocked

def create_action_log
Decidim::ActionLogger.log(
"bulk_unblock",
current_user,
first_unblocked,
nil,
extra: {
unblocked:,
reportable_type: first_unblocked.class.name
}
)
end

def unblocked
@unblocked ||= result[:ok].to_h { |blocked_user| [blocked_user.id, blocked_user.extended_data["user_name"]] }
end

def unblock_users!
blocked_users.each do |blocked_user|
transaction do
blocked_user.blocked = false
blocked_user.blocked_at = nil
blocked_user.block_id = nil
blocked_user.name = blocked_user.extended_data["user_name"]
blocked_user.save!
end
result[:ok] << blocked_user
@first_unblocked ||= blocked_user
rescue ActiveRecord::RecordInvalid
result[:ko] << blocked_user
end
end
end
end
end
69 changes: 69 additions & 0 deletions decidim-admin/app/commands/decidim/admin/bulk_unreport_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# frozen_string_literal: true

module Decidim
module Admin
class BulkUnreportUsers < Decidim::Command
# Public: Initializes the command.
#
# current_user - the user that performs the action
# reportables - all Decidim::Reportable selected by current_user
def initialize(current_user, reportables)
@current_user = current_user
@reportables = reportables
@result = { ok: [], ko: [] }
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid, together with the resource.
# - :invalid if the resource is not reported
#
# Returns nothing.
def call
return broadcast(:invalid) if reportables.blank?

bulk_unreport_users!
create_action_log if first_unreported

broadcast(:ok, **result)
end

private

attr_reader :reportables, :current_user, :result, :first_unreported

def create_action_log
Decidim::ActionLogger.log(
"bulk_ignore",
current_user,
first_unreported,
nil,
extra: {
unreported:,
reportable_type: first_unreported.class.name
}
)
end

def unreported
@unreported ||= result[:ok].to_h { |reportable| [reportable.id, reportable.name] }
end

def bulk_unreport_users!
reportables.each do |reportable|
next unless reportable

if reportable.respond_to?(:organization) && reportable.organization != current_user.organization
result[:ok] << reportable
next
end
reportable.user_moderation.destroy!
result[:ok] << reportable
@first_unreported ||= reportable
rescue ActiveRecord::RecordInvalid
result[:ko] << reportable
end
end
end
end
end
6 changes: 4 additions & 2 deletions decidim-admin/app/commands/decidim/admin/hide_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ class HideResource < Decidim::Command
#
# reportable - A Decidim::Reportable
# current_user - the user that performs the action
def initialize(reportable, current_user)
# with_admin_log Boolean - determines whether to log the action of hiding a resource in the admin log
def initialize(reportable, current_user, with_admin_log: true)
ElviaBth marked this conversation as resolved.
Show resolved Hide resolved
@reportable = reportable
@current_user = current_user
@with_admin_log = with_admin_log
end

# Executes the command. Broadcasts these events:
Expand All @@ -24,7 +26,7 @@ def call

with_events do
tool = Decidim::ModerationTools.new(@reportable, @current_user)
tool.hide!
@with_admin_log ? tool.hide_with_admin_log! : tool.hide!
tool.send_notification_to_author
end

Expand Down
14 changes: 11 additions & 3 deletions decidim-admin/app/commands/decidim/admin/unhide_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ class UnhideResource < Decidim::Command
#
# reportable - A Decidim::Reportable
# current_user - the user that performs the action
def initialize(reportable, current_user)
# with_admin_log Boolean - determines whether to log the action of unhide a resource in the admin log
def initialize(reportable, current_user, with_admin_log: true)
ElviaBth marked this conversation as resolved.
Show resolved Hide resolved
@reportable = reportable
@current_user = current_user
@with_admin_log = with_admin_log
end

# Executes the command. Broadcasts these events:
Expand All @@ -22,7 +24,7 @@ def initialize(reportable, current_user)
def call
return broadcast(:invalid) unless unhideable?

unhide!
@with_admin_log ? unhide_with_admin_log! : unhide!
broadcast(:ok, @reportable)
end

Expand All @@ -32,7 +34,7 @@ def unhideable?
@reportable.hidden? && @reportable.reported?
end

def unhide!
def unhide_with_admin_log!
Decidim.traceability.perform_action!(
"unhide",
@reportable.moderation,
Expand All @@ -41,6 +43,12 @@ def unhide!
reportable_type: @reportable.class.name
}
) do
unhide!
end
end

def unhide!
Decidim.traceability.perform_action_without_log!(@current_user) do
@reportable.moderation.update!(hidden_at: nil)
end
end
Expand Down
Loading
Loading