diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index ad6f5190f1cdfeab1536d7d1d5736366aea7e7c3..004c3b303ec0bf51169cb5d7b95fa26e8673d958 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -783,7 +783,20 @@ box.schema.user.grant = function(user_name, privilege, object_type, grantor = user_resolve(grantor) end local _priv = box.space[box.schema.PRIV_ID] - _priv:replace{grantor, uid, object_type, oid, privilege} + -- add the granted privilege to the current set + local tuple = _priv:get{uid, object_type, oid} + local old_privilege + if tuple ~= nil then + old_privilege = tuple[5] + else + old_privilege = 0 + end + privilege = bit.bor(privilege, old_privilege) + -- do not execute a replace if it does not change anything + -- XXX bug: new grantor replaces the old one, old grantor is lost + if privilege ~= old_privilege then + _priv:replace{grantor, uid, object_type, oid, privilege} + end end box.schema.user.revoke = function(user_name, privilege, object_type, object_name) @@ -799,9 +812,12 @@ box.schema.user.revoke = function(user_name, privilege, object_type, object_name return end local old_privilege = tuple[5] - if old_privilege ~= privilege then + local grantor = tuple[1] + -- XXX bug: the privilege may be removed by someone who did + -- not grant it + if privilege ~= old_privilege then privilege = bit.band(old_privilege, bit.bnot(privilege)) - _priv:update({uid, object_type, oid}, { "=", 5, privilege}) + _priv:replace{grantor, uid, object_type, oid, privilege} else _priv:delete{uid, object_type, oid} end diff --git a/test/box/access.result b/test/box/access.result index d4fdbc98140a02a4901e96160de4863be7df8d1a..6bf3f6c5e2b409fe07cc239d97dbaffc7831f0c5 100644 --- a/test/box/access.result +++ b/test/box/access.result @@ -330,6 +330,62 @@ box.space._user.index.name:select{'user1'} --- - [] ... +-- A test case for gh-??? Granting a privilege revokes an existing grant +box.schema.user.create('user') +--- +... +id = box.space._user.index.name:get{'user'}[1] +--- +... +box.schema.user.grant('user', 'read,write', 'universe') +--- +... +box.space._priv.index.owner:select{id} +--- +- - [1, 3, 'universe', 0, 3] +... +box.schema.user.grant('user', 'read', 'universe') +--- +... +box.space._priv.index.owner:select{id} +--- +- - [1, 3, 'universe', 0, 3] +... +box.schema.user.revoke('user', 'write', 'universe') +--- +... +box.space._priv.index.owner:select{id} +--- +- - [1, 3, 'universe', 0, 1] +... +box.schema.user.revoke('user', 'read', 'universe') +--- +... +box.space._priv.index.owner:select{id} +--- +- [] +... +box.schema.user.grant('user', 'write', 'universe') +--- +... +box.space._priv.index.owner:select{id} +--- +- - [1, 3, 'universe', 0, 2] +... +box.schema.user.grant('user', 'read', 'universe') +--- +... +box.space._priv.index.owner:select{id} +--- +- - [1, 3, 'universe', 0, 3] +... +box.schema.user.drop('user') +--- +... +box.space._priv.index.owner:select{id} +--- +- [] +... session = nil --- ... diff --git a/test/box/access.test.lua b/test/box/access.test.lua index 3b41ced8c11c290901b4948ca066620661c08271..94fb6afd6167f80f30519f087f12bc2378fd66b6 100644 --- a/test/box/access.test.lua +++ b/test/box/access.test.lua @@ -147,4 +147,24 @@ session.su('admin') box.space._user.index.name:select{'user1'} box.schema.user.drop('user1') box.space._user.index.name:select{'user1'} +-- ---------------------------------------------------------- +-- A test case for gh-421 Granting a privilege revokes an +-- existing grant +-- ---------------------------------------------------------- +box.schema.user.create('user') +id = box.space._user.index.name:get{'user'}[1] +box.schema.user.grant('user', 'read,write', 'universe') +box.space._priv.index.owner:select{id} +box.schema.user.grant('user', 'read', 'universe') +box.space._priv.index.owner:select{id} +box.schema.user.revoke('user', 'write', 'universe') +box.space._priv.index.owner:select{id} +box.schema.user.revoke('user', 'read', 'universe') +box.space._priv.index.owner:select{id} +box.schema.user.grant('user', 'write', 'universe') +box.space._priv.index.owner:select{id} +box.schema.user.grant('user', 'read', 'universe') +box.space._priv.index.owner:select{id} +box.schema.user.drop('user') +box.space._priv.index.owner:select{id} session = nil diff --git a/test/box/auth_access.result b/test/box/auth_access.result index 47f6b8bec95929b8f1a93a0e70d3161217704490..0308afa85d61ef35a96459537bb0e59b71f2240f 100644 --- a/test/box/auth_access.result +++ b/test/box/auth_access.result @@ -469,6 +469,9 @@ t = {} session.su('admin') --- ... +box.schema.user.revoke('testuser', 'read', 'space', 'glade') +--- +... box.schema.user.grant('testuser', 'write', 'space', 'glade') --- ... diff --git a/test/box/auth_access.test.lua b/test/box/auth_access.test.lua index feed2093296bfe231582cd6c231a146328912b83..7e4833f8eb1c6ae1ab8450c5f8909c768b71e4d1 100644 --- a/test/box/auth_access.test.lua +++ b/test/box/auth_access.test.lua @@ -190,6 +190,7 @@ for key, v in s.index.primary:pairs(3, {iterator = 'GE'}) do table.insert (t, v) t t = {} session.su('admin') +box.schema.user.revoke('testuser', 'read', 'space', 'glade') box.schema.user.grant('testuser', 'write', 'space', 'glade') session.su('testuser') s:select() diff --git a/test/box/transaction.result b/test/box/transaction.result index a0dbea0e80e73bb8e93c46b9e83f479e95da3b8b..482a0ef36332eaa2e07d200be55aee16fc7ede70 100644 --- a/test/box/transaction.result +++ b/test/box/transaction.result @@ -86,7 +86,7 @@ box.begin() box.schema.user.create('test'); box.rollback(); --- ... -box.begin() box.schema.user.grant('guest', 'read', 'universe'); +box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv'); --- - error: Space _priv does not support multi-statement transactions ... diff --git a/test/box/transaction.test.lua b/test/box/transaction.test.lua index 9d296148ba4ad158231f75fc80fca932a4070896..799b8bf3ce8e8bb49fb3ad7b640f596123c8093a 100644 --- a/test/box/transaction.test.lua +++ b/test/box/transaction.test.lua @@ -35,7 +35,7 @@ box.begin() box.schema.func.create('test'); box.rollback(); box.begin() box.schema.user.create('test'); box.rollback(); -box.begin() box.schema.user.grant('guest', 'read', 'universe'); +box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv'); box.rollback(); box.begin() box.space._schema:insert{'test'}; box.rollback();