gitlab-org--gitlab-foss/lib/gitlab/database/grant.rb
Yorick Peterse 8a72f5c427
Added FromUnion to easily select from a UNION
This commit adds the module `FromUnion`, which provides the class method
`from_union`. This simplifies the process of selecting data from the
result of a UNION, and reduces the likelihood of making mistakes. As a
result, instead of this:

    union = Gitlab::SQL::Union.new([foo, bar])

    Foo.from("(#{union.to_sql}) #{Foo.table_name}")

We can now write this instead:

    Foo.from_union([foo, bar])

This commit also includes some changes to make this new setup work
properly. For example, a bug in Rails 4
(https://github.com/rails/rails/issues/24193) would break the use of
`from("sub-query-here").includes(:relation)` in certain cases. There was
also a CI query which appeared to repeat a lot of conditions from an
outer query on an inner query, which isn't necessary.

Finally, we include a RuboCop cop to ensure developers use this new
module, instead of using Gitlab::SQL::Union directly.

Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/51307
2018-09-17 12:39:43 +02:00

52 lines
1.8 KiB
Ruby

module Gitlab
module Database
# Model that can be used for querying permissions of a SQL user.
class Grant < ActiveRecord::Base
include FromUnion
self.table_name =
if Database.postgresql?
'information_schema.role_table_grants'
else
'information_schema.schema_privileges'
end
# Returns true if the current user can create and execute triggers on the
# given table.
def self.create_and_execute_trigger?(table)
if Database.postgresql?
# We _must not_ use quote_table_name as this will produce double
# quotes on PostgreSQL and for "has_table_privilege" we need single
# quotes.
quoted_table = connection.quote(table)
begin
from(nil)
.pluck("has_table_privilege(#{quoted_table}, 'TRIGGER')")
.first
rescue ActiveRecord::StatementInvalid
# This error is raised when using a non-existing table name. In this
# case we just want to return false as a user technically can't
# create triggers for such a table.
false
end
else
queries = [
Grant.select(1)
.from('information_schema.user_privileges')
.where("PRIVILEGE_TYPE = 'SUPER'")
.where("GRANTEE = CONCAT('\\'', REPLACE(CURRENT_USER(), '@', '\\'@\\''), '\\'')"),
Grant.select(1)
.from('information_schema.schema_privileges')
.where("PRIVILEGE_TYPE = 'TRIGGER'")
.where('TABLE_SCHEMA = ?', Gitlab::Database.database_name)
.where("GRANTEE = CONCAT('\\'', REPLACE(CURRENT_USER(), '@', '\\'@\\''), '\\'')")
]
Grant.from_union(queries, alias_as: 'privs').any?
end
end
end
end
end