summaryrefslogtreecommitdiff
path: root/lib/gitlab/database/grant.rb
blob: 862ab96c887106ed3223b95f8d76af9c0c10eb3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# frozen_string_literal: true

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