grant.rb 1.85 KB
Newer Older
1
2
# frozen_string_literal: true

3
4
5
6
module Gitlab
  module Database
    # Model that can be used for querying permissions of a SQL user.
    class Grant < ActiveRecord::Base
7
8
      include FromUnion

9
10
11
12
      self.table_name =
        if Database.postgresql?
          'information_schema.role_table_grants'
        else
Yorick Peterse's avatar
Yorick Peterse committed
13
          'information_schema.schema_privileges'
14
15
16
17
18
        end

      # Returns true if the current user can create and execute triggers on the
      # given table.
      def self.create_and_execute_trigger?(table)
19
20
21
22
23
        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)
Yorick Peterse's avatar
Yorick Peterse committed
24

25
26
          begin
            from(nil)
Heinrich Lee Yu's avatar
Heinrich Lee Yu committed
27
              .pluck(Arel.sql("has_table_privilege(#{quoted_table}, 'TRIGGER')"))
28
29
30
31
32
33
34
35
36
37
38
39
40
              .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(), '@', '\\'@\\''), '\\'')"),
Yorick Peterse's avatar
Yorick Peterse committed
41

42
43
44
45
46
47
            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(), '@', '\\'@\\''), '\\'')")
          ]
Yorick Peterse's avatar
Yorick Peterse committed
48

49
          Grant.from_union(queries, alias_as: 'privs').any?
50
        end
51
52
53
54
      end
    end
  end
end