summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2017-01-19 20:16:49 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2017-01-19 20:16:49 +0000
commit151a215ea45c1870842de49d0640b1557f712498 (patch)
tree36750e8c39c1235bf82d1ffb49f4bee3405e99c0 /app
parentdf5dba5ddec5f61a2022abcd1789da4604b21055 (diff)
downloadredmine-151a215ea45c1870842de49d0640b1557f712498.tar.gz
redmine-151a215ea45c1870842de49d0640b1557f712498.zip
Adds updated_by and last_updated_by filters on issues (#17720).
git-svn-id: http://svn.redmine.org/redmine/trunk@16228 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r--app/models/issue_query.rb29
-rw-r--r--app/models/journal.rb13
-rw-r--r--app/models/project.rb9
-rw-r--r--app/models/query.rb2
4 files changed, 45 insertions, 8 deletions
diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb
index 53702b9ba..1b1477e3c 100644
--- a/app/models/issue_query.rb
+++ b/app/models/issue_query.rb
@@ -165,6 +165,14 @@ class IssueQuery < Query
add_available_filter "issue_id", :type => :integer, :label => :label_issue
+ add_available_filter("updated_by",
+ :type => :list, :values => lambda { author_values }
+ )
+
+ add_available_filter("last_updated_by",
+ :type => :list, :values => lambda { author_values }
+ )
+
Tracker.disabled_core_fields(trackers).each {|field|
delete_available_filter field
}
@@ -341,6 +349,27 @@ class IssueQuery < Query
raise StatementInvalid.new(e.message)
end
+ def sql_for_updated_by_field(field, operator, value)
+ neg = (operator == '!' ? 'NOT' : '')
+ subquery = "SELECT 1 FROM #{Journal.table_name}" +
+ " WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" +
+ " AND (#{sql_for_field field, '=', value, Journal.table_name, 'user_id'})" +
+ " AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)})"
+
+ "#{neg} EXISTS (#{subquery})"
+ end
+
+ def sql_for_last_updated_by_field(field, operator, value)
+ neg = (operator == '!' ? 'NOT' : '')
+ subquery = "SELECT 1 FROM #{Journal.table_name} sj" +
+ " WHERE sj.journalized_type='Issue' AND sj.journalized_id=#{Issue.table_name}.id AND (#{sql_for_field field, '=', value, 'sj', 'user_id'})" +
+ " AND sj.id = (SELECT MAX(#{Journal.table_name}.id) FROM #{Journal.table_name}" +
+ " WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" +
+ " AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)}))"
+
+ "#{neg} EXISTS (#{subquery})"
+ end
+
def sql_for_watcher_id_field(field, operator, value)
db_table = Watcher.table_name
"#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='Issue' AND " +
diff --git a/app/models/journal.rb b/app/models/journal.rb
index 447cbe4b5..7d1a6eb34 100644
--- a/app/models/journal.rb
+++ b/app/models/journal.rb
@@ -47,10 +47,11 @@ class Journal < ActiveRecord::Base
scope :visible, lambda {|*args|
user = args.shift || User.current
- private_notes_condition = Project.allowed_to_condition(user, :view_private_notes, *args)
+ options = args.shift || {}
+
joins(:issue => :project).
- where(Issue.visible_condition(user, *args)).
- where("(#{Journal.table_name}.private_notes = ? OR #{Journal.table_name}.user_id = ? OR (#{private_notes_condition}))", false, user.id)
+ where(Issue.visible_condition(user, options)).
+ where(Journal.visible_notes_condition(user, :skip_pre_condition => true))
}
safe_attributes 'notes',
@@ -58,6 +59,12 @@ class Journal < ActiveRecord::Base
safe_attributes 'private_notes',
:if => lambda {|journal, user| user.allowed_to?(:set_notes_private, journal.project)}
+ # Returns a SQL condition to filter out journals with notes that are not visible to user
+ def self.visible_notes_condition(user=User.current, options={})
+ private_notes_permission = Project.allowed_to_condition(user, :view_private_notes, options)
+ sanitize_sql_for_conditions(["(#{table_name}.private_notes = ? OR #{table_name}.user_id = ? OR (#{private_notes_permission}))", false, user.id])
+ end
+
def initialize(*args)
super
if journalized
diff --git a/app/models/project.rb b/app/models/project.rb
index e5eb12c58..fb2ffc3a6 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -173,13 +173,14 @@ class Project < ActiveRecord::Base
# Returns a SQL conditions string used to find all projects for which +user+ has the given +permission+
#
# Valid options:
- # * :project => limit the condition to project
- # * :with_subprojects => limit the condition to project and its subprojects
- # * :member => limit the condition to the user projects
+ # * :skip_pre_condition => true don't check that the module is enabled (eg. when the condition is already set elsewhere in the query)
+ # * :project => project limit the condition to project
+ # * :with_subprojects => true limit the condition to project and its subprojects
+ # * :member => true limit the condition to the user projects
def self.allowed_to_condition(user, permission, options={})
perm = Redmine::AccessControl.permission(permission)
base_statement = (perm && perm.read? ? "#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED}" : "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}")
- if perm && perm.project_module
+ if !options[:skip_pre_condition] && perm && perm.project_module
# If the permission belongs to a project module, make sure the module is enabled
base_statement << " AND #{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.project_module}')"
end
diff --git a/app/models/query.rb b/app/models/query.rb
index 7c85d7164..4f183329a 100644
--- a/app/models/query.rb
+++ b/app/models/query.rb
@@ -802,7 +802,7 @@ class Query < ActiveRecord::Base
operator = operator_for(field)
# "me" value substitution
- if %w(assigned_to_id author_id user_id watcher_id).include?(field)
+ if %w(assigned_to_id author_id user_id watcher_id updated_by last_updated_by).include?(field)
if v.delete("me")
if User.current.logged?
v.push(User.current.id.to_s)