diff --git a/app/jobs/additionals_job.rb b/app/jobs/additionals_job.rb index 825904f8..5b5c73ac 100644 --- a/app/jobs/additionals_job.rb +++ b/app/jobs/additionals_job.rb @@ -1,9 +1,17 @@ # frozen_string_literal: true -class AdditionalsJob < ActiveJob::Base - # Automatically retry jobs that encountered a deadlock - # retry_on ActiveRecord::Deadlocked +if Redmine::VERSION.to_s >= '5.1' + class AdditionalsJob < ApplicationJob + end +else + class AdditionalsJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked - # Most jobs are safe to ignore if the underlying records are no longer available - # discard_on ActiveJob::DeserializationError + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError + + include Additionals::JobWrapper + around_enqueue :keep_current_user + end end diff --git a/app/models/dashboard.rb b/app/models/dashboard.rb index bf1c0024..def833c5 100644 --- a/app/models/dashboard.rb +++ b/app/models/dashboard.rb @@ -118,20 +118,19 @@ class Dashboard < ActiveRecord::Base if user.admin? scope.where.not(visibility: VISIBILITY_PRIVATE).or(scope.where(author_id: user.id)) elsif user.memberships.includes([:memberships]).any? - scope.where("#{table_name}.visibility = ?" \ - " OR (#{table_name}.visibility = ? AND #{table_name}.id IN (" \ + scope.where "#{table_name}.visibility = :public" \ + " OR (#{table_name}.visibility = :roles AND #{table_name}.id IN (" \ "SELECT DISTINCT d.id FROM #{table_name} d" \ " INNER JOIN #{DashboardRole.table_name} dr ON dr.dashboard_id = d.id" \ " INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = dr.role_id" \ - " INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" \ - " INNER JOIN #{Project.table_name} p ON p.id = m.project_id AND p.status <> ?" \ + " INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = :user_id" \ + " INNER JOIN #{Project.table_name} p ON p.id = m.project_id AND p.status IN(:statuses)" \ ' WHERE d.project_id IS NULL OR d.project_id = m.project_id))' \ - " OR #{table_name}.author_id = ?", - VISIBILITY_PUBLIC, - VISIBILITY_ROLES, - user.id, - Project::STATUS_ARCHIVED, - user.id) + " OR #{table_name}.author_id = :user_id", + public: VISIBILITY_PUBLIC, + roles: VISIBILITY_ROLES, + user_id: user.id, + statuses: Project.usable_status_ids elsif user.logged? scope.where(visibility: VISIBILITY_PUBLIC).or(scope.where(author_id: user.id)) else diff --git a/lib/additionals/job_wrapper.rb b/lib/additionals/job_wrapper.rb new file mode 100644 index 00000000..4c5e68d6 --- /dev/null +++ b/lib/additionals/job_wrapper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Additionals + module JobWrapper + def keep_current_user + current_user = User.current + yield + User.current = current_user + end + end +end diff --git a/lib/additionals/patches/project_patch.rb b/lib/additionals/patches/project_patch.rb index 46d9c551..b80926ca 100644 --- a/lib/additionals/patches/project_patch.rb +++ b/lib/additionals/patches/project_patch.rb @@ -5,6 +5,9 @@ module Additionals module ProjectPatch extend ActiveSupport::Concern + USABLE_STATUSES = { Project::STATUS_ACTIVE => :active, + Project::STATUS_CLOSED => :closed }.freeze + included do prepend InstanceOverwriteMethods include InstanceMethods @@ -14,6 +17,30 @@ module Additionals safe_attributes 'enable_new_ticket_message', 'new_ticket_message' end + class_methods do + def usable_status_ids + USABLE_STATUSES.keys + end + + def sql_for_usable_status(table = nil) + table ||= Project.table_name + + "#{table}.status IN(#{usable_status_ids.join ', '})" + end + + def available_status_ids + available_statuses.keys + end + + def available_statuses + statuses = USABLE_STATUSES.dup + statuses[Project::STATUS_ARCHIVED] = :archived + statuses[Project::STATUS_SCHEDULED_FOR_DELETION] = :scheduled_for_deletion if Redmine::VERSION.to_s >= '5.1' + + statuses + end + end + module InstanceOverwriteMethods def assignable_users(tracker = nil) super diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index 811b2e2f..73430839 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -150,4 +150,29 @@ class ProjectTest < Additionals::TestCase assert_save role assert project.consider_hidden_roles? end + + def test_usable_status_ids + ids = Project.usable_status_ids + + assert_sorted_equal ids, [Project::STATUS_ACTIVE, Project::STATUS_CLOSED] + end + + def test_sql_for_usable_status + assert_equal "projects.status IN(#{Project::STATUS_ACTIVE}, #{Project::STATUS_CLOSED})", + Project.sql_for_usable_status + assert_equal "projects.status IN(#{Project::STATUS_ACTIVE}, #{Project::STATUS_CLOSED})", + Project.sql_for_usable_status(:projects) + assert_equal "subprojects.status IN(#{Project::STATUS_ACTIVE}, #{Project::STATUS_CLOSED})", + Project.sql_for_usable_status('subprojects') + end + + def test_available_status_ids + ids = Project.available_status_ids + + if Redmine::VERSION.to_s < '5.1' + assert_equal 3, ids.count + else + assert_operator ids.count, :>, 3 + end + end end