Fix TRIGGER checks for MySQL
This ensures we can check if the user has TRIGGER permissions without querying restricted tables. Thanks to Steve Norman (https://gitlab.com/stevenorman) for helping out with this merge request. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/38372
This commit is contained in:
parent
c71cf908cd
commit
60526a5291
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix TRIGGER checks for MySQL
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
|
@ -6,28 +6,36 @@ module Gitlab
|
|||
if Database.postgresql?
|
||||
'information_schema.role_table_grants'
|
||||
else
|
||||
'mysql.user'
|
||||
'information_schema.schema_privileges'
|
||||
end
|
||||
|
||||
def self.scope_to_current_user
|
||||
if Database.postgresql?
|
||||
where('grantee = user')
|
||||
else
|
||||
where("CONCAT(User, '@', Host) = current_user()")
|
||||
end
|
||||
end
|
||||
|
||||
# Returns true if the current user can create and execute triggers on the
|
||||
# given table.
|
||||
def self.create_and_execute_trigger?(table)
|
||||
priv =
|
||||
if Database.postgresql?
|
||||
where(privilege_type: 'TRIGGER', table_name: table)
|
||||
.where('grantee = user')
|
||||
else
|
||||
where(Trigger_priv: 'Y')
|
||||
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(), '@', '\\'@\\''), '\\'')")
|
||||
]
|
||||
|
||||
union = SQL::Union.new(queries).to_sql
|
||||
|
||||
Grant.from("(#{union}) privs")
|
||||
end
|
||||
|
||||
priv.scope_to_current_user.any?
|
||||
priv.any?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Database::Grant do
|
||||
describe '.scope_to_current_user' do
|
||||
it 'scopes the relation to the current user' do
|
||||
user = Gitlab::Database.username
|
||||
column = Gitlab::Database.postgresql? ? :grantee : :User
|
||||
names = described_class.scope_to_current_user.pluck(column).uniq
|
||||
|
||||
expect(names).to eq([user])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.create_and_execute_trigger' do
|
||||
it 'returns true when the user can create and execute a trigger' do
|
||||
# We assume the DB/user is set up correctly so that triggers can be
|
||||
|
@ -18,13 +8,11 @@ describe Gitlab::Database::Grant do
|
|||
expect(described_class.create_and_execute_trigger?('users')).to eq(true)
|
||||
end
|
||||
|
||||
it 'returns false when the user can not create and/or execute a trigger' do
|
||||
allow(described_class).to receive(:scope_to_current_user)
|
||||
.and_return(described_class.none)
|
||||
|
||||
result = described_class.create_and_execute_trigger?('kittens')
|
||||
|
||||
expect(result).to eq(false)
|
||||
it 'returns false when the user can not create and/or execute a trigger', :postgresql do
|
||||
# In case of MySQL the user may have SUPER permissions, making it
|
||||
# impossible to have `false` returned when running tests; hence we only
|
||||
# run these tests on PostgreSQL.
|
||||
expect(described_class.create_and_execute_trigger?('foo')).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue