From 967d2544c72042b4ee472e1402b1d3ba25b7291c Mon Sep 17 00:00:00 2001 From: Vincent Robert Date: Fri, 8 Mar 2024 12:52:32 +0100 Subject: [PATCH] Enhance plugin compatibility with Redmine 5.1.2 --- .github/workflows/4_2_11.yml | 2 +- .github/workflows/{5_1_1.yml => 5_1_2.yml} | 7 +- .github/workflows/master.yml | 2 +- README.md | 4 +- app/helpers/journal_settings_helper.rb | 2 +- config/locales/en.yml | 2 +- config/locales/fr.yml | 2 +- .../custom_field_enumerations_controller.rb | 28 -- ...tom_field_enumerations_controller_patch.rb | 34 +++ .../controllers/custom_fields_controller.rb | 131 --------- .../custom_fields_controller_patch.rb | 137 +++++++++ .../issue_categories_controller.rb | 40 --- .../issue_categories_controller_patch.rb | 46 +++ .../controllers/members_controller.rb | 46 --- .../controllers/members_controller_patch.rb | 51 ++++ ...ler.rb => memberships_controller_patch.rb} | 35 +-- .../controllers/organizations_controller.rb | 58 ---- .../organizations_controller_patch.rb | 65 +++++ .../principal_memberships_controller.rb | 30 -- .../principal_memberships_controller_patch.rb | 35 +++ .../controllers/projects_controller.rb | 256 ----------------- .../controllers/projects_controller_patch.rb | 268 ++++++++++++++++++ .../controllers/settings_controller.rb | 49 ---- .../controllers/settings_controller_patch.rb | 55 ++++ .../controllers/trackers_controller.rb | 79 ------ .../controllers/trackers_controller_patch.rb | 85 ++++++ .../controllers/users_controller.rb | 84 ------ .../controllers/users_controller_patch.rb | 93 ++++++ .../controllers/wiki_controller.rb | 24 -- .../controllers/wiki_controller_patch.rb | 30 ++ ...ssues_helper.rb => issues_helper_patch.rb} | 6 +- ...cts_helper.rb => projects_helper_patch.rb} | 6 +- ...ngs_helper.rb => settings_helper_patch.rb} | 6 +- lib/redmine_admin_activity/hooks.rb | 49 ++-- .../jobs/destroy_project_job_patch.rb | 34 +++ .../concerns => }/journalizable.rb | 0 ...{custom_field.rb => custom_field_patch.rb} | 12 +- .../models/issue_template.rb | 31 -- .../models/issue_template_patch.rb | 35 +++ .../models/{journal.rb => journal_patch.rb} | 6 +- .../models/{member.rb => member_patch.rb} | 16 +- ...{organization.rb => organization_patch.rb} | 25 +- lib/redmine_admin_activity/models/project.rb | 54 ---- .../models/project_patch.rb | 59 ++++ lib/redmine_admin_activity/models/user.rb | 55 ---- .../models/user_patch.rb | 60 ++++ lib/redmine_admin_activity/models/version.rb | 30 -- .../models/version_patch.rb | 34 +++ .../issue_templates_controller_spec.rb | 4 +- .../memberships_controller_spec.rb | 2 +- spec/helpers/journal_settings_helper_spec.rb | 2 +- 51 files changed, 1223 insertions(+), 1083 deletions(-) rename .github/workflows/{5_1_1.yml => 5_1_2.yml} (94%) delete mode 100644 lib/redmine_admin_activity/controllers/custom_field_enumerations_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/custom_field_enumerations_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/custom_fields_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/custom_fields_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/issue_categories_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/issue_categories_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/members_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/members_controller_patch.rb rename lib/redmine_admin_activity/controllers/organizations/{memberships_controller.rb => memberships_controller_patch.rb} (80%) delete mode 100644 lib/redmine_admin_activity/controllers/organizations_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/organizations_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/principal_memberships_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/principal_memberships_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/projects_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/projects_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/settings_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/settings_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/trackers_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/trackers_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/users_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/users_controller_patch.rb delete mode 100644 lib/redmine_admin_activity/controllers/wiki_controller.rb create mode 100644 lib/redmine_admin_activity/controllers/wiki_controller_patch.rb rename lib/redmine_admin_activity/helpers/{issues_helper.rb => issues_helper_patch.rb} (99%) rename lib/redmine_admin_activity/helpers/{projects_helper.rb => projects_helper_patch.rb} (79%) rename lib/redmine_admin_activity/helpers/{settings_helper.rb => settings_helper_patch.rb} (76%) create mode 100644 lib/redmine_admin_activity/jobs/destroy_project_job_patch.rb rename lib/redmine_admin_activity/{controllers/concerns => }/journalizable.rb (100%) rename lib/redmine_admin_activity/models/{custom_field.rb => custom_field_patch.rb} (66%) delete mode 100644 lib/redmine_admin_activity/models/issue_template.rb create mode 100644 lib/redmine_admin_activity/models/issue_template_patch.rb rename lib/redmine_admin_activity/models/{journal.rb => journal_patch.rb} (67%) rename lib/redmine_admin_activity/models/{member.rb => member_patch.rb} (83%) rename lib/redmine_admin_activity/models/{organization.rb => organization_patch.rb} (81%) delete mode 100644 lib/redmine_admin_activity/models/project.rb create mode 100644 lib/redmine_admin_activity/models/project_patch.rb delete mode 100644 lib/redmine_admin_activity/models/user.rb create mode 100644 lib/redmine_admin_activity/models/user_patch.rb delete mode 100644 lib/redmine_admin_activity/models/version.rb create mode 100644 lib/redmine_admin_activity/models/version_patch.rb diff --git a/.github/workflows/4_2_11.yml b/.github/workflows/4_2_11.yml index 23c8334..81c60dc 100644 --- a/.github/workflows/4_2_11.yml +++ b/.github/workflows/4_2_11.yml @@ -48,7 +48,7 @@ jobs: - name: Install package dependencies run: > - sudo apt-get install --yes --quiet + sudo apt-get update && sudo apt-get install --yes --quiet build-essential cmake libicu-dev diff --git a/.github/workflows/5_1_1.yml b/.github/workflows/5_1_2.yml similarity index 94% rename from .github/workflows/5_1_1.yml rename to .github/workflows/5_1_2.yml index 0e430e9..5c511f6 100644 --- a/.github/workflows/5_1_1.yml +++ b/.github/workflows/5_1_2.yml @@ -1,8 +1,8 @@ -name: Tests 5.1.1 +name: Tests 5.1.2 env: PLUGIN_NAME: redmine_admin_activity - REDMINE_VERSION: 5.1.1 + REDMINE_VERSION: 5.1.2 RAILS_ENV: test on: @@ -48,7 +48,7 @@ jobs: - name: Install package dependencies run: > - sudo apt-get install --yes --quiet + sudo apt-get update && sudo apt-get install --yes --quiet build-essential cmake libicu-dev @@ -89,6 +89,7 @@ jobs: - name: Prepare Redmine source working-directory: redmine run: | + rm -f test/integration/routing/plugins_test.rb # Fix routing tests # TODO Remove this line when https://www.redmine.org/issues/38707 is fixed sed -i '/rubocop/d' Gemfile rm -f .rubocop* cp plugins/redmine_base_rspec/spec/support/database-${{ matrix.db }}.yml config/database.yml diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index d544cff..5b20031 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -48,7 +48,7 @@ jobs: - name: Install package dependencies run: > - sudo apt-get install --yes --quiet + sudo apt-get update && sudo apt-get install --yes --quiet build-essential cmake libicu-dev diff --git a/README.md b/README.md index cb994b8..bac4303 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ To run tests, install the redmine_base_rspec plugin (https://github.com/jbbarth/ |Plugin branch| Redmine Version | Test Status | |-------------|-----------------|-------------------| -|master | 5.1.1 | [![5.1.1][1]][5] | +|master | 5.1.2 | [![5.1.2][1]][5] | |master | 4.2.11 | [![4.2.11][2]][5] | |master | master | [![master][4]][5] | -[1]: https://github.com/nanego/redmine_admin_activity/actions/workflows/5_1_1.yml/badge.svg +[1]: https://github.com/nanego/redmine_admin_activity/actions/workflows/5_1_2.yml/badge.svg [2]: https://github.com/nanego/redmine_admin_activity/actions/workflows/4_2_11.yml/badge.svg [4]: https://github.com/nanego/redmine_admin_activity/actions/workflows/master.yml/badge.svg [5]: https://github.com/nanego/redmine_admin_activity/actions diff --git a/app/helpers/journal_settings_helper.rb b/app/helpers/journal_settings_helper.rb index 9175e07..acd08c0 100644 --- a/app/helpers/journal_settings_helper.rb +++ b/app/helpers/journal_settings_helper.rb @@ -101,7 +101,7 @@ def link_to_journalized_if_exists(journalized) link_to((journalized.to_s), (journalized.class.send :representative_link_path, journalized)) if journalized.present? && journalized.persisted? else # case of absence of implementation methods representative_link_path, to_s - return l(:label_absence_methodes) if journalized.present? + return l(:label_missing_methods) if journalized.present? end end diff --git a/config/locales/en.yml b/config/locales/en.yml index dd56fd0..02fcc97 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -70,7 +70,7 @@ en: text_journal_has_many_changed: "%{class_name} has been changed from [%{old}] to [%{new}]" label_customfieldenumeration: Key/value list label_customfieldssection: Section - label_absence_methodes: TODO Absence of methods implementation representative_link_path or to_s + label_missing_methods: TODO Absence of methods implementation representative_link_path or to_s label_this_user: "This user" label_from_project: "from the project" label_to_project: "to the project" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 49fa049..6ce3362 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -70,7 +70,7 @@ fr: text_journal_has_many_changed: "%{class_name} a été changé de [%{old}] à [%{new}]" label_customfieldenumeration: Liste clé/valeur label_customfieldssection: Section - label_absence_methodes: TODO Absence d'implémentation des méthodes representative_link_path or to_s + label_missing_methods: TODO Absence d'implémentation des méthodes representative_link_path or to_s label_this_user: "Cet utilisateur" label_from_project: "du projet" label_to_project: "au projet" diff --git a/lib/redmine_admin_activity/controllers/custom_field_enumerations_controller.rb b/lib/redmine_admin_activity/controllers/custom_field_enumerations_controller.rb deleted file mode 100644 index a754ccf..0000000 --- a/lib/redmine_admin_activity/controllers/custom_field_enumerations_controller.rb +++ /dev/null @@ -1,28 +0,0 @@ -require_dependency 'custom_field_enumerations_controller' - -class CustomFieldEnumerationsController - include RedmineAdminActivity::Journalizable - - append_before_action :get_previous_custom_field_enumerations, :only => [:create, :destroy, :update_each] - after_action :create_custom_field_history, :only => [:create, :destroy, :update_each] - - private - - def get_previous_custom_field_enumerations - @previous_custom_field_enumerations_ids = @custom_field.enumerations.select { |i| i.active }.map(&:id) - end - - def create_custom_field_history - - changes = get_custom_field_enumerations_changes(@custom_field, @previous_custom_field_enumerations_ids) - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes.except!(:custom_values), - :journalized_type => @custom_field.class.name, - :journalized_id => @custom_field.id, - :journalized_entry_type => "update", - ) - - end -end \ No newline at end of file diff --git a/lib/redmine_admin_activity/controllers/custom_field_enumerations_controller_patch.rb b/lib/redmine_admin_activity/controllers/custom_field_enumerations_controller_patch.rb new file mode 100644 index 0000000..e6e2840 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/custom_field_enumerations_controller_patch.rb @@ -0,0 +1,34 @@ +require_dependency 'custom_field_enumerations_controller' + +module RedmineAdminActivity::Controllers + module CustomFieldEnumerationsControllerPatch + extend ActiveSupport::Concern + + def get_previous_custom_field_enumerations + @previous_custom_field_enumerations_ids = @custom_field.enumerations.select { |i| i.active }.map(&:id) + end + + def create_custom_field_history + + changes = get_custom_field_enumerations_changes(@custom_field, @previous_custom_field_enumerations_ids) + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes.except!(:custom_values), + :journalized_type => @custom_field.class.name, + :journalized_id => @custom_field.id, + :journalized_entry_type => "update", + ) + + end + end +end + +class CustomFieldEnumerationsController + include RedmineAdminActivity::Journalizable + include RedmineAdminActivity::Controllers::CustomFieldEnumerationsControllerPatch + + append_before_action :get_previous_custom_field_enumerations, :only => [:create, :destroy, :update_each] + after_action :create_custom_field_history, :only => [:create, :destroy, :update_each] + +end diff --git a/lib/redmine_admin_activity/controllers/custom_fields_controller.rb b/lib/redmine_admin_activity/controllers/custom_fields_controller.rb deleted file mode 100644 index aa66d37..0000000 --- a/lib/redmine_admin_activity/controllers/custom_fields_controller.rb +++ /dev/null @@ -1,131 +0,0 @@ -require_dependency 'custom_fields_controller' - -class CustomFieldsController - include RedmineAdminActivity::Journalizable - - append_before_action :store_project_ids, :only => [:update] - after_action :custom_fields_creation, :only => [:create] - after_action :custom_fields_upgrade, :only => [:update] - before_action :custom_fields_deletion_preparation, :only => [:destroy] - after_action :custom_fields_deletion, :only => [:destroy] - - private - - def store_project_ids - @previous_has_and_belongs_to_many = get_previous_has_and_belongs_to_many(@custom_field) - @previous_project_ids = @custom_field.project_ids if trackable_custom_field? - end - - def custom_fields_creation - return unless @custom_field.persisted? - - # Tracing on JournalSetting - changes = add_has_and_belongs_to_many_to_previous_changes( - @custom_field, - @custom_field.previous_changes - ) - # Pass @custom_field.class.name in order to use the child class, - # Not using the parent class, to be able to retrieve the correct associations - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes, - :journalized_type => @custom_field.class.name, - :journalized_id => @custom_field.id, - :journalized_entry_type => "create", - ) - - if trackable_custom_field? - @custom_field.projects.each do |project| - add_journal_entry project, JournalDetail.new( - :property => :custom_fields, - :prop_key => :custom_fields, - :value => @custom_field.name - ) - end - end - end - - def custom_fields_upgrade - # Tracing on JournalSetting - journalized_changes = @custom_field.previous_changes.select { |key, val| @custom_field.journalized_attribute_names.include?(key) } - - changes = update_has_and_belongs_to_many_in_previous_changes(@custom_field, - journalized_changes, - @previous_has_and_belongs_to_many - ) - # Pass @custom_field.class.name in order to use the child class, - # Not using the parent class, to be able to retrieve the correct associations - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes, - :journalized_type => @custom_field.class.name, - :journalized_id => @custom_field.id, - :journalized_entry_type => "update", - ) - - return unless trackable_custom_field? && @previous_project_ids != @custom_field.project_ids - - changed_project_ids = array_difference(@previous_project_ids, @custom_field.project_ids) - - Project.where(id: changed_project_ids).each do |project| - journal_detail = JournalDetail.new( - :property => :custom_fields, - :prop_key => :custom_fields - ) - - if @previous_project_ids.include?(project.id) && !@custom_field.project_ids.include?(project.id) - journal_detail.old_value = @custom_field.name - elsif !@previous_project_ids.include?(project.id) && @custom_field.project_ids.include?(project.id) - journal_detail.value = @custom_field.name - end - - add_journal_entry project, journal_detail - end - end - - def custom_fields_deletion_preparation - return unless trackable_custom_field? - - @journals_projects = [] - custom_field = CustomField.find(params[:id]) - custom_field.projects.each do |project| - project.init_journal(User.current) - project.current_journal.details << JournalDetail.new( - :property => :custom_fields, - :prop_key => :custom_fields, - :old_value => custom_field.name - ) - @journals_projects << project - end - end - - def custom_fields_deletion - return unless @custom_field.present? && @custom_field.destroyed? - - # Tracing on JournalSetting - changes = Array.new - @custom_field.attributes.to_a.map do |col| - changes << [col[0], [col[1], nil]] if @custom_field.journalized_attribute_names.include?(col.first) - end - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes.to_h, - :journalized_type => @custom_field.class.name, - :journalized_id => @custom_field.id, - :journalized_entry_type => "destroy", - ) - - return unless trackable_custom_field? - - @journals_projects.each { |project| project.current_journal.save } - end - - def array_difference(arr1, arr2) - arr1 - arr2 | arr2 - arr1 - end - - def trackable_custom_field? - @custom_field.is_a?(IssueCustomField) - end -end diff --git a/lib/redmine_admin_activity/controllers/custom_fields_controller_patch.rb b/lib/redmine_admin_activity/controllers/custom_fields_controller_patch.rb new file mode 100644 index 0000000..0171adc --- /dev/null +++ b/lib/redmine_admin_activity/controllers/custom_fields_controller_patch.rb @@ -0,0 +1,137 @@ +require_dependency 'custom_fields_controller' + +module RedmineAdminActivity::Controllers + module CustomFieldsControllerPatch + extend ActiveSupport::Concern + + def store_project_ids + @previous_has_and_belongs_to_many = get_previous_has_and_belongs_to_many(@custom_field) + @previous_project_ids = @custom_field.project_ids if trackable_custom_field? + end + + def custom_fields_creation + return unless @custom_field.persisted? + + # Tracing on JournalSetting + changes = add_has_and_belongs_to_many_to_previous_changes( + @custom_field, + @custom_field.previous_changes + ) + # Pass @custom_field.class.name in order to use the child class, + # Not using the parent class, to be able to retrieve the correct associations + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized_type => @custom_field.class.name, + :journalized_id => @custom_field.id, + :journalized_entry_type => "create", + ) + + if trackable_custom_field? + @custom_field.projects.each do |project| + add_journal_entry project, JournalDetail.new( + :property => :custom_fields, + :prop_key => :custom_fields, + :value => @custom_field.name + ) + end + end + end + + def custom_fields_upgrade + # Tracing on JournalSetting + journalized_changes = @custom_field.previous_changes.select { |key, val| @custom_field.journalized_attribute_names.include?(key) } + + changes = update_has_and_belongs_to_many_in_previous_changes(@custom_field, + journalized_changes, + @previous_has_and_belongs_to_many + ) + # Pass @custom_field.class.name in order to use the child class, + # Not using the parent class, to be able to retrieve the correct associations + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized_type => @custom_field.class.name, + :journalized_id => @custom_field.id, + :journalized_entry_type => "update", + ) + + return unless trackable_custom_field? && @previous_project_ids != @custom_field.project_ids + + changed_project_ids = array_difference(@previous_project_ids, @custom_field.project_ids) + + Project.where(id: changed_project_ids).each do |project| + journal_detail = JournalDetail.new( + :property => :custom_fields, + :prop_key => :custom_fields + ) + + if @previous_project_ids.include?(project.id) && !@custom_field.project_ids.include?(project.id) + journal_detail.old_value = @custom_field.name + elsif !@previous_project_ids.include?(project.id) && @custom_field.project_ids.include?(project.id) + journal_detail.value = @custom_field.name + end + + add_journal_entry project, journal_detail + end + end + + def custom_fields_deletion_preparation + return unless trackable_custom_field? + + @journals_projects = [] + custom_field = CustomField.find(params[:id]) + custom_field.projects.each do |project| + project.init_journal(User.current) + project.current_journal.details << JournalDetail.new( + :property => :custom_fields, + :prop_key => :custom_fields, + :old_value => custom_field.name + ) + @journals_projects << project + end + end + + def custom_fields_deletion + return unless @custom_field.present? && @custom_field.destroyed? + + # Tracing on JournalSetting + changes = Array.new + @custom_field.attributes.to_a.map do |col| + changes << [col[0], [col[1], nil]] if @custom_field.journalized_attribute_names.include?(col.first) + end + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes.to_h, + :journalized_type => @custom_field.class.name, + :journalized_id => @custom_field.id, + :journalized_entry_type => "destroy", + ) + + return unless trackable_custom_field? + + @journals_projects.each { |project| project.current_journal.save } + end + + def array_difference(arr1, arr2) + arr1 - arr2 | arr2 - arr1 + end + + def trackable_custom_field? + @custom_field.is_a?(IssueCustomField) + end + + end +end + +class CustomFieldsController + include RedmineAdminActivity::Journalizable + include RedmineAdminActivity::Controllers::CustomFieldsControllerPatch + + append_before_action :store_project_ids, :only => [:update] + after_action :custom_fields_creation, :only => [:create] + after_action :custom_fields_upgrade, :only => [:update] + before_action :custom_fields_deletion_preparation, :only => [:destroy] + after_action :custom_fields_deletion, :only => [:destroy] +end diff --git a/lib/redmine_admin_activity/controllers/issue_categories_controller.rb b/lib/redmine_admin_activity/controllers/issue_categories_controller.rb deleted file mode 100644 index 8736295..0000000 --- a/lib/redmine_admin_activity/controllers/issue_categories_controller.rb +++ /dev/null @@ -1,40 +0,0 @@ -require_dependency 'issue_categories_controller' - -class IssueCategoriesController - before_action :init_journal, :only => [:create, :update, :destroy] - after_action :journalized_issue_categories_creation, :only => [:create] - after_action :journalized_issue_categories_upgrade, :only => [:update] - after_action :journalized_issue_categories_deletion, :only => [:destroy] - - private - - def init_journal - @project.init_journal(User.current) - end - - def journalized_issue_categories_creation - return unless @category.persisted? - add_journal_entry value: @category.name - end - - def journalized_issue_categories_upgrade - return unless @category.name_previously_changed? - add_journal_entry old_value: @category.name_previous_change[0], - value: @category.name - end - - def journalized_issue_categories_deletion - add_journal_entry old_value: @category.name - end - - def add_journal_entry(value: nil, old_value: nil) - journal_detail = JournalDetail.new( - property: :issue_category, - prop_key: :issue_category, - value: helpers.sanitize(value), - old_value: helpers.sanitize(old_value) - ) - @project.current_journal.details << journal_detail - @project.current_journal.save - end -end diff --git a/lib/redmine_admin_activity/controllers/issue_categories_controller_patch.rb b/lib/redmine_admin_activity/controllers/issue_categories_controller_patch.rb new file mode 100644 index 0000000..7ad5496 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/issue_categories_controller_patch.rb @@ -0,0 +1,46 @@ +require_dependency 'issue_categories_controller' + +module RedmineAdminActivity::Controllers + module IssueCategoriesControllerPatch + extend ActiveSupport::Concern + + def init_journal + @project.init_journal(User.current) + end + + def journalized_issue_categories_creation + return unless @category.persisted? + add_journal_entry value: @category.name + end + + def journalized_issue_categories_upgrade + return unless @category.name_previously_changed? + add_journal_entry old_value: @category.name_previous_change[0], + value: @category.name + end + + def journalized_issue_categories_deletion + add_journal_entry old_value: @category.name + end + + def add_journal_entry(value: nil, old_value: nil) + journal_detail = JournalDetail.new( + property: :issue_category, + prop_key: :issue_category, + value: helpers.sanitize(value), + old_value: helpers.sanitize(old_value) + ) + @project.current_journal.details << journal_detail + @project.current_journal.save + end + end +end + +class IssueCategoriesController + include RedmineAdminActivity::Controllers::IssueCategoriesControllerPatch + + before_action :init_journal, :only => [:create, :update, :destroy] + after_action :journalized_issue_categories_creation, :only => [:create] + after_action :journalized_issue_categories_upgrade, :only => [:update] + after_action :journalized_issue_categories_deletion, :only => [:destroy] +end diff --git a/lib/redmine_admin_activity/controllers/members_controller.rb b/lib/redmine_admin_activity/controllers/members_controller.rb deleted file mode 100644 index 59c3d31..0000000 --- a/lib/redmine_admin_activity/controllers/members_controller.rb +++ /dev/null @@ -1,46 +0,0 @@ -require_dependency 'members_controller' - -class MembersController - include RedmineAdminActivity::Journalizable - - before_action :store_role_ids, :only => [:update, :destroy] - after_action :journalized_members_creation, :only => [:create] - after_action :journalized_members_upgrade, :only => [:update] - after_action :journalized_member_deletion, :only => [:destroy] - - private - - def store_role_ids - member = Member.find(params[:id]) - @previous_role_ids = member.role_ids - @previous_function_ids = member.function_ids if limited_visibility_plugin_installed? - end - - def journalized_members_creation - if params[:membership] - user_ids = Array.wrap(params[:membership][:user_id] || params[:membership][:user_ids]) - user_ids << nil if user_ids.empty? - user_ids.each do |user_id| - role_ids = params[:membership][:role_ids] - function_ids = params[:membership][:function_ids] - member = Member.new(:project => @project, :user_id => user_id) - member.set_editable_role_ids(role_ids) - add_member_creation_to_journal(member, role_ids, function_ids) - end - end - end - - def journalized_members_upgrade - if limited_visibility_plugin_installed? - return if @previous_role_ids == @member.roles.ids && @previous_function_ids == @member.functions.ids - current_functions = @member.functions.ids - else - return if @previous_role_ids == @member.roles.ids - end - add_member_edition_to_journal(@member, @previous_role_ids, @member.roles.ids, @previous_function_ids, current_functions) - end - - def journalized_member_deletion - add_member_deletion_to_journal(@member, @previous_role_ids, @previous_function_ids) - end -end diff --git a/lib/redmine_admin_activity/controllers/members_controller_patch.rb b/lib/redmine_admin_activity/controllers/members_controller_patch.rb new file mode 100644 index 0000000..64263e0 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/members_controller_patch.rb @@ -0,0 +1,51 @@ +require_dependency 'members_controller' + +module RedmineAdminActivity::Controllers + module MembersControllerPatch + extend ActiveSupport::Concern + + def store_role_ids + member = Member.find(params[:id]) + @previous_role_ids = member.role_ids + @previous_function_ids = member.function_ids if limited_visibility_plugin_installed? + end + + def journalized_members_creation + if params[:membership] + user_ids = Array.wrap(params[:membership][:user_id] || params[:membership][:user_ids]) + user_ids << nil if user_ids.empty? + user_ids.each do |user_id| + role_ids = params[:membership][:role_ids] + function_ids = params[:membership][:function_ids] + member = Member.new(:project => @project, :user_id => user_id) + member.set_editable_role_ids(role_ids) + add_member_creation_to_journal(member, role_ids, function_ids) + end + end + end + + def journalized_members_upgrade + if limited_visibility_plugin_installed? + return if @previous_role_ids == @member.roles.ids && @previous_function_ids == @member.functions.ids + current_functions = @member.functions.ids + else + return if @previous_role_ids == @member.roles.ids + end + add_member_edition_to_journal(@member, @previous_role_ids, @member.roles.ids, @previous_function_ids, current_functions) + end + + def journalized_member_deletion + add_member_deletion_to_journal(@member, @previous_role_ids, @previous_function_ids) + end + end +end + +class MembersController + include RedmineAdminActivity::Journalizable + include RedmineAdminActivity::Controllers::MembersControllerPatch + + before_action :store_role_ids, :only => [:update, :destroy] + after_action :journalized_members_creation, :only => [:create] + after_action :journalized_members_upgrade, :only => [:update] + after_action :journalized_member_deletion, :only => [:destroy] +end diff --git a/lib/redmine_admin_activity/controllers/organizations/memberships_controller.rb b/lib/redmine_admin_activity/controllers/organizations/memberships_controller_patch.rb similarity index 80% rename from lib/redmine_admin_activity/controllers/organizations/memberships_controller.rb rename to lib/redmine_admin_activity/controllers/organizations/memberships_controller_patch.rb index 8bc1f76..6b5b768 100644 --- a/lib/redmine_admin_activity/controllers/organizations/memberships_controller.rb +++ b/lib/redmine_admin_activity/controllers/organizations/memberships_controller_patch.rb @@ -1,20 +1,6 @@ -require_dependency 'organizations/memberships_controller' - -class Organizations::MembershipsController - include RedmineAdminActivity::Journalizable - - before_action :store_previous_values, :only => [:update] - after_action :journalized_memberships_edition, :only => [:update] - after_action :journalized_non_members_roles_creation, :only => [:create_non_members_roles] - - before_action :store_previous_values_non_members_roles, :only => [:update_non_members_roles, :destroy_non_members_roles, :update_non_members_functions] - after_action :journalized_non_members_roles_edition, :only => [:update_non_members_roles] - after_action :journalized_non_members_functions_edition, :only => [:update_non_members_functions] - after_action :add_non_members_deletion_to_journal, :only => [:destroy_non_members_roles] - after_action :add_non_members_deletion_to_journal, :only => [:destroy_non_members_roles] - - private +require_dependency 'organizations/memberships_controller' if Redmine::VERSION::MAJOR < 5 +module RedmineAdminActivity::Controllers::Organizations::MembershipsControllerPatch def store_previous_values @requested_users = User.where(id: params[:membership][:user_ids].reject(&:empty?)) @requested_roles = Role.where(id: params[:membership][:role_ids].reject(&:empty?)) @@ -120,3 +106,20 @@ def add_non_members_deletion_to_journal add_member_exception_deletion_to_journal(@member_exception, @previous_roles_ids, @previous_functions_ids) end end + +if Redmine::Plugin.installed?(:redmine_organizations) + class Organizations::MembershipsController < ApplicationController + include RedmineAdminActivity::Journalizable + include RedmineAdminActivity::Controllers::Organizations::MembershipsControllerPatch + + before_action :store_previous_values, :only => [:update] + after_action :journalized_memberships_edition, :only => [:update] + after_action :journalized_non_members_roles_creation, :only => [:create_non_members_roles] + + before_action :store_previous_values_non_members_roles, :only => [:update_non_members_roles, :destroy_non_members_roles, :update_non_members_functions] + after_action :journalized_non_members_roles_edition, :only => [:update_non_members_roles] + after_action :journalized_non_members_functions_edition, :only => [:update_non_members_functions] + after_action :add_non_members_deletion_to_journal, :only => [:destroy_non_members_roles] + after_action :add_non_members_deletion_to_journal, :only => [:destroy_non_members_roles] + end +end diff --git a/lib/redmine_admin_activity/controllers/organizations_controller.rb b/lib/redmine_admin_activity/controllers/organizations_controller.rb deleted file mode 100644 index ef75e11..0000000 --- a/lib/redmine_admin_activity/controllers/organizations_controller.rb +++ /dev/null @@ -1,58 +0,0 @@ -require_dependency 'organizations_controller' - -class OrganizationsController < ApplicationController - - after_action :journalized_organizations_creation, :only => [:create] - after_action :journalized_organizations_deletion, :only => [:destroy] - before_action :memorize_deleted_organizations, :only => [:destroy] - before_action :memorize_attributes_organizations, :only => [:update] - after_action :journalized_organizations_update, :only => [:update] - - private - - def journalized_organizations_creation - return unless @organization.present? && @organization.persisted? - @organization.journalize_creation(User.current) - end - - def journalized_organizations_deletion - return unless @organization.destroyed? - - @deleted_organizations.each do |org| - changes = org.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes, - :journalized => org, - :journalized_entry_type => "destroy", - ) - end - - end - - def memorize_deleted_organizations - @deleted_organizations = @organization.self_and_descendants.to_a - end - - def memorize_attributes_organizations - @old_attributes = @organization.attributes - end - - def journalized_organizations_update - # Build hash of previous_changes manually, After a long search, I couldn't know why the previous changes are empty when changing the parent. - @previous_changes = {} - @new_attributes = @organization.attributes - @new_attributes.each do |key, val| - @previous_changes[key] = - [@old_attributes[key], val] if @organization.journalized_attribute_names.include?(key) && @old_attributes[key] != val - end - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => @previous_changes, - :journalized => @organization, - :journalized_entry_type => "update", - ) - end -end diff --git a/lib/redmine_admin_activity/controllers/organizations_controller_patch.rb b/lib/redmine_admin_activity/controllers/organizations_controller_patch.rb new file mode 100644 index 0000000..dc81eb9 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/organizations_controller_patch.rb @@ -0,0 +1,65 @@ +require_dependency 'organizations_controller' if Redmine::VERSION::MAJOR < 5 + +module RedmineAdminActivity::Controllers + module OrganizationsControllerPatch + extend ActiveSupport::Concern + + def journalized_organizations_creation + return unless @organization.present? && @organization.persisted? + @organization.journalize_creation(User.current) + end + + def journalized_organizations_deletion + return unless @organization.destroyed? + + @deleted_organizations.each do |org| + changes = org.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized => org, + :journalized_entry_type => "destroy", + ) + end + + end + + def memorize_deleted_organizations + @deleted_organizations = @organization.self_and_descendants.to_a + end + + def memorize_attributes_organizations + @old_attributes = @organization.attributes + end + + def journalized_organizations_update + # Build hash of previous_changes manually, After a long search, I couldn't know why the previous changes are empty when changing the parent. + @previous_changes = {} + @new_attributes = @organization.attributes + @new_attributes.each do |key, val| + @previous_changes[key] = + [@old_attributes[key], val] if @organization.journalized_attribute_names.include?(key) && @old_attributes[key] != val + end + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => @previous_changes, + :journalized => @organization, + :journalized_entry_type => "update", + ) + end + end +end + +class OrganizationsController < ApplicationController + + prepend RedmineAdminActivity::Controllers::OrganizationsControllerPatch + + after_action :journalized_organizations_creation, :only => [:create] + after_action :journalized_organizations_deletion, :only => [:destroy] + before_action :memorize_deleted_organizations, :only => [:destroy] + before_action :memorize_attributes_organizations, :only => [:update] + after_action :journalized_organizations_update, :only => [:update] + +end diff --git a/lib/redmine_admin_activity/controllers/principal_memberships_controller.rb b/lib/redmine_admin_activity/controllers/principal_memberships_controller.rb deleted file mode 100644 index 68f1fe4..0000000 --- a/lib/redmine_admin_activity/controllers/principal_memberships_controller.rb +++ /dev/null @@ -1,30 +0,0 @@ -require_dependency 'principal_memberships_controller' - -class PrincipalMembershipsController - include RedmineAdminActivity::Journalizable - - before_action :store_role_ids, :only => [:destroy] - after_action :journalized_memberships_creation, :only => [:create] - after_action :journalized_memberships_deletion, :only => [:destroy] - - private - - def store_role_ids - member = Member.find(params[:id]) - @previous_role_ids = member.role_ids - @previous_function_ids = member.function_ids if limited_visibility_plugin_installed? - end - - def journalized_memberships_creation - @members.each do |member| - next unless member.persisted? - role_ids = params[:membership][:role_ids] - function_ids = params[:membership][:function_ids] if limited_visibility_plugin_installed? - add_member_creation_to_journal(member, role_ids, function_ids) - end - end - - def journalized_memberships_deletion - add_member_deletion_to_journal(@membership, @previous_role_ids, @previous_function_ids) - end -end diff --git a/lib/redmine_admin_activity/controllers/principal_memberships_controller_patch.rb b/lib/redmine_admin_activity/controllers/principal_memberships_controller_patch.rb new file mode 100644 index 0000000..045a8bf --- /dev/null +++ b/lib/redmine_admin_activity/controllers/principal_memberships_controller_patch.rb @@ -0,0 +1,35 @@ +require_dependency 'principal_memberships_controller' + +module RedmineAdminActivity::Controllers + module PrincipalMembershipsControllerPatch + extend ActiveSupport::Concern + + def store_role_ids + member = Member.find(params[:id]) + @previous_role_ids = member.role_ids + @previous_function_ids = member.function_ids if limited_visibility_plugin_installed? + end + + def journalized_memberships_creation + @members.each do |member| + next unless member.persisted? + role_ids = params[:membership][:role_ids] + function_ids = params[:membership][:function_ids] if limited_visibility_plugin_installed? + add_member_creation_to_journal(member, role_ids, function_ids) + end + end + + def journalized_memberships_deletion + add_member_deletion_to_journal(@membership, @previous_role_ids, @previous_function_ids) + end + end +end + +class PrincipalMembershipsController + include RedmineAdminActivity::Journalizable + include RedmineAdminActivity::Controllers::PrincipalMembershipsControllerPatch + + before_action :store_role_ids, :only => [:destroy] + after_action :journalized_memberships_creation, :only => [:create] + after_action :journalized_memberships_deletion, :only => [:destroy] +end diff --git a/lib/redmine_admin_activity/controllers/projects_controller.rb b/lib/redmine_admin_activity/controllers/projects_controller.rb deleted file mode 100644 index 2833ad8..0000000 --- a/lib/redmine_admin_activity/controllers/projects_controller.rb +++ /dev/null @@ -1,256 +0,0 @@ -require_dependency 'projects_controller' - -class ProjectsController - - helper :journal_settings - include JournalSettingsHelper - - before_action :init_journal, :only => [:update] - after_action :update_journal, :only => [:update] - after_action :journalized_projects_duplication, :only => [:copy] - after_action :journalized_projects_creation, :only => [:create] - after_action :journalized_projects_deletion, :only => [:destroy] - append_before_action :self_and_descendants_or_ancestors, :only => [:close, :archive, :unarchive, :reopen, :destroy] - after_action :journalized_projects_activation, :only => [:unarchive] - after_action :journalized_projects_closing, :only => [:close] - after_action :journalized_projects_archivation, :only => [:archive] - after_action :journalized_projects_reopen, :only => [:reopen] - append_before_action :get_projects_journals_for_pagination, :only => [:settings] - - def init_journal - find_project unless @project - @project.init_journal(User.current) - @previous_enabled_module_names = @project.enabled_module_names - @previous_enabled_tracker_ids = @project.tracker_ids - @previous_enabled_issue_custom_field_ids = @project.issue_custom_field_ids - @previous_enabled_template_ids = @project.issue_template_ids if Redmine::Plugin.installed?(:redmine_templates) - end - - def add_journal_entry(property:, prop_key: nil, value: nil, old_value: nil) - prop_key = property if prop_key.nil? - @project.current_journal.details << JournalDetail.new( - :property => property, - :prop_key => prop_key, - :value => value, - :old_value => old_value - ) - end - - def update_journal - @project.init_journal(User.current) - - if @previous_enabled_tracker_ids != @project.tracker_ids - previous_tracker_names = Tracker.where(:id => @previous_enabled_tracker_ids.map(&:to_i)).sorted.pluck(:name) - add_journal_entry(property: 'trackers', - value: @project.trackers.map(&:name).join(','), - old_value: previous_tracker_names.join(',')) - end - - if @previous_enabled_issue_custom_field_ids != @project.issue_custom_field_ids - previous_custom_field_names = CustomField.where(:id => @previous_enabled_issue_custom_field_ids.map(&:to_i)).sorted.pluck(:name) - add_journal_entry(property: 'custom_fields', - value: @project.issue_custom_fields.map(&:name).join(','), - old_value: previous_custom_field_names.join(',')) - end - - if @previous_enabled_module_names != @project.enabled_module_names - add_journal_entry(property: 'modules', - value: @project.enabled_module_names.join(','), - old_value: @previous_enabled_module_names.join(',')) - end - - if Redmine::Plugin.installed?(:redmine_templates) && (@previous_enabled_template_ids != @project.issue_template_ids) - previous_issue_templates_titles = IssueTemplate.where(:id => @previous_enabled_template_ids.map(&:to_i)).pluck(:template_title) - activated_templates_titles = @project.issue_templates.map(&:template_title) - previous_issue_templates_titles - deactivated_templates_titles = previous_issue_templates_titles - @project.issue_templates.map(&:template_title) - activated_templates_titles.each do |temp_title| - add_journal_entry(property: 'templates', - prop_key: 'enabled_template', - value: temp_title, - old_value: nil) - end - deactivated_templates_titles.each do |temp_title| - add_journal_entry(property: 'templates', - prop_key: 'enabled_template', - value: nil, - old_value: temp_title) - end - end - @project.current_journal.save if @project.current_journal.details.any? - end - - def journalized_projects_duplication - return unless @project.present? && @project.persisted? - - @project.init_journal(User.current) - - @project.current_journal.details << JournalDetail.new( - :property => 'copy_project', - :prop_key => 'copy_project', - :value => "#{@source_project.name} (id: #{@source_project.id})" - ) - - @project.current_journal.save if @project.current_journal.details.any? - - changes = @project.attributes.to_a.map { |i| [i[0], [nil, i[1]]] }.to_h - changes["source_project"] = @source_project.id - changes["source_project_name"] = @source_project.name - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes, - :journalized => @project, - :journalized_entry_type => "copy", - ) - end - - def journalized_projects_creation - return unless @project.present? && @project.persisted? - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => @project.previous_changes, - :journalized => @project, - :journalized_entry_type => "create", - ) - end - - def journalized_projects_deletion - return unless @project_to_destroy.present? && @project_to_destroy.destroyed? - - @self_and_descendants_or_ancestors.each do |project| - changes = project.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes, - :journalized => project, - :journalized_entry_type => "destroy", - ) - end - end - - def journalized_projects_activation - return unless @project.present? && @project.persisted? - - new_status = @project.ancestors.any?(&:closed?) ? Project::STATUS_CLOSED : Project::STATUS_ACTIVE - entry_type = @project.ancestors.any?(&:closed?) ? "close" : "active" - @self_and_descendants_or_ancestors.each do |ancestor| - # build hash of previous_changes manually - previous_changes = { - "status" => [Project::STATUS_ARCHIVED, new_status], - } - - # Saves the changes in a JournalDetail - ancestor.add_journal_entry(property: 'status', - value: new_status, - old_value: Project::STATUS_ARCHIVED) - - # Saves the changes in a JournalSetting - JournalSetting.create( - :user_id => User.current.id, - :value_changes => previous_changes, - :journalized => ancestor, - :journalized_entry_type => entry_type, - ) - end - end - - def journalized_projects_closing - return unless @project.present? && @project.persisted? - - @self_and_descendants_or_ancestors.each do |child| - # build hash of previous_changes manually - previous_changes = { - "status" => [Project::STATUS_ACTIVE, Project::STATUS_CLOSED], - } - - # Saves the changes in a JournalDetail - child.add_journal_entry(property: 'status', - value: Project::STATUS_CLOSED, - old_value: Project::STATUS_ACTIVE) - - # Saves the changes in a JournalSetting - JournalSetting.create( - :user_id => User.current.id, - :value_changes => previous_changes, - :journalized => child, - :journalized_entry_type => "close", - ) - end - end - - def journalized_projects_archivation - return unless @project.present? && @project.persisted? - - @self_and_descendants_or_ancestors.each do |child| - - if child.status != Project::STATUS_ARCHIVED - # build hash of previous_changes manually - previous_changes = { - "status" => [child.status, Project::STATUS_ARCHIVED], - } - - # Saves the changes in a JournalDetail - child.add_journal_entry(property: 'status', - value: Project::STATUS_ARCHIVED, - old_value: child.status) - - # Saves the changes in a JournalSetting - JournalSetting.create( - :user_id => User.current.id, - :value_changes => previous_changes, - :journalized => child, - :journalized_entry_type => "archive", - ) - end - end - end - - def journalized_projects_reopen - return unless @project.present? && @project.persisted? - - @self_and_descendants_or_ancestors.each do |child| - # build hash of previous_changes manually - previous_changes = { - "status" => [Project::STATUS_CLOSED, Project::STATUS_ACTIVE], - } - - # Saves the changes in a JournalDetail - child.add_journal_entry(property: 'status', - value: Project::STATUS_ACTIVE, - old_value: Project::STATUS_CLOSED) - - # Saves the changes in a JournalSetting - JournalSetting.create( - :user_id => User.current.id, - :value_changes => previous_changes, - :journalized => child, - :journalized_entry_type => "reopen", - ) - end - end - - def self_and_descendants_or_ancestors - @self_and_descendants_or_ancestors = case action_name - when "close" - @project.self_and_descendants.status(Project::STATUS_ACTIVE).to_a - when "reopen" - @project.self_and_descendants.status(Project::STATUS_CLOSED).to_a - when "unarchive" - @project.self_and_ancestors.status(Project::STATUS_ARCHIVED).to_a - when "archive", "destroy" - @project.self_and_descendants.to_a - end - end - - def get_projects_journals_for_pagination - find_project unless @project - @scope = get_journal_for_history(@project.journals) - @journal_count = @scope.count - @journal_pages = Paginator.new @journal_count, per_page_option, params['page'] - @journals = @scope.limit(@journal_pages.per_page).offset(@journal_pages.offset).to_a - @journals = add_index_to_journal_for_history(@journals) - end - -end diff --git a/lib/redmine_admin_activity/controllers/projects_controller_patch.rb b/lib/redmine_admin_activity/controllers/projects_controller_patch.rb new file mode 100644 index 0000000..7441683 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/projects_controller_patch.rb @@ -0,0 +1,268 @@ +require_dependency 'projects_controller' + +module RedmineAdminActivity::Controllers + module ProjectsControllerPatch + extend ActiveSupport::Concern + include Redmine::Pagination + + def init_journal + find_project unless @project + @project.init_journal(User.current) + @previous_enabled_module_names = @project.enabled_module_names + @previous_enabled_tracker_ids = @project.tracker_ids + @previous_enabled_issue_custom_field_ids = @project.issue_custom_field_ids + @previous_enabled_template_ids = @project.issue_template_ids if Redmine::Plugin.installed?(:redmine_templates) + end + + def add_journal_entry(property:, prop_key: nil, value: nil, old_value: nil) + prop_key = property if prop_key.nil? + @project.current_journal.details << JournalDetail.new( + :property => property, + :prop_key => prop_key, + :value => value, + :old_value => old_value + ) + end + + def update_journal + @project.init_journal(User.current) + + if @previous_enabled_tracker_ids != @project.tracker_ids + previous_tracker_names = Tracker.where(:id => @previous_enabled_tracker_ids.map(&:to_i)).sorted.pluck(:name) + add_journal_entry(property: 'trackers', + value: @project.trackers.map(&:name).join(','), + old_value: previous_tracker_names.join(',')) + end + + if @previous_enabled_issue_custom_field_ids != @project.issue_custom_field_ids + previous_custom_field_names = CustomField.where(:id => @previous_enabled_issue_custom_field_ids.map(&:to_i)).sorted.pluck(:name) + add_journal_entry(property: 'custom_fields', + value: @project.issue_custom_fields.map(&:name).join(','), + old_value: previous_custom_field_names.join(',')) + end + + if @previous_enabled_module_names != @project.enabled_module_names + add_journal_entry(property: 'modules', + value: @project.enabled_module_names.join(','), + old_value: @previous_enabled_module_names.join(',')) + end + + if Redmine::Plugin.installed?(:redmine_templates) && (@previous_enabled_template_ids != @project.issue_template_ids) + previous_issue_templates_titles = IssueTemplate.where(:id => @previous_enabled_template_ids.map(&:to_i)).pluck(:template_title) + activated_templates_titles = @project.issue_templates.map(&:template_title) - previous_issue_templates_titles + deactivated_templates_titles = previous_issue_templates_titles - @project.issue_templates.map(&:template_title) + activated_templates_titles.each do |temp_title| + add_journal_entry(property: 'templates', + prop_key: 'enabled_template', + value: temp_title, + old_value: nil) + end + deactivated_templates_titles.each do |temp_title| + add_journal_entry(property: 'templates', + prop_key: 'enabled_template', + value: nil, + old_value: temp_title) + end + end + @project.current_journal.save if @project.current_journal.details.any? + end + + def journalized_projects_duplication + return unless @project.present? && @project.persisted? + + @project.init_journal(User.current) + + @project.current_journal.details << JournalDetail.new( + :property => 'copy_project', + :prop_key => 'copy_project', + :value => "#{@source_project.name} (id: #{@source_project.id})" + ) + + @project.current_journal.save if @project.current_journal.details.any? + + changes = @project.attributes.to_a.map { |i| [i[0], [nil, i[1]]] }.to_h + changes["source_project"] = @source_project.id + changes["source_project_name"] = @source_project.name + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized => @project, + :journalized_entry_type => "copy", + ) + end + + def journalized_projects_creation + return unless @project.present? && @project.persisted? + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => @project.previous_changes, + :journalized => @project, + :journalized_entry_type => "create", + ) + end + + def journalized_projects_deletion + if Redmine::VERSION::MAJOR >= 5 + return unless @project_to_destroy.present? && (@project_to_destroy.destroyed? || @project_to_destroy.scheduled_for_deletion?) + else + return unless @project_to_destroy.present? && @project_to_destroy.destroyed? + end + + @self_and_descendants_or_ancestors.each do |project| + changes = project.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized => project, + :journalized_entry_type => "destroy", + ) + end + end + + def journalized_projects_activation + return unless @project.present? && @project.persisted? + + new_status = @project.ancestors.any?(&:closed?) ? Project::STATUS_CLOSED : Project::STATUS_ACTIVE + entry_type = @project.ancestors.any?(&:closed?) ? "close" : "active" + @self_and_descendants_or_ancestors.each do |ancestor| + # build hash of previous_changes manually + previous_changes = { + "status" => [Project::STATUS_ARCHIVED, new_status], + } + + # Saves the changes in a JournalDetail + ancestor.add_journal_entry(property: 'status', + value: new_status, + old_value: Project::STATUS_ARCHIVED) + + # Saves the changes in a JournalSetting + JournalSetting.create( + :user_id => User.current.id, + :value_changes => previous_changes, + :journalized => ancestor, + :journalized_entry_type => entry_type, + ) + end + end + + def journalized_projects_closing + return unless @project.present? && @project.persisted? + + @self_and_descendants_or_ancestors.each do |child| + # build hash of previous_changes manually + previous_changes = { + "status" => [Project::STATUS_ACTIVE, Project::STATUS_CLOSED], + } + + # Saves the changes in a JournalDetail + child.add_journal_entry(property: 'status', + value: Project::STATUS_CLOSED, + old_value: Project::STATUS_ACTIVE) + + # Saves the changes in a JournalSetting + JournalSetting.create( + :user_id => User.current.id, + :value_changes => previous_changes, + :journalized => child, + :journalized_entry_type => "close", + ) + end + end + + def journalized_projects_archivation + return unless @project.present? && @project.persisted? + + @self_and_descendants_or_ancestors.each do |child| + + if child.status != Project::STATUS_ARCHIVED + # build hash of previous_changes manually + previous_changes = { + "status" => [child.status, Project::STATUS_ARCHIVED], + } + + # Saves the changes in a JournalDetail + child.add_journal_entry(property: 'status', + value: Project::STATUS_ARCHIVED, + old_value: child.status) + + # Saves the changes in a JournalSetting + JournalSetting.create( + :user_id => User.current.id, + :value_changes => previous_changes, + :journalized => child, + :journalized_entry_type => "archive", + ) + end + end + end + + def journalized_projects_reopen + return unless @project.present? && @project.persisted? + + @self_and_descendants_or_ancestors.each do |child| + # build hash of previous_changes manually + previous_changes = { + "status" => [Project::STATUS_CLOSED, Project::STATUS_ACTIVE], + } + + # Saves the changes in a JournalDetail + child.add_journal_entry(property: 'status', + value: Project::STATUS_ACTIVE, + old_value: Project::STATUS_CLOSED) + + # Saves the changes in a JournalSetting + JournalSetting.create( + :user_id => User.current.id, + :value_changes => previous_changes, + :journalized => child, + :journalized_entry_type => "reopen", + ) + end + end + + def self_and_descendants_or_ancestors + @self_and_descendants_or_ancestors = case action_name + when "close" + @project.self_and_descendants.status(Project::STATUS_ACTIVE).to_a + when "reopen" + @project.self_and_descendants.status(Project::STATUS_CLOSED).to_a + when "unarchive" + @project.self_and_ancestors.status(Project::STATUS_ARCHIVED).to_a + when "archive", "destroy" + @project.self_and_descendants.to_a + end + end + + def get_projects_journals_for_pagination + find_project unless @project + @scope = get_journal_for_history(@project.journals) + @journal_count = @scope.count + @journal_pages = Paginator.new @journal_count, per_page_option, params['page'] + @journals = @scope.limit(@journal_pages.per_page).offset(@journal_pages.offset).to_a + @journals = add_index_to_journal_for_history(@journals) + end + end +end + +class ProjectsController + + prepend RedmineAdminActivity::Controllers::ProjectsControllerPatch + + helper :journal_settings + include JournalSettingsHelper + + before_action :init_journal, :only => [:update] + after_action :update_journal, :only => [:update] + after_action :journalized_projects_duplication, :only => [:copy] + after_action :journalized_projects_creation, :only => [:create] + after_action :journalized_projects_deletion, :only => [:destroy] + append_before_action :self_and_descendants_or_ancestors, :only => [:close, :archive, :unarchive, :reopen, :destroy] + after_action :journalized_projects_activation, :only => [:unarchive] + after_action :journalized_projects_closing, :only => [:close] + after_action :journalized_projects_archivation, :only => [:archive] + after_action :journalized_projects_reopen, :only => [:reopen] + append_before_action :get_projects_journals_for_pagination, :only => [:settings] + +end diff --git a/lib/redmine_admin_activity/controllers/settings_controller.rb b/lib/redmine_admin_activity/controllers/settings_controller.rb deleted file mode 100644 index 7d72d02..0000000 --- a/lib/redmine_admin_activity/controllers/settings_controller.rb +++ /dev/null @@ -1,49 +0,0 @@ -require_dependency 'settings_controller' - -class SettingsController - before_action :intialize_settings_was, :only => [:edit] - after_action :track_settings_was_changes, :only => [:edit] - before_action :get_settings_journals_for_pagination, :only => [:index] - - helper :journal_settings - include JournalSettingsHelper - - private - - def intialize_settings_was - @settings_was = Setting.pluck(:name) - .select { |name| Setting.find_by_name(name).valid? } - .map { |name| [name.to_sym, Setting[name]] } - end - - def track_settings_was_changes - settings_was = @settings_was.dup - changes = settings_was.map do |entry| - name = entry[0] - old_value = entry[1] - new_value = Setting[entry[0]] - [name, [old_value, new_value]] - end - - changes = changes.reject { |entry| entry[1][0] == entry[1][1] }.to_h - - return unless changes.any? - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes - ) - end - - def get_settings_journals_for_pagination - @scope = JournalSetting.includes(:user) - .search_scope(params[:name]) - .reorder(created_on: :desc) - .references(:user) - @journal_count = @scope.count - @journal_pages = Paginator.new @journal_count, per_page_option, params['page'] - @journals = @scope.limit(@journal_pages.per_page).offset(@journal_pages.offset).to_a - @journals = add_index_to_journal_for_history(@journals) - end - -end diff --git a/lib/redmine_admin_activity/controllers/settings_controller_patch.rb b/lib/redmine_admin_activity/controllers/settings_controller_patch.rb new file mode 100644 index 0000000..d0268c7 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/settings_controller_patch.rb @@ -0,0 +1,55 @@ +require_dependency 'settings_controller' + +module RedmineAdminActivity::Controllers + module SettingsControllerPatch + extend ActiveSupport::Concern + include Redmine::Pagination + + def intialize_settings_was + @settings_was = Setting.pluck(:name) + .select { |name| Setting.find_by_name(name).valid? } + .map { |name| [name.to_sym, Setting[name]] } + end + + def track_settings_was_changes + settings_was = @settings_was.dup + changes = settings_was.map do |entry| + name = entry[0] + old_value = entry[1] + new_value = Setting[entry[0]] + [name, [old_value, new_value]] + end + + changes = changes.reject { |entry| entry[1][0] == entry[1][1] }.to_h + + return unless changes.any? + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes + ) + end + + def get_settings_journals_for_pagination + @scope = JournalSetting.includes(:user) + .search_scope(params[:name]) + .reorder(created_on: :desc) + .references(:user) + @journal_count = @scope.count + @journal_pages = Paginator.new @journal_count, per_page_option, params['page'] + @journals = @scope.limit(@journal_pages.per_page).offset(@journal_pages.offset).to_a + @journals = add_index_to_journal_for_history(@journals) + end + end +end + +class SettingsController + include RedmineAdminActivity::Controllers::SettingsControllerPatch + + before_action :intialize_settings_was, :only => [:edit] + after_action :track_settings_was_changes, :only => [:edit] + before_action :get_settings_journals_for_pagination, :only => [:index] + + helper :journal_settings + include JournalSettingsHelper +end diff --git a/lib/redmine_admin_activity/controllers/trackers_controller.rb b/lib/redmine_admin_activity/controllers/trackers_controller.rb deleted file mode 100644 index 41ccc60..0000000 --- a/lib/redmine_admin_activity/controllers/trackers_controller.rb +++ /dev/null @@ -1,79 +0,0 @@ -require_dependency 'trackers_controller' - -class TrackersController - before_action :store_project_ids, :only => [:update] - after_action :journalized_trackers_creation, :only => [:create] - after_action :journalized_trackers_upgrade, :only => [:update] - before_action :journalized_trackers_deletion_preparation, :only => [:destroy] - after_action :journalized_trackers_deletion, :only => [:destroy] - - private - - def store_project_ids - tracker = Tracker.find(params[:id]) - @previous_project_ids = tracker.project_ids - end - - def journalized_trackers_creation - # TODO: check projects - return unless @tracker.persisted? - - @tracker.projects.each do |project| - add_journal_entry project, JournalDetail.new( - :property => :trackers, - :prop_key => :trackers, - :value => @tracker.name - ) - end - end - - def journalized_trackers_upgrade - return if @previous_project_ids == @tracker.project_ids - - changed_project_ids = array_difference(@previous_project_ids, @tracker.project_ids) - - Project.where(id: changed_project_ids).each do |project| - journal_detail = JournalDetail.new( - :property => :trackers, - :prop_key => :trackers - ) - - if @previous_project_ids.include?(project.id) && !@tracker.project_ids.include?(project.id) - journal_detail.old_value = @tracker.name - elsif !@previous_project_ids.include?(project.id) && @tracker.project_ids.include?(project.id) - journal_detail.value = @tracker.name - end - - add_journal_entry project, journal_detail - end - end - - def journalized_trackers_deletion_preparation - @jouarnals_projects = [] - - tracker = Tracker.find(params[:id]) - tracker.projects.each do |project| - project.init_journal(User.current) - project.current_journal.details << JournalDetail.new( - :property => :trackers, - :prop_key => :trackers, - :old_value => tracker.name - ) - @jouarnals_projects << project - end - end - - def journalized_trackers_deletion - @jouarnals_projects.each { |project| project.current_journal.save } - end - - def add_journal_entry(project, journal_detail) - project.init_journal(User.current) - project.current_journal.details << journal_detail - project.current_journal.save - end - - def array_difference(arr1, arr2) - arr1 - arr2 | arr2 - arr1 - end -end diff --git a/lib/redmine_admin_activity/controllers/trackers_controller_patch.rb b/lib/redmine_admin_activity/controllers/trackers_controller_patch.rb new file mode 100644 index 0000000..0c15c18 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/trackers_controller_patch.rb @@ -0,0 +1,85 @@ +require_dependency 'trackers_controller' + +module RedmineAdminActivity::Controllers + module TrackersControllerPatch + extend ActiveSupport::Concern + + def store_project_ids + tracker = Tracker.find(params[:id]) + @previous_project_ids = tracker.project_ids + end + + def journalized_trackers_creation + # TODO: check projects + return unless @tracker.persisted? + + @tracker.projects.each do |project| + add_journal_entry project, JournalDetail.new( + :property => :trackers, + :prop_key => :trackers, + :value => @tracker.name + ) + end + end + + def journalized_trackers_upgrade + return if @previous_project_ids == @tracker.project_ids + + changed_project_ids = array_difference(@previous_project_ids, @tracker.project_ids) + + Project.where(id: changed_project_ids).each do |project| + journal_detail = JournalDetail.new( + :property => :trackers, + :prop_key => :trackers + ) + + if @previous_project_ids.include?(project.id) && !@tracker.project_ids.include?(project.id) + journal_detail.old_value = @tracker.name + elsif !@previous_project_ids.include?(project.id) && @tracker.project_ids.include?(project.id) + journal_detail.value = @tracker.name + end + + add_journal_entry project, journal_detail + end + end + + def journalized_trackers_deletion_preparation + @jouarnals_projects = [] + + tracker = Tracker.find(params[:id]) + tracker.projects.each do |project| + project.init_journal(User.current) + project.current_journal.details << JournalDetail.new( + :property => :trackers, + :prop_key => :trackers, + :old_value => tracker.name + ) + @jouarnals_projects << project + end + end + + def journalized_trackers_deletion + @jouarnals_projects.each { |project| project.current_journal.save } + end + + def add_journal_entry(project, journal_detail) + project.init_journal(User.current) + project.current_journal.details << journal_detail + project.current_journal.save + end + + def array_difference(arr1, arr2) + arr1 - arr2 | arr2 - arr1 + end + end +end + +class TrackersController + include RedmineAdminActivity::Controllers::TrackersControllerPatch + + before_action :store_project_ids, :only => [:update] + after_action :journalized_trackers_creation, :only => [:create] + after_action :journalized_trackers_upgrade, :only => [:update] + before_action :journalized_trackers_deletion_preparation, :only => [:destroy] + after_action :journalized_trackers_deletion, :only => [:destroy] +end diff --git a/lib/redmine_admin_activity/controllers/users_controller.rb b/lib/redmine_admin_activity/controllers/users_controller.rb deleted file mode 100644 index 7f6ec2e..0000000 --- a/lib/redmine_admin_activity/controllers/users_controller.rb +++ /dev/null @@ -1,84 +0,0 @@ -require_dependency 'users_controller' - -class UsersController - - helper :journal_settings - include JournalSettingsHelper - include RedmineAdminActivity::Journalizable - - after_action :journalized_users_creation, :only => [:create] - after_action :journalized_users_update_status, :only => [:update] - after_action :journalized_users_deletion, :only => [:destroy] - before_action :init_journal, :only => [:update] - before_action lambda { find_user(false) }, :only => :history - - def history - @scope = get_journal_for_history(@user.journals) - @journal_count = @scope.count - @journal_pages = Paginator.new @journal_count, per_page_option, params['page'] - @journals = @scope.limit(@journal_pages.per_page).offset(@journal_pages.offset).to_a - @journals = add_index_to_journal_for_history(@journals) - end - - def journalized_users_creation - - return unless @user.present? && @user.persisted? - - JournalSetting.create( - :user_id => User.current.id, - :value_changes => @user.previous_changes, - :journalized => @user, - :journalized_entry_type => "create", - ) - add_journal_entry_for_user(user: @user, property: 'creation', prop_key: 'creation', value: User::USER_MANUAL_CREATION) - end - - def journalized_users_update_status - - return unless @user.present? && @user.persisted? - - if @user.previous_changes[:status] == [User::STATUS_REGISTERED, User::STATUS_ACTIVE] - JournalSetting.create( - :user_id => User.current.id, - :value_changes => @user.previous_changes, - :journalized => @user, - :journalized_entry_type => "active", - ) - end - - if @user.previous_changes[:status] == [User::STATUS_ACTIVE, User::STATUS_LOCKED] - JournalSetting.create( - :user_id => User.current.id, - :value_changes => @user.previous_changes, - :journalized => @user, - :journalized_entry_type => "lock", - ) - end - - if @user.previous_changes[:status] == [User::STATUS_LOCKED, User::STATUS_ACTIVE] - JournalSetting.create( - :user_id => User.current.id, - :value_changes => @user.previous_changes, - :journalized => @user, - :journalized_entry_type => "unlock", - ) - end - - end - - def journalized_users_deletion - return unless @user.destroyed? - - changes = @user.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h - JournalSetting.create( - :user_id => User.current.id, - :value_changes => changes, - :journalized => @user, - :journalized_entry_type => "destroy", - ) - end - - def init_journal - @user.init_journal(User.current) - end -end diff --git a/lib/redmine_admin_activity/controllers/users_controller_patch.rb b/lib/redmine_admin_activity/controllers/users_controller_patch.rb new file mode 100644 index 0000000..c58b614 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/users_controller_patch.rb @@ -0,0 +1,93 @@ +require_dependency 'users_controller' + +module RedmineAdminActivity::Controllers + module UsersControllerPatch + extend ActiveSupport::Concern + include Redmine::Pagination + + def history + @scope = get_journal_for_history(@user.journals) + @journal_count = @scope.count + @journal_pages = Paginator.new @journal_count, per_page_option, params['page'] + @journals = @scope.limit(@journal_pages.per_page).offset(@journal_pages.offset).to_a + @journals = add_index_to_journal_for_history(@journals) + end + + def journalized_users_creation + + return unless @user.present? && @user.persisted? + + JournalSetting.create( + :user_id => User.current.id, + :value_changes => @user.previous_changes, + :journalized => @user, + :journalized_entry_type => "create", + ) + add_journal_entry_for_user(user: @user, property: 'creation', prop_key: 'creation', value: User::USER_MANUAL_CREATION) + end + + def journalized_users_update_status + + return unless @user.present? && @user.persisted? + + if @user.previous_changes[:status] == [User::STATUS_REGISTERED, User::STATUS_ACTIVE] + JournalSetting.create( + :user_id => User.current.id, + :value_changes => @user.previous_changes, + :journalized => @user, + :journalized_entry_type => "active", + ) + end + + if @user.previous_changes[:status] == [User::STATUS_ACTIVE, User::STATUS_LOCKED] + JournalSetting.create( + :user_id => User.current.id, + :value_changes => @user.previous_changes, + :journalized => @user, + :journalized_entry_type => "lock", + ) + end + + if @user.previous_changes[:status] == [User::STATUS_LOCKED, User::STATUS_ACTIVE] + JournalSetting.create( + :user_id => User.current.id, + :value_changes => @user.previous_changes, + :journalized => @user, + :journalized_entry_type => "unlock", + ) + end + + end + + def journalized_users_deletion + return unless @user.destroyed? + + changes = @user.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized => @user, + :journalized_entry_type => "destroy", + ) + end + + def init_journal + @user.init_journal(User.current) + end + end +end + +class UsersController + include RedmineAdminActivity::Controllers::UsersControllerPatch + + helper :journal_settings + include JournalSettingsHelper + include RedmineAdminActivity::Journalizable + + after_action :journalized_users_creation, :only => [:create] + after_action :journalized_users_update_status, :only => [:update] + after_action :journalized_users_deletion, :only => [:destroy] + before_action :init_journal, :only => [:update] + before_action lambda { find_user(false) }, :only => :history + +end diff --git a/lib/redmine_admin_activity/controllers/wiki_controller.rb b/lib/redmine_admin_activity/controllers/wiki_controller.rb deleted file mode 100644 index 9313b53..0000000 --- a/lib/redmine_admin_activity/controllers/wiki_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -require_dependency 'wiki_controller' - -class WikiController - include RedmineAdminActivity::Journalizable - - before_action :keep_self_and_descendants, :only => [:destroy] - after_action :journalize_wiki_page_deletion, :only => [:destroy] - - def keep_self_and_descendants - @kept_self_and_descendants = [@page] # case of leaf page, or page without children, or page with children and params[:todo] = nullify or reassign - @kept_self_and_descendants += @page.descendants.to_a if params[:todo].present? && params[:todo] == 'destroy' - end - - def journalize_wiki_page_deletion - return unless @page.present? && @page.destroyed? - - @kept_self_and_descendants.each do |wiki| - add_wiki_page_journal_entry(project: wiki.project, - value: nil, - old_value: wiki.title) - end - end - -end diff --git a/lib/redmine_admin_activity/controllers/wiki_controller_patch.rb b/lib/redmine_admin_activity/controllers/wiki_controller_patch.rb new file mode 100644 index 0000000..a4dad46 --- /dev/null +++ b/lib/redmine_admin_activity/controllers/wiki_controller_patch.rb @@ -0,0 +1,30 @@ +require_dependency 'wiki_controller' + +module RedmineAdminActivity::Controllers + module WikiControllerPatch + extend ActiveSupport::Concern + + def keep_self_and_descendants + @kept_self_and_descendants = [@page] # case of leaf page, or page without children, or page with children and params[:todo] = nullify or reassign + @kept_self_and_descendants += @page.descendants.to_a if params[:todo].present? && params[:todo] == 'destroy' + end + + def journalize_wiki_page_deletion + return unless @page.present? && @page.destroyed? + + @kept_self_and_descendants.each do |wiki| + add_wiki_page_journal_entry(project: wiki.project, + value: nil, + old_value: wiki.title) + end + end + end +end + +class WikiController + include RedmineAdminActivity::Journalizable + include RedmineAdminActivity::Controllers::WikiControllerPatch + + before_action :keep_self_and_descendants, :only => [:destroy] + after_action :journalize_wiki_page_deletion, :only => [:destroy] +end diff --git a/lib/redmine_admin_activity/helpers/issues_helper.rb b/lib/redmine_admin_activity/helpers/issues_helper_patch.rb similarity index 99% rename from lib/redmine_admin_activity/helpers/issues_helper.rb rename to lib/redmine_admin_activity/helpers/issues_helper_patch.rb index 783b0a7..6badb78 100644 --- a/lib/redmine_admin_activity/helpers/issues_helper.rb +++ b/lib/redmine_admin_activity/helpers/issues_helper_patch.rb @@ -1,8 +1,8 @@ require_dependency 'issues_helper' require 'json' -module PluginAdminActivity - module IssuesHelper +module RedmineAdminActivity::Helpers + module IssuesHelperPatch # Returns the textual representation of a single journal detail # Core properties are 'attr', 'attachment' or 'cf' : this patch specify how to display 'modules' journal details @@ -340,5 +340,5 @@ def val_to_bool(val) end end -IssuesHelper.prepend PluginAdminActivity::IssuesHelper +IssuesHelper.prepend RedmineAdminActivity::Helpers::IssuesHelperPatch ActionView::Base.prepend IssuesHelper diff --git a/lib/redmine_admin_activity/helpers/projects_helper.rb b/lib/redmine_admin_activity/helpers/projects_helper_patch.rb similarity index 79% rename from lib/redmine_admin_activity/helpers/projects_helper.rb rename to lib/redmine_admin_activity/helpers/projects_helper_patch.rb index 5a724d9..537c3f4 100644 --- a/lib/redmine_admin_activity/helpers/projects_helper.rb +++ b/lib/redmine_admin_activity/helpers/projects_helper_patch.rb @@ -1,8 +1,8 @@ require_dependency 'projects_helper' -module RedmineAdminActivity +module RedmineAdminActivity::Helpers - module ProjectsHelper + module ProjectsHelperPatch def project_settings_tabs tabs = super @@ -21,5 +21,5 @@ def project_settings_tabs end -ProjectsHelper.prepend RedmineAdminActivity::ProjectsHelper +ProjectsHelper.prepend RedmineAdminActivity::Helpers::ProjectsHelperPatch ActionView::Base.send(:include, ProjectsHelper) diff --git a/lib/redmine_admin_activity/helpers/settings_helper.rb b/lib/redmine_admin_activity/helpers/settings_helper_patch.rb similarity index 76% rename from lib/redmine_admin_activity/helpers/settings_helper.rb rename to lib/redmine_admin_activity/helpers/settings_helper_patch.rb index ef67be7..4549d42 100644 --- a/lib/redmine_admin_activity/helpers/settings_helper.rb +++ b/lib/redmine_admin_activity/helpers/settings_helper_patch.rb @@ -1,7 +1,7 @@ require_dependency 'settings_helper' -module RedmineAdminActivity - module SettingsHelper +module RedmineAdminActivity::Helpers + module SettingsHelperPatch def administration_settings_tabs tabs = super admin_activity_tab = {name: 'admin_activity', action: :admin_activity, partial: 'settings/admin_activity', label: :project_module_admin_activity} @@ -15,5 +15,5 @@ def administration_settings_tabs end end -SettingsHelper.prepend RedmineAdminActivity::SettingsHelper +SettingsHelper.prepend RedmineAdminActivity::Helpers::SettingsHelperPatch ActionView::Base.send(:include, SettingsHelper) diff --git a/lib/redmine_admin_activity/hooks.rb b/lib/redmine_admin_activity/hooks.rb index 9ca9a28..02a292e 100644 --- a/lib/redmine_admin_activity/hooks.rb +++ b/lib/redmine_admin_activity/hooks.rb @@ -4,37 +4,38 @@ module RedmineAdminActivity module Hooks class ModelHook < Redmine::Hook::Listener def after_plugins_loaded(_context = {}) - require_relative 'controllers/concerns/journalizable' + require_relative 'journalizable' - require_relative 'controllers/projects_controller' # unless Rails.env.test? - require_relative 'controllers/issue_categories_controller' - require_relative 'controllers/members_controller' - require_relative 'controllers/principal_memberships_controller' - require_relative 'controllers/trackers_controller' - require_relative 'controllers/custom_fields_controller' - require_relative 'controllers/settings_controller' - require_relative 'controllers/custom_field_enumerations_controller' - require_relative 'controllers/wiki_controller' + require_relative 'controllers/projects_controller_patch' + require_relative 'jobs/destroy_project_job_patch' + require_relative 'controllers/issue_categories_controller_patch' + require_relative 'controllers/members_controller_patch' + require_relative 'controllers/principal_memberships_controller_patch' + require_relative 'controllers/trackers_controller_patch' + require_relative 'controllers/custom_fields_controller_patch' + require_relative 'controllers/settings_controller_patch' + require_relative 'controllers/custom_field_enumerations_controller_patch' + require_relative 'controllers/wiki_controller_patch' if Redmine::Plugin.installed?(:redmine_organizations) - require_relative 'controllers/organizations/memberships_controller' - require_relative 'controllers/organizations_controller' - require_relative 'models/organization' + require_relative 'controllers/organizations/memberships_controller_patch' + require_relative 'controllers/organizations_controller_patch' + require_relative 'models/organization_patch' end - require_relative 'controllers/users_controller' + require_relative 'controllers/users_controller_patch' - require_relative 'models/project' - require_relative 'models/member' - require_relative 'models/journal' - require_relative 'models/version' - require_relative 'models/custom_field' - require_relative 'models/user' - require_relative 'models/issue_template' if Redmine::Plugin.installed?(:redmine_templates) + require_relative 'models/project_patch' + require_relative 'models/member_patch' + require_relative 'models/journal_patch' + require_relative 'models/version_patch' + require_relative 'models/custom_field_patch' + require_relative 'models/user_patch' + require_relative 'models/issue_template_patch' if Redmine::Plugin.installed?(:redmine_templates) - require_relative 'helpers/projects_helper' - require_relative 'helpers/issues_helper' - require_relative 'helpers/settings_helper' + require_relative 'helpers/projects_helper_patch' + require_relative 'helpers/issues_helper_patch' + require_relative 'helpers/settings_helper_patch' end end end diff --git a/lib/redmine_admin_activity/jobs/destroy_project_job_patch.rb b/lib/redmine_admin_activity/jobs/destroy_project_job_patch.rb new file mode 100644 index 0000000..b9024e6 --- /dev/null +++ b/lib/redmine_admin_activity/jobs/destroy_project_job_patch.rb @@ -0,0 +1,34 @@ +module RedmineAdminActivity::Jobs + module DestroyProjectJobPatch + + def self.prepended(base) + class << base + prepend ClassMethods + end + end + + module ClassMethods + def schedule(project, user: User.current) + projects_to_destroy = project.self_and_descendants + projects_to_destroy.each do |p| + changes = p.attributes.to_a.map { |i| [i[0], [i[1], nil]] }.to_h + JournalSetting.create( + :user_id => User.current.id, + :value_changes => changes, + :journalized => p, + :journalized_entry_type => "destroy", + ) + end + + super + end + end + + end +end + +if Redmine::VERSION::MAJOR >= 5 + class DestroyProjectJob < ApplicationJob + prepend RedmineAdminActivity::Jobs::DestroyProjectJobPatch + end +end diff --git a/lib/redmine_admin_activity/controllers/concerns/journalizable.rb b/lib/redmine_admin_activity/journalizable.rb similarity index 100% rename from lib/redmine_admin_activity/controllers/concerns/journalizable.rb rename to lib/redmine_admin_activity/journalizable.rb diff --git a/lib/redmine_admin_activity/models/custom_field.rb b/lib/redmine_admin_activity/models/custom_field_patch.rb similarity index 66% rename from lib/redmine_admin_activity/models/custom_field.rb rename to lib/redmine_admin_activity/models/custom_field_patch.rb index b197e44..001af30 100644 --- a/lib/redmine_admin_activity/models/custom_field.rb +++ b/lib/redmine_admin_activity/models/custom_field_patch.rb @@ -1,9 +1,7 @@ require_dependency 'custom_field' -class CustomField < ActiveRecord::Base - # Returns the names of attributes that are journalized when updating the custom_field - # TODO à discuter - +module RedmineAdminActivity::Models::CustomFieldPatch + # Returns the names of attributes that are journalized when updating the custom_field def journalized_attribute_names names = %w(type name field_format visible is_required description) names @@ -12,6 +10,10 @@ def journalized_attribute_names def to_s name end +end + +class CustomField < ActiveRecord::Base + prepend RedmineAdminActivity::Models::CustomFieldPatch def self.representative_columns return ["name"] @@ -20,4 +22,4 @@ def self.representative_columns def self.representative_link_path(obj) Rails.application.routes.url_helpers.edit_custom_field_url(obj, only_path: true) end -end \ No newline at end of file +end diff --git a/lib/redmine_admin_activity/models/issue_template.rb b/lib/redmine_admin_activity/models/issue_template.rb deleted file mode 100644 index c020a80..0000000 --- a/lib/redmine_admin_activity/models/issue_template.rb +++ /dev/null @@ -1,31 +0,0 @@ -require_dependency 'issue_template' - -class IssueTemplate < ActiveRecord::Base - has_many :template_projects, through: :issue_template_projects, source: :project, before_remove: :journalized_deactivation_template, after_add: :journalized_activation_template - - def journalized_activation_template(project) - if project.present? - project.init_journal(User.current) - project.current_journal.details << JournalDetail.new( - :property => 'templates', - :prop_key => 'enabled_template', - :value => self.template_title, - :old_value => nil - ) - project.current_journal.save - end - end - - def journalized_deactivation_template(project) - if project.present? - project.init_journal(User.current) - project.current_journal.details << JournalDetail.new( - :property => 'templates', - :prop_key => 'enabled_template', - :value => nil, - :old_value => self.template_title - ) - project.current_journal.save - end - end -end \ No newline at end of file diff --git a/lib/redmine_admin_activity/models/issue_template_patch.rb b/lib/redmine_admin_activity/models/issue_template_patch.rb new file mode 100644 index 0000000..9d67383 --- /dev/null +++ b/lib/redmine_admin_activity/models/issue_template_patch.rb @@ -0,0 +1,35 @@ +require_dependency 'issue_template' if Redmine::VERSION::MAJOR < 5 + +module RedmineAdminActivity::Models::IssueTemplatePatch + def journalized_activation_template(project) + if project.present? + project.init_journal(User.current) + project.current_journal.details << JournalDetail.new( + :property => 'templates', + :prop_key => 'enabled_template', + :value => self.template_title, + :old_value => nil + ) + project.current_journal.save + end + end + + def journalized_deactivation_template(project) + if project.present? + project.init_journal(User.current) + project.current_journal.details << JournalDetail.new( + :property => 'templates', + :prop_key => 'enabled_template', + :value => nil, + :old_value => self.template_title + ) + project.current_journal.save + end + end +end + +class IssueTemplate < ActiveRecord::Base + prepend RedmineAdminActivity::Models::IssueTemplatePatch + + has_many :template_projects, through: :issue_template_projects, source: :project, before_remove: :journalized_deactivation_template, after_add: :journalized_activation_template +end diff --git a/lib/redmine_admin_activity/models/journal.rb b/lib/redmine_admin_activity/models/journal_patch.rb similarity index 67% rename from lib/redmine_admin_activity/models/journal.rb rename to lib/redmine_admin_activity/models/journal_patch.rb index fc7f752..ac85861 100644 --- a/lib/redmine_admin_activity/models/journal.rb +++ b/lib/redmine_admin_activity/models/journal_patch.rb @@ -1,8 +1,8 @@ require_dependency 'journal' -module RedmineAdminActivity +module RedmineAdminActivity::Models - module Journal + module JournalPatch def send_notification # Do not send any notification after create project's or user's journals @@ -14,4 +14,4 @@ def send_notification end -Journal.prepend RedmineAdminActivity::Journal +Journal.prepend RedmineAdminActivity::Models::JournalPatch diff --git a/lib/redmine_admin_activity/models/member.rb b/lib/redmine_admin_activity/models/member_patch.rb similarity index 83% rename from lib/redmine_admin_activity/models/member.rb rename to lib/redmine_admin_activity/models/member_patch.rb index 94b2800..4c2a376 100644 --- a/lib/redmine_admin_activity/models/member.rb +++ b/lib/redmine_admin_activity/models/member_patch.rb @@ -1,11 +1,6 @@ require_dependency 'member' -class Member < ActiveRecord::Base - attr_reader :project_journal - - # after_create :update_project_journal - # after_save :save_project_journal - +module RedmineAdminActivity::Models::MemberPatch def save_project_journal if @project_journal @project_journal.save @@ -23,3 +18,12 @@ def update_project_journal ) end end + +class Member < ActiveRecord::Base + prepend RedmineAdminActivity::Models::MemberPatch + + attr_reader :project_journal + + # after_create :update_project_journal + # after_save :save_project_journal +end diff --git a/lib/redmine_admin_activity/models/organization.rb b/lib/redmine_admin_activity/models/organization_patch.rb similarity index 81% rename from lib/redmine_admin_activity/models/organization.rb rename to lib/redmine_admin_activity/models/organization_patch.rb index a18a7f9..627d9df 100644 --- a/lib/redmine_admin_activity/models/organization.rb +++ b/lib/redmine_admin_activity/models/organization_patch.rb @@ -1,21 +1,12 @@ -require_dependency 'organization' - -class Organization < ActiveRecord::Base +require_dependency 'organization' if Redmine::VERSION::MAJOR < 5 +module RedmineAdminActivity::Models::OrganizationPatch # Returns the names of attributes that are journalized when updating the organization def journalized_attribute_names names = Organization.column_names - %w(id lft rgt created_at updated_at name_with_parents identifier) names end - def self.representative_columns - return ["name_with_parents"] - end - - def self.representative_link_path(obj) - Rails.application.routes.url_helpers.organization_url(obj, only_path: true) - end - def journalize_creation(user) return if !persisted? changes = self.attributes.to_a.map { |i| [i[0], [nil, i[1]]] }.to_h @@ -27,3 +18,15 @@ def journalize_creation(user) ) end end + +class Organization < ActiveRecord::Base + prepend RedmineAdminActivity::Models::OrganizationPatch + + def self.representative_columns + return ["name_with_parents"] + end + + def self.representative_link_path(obj) + Rails.application.routes.url_helpers.organization_url(obj, only_path: true) + end +end diff --git a/lib/redmine_admin_activity/models/project.rb b/lib/redmine_admin_activity/models/project.rb deleted file mode 100644 index f26df33..0000000 --- a/lib/redmine_admin_activity/models/project.rb +++ /dev/null @@ -1,54 +0,0 @@ -require_dependency 'project' - -class Project < ActiveRecord::Base - - acts_as_watchable - - has_many :journals, :as => :journalized, :dependent => :destroy, :inverse_of => :journalized - - attr_reader :current_journal - - after_save :create_journal - - def init_journal(user) - @current_journal ||= Journal.new(:journalized => self, :user => user) - end - - def add_journal_entry(property:, value:, old_value: nil) - init_journal(User.current) - current_journal.details << JournalDetail.new( - property: property, - prop_key: property, - value: value, - old_value: old_value) - current_journal.save - end - - # Returns the current journal or nil if it's not initialized - def current_journal - @current_journal - end - - # Returns the names of attributes that are journalized when updating the project - def journalized_attribute_names - names = Project.column_names - %w(id root_id lft rgt lock_version created_on updated_on closed_on) - names - end - - # Saves the changes in a Journal - # Called after_save - def create_journal - if current_journal - current_journal.save - end - end - - def self.representative_columns - return ["name"] - end - - def self.representative_link_path(obj) - Rails.application.routes.url_helpers.project_url(obj, only_path: true) - end - -end diff --git a/lib/redmine_admin_activity/models/project_patch.rb b/lib/redmine_admin_activity/models/project_patch.rb new file mode 100644 index 0000000..b664faf --- /dev/null +++ b/lib/redmine_admin_activity/models/project_patch.rb @@ -0,0 +1,59 @@ +require_dependency 'project' + +module RedmineAdminActivity::Models + module ProjectPatch + def init_journal(user) + @current_journal ||= Journal.new(:journalized => self, :user => user) + end + + def add_journal_entry(property:, value:, old_value: nil) + init_journal(User.current) + current_journal.details << JournalDetail.new( + property: property, + prop_key: property, + value: value, + old_value: old_value) + current_journal.save + end + + # Returns the current journal or nil if it's not initialized + def current_journal + @current_journal + end + + # Returns the names of attributes that are journalized when updating the project + def journalized_attribute_names + names = Project.column_names - %w(id root_id lft rgt lock_version created_on updated_on closed_on) + names + end + + # Saves the changes in a Journal + # Called after_save + def create_journal + if current_journal + current_journal.save + end + end + end +end + +class Project < ActiveRecord::Base + prepend RedmineAdminActivity::Models::ProjectPatch + + acts_as_watchable + + has_many :journals, :as => :journalized, :dependent => :destroy, :inverse_of => :journalized + + attr_reader :current_journal + + after_save :create_journal + + def self.representative_columns + return ["name"] + end + + def self.representative_link_path(obj) + Rails.application.routes.url_helpers.project_url(obj, only_path: true) + end + +end diff --git a/lib/redmine_admin_activity/models/user.rb b/lib/redmine_admin_activity/models/user.rb deleted file mode 100644 index 2c3a347..0000000 --- a/lib/redmine_admin_activity/models/user.rb +++ /dev/null @@ -1,55 +0,0 @@ -require_dependency 'user' - -class User < Principal - - has_many :journal_settings, :dependent => :nullify - has_many :journals, :as => :journalized, :dependent => :destroy, :inverse_of => :journalized - - attr_reader :current_journal - - after_save :create_journal - - USER_MANUAL_CREATION = 'manual' - USER_AUTO_CREATION = 'auto' - - def init_journal(user) - @current_journal ||= Journal.new(:journalized => self, :user => user) - end - - # Returns the current journal or nil if it's not initialized - def current_journal - @current_journal - end - - # Returns the names of attributes that are journalized when updating the user - def journalized_attribute_names - names = %w(login firstname lastname status mails) - names << 'organization' if Redmine::Plugin.installed?(:redmine_organizations) - names << (Redmine::Plugin.installed?(:redmine_sudo) ? 'sudoer' : 'admin') - names |= %w(staff beta_tester instance_manager issue_display_mode trusted_api_user) if Redmine::Plugin.installed?(:redmine_scn) - names - end - - def create_journal - if current_journal - current_journal.save - end - end - - def notified_users - [] - end - - def notified_watchers - [] - end - - def self.representative_columns - return "firstname", "lastname" - end - - def self.representative_link_path(obj) - Rails.application.routes.url_helpers.user_url(obj, only_path: true) - end - -end diff --git a/lib/redmine_admin_activity/models/user_patch.rb b/lib/redmine_admin_activity/models/user_patch.rb new file mode 100644 index 0000000..33c7e1d --- /dev/null +++ b/lib/redmine_admin_activity/models/user_patch.rb @@ -0,0 +1,60 @@ +require_dependency 'user' + +module RedmineAdminActivity::Models + module UserPatch + def init_journal(user) + @current_journal ||= Journal.new(:journalized => self, :user => user) + end + + # Returns the current journal or nil if it's not initialized + def current_journal + @current_journal + end + + # Returns the names of attributes that are journalized when updating the user + def journalized_attribute_names + names = %w(login firstname lastname status mails) + names << 'organization' if Redmine::Plugin.installed?(:redmine_organizations) + names << (Redmine::Plugin.installed?(:redmine_sudo) ? 'sudoer' : 'admin') + names |= %w(staff beta_tester instance_manager issue_display_mode trusted_api_user) if Redmine::Plugin.installed?(:redmine_scn) + names + end + + def create_journal + if current_journal + current_journal.save + end + end + + def notified_users + [] + end + + def notified_watchers + [] + end + end +end + +class User < Principal + prepend RedmineAdminActivity::Models::UserPatch + + has_many :journal_settings, :dependent => :nullify + has_many :journals, :as => :journalized, :dependent => :destroy, :inverse_of => :journalized + + attr_reader :current_journal + + after_save :create_journal + + USER_MANUAL_CREATION = 'manual' + USER_AUTO_CREATION = 'auto' + + def self.representative_columns + return "firstname", "lastname" + end + + def self.representative_link_path(obj) + Rails.application.routes.url_helpers.user_url(obj, only_path: true) + end + +end diff --git a/lib/redmine_admin_activity/models/version.rb b/lib/redmine_admin_activity/models/version.rb deleted file mode 100644 index cb57c95..0000000 --- a/lib/redmine_admin_activity/models/version.rb +++ /dev/null @@ -1,30 +0,0 @@ -require_dependency 'version' - -class Version < ActiveRecord::Base - - before_update :save_previous_version - - after_create :log_version_creation - after_update :log_version_update - after_destroy :log_version_deletion - - def log_version_creation - project.add_journal_entry(property: 'versions', value: name) - end - - def log_version_update - if name != @prev_version.name - project.add_journal_entry(property: 'versions', value: name, old_value: @prev_version.name) - end - end - - def log_version_deletion - project.add_journal_entry(property: 'versions', value: nil, old_value: name) - end - - def save_previous_version - @prev_version = Version.find(self.id) - end - -end - diff --git a/lib/redmine_admin_activity/models/version_patch.rb b/lib/redmine_admin_activity/models/version_patch.rb new file mode 100644 index 0000000..567bdbb --- /dev/null +++ b/lib/redmine_admin_activity/models/version_patch.rb @@ -0,0 +1,34 @@ +require_dependency 'version' + +module RedmineAdminActivity::Models + module VersionPatch + def log_version_creation + project.add_journal_entry(property: 'versions', value: name) + end + + def log_version_update + if name != @prev_version.name + project.add_journal_entry(property: 'versions', value: name, old_value: @prev_version.name) + end + end + + def log_version_deletion + project.add_journal_entry(property: 'versions', value: nil, old_value: name) + end + + def save_previous_version + @prev_version = Version.find(self.id) + end + end +end + +class Version < ActiveRecord::Base + prepend RedmineAdminActivity::Models::VersionPatch + + before_update :save_previous_version + + after_create :log_version_creation + after_update :log_version_update + after_destroy :log_version_deletion +end + diff --git a/spec/controllers/issue_templates_controller_spec.rb b/spec/controllers/issue_templates_controller_spec.rb index 35af73a..fa551d8 100644 --- a/spec/controllers/issue_templates_controller_spec.rb +++ b/spec/controllers/issue_templates_controller_spec.rb @@ -12,7 +12,7 @@ @request.session[:user_id] = 1 end - it "Trace template activation/deactivation in project history" do + it "logs template activation/deactivation in project history" do # disable the template on project 2, enable it on project 1 expect do patch :update, params: { id: 1, issue_template: { template_project_ids: ["1"] } } @@ -26,4 +26,4 @@ expect(JournalDetail.last(2)[1].old_value).to be_nil end end -end \ No newline at end of file +end diff --git a/spec/controllers/organizations/memberships_controller_spec.rb b/spec/controllers/organizations/memberships_controller_spec.rb index 55d15ba..47f5990 100644 --- a/spec/controllers/organizations/memberships_controller_spec.rb +++ b/spec/controllers/organizations/memberships_controller_spec.rb @@ -127,7 +127,7 @@ it "creates, adds a new entry in the project journal" do expect do - post :create_non_members_roles, params: { project_id: project.id, membership: { organization_id: 2 } } + post :create_non_members_roles, params: { format: :js, project_id: project.id, membership: { organization_id: 2 } } end.to change { JournalDetail.count }.by(1) journal = JournalDetail.last diff --git a/spec/helpers/journal_settings_helper_spec.rb b/spec/helpers/journal_settings_helper_spec.rb index 5f5e74a..d154225 100644 --- a/spec/helpers/journal_settings_helper_spec.rb +++ b/spec/helpers/journal_settings_helper_spec.rb @@ -3,7 +3,7 @@ describe "JournalSettingsHelper" do include ApplicationHelper include JournalSettingsHelper - include PluginAdminActivity::IssuesHelper + include RedmineAdminActivity::Helpers::IssuesHelperPatch fixtures :projects, :users