Consistently use OpenProject::SqlSanitization instead of forwarding to sanitize_sql_array

This commit is contained in:
Oliver Günther
2026-05-27 09:17:57 +02:00
committed by Oliver Günther
parent 595275a218
commit 4cc9faef4f
19 changed files with 88 additions and 117 deletions
+8 -11
View File
@@ -59,17 +59,14 @@ module Actions::Scopes
def map_actions(permission, actions:, global:, module_name:, grant_to_admin:, public:)
actions.map do |namespace, actions|
actions.map do |action|
ActiveRecord::Base.send(
:sanitize_sql_array,
[
"(?, ?, ?, ?, ?, ?)",
"#{action_v3_name(namespace)}/#{action}",
permission,
global,
module_name,
grant_to_admin,
public
]
OpenProject::SqlSanitization.sanitize(
"(?, ?, ?, ?, ?, ?)",
"#{action_v3_name(namespace)}/#{action}",
permission,
global,
module_name,
grant_to_admin,
public
)
end
end
+2 -3
View File
@@ -113,9 +113,8 @@ module CustomField::OrderStatements
# ) cf_order_NNN ON cf_order_NNN.customized_id = …
#
def join_for_order_sql(value:, add_select: nil, join: nil, multi_value: false)
customized_type_condition = ActiveRecord::Base.send(
:sanitize_sql_array,
["cv.customized_type = ?", self.class.customized_class.base_class.name]
customized_type_condition = OpenProject::SqlSanitization.sanitize(
"cv.customized_type = ?", self.class.customized_class.base_class.name
)
<<~SQL.squish
+2 -2
View File
@@ -56,8 +56,8 @@ module Groups::Hierarchy
# ancestor_ids are returned child-first by the CTE.
# Use array_position to preserve that order, then apply asc/desc.
ordered_ids = order == :asc ? ids.reverse : ids
order_sql = self.class.sanitize_sql_array(
["array_position(ARRAY[?]::bigint[], #{Group.table_name}.id)", ordered_ids]
order_sql = OpenProject::SqlSanitization.sanitize(
"array_position(ARRAY[?]::bigint[], #{Group.table_name}.id)", ordered_ids
)
scope.order(Arel.sql(order_sql))
else
@@ -40,7 +40,7 @@ module Queries::Operators
sql = "#{db_table}.#{db_field} IS NULL OR "
end
sql += ActiveRecord::Base.send(:sanitize_sql_array, ["#{db_table}.#{db_field} IN (?)", values])
sql += OpenProject::SqlSanitization.sanitize("#{db_table}.#{db_field} IN (?)", values)
sql
end
@@ -34,7 +34,7 @@ module Queries::Operators
set_symbol "="
def self.sql_for_field(values, db_table, db_field)
ActiveRecord::Base.send(:sanitize_sql_array, ["#{db_table}.#{db_field} IN (?)", values])
OpenProject::SqlSanitization.sanitize("#{db_table}.#{db_field} IN (?)", values)
end
end
end
@@ -41,17 +41,14 @@ module Queries::Operators
if values.present?
sql = values.map do |val|
ActiveRecord::Base.send(
:sanitize_sql_array,
[
"EXISTS (SELECT 1 FROM #{cv_table} WHERE customized_type = ? " \
"AND custom_field_id = ? " \
"AND customized_id = #{customized_id_join_field} " \
"AND value = ?)",
customized_type,
custom_field_id,
val
]
OpenProject::SqlSanitization.sanitize(
"EXISTS (SELECT 1 FROM #{cv_table} WHERE customized_type = ? " \
"AND custom_field_id = ? " \
"AND customized_id = #{customized_id_join_field} " \
"AND value = ?)",
customized_type,
custom_field_id,
val
)
end
@@ -38,17 +38,14 @@ module Queries::Operators
if values.present?
sql = values.map do |val|
ActiveRecord::Base.send(
:sanitize_sql_array,
[
"NOT EXISTS (SELECT 1 FROM #{cv_table} WHERE customized_type = ? " \
"AND custom_field_id = ? " \
"AND customized_id = #{customized_id_join_field} " \
"AND value = ?)",
customized_type,
custom_field_id,
val
]
OpenProject::SqlSanitization.sanitize(
"NOT EXISTS (SELECT 1 FROM #{cv_table} WHERE customized_type = ? " \
"AND custom_field_id = ? " \
"AND customized_id = #{customized_id_join_field} " \
"AND value = ?)",
customized_type,
custom_field_id,
val
)
end
+1 -1
View File
@@ -44,7 +44,7 @@ module Queries::Operators
sql = "#{db_table}.#{db_field} IS NULL OR "
end
sql += ActiveRecord::Base.send(:sanitize_sql_array, ["#{db_table}.#{db_field} IN (?)", values])
sql += OpenProject::SqlSanitization.sanitize("#{db_table}.#{db_field} IN (?)", values)
else
# empty set of allowed values produces no result
sql = "0=1"
+1 -1
View File
@@ -38,7 +38,7 @@ module Queries::Operators
values = values.map(&:to_s)
if values.present?
not_in = ActiveRecord::Base.send(:sanitize_sql_array, ["#{db_table}.#{db_field} NOT IN (?)", values])
not_in = OpenProject::SqlSanitization.sanitize("#{db_table}.#{db_field} NOT IN (?)", values)
"(#{db_table}.#{db_field} IS NULL OR #{not_in})"
else
# empty set of forbidden values allows all results
@@ -98,15 +98,12 @@ class Queries::WorkPackages::Filter::SharedWithUserFilter <
if normalized_user_id.nil?
"1=0"
else
ActiveRecord::Base.send(
:sanitize_sql_array,
[<<~SQL.squish, normalized_user_id]
EXISTS (SELECT 1
FROM #{members_table}
WHERE #{members_table}.entity_id = #{work_packages_table}.id
AND #{members_table}.user_id = ?)
SQL
)
OpenProject::SqlSanitization.sanitize(<<~SQL.squish, normalized_user_id)
EXISTS (SELECT 1
FROM #{members_table}
WHERE #{members_table}.entity_id = #{work_packages_table}.id
AND #{members_table}.user_id = ?)
SQL
end
end
+22 -28
View File
@@ -82,40 +82,34 @@ module Sessions
def insert!
@new_record = false
sql = ActiveRecord::Base.send(
:sanitize_sql_array,
[
<<~SQL.squish,
INSERT INTO sessions (session_id, data, user_id, updated_at)
VALUES (?, ?, ?, (now() at time zone 'utc'))
SQL
session_id,
self.class.serialize(data),
user_id
]
sql = OpenProject::SqlSanitization.sanitize(
<<~SQL.squish,
INSERT INTO sessions (session_id, data, user_id, updated_at)
VALUES (?, ?, ?, (now() at time zone 'utc'))
SQL
session_id,
self.class.serialize(data),
user_id
)
connection.update sql, "Create session"
end
def update!
sql = ActiveRecord::Base.send(
:sanitize_sql_array,
[
<<~SQL.squish,
UPDATE sessions
SET
data = ?,
session_id = ?,
user_id = ?,
updated_at = (now() at time zone 'utc')
WHERE session_id = ?
SQL
self.class.serialize(data),
session_id,
user_id,
@retrieved_by
]
sql = OpenProject::SqlSanitization.sanitize(
<<~SQL.squish,
UPDATE sessions
SET
data = ?,
session_id = ?,
user_id = ?,
updated_at = (now() at time zone 'utc')
WHERE session_id = ?
SQL
self.class.serialize(data),
session_id,
user_id,
@retrieved_by
)
connection.update sql, "Update session"
+3 -3
View File
@@ -222,15 +222,15 @@ class Version < ApplicationRecord
# Examples:
# issues_progress(true) => returns the progress percentage for open issues.
# issues_progress(false) => returns the progress percentage for closed issues.
def issues_progress(open)
def issues_progress(open) # rubocop:disable Metrics/AbcSize
@issues_progress ||= {}
@issues_progress[open] ||= begin
progress = 0
if issues_count > 0
ratio = open ? "done_ratio" : 100
sum_sql = self.class.sanitize_sql_array(
["COALESCE(#{WorkPackage.table_name}.estimated_hours, ?) * #{ratio}", estimated_average]
sum_sql = OpenProject::SqlSanitization.sanitize(
"COALESCE(#{WorkPackage.table_name}.estimated_hours, ?) * #{ratio}", estimated_average
)
done = work_packages
@@ -73,9 +73,8 @@ module API
end
def ancestor_projection
undisclosed_ancestor_title = ActiveRecord::Base.send(
:sanitize_sql_array,
["?", I18n.t(:"api_v3.undisclosed.ancestor")]
undisclosed_ancestor_title = OpenProject::SqlSanitization.sanitize(
"?", I18n.t(:"api_v3.undisclosed.ancestor")
)
if User.current.admin?
+2 -4
View File
@@ -39,10 +39,8 @@ module OpenProject
language = OpenProject::Configuration.main_content_language
ActiveRecord::Base.send(
:sanitize_sql_array, ["#{column} @@ to_tsquery(?, ?)",
language,
query]
OpenProject::SqlSanitization.sanitize(
"#{column} @@ to_tsquery(?, ?)", language, query
)
end
end
+2 -3
View File
@@ -55,9 +55,8 @@ module OpenProject::NestedSet::RebuildPatch
if acts_as_nested_set_options[:scope]
scope = lambda { |node|
scope_column_names.inject("") do |str, column_name|
str << ActiveRecord::Base.send(
:sanitize_sql_array,
["AND #{connection.quote_column_name(column_name)} = ? ", node.send(column_name.to_sym)]
str << OpenProject::SqlSanitization.sanitize(
"AND #{connection.quote_column_name(column_name)} = ? ", node.send(column_name.to_sym)
)
end
}
@@ -48,17 +48,14 @@ class Queries::Meetings::Filters::AttendedUserFilter < Queries::Meetings::Filter
user_id = normalized_user_id(values.first)
return "1=1" if user_id.nil?
ActiveRecord::Base.send(
:sanitize_sql_array,
[<<~SQL.squish, user_id]
NOT EXISTS (
SELECT 1 FROM #{MeetingParticipant.table_name}
WHERE #{MeetingParticipant.table_name}.meeting_id = meetings.id
AND #{MeetingParticipant.table_name}.user_id = ?
AND #{condition}
)
SQL
)
OpenProject::SqlSanitization.sanitize(<<~SQL.squish, user_id)
NOT EXISTS (
SELECT 1 FROM #{MeetingParticipant.table_name}
WHERE #{MeetingParticipant.table_name}.meeting_id = meetings.id
AND #{MeetingParticipant.table_name}.user_id = ?
AND #{condition}
)
SQL
when "*"
["#{MeetingParticipant.table_name}.user_id IS NOT NULL", condition].join(" AND ")
when "!*"
@@ -48,17 +48,14 @@ class Queries::Meetings::Filters::InvitedUserFilter < Queries::Meetings::Filters
user_id = normalized_user_id(values.first)
return "1=1" if user_id.nil?
ActiveRecord::Base.send(
:sanitize_sql_array,
[<<~SQL.squish, user_id]
NOT EXISTS (
SELECT 1 FROM #{MeetingParticipant.table_name}
WHERE #{MeetingParticipant.table_name}.meeting_id = meetings.id
AND #{MeetingParticipant.table_name}.user_id = ?
AND #{condition}
)
SQL
)
OpenProject::SqlSanitization.sanitize(<<~SQL.squish, user_id)
NOT EXISTS (
SELECT 1 FROM #{MeetingParticipant.table_name}
WHERE #{MeetingParticipant.table_name}.meeting_id = meetings.id
AND #{MeetingParticipant.table_name}.user_id = ?
AND #{condition}
)
SQL
when "*"
["#{MeetingParticipant.table_name}.user_id IS NOT NULL", condition].join(" AND ")
when "!*"
@@ -35,8 +35,8 @@ module API
# @param [Hash] id_status_map A hash mapping file link IDs to their origin status
# in the format { 137: "view_allowed", 142: "error" }
def self.create(id_status_map)
sanitized_sql = ActiveRecord::Base.sanitize_sql_array(
[origin_status_join(id_status_map.size), *id_status_map.flatten]
sanitized_sql = OpenProject::SqlSanitization.sanitize(
origin_status_join(id_status_map.size), *id_status_map.flatten
)
::Storages::FileLink.where(id: id_status_map.keys)
@@ -68,7 +68,7 @@ module Wikis
ON metadata.identifier = wiki_page_links.identifier AND metadata.provider_id = wiki_page_links.provider_id
SQL
join_expression = ActiveRecord::Base.sanitize_sql_array([join_string, *identifier_title_map.flatten])
join_expression = OpenProject::SqlSanitization.sanitize(join_string, *identifier_title_map.flatten)
relation.joins(join_expression).select("wiki_page_links.*, metadata.title as title")
end