summaryrefslogtreecommitdiffstats
path: root/app/jobs
diff options
context:
space:
mode:
authorMarius Balteanu <marius.balteanu@zitec.com>2022-05-17 20:45:41 +0000
committerMarius Balteanu <marius.balteanu@zitec.com>2022-05-17 20:45:41 +0000
commit883aa3b5cca1645f2aae353f4f180f77c5693c7e (patch)
tree97c45c8f806b96f5a41dd4853d89dffd27b9f3c8 /app/jobs
parent3719eb32f44681987df6bd55c9ca1888190daecb (diff)
downloadredmine-883aa3b5cca1645f2aae353f4f180f77c5693c7e.tar.gz
redmine-883aa3b5cca1645f2aae353f4f180f77c5693c7e.zip
Background job for project deletion (#36691).
Due to the deletion of dependent objects (issues etc), project deletion may take a long time. This patch moves the actual project deletion into an ActiveJob job. It also introduces a new project status (SCHEDULED_FOR_DELETION) that is used to effectively hide the project that is about to be deleted (and any potential descendant projects) from the system immediately. A security notification is sent out to the user that deleted the project, informing about success / failure. The projects list is extended to be able to filter for the new status, so in case of a failure, the project can still be accessed for examination. Patch by Jens Krämer. git-svn-id: https://svn.redmine.org/redmine/trunk@21591 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/jobs')
-rw-r--r--app/jobs/application_job.rb4
-rw-r--r--app/jobs/destroy_project_job.rb77
2 files changed, 81 insertions, 0 deletions
diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb
new file mode 100644
index 000000000..d92ffddcb
--- /dev/null
+++ b/app/jobs/application_job.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+class ApplicationJob < ActiveJob::Base
+end
diff --git a/app/jobs/destroy_project_job.rb b/app/jobs/destroy_project_job.rb
new file mode 100644
index 000000000..372e77240
--- /dev/null
+++ b/app/jobs/destroy_project_job.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+class DestroyProjectJob < ApplicationJob
+ include Redmine::I18n
+
+ def self.schedule(project, user: User.current)
+ # make the project (and any children) disappear immediately
+ project.self_and_descendants.update_all status: Project::STATUS_SCHEDULED_FOR_DELETION
+ perform_later project.id, user.id, user.remote_ip
+ end
+
+ def perform(project_id, user_id, remote_ip)
+ user_current_was = User.current
+
+ unless @user = User.active.find_by_id(user_id)
+ info "User check failed: User #{user_id} triggering project destroy does not exist anymore or isn't active."
+ return
+ end
+ @user.remote_ip = remote_ip
+ User.current = @user
+ set_language_if_valid @user.language || Setting.default_language
+
+ unless @project = Project.find_by_id(project_id)
+ info "Project check failed: Project has already been deleted."
+ return
+ end
+
+ unless @project.deletable?
+ info "Project check failed: User #{user_id} lacks permissions."
+ return
+ end
+
+ message = if @project.descendants.any?
+ :mail_destroy_project_with_subprojects_successful
+ else
+ :mail_destroy_project_successful
+ end
+ delete_project ? success(message) : failure
+ ensure
+ User.current = user_current_was
+ info "End destroy project"
+ end
+
+ private
+
+ def delete_project
+ info "Starting with project deletion"
+ return !!@project.destroy
+ rescue
+ info "Error while deleting project: #{$!}"
+ false
+ end
+
+ def success(message)
+ Mailer.deliver_security_notification(
+ @user, @user,
+ message: message,
+ value: @project.name,
+ url: {controller: 'admin', action: 'projects'},
+ title: :label_project_plural
+ )
+ end
+
+ def failure
+ Mailer.deliver_security_notification(
+ @user, @user,
+ message: :mail_destroy_project_failed,
+ value: @project.name,
+ url: {controller: 'admin', action: 'projects'},
+ title: :label_project_plural
+ )
+ end
+
+ def info(msg)
+ Rails.logger.info("[DestroyProjectJob] --- #{msg}")
+ end
+end