diff --git a/src/luamod.lua b/src/luamod.lua index 473ecb26999d1f4ff362ac35849669891fbc2122..50a2f2af24924464c0a18762e895addc1572e25c 100644 --- a/src/luamod.lua +++ b/src/luamod.lua @@ -843,6 +843,7 @@ function pico.grant_privilege(grantee, privilege, object_type, object_name, opts op_kind = 'grant_privilege', priv_def = { grantee_id = grantee_def.id, + grantor_id = box.session.uid(), object_type = object_type, object_name = object_name, privilege = privilege, @@ -932,7 +933,8 @@ function pico.revoke_privilege(grantee, privilege, object_type, object_name, opt -- Throws error if object doesn't exist object_resolve(object_type, object_name) - if box.space._pico_privilege:get{grantee_def.id, object_type, object_name, privilege} == nil then + local priv = box.space._pico_privilege:get{grantee_def.id, object_type, object_name, privilege} + if priv == nil then -- Privilege is not yet granted, no op needed return nil end @@ -942,6 +944,7 @@ function pico.revoke_privilege(grantee, privilege, object_type, object_name, opt op_kind = 'revoke_privilege', priv_def = { grantee_id = grantee_def.id, + grantor_id = priv.grantor_id, object_type = object_type, object_name = object_name, privilege = privilege, diff --git a/src/schema.rs b/src/schema.rs index 5f30c5a0ef21707bb9dbc0c483a0fe78758ef39b..8c5326c488b2a92fc3fbb82b4456a2dd24e8c12b 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -237,6 +237,7 @@ pub struct PrivilegeDef { /// In tarantool users and roles are stored in the same space, which means a /// role and a user cannot have the same id or name. pub grantee_id: UserId, + pub grantor_id: UserId, pub object_type: String, pub object_name: String, pub privilege: String, diff --git a/src/storage.rs b/src/storage.rs index 19d82b24394e86a009c2fbe0d0bc8189bd4cb835..a2395efa89d1183b5e65787be7418ccd770e0c51 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -2162,6 +2162,7 @@ impl Privileges { .is_local(true) .is_temporary(false) .field(("grantee_id", FieldType::Unsigned)) + .field(("grantor_id", FieldType::Unsigned)) .field(("object_type", FieldType::String)) .field(("object_name", FieldType::String)) .field(("privilege", FieldType::String)) diff --git a/src/traft/op.rs b/src/traft/op.rs index 5193515be85a7c5fe0a53a67fd708f70bf62ec1e..df89e24b9f2954e21aee10034dc666f74741b250 100644 --- a/src/traft/op.rs +++ b/src/traft/op.rs @@ -152,24 +152,26 @@ impl std::fmt::Display for Op { Self::Acl(Acl::GrantPrivilege { priv_def }) => { let PrivilegeDef { grantee_id, + grantor_id, object_type, object_name, privilege, schema_version, .. } = priv_def; - write!(f, "GrantPrivilege({schema_version}, {grantee_id}, {object_type}, {object_name}, {privilege})") + write!(f, "GrantPrivilege({schema_version}, {grantee_id}, {grantor_id}, {object_type}, {object_name}, {privilege})") } Self::Acl(Acl::RevokePrivilege { priv_def }) => { let PrivilegeDef { grantee_id, + grantor_id, object_type, object_name, privilege, schema_version, .. } = priv_def; - write!(f, "RevokePrivilege({schema_version}, {grantee_id}, {object_type}, {object_name}, {privilege})") + write!(f, "RevokePrivilege({schema_version}, {grantee_id}, {grantor_id}, {object_type}, {object_name}, {privilege})") } }; diff --git a/test/int/test_acl.py b/test/int/test_acl.py index 44358c68b8965da81efaa3c7209b1afb659e2d59..df1565c378de5c9a515e445661f81125cdb66bfe 100644 --- a/test/int/test_acl.py +++ b/test/int/test_acl.py @@ -190,6 +190,14 @@ def test_acl_lua_api(cluster: Cluster): "_pico_property", ) + dave_id = i1.call("box.space._pico_user.index.name:get", "Dave")[0] + + priv = i1.call( + "box.space._pico_privilege:get", (dave_id, "space", "_pico_property", "read") + ) + + assert priv[1] == 0 # The above grant was executed from guest. 0 is guest user id. + # Already granted -> ok. i1.call( "pico.grant_privilege",