diff options
author | Marius Balteanu <marius.balteanu@zitec.com> | 2022-05-17 20:45:41 +0000 |
---|---|---|
committer | Marius Balteanu <marius.balteanu@zitec.com> | 2022-05-17 20:45:41 +0000 |
commit | 883aa3b5cca1645f2aae353f4f180f77c5693c7e (patch) | |
tree | 97c45c8f806b96f5a41dd4853d89dffd27b9f3c8 /app/jobs | |
parent | 3719eb32f44681987df6bd55c9ca1888190daecb (diff) | |
download | redmine-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.rb | 4 | ||||
-rw-r--r-- | app/jobs/destroy_project_job.rb | 77 |
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 |