[tarantool-patches] Re: [PATCH v2] Introduce separate entity object types for entity privileges.
Serge Petrenko
sergepetrenko at tarantool.org
Fri Aug 17 15:19:29 MSK 2018
Hi! Thank you for review. I fixed your comments, the new diff is below.
> 17 авг. 2018 г., в 12:19, Vladimir Davydov <vdavydov.dev at gmail.com> написал(а):
>
> On Tue, Aug 14, 2018 at 04:41:25PM +0300, Serge Petrenko wrote:
>> diff --git a/src/box/alter.cc b/src/box/alter.cc
>> index 3007a131d..7d65cab3a 100644
>> --- a/src/box/alter.cc
>> +++ b/src/box/alter.cc
>> @@ -2537,10 +2537,41 @@ priv_def_create_from_tuple(struct priv_def *priv, struct tuple *tuple)
>> {
>> priv->grantor_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_ID);
>> priv->grantee_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_UID);
>> +
>> const char *object_type =
>> tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_TYPE);
>> - priv->object_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_OBJECT_ID);
>> priv->object_type = schema_object_type(object_type);
>> +
>> + const char *object_id = tuple_field(tuple, BOX_PRIV_FIELD_OBJECT_ID);
>
> This isn't object_id. It's msgpack. Please rename this variable to
> emphasize that. For instance, 'object_id_field', 'object_id_raw', or
> simply 'data’.
Ok, let it be ‘data’.
>
>> + if (object_id == NULL) {
>> + tnt_raise(ClientError, ER_NO_SUCH_FIELD,
>> + BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE);
>> + }
>> + /*
>> + * When granting or revoking privileges on a whole entity
>> + * we pass an asterisk ('*') to object_id to indicate
>> + * grant on every object of that entity.
>> + * So check for that first.
>> + */
>> + if (mp_typeof(*object_id) == MP_STR) {
>> + object_id = tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_ID);
>> + if(*object_id == '*' && strlen(object_id) == 1) {
>
> Nit: in a case like this, better use strcmp.
We decided to switch to «» (empty string), so use mp_decode_strl(&data) == 0 here
>
>> + priv->object_id = 0;
>> + priv->object_type = schema_entity_type(priv->object_type);
>> + } else {
>> + tnt_raise(ClientError, ER_FIELD_TYPE,
>> + BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE,
>> + field_type_strs[FIELD_TYPE_UNSIGNED]);
>> + }
>> + } else if (mp_typeof(*object_id) == MP_UINT) {
>> + priv->object_id = tuple_field_u32_xc(tuple,
>> + BOX_PRIV_FIELD_OBJECT_ID);
>> + } else {
>> + tnt_raise(ClientError, ER_FIELD_TYPE,
>> + BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE,
>> + field_type_strs[FIELD_TYPE_UNSIGNED]);
>> + }
>> +
>
> Somehow, I don't like this piece of code. For instance, you raise
> the same error (FIELD_TYPE_UNSIGNED) in two places. Also, you use
> tuple_field_*_xc after you explicitly check the type, which is
> pointless, because they can't fail.
>
> May be, something like this?
>
> switch (mp_typeof(*data)) {
> case MP_STR:
> if (mp_decode_strl(&data) == 0) {
> /* Entity-wide privilege. */
> priv->object_id = 0;
> break;
> }
> FALLTHROUGH;
> default:
> priv->object_id = tuple_field_u32_xc(...);
> }
Ok, I use your variant.
>
>> if (priv->object_type == SC_UNKNOWN) {
>> tnt_raise(ClientError, ER_UNKNOWN_SCHEMA_OBJECT,
>> object_type);
>> diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
>> index b9b8c9004..361810c79 100644
>> --- a/src/box/lua/schema.lua
>> +++ b/src/box/lua/schema.lua
>> @@ -1801,17 +1801,19 @@ local function privilege_name(privilege)
>> end
>>
>> local function object_resolve(object_type, object_name)
>> + if object_name ~= nil and type(object_name) ~= 'string'
>> + and type(object_name) ~= 'number' then
>> + box.error(box.error.ILLEGAL_PARAMS, "wrong object name type")
>> + end
>> if object_type == 'universe' then
>> - if object_name ~= nil and type(object_name) ~= 'string'
>> - and type(object_name) ~= 'number' then
>> - box.error(box.error.ILLEGAL_PARAMS, "wrong object name type")
>> - end
>> return 0
>> end
>> + if (object_type == 'space' or object_type == 'function' or
>> + object_type == 'sequence' or object_type == 'role') and
>> + object_name == nil then
>> + return '*'
>> + end
>
> No, I don't like this: now, if you want to add a new object type,
> you have to patch two places: here and below, where the object name
> is resolved. Let's leave it as before.
Ok.
>
>> if object_type == 'space' then
>> - if object_name == nil or object_name == 0 then
>> - return 0
>> - end
>> local space = box.space[object_name]
>> if space == nil then
>> box.error(box.error.NO_SUCH_SPACE, object_name)
>> @@ -1819,9 +1821,6 @@ local function object_resolve(object_type, object_name)
>> return space.id
>> end
>> if object_type == 'function' then
>> - if object_name == nil or object_name == 0 then
>> - return 0
>> - end
>> local _vfunc = box.space[box.schema.VFUNC_ID]
>> local func
>> if type(object_name) == 'string' then
>> @@ -1836,9 +1835,6 @@ local function object_resolve(object_type, object_name)
>> end
>> end
>> if object_type == 'sequence' then
>> - if object_name == nil or object_name == 0 then
>> - return 0
>> - end
>> local seq = sequence_resolve(object_name)
>> if seq == nil then
>> box.error(box.error.NO_SUCH_SEQUENCE, object_name)
>> @@ -1867,6 +1863,9 @@ local function object_name(object_type, object_id)
>> if object_type == 'universe' then
>> return ""
>> end
>> + if object_id == '*' then
>> + return '*'
>> + end
>> local space
>> if object_type == 'space' then
>> space = box.space._vspace
>> @@ -2106,10 +2105,10 @@ local function grant(uid, name, privilege, object_type,
>> _priv:replace{options.grantor, uid, object_type, oid, privilege_hex}
>> elseif not options.if_not_exists then
>> if object_type == 'role' then
>> - box.error(box.error.ROLE_GRANTED, name, object_name)
>> + box.error(box.error.ROLE_GRANTED, name, object_name or '*')
>> else
>> box.error(box.error.PRIV_GRANTED, name, privilege,
>> - object_type, object_name)
>> + object_type, object_name or '*')
>> end
>> end
>> end
>> @@ -2134,10 +2133,10 @@ local function revoke(uid, name, privilege, object_type, object_name, options)
>> return
>> end
>> if object_type == 'role' then
>> - box.error(box.error.ROLE_NOT_GRANTED, name, object_name)
>> + box.error(box.error.ROLE_NOT_GRANTED, name, object_name or '*')
>> else
>> box.error(box.error.PRIV_NOT_GRANTED, name, privilege,
>> - object_type, object_name)
>> + object_type, object_name or '*')
>> end
>> end
>> local old_privilege = tuple[5]
>> @@ -2153,13 +2152,14 @@ local function revoke(uid, name, privilege, object_type, object_name, options)
>> return
>> end
>> box.error(box.error.PRIV_NOT_GRANTED, name, privilege,
>> - object_type, object_name)
>> + object_type, object_name or '*')
>> end
>> if privilege_hex ~= 0 then
>> _priv:replace{grantor, uid, object_type, oid, privilege_hex}
>> else
>> _priv:delete{uid, object_type, oid}
>> end
>> +
>
> Extra new line, please remove.
Done
>
>> end
>>
>> local function drop(uid, opts)
>> @@ -2192,9 +2192,10 @@ local function drop(uid, opts)
>> local privs = _vpriv.index.primary:select{uid}
>>
>> for k, tuple in pairs(privs) do
>> - -- we need an additional box.session.su() here, because of
>> - -- unnecessary check for privilege PRIV_REVOKE in priv_def_check()
>> - box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], tuple[4])
>> + -- we need an additional box.session.su() here, because of
>> + -- unnecessary check for privilege PRIV_REVOKE in priv_def_check()
>> + local oid = tuple[4] ~= '*' and tuple[4] or nil
>> + box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], oid)
>> end
>> box.space[box.schema.USER_ID]:delete{uid}
>> end
>> diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
>> index 0293f6ef8..5dbc09bbb 100644
>> --- a/src/box/lua/upgrade.lua
>> +++ b/src/box/lua/upgrade.lua
>> @@ -964,6 +964,28 @@ local function upgrade_to_1_10_0()
>> create_vsequence_space()
>> end
>>
>> +--------------------------------------------------------------------------------
>> +--- Tarantool 1.10.1
>> +--------------------------------------------------------------------------------
>> +local function upgrade_space_priv_to_1_10_1()
>> + local _priv = box.space._priv
>> + local _vpriv = box.space._vpriv
>> + local f = _priv:format()
>> +
>> + f[4].type = 'scalar'
>> + _priv:format(f)
>> + f = _vpriv:format()
>> + f[4].type = 'scalar'
>> + _vpriv:format(f)
>> + _priv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}
>> + _vpriv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}
>> + _priv.index.object:alter{parts={3, 'string', 4, 'scalar'}}
>> + _vpriv.index.object:alter{parts={3, 'string', 4, 'scalar'}}
>> +end
>> +
>> +local function upgrade_to_1_10_1()
>> + upgrade_space_priv_to_1_10_1()
>> +end
>>
>> local function get_version()
>> local version = box.space._schema:get{'version'}
>> @@ -991,6 +1013,7 @@ local function upgrade(options)
>> {version = mkversion(1, 7, 6), func = upgrade_to_1_7_6, auto = false},
>> {version = mkversion(1, 7, 7), func = upgrade_to_1_7_7, auto = true},
>> {version = mkversion(1, 10, 0), func = upgrade_to_1_10_0, auto = true},
>> + {version = mkversion(1, 10, 1), func = upgrade_to_1_10_1, auto = true},
>
> Should be 1.10.2
>
> 1.10.1 has already been released.
Changed to 1.10.2 and updated bootstrap.snap
>
>> }
>>
>> for _, handler in ipairs(handlers) do
>> diff --git a/src/box/schema.cc b/src/box/schema.cc
>> index 433f52c08..9958e9016 100644
>> --- a/src/box/schema.cc
>> +++ b/src/box/schema.cc
>> @@ -536,10 +536,18 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
>> switch (type) {
>> case SC_UNIVERSE:
>> return "";
>> + case SC_ENTITY_SPACE:
>> + return "";
>> + case SC_ENTITY_FUNCTION:
>> + return "";
>> + case SC_ENTITY_SEQUENCE:
>> + return "";
>> + case SC_ENTITY_ROLE:
>> + return "";
>> + case SC_ENTITY_USER:
>> + return "";
>
> Please rewrite it as
>
> case SC_ENTITY_SPACE:
> case SC_ENTITY_FUNCTION:
> case SC_ENTITY_SEQUENCE:
> ...
> return "";
>
> Also, I don't like that sometimes we use '*' and sometimes '' when
> reporting errors. What about using '' for entity-wide privileges
> everywhere, including the _priv space? This would save us from
> possible conflicts with objects named '*' (yeah, no sane user would
> call a space like that, but still). This would also allow us to
> simplify object_resolve() as I suggested in the previous review
> round.
Done. I like the idea with using «» instead of «*», switched to that.
>
>> case SC_SPACE:
>> {
>> - if (object_id == 0)
>> - return "SPACE";
>> struct space *space = space_by_id(object_id);
>> if (space == NULL)
>> break;
>> @@ -547,8 +555,6 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
>> }
>> case SC_FUNCTION:
>> {
>> - if (object_id == 0)
>> - return "FUNCTION";
>> struct func *func = func_by_id(object_id);
>> if (func == NULL)
>> break;
>> @@ -556,8 +562,6 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
>> }
>> case SC_SEQUENCE:
>> {
>> - if (object_id == 0)
>> - return "SEQUENCE";
>> struct sequence *seq = sequence_by_id(object_id);
>> if (seq == NULL)
>> break;
>> diff --git a/src/box/schema.h b/src/box/schema.h
>> index 0822262d0..f1735ff34 100644
>> --- a/src/box/schema.h
>> +++ b/src/box/schema.h
>> @@ -250,16 +250,19 @@ static inline
>> struct access *
>> entity_access_get(enum schema_object_type type)
>> {
>> - switch (type) {
>> - case SC_SPACE:
>> - return entity_access.space;
>> - case SC_FUNCTION:
>> - return entity_access.function;
>> - case SC_SEQUENCE:
>> - return entity_access.sequence;
>> - default:
>> - return NULL;
>> - }
>> + switch (type) {
>> + case SC_SPACE:
>> + case SC_ENTITY_SPACE:
>> + return entity_access.space;
>> + case SC_FUNCTION:
>> + case SC_ENTITY_FUNCTION:
>> + return entity_access.function;
>> + case SC_SEQUENCE:
>> + case SC_ENTITY_SEQUENCE:
>> + return entity_access.sequence;
>> + default:
>> + return NULL;
>> + }
>> }
>>
>> #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */
>> diff --git a/src/box/schema_def.c b/src/box/schema_def.c
>> index 97c074ab2..18ec6c8d2 100644
>> --- a/src/box/schema_def.c
>> +++ b/src/box/schema_def.c
>> @@ -31,16 +31,39 @@
>> #include "schema_def.h"
>>
>> static const char *object_type_strs[] = {
>> - /* [SC_UKNNOWN] = */ "unknown",
>> - /* [SC_UNIVERSE] = */ "universe",
>> - /* [SC_SPACE] = */ "space",
>> - /* [SC_FUNCTION] = */ "function",
>> - /* [SC_USER] = */ "user",
>> - /* [SC_ROLE] = */ "role",
>> - /* [SC_SEQUENCE] = */ "sequence",
>> - /* [SC_COLLATION] = */ "collation",
>> + /* [SC_UKNNOWN] = */ "unknown",
>> + /* [SC_UNIVERSE] = */ "universe",
>> + /* [SC_SPACE] = */ "space",
>> + /* [SC_ENTITY_SPACE] = */ "space",
>> + /* [SC_FUNCTION] = */ "function",
>> + /* [SC_ENTITY_FUNCTION] = */ "function",
>> + /* [SC_USER] = */ "user",
>> + /* [SC_ENTITY_USER] = */ "user",
>> + /* [SC_ROLE] = */ "role",
>> + /* [SC_ENTITY_ROLE] = */ "role",
>> + /* [SC_SEQUENCE] = */ "sequence",
>> + /* [SC_ENTITY_SEQUENCE] = */ "sequence",
>> + /* [SC_COLLATION] = */ "collation",
>> + /* [SC_ENTITY_COLLATION] = */ "collation",
>
> I don't like this code duplication. Actually, I don't think that you
> need to have separate names for entity-wide privileges at all: AFAICS,
> schema_object_name() is never called for SC_ENTITY_*. Let's remove
> SC_ENTITY_* from this array.
>
> If you do that, you won't be able to increment object type to get entity
> type. Well, OK, it's not that scary, taking into account the fact that
> you always use a helper function for that (see right below). I see it
> that way
>
> enum schema_object_type {
> SC_UNKNOWN = 0,
> SC_UNIVERSE = 1,
> SC_SPACE = 2,
> SC_FUNCTION = 3,
> SC_USER = 4,
> SC_ROLE = 5,
> SC_SEQUENCE = 6,
> SC_COLLATION = 7,
> schema_object_type_MAX = 8
>
> /* Entity types. */
> SC_ENTITY_SPACE,
> SC_ENTITY_FUNCTION,
> …
> }
>
> enum schema_object_type
> schema_entity_type(enum schema_object_type type)
> {
> switch (type) {
> case SC_SPACE:
> return SC_ENTITY_SPACE;
> case SC_FUNCTION:
> return SC_ENTITY_FUNCTION;
> ...
> }
> }
>
Ok, switched to your variant with slight differences.
>> };
>>
>> +enum schema_object_type
>> +schema_entity_type(enum schema_object_type type)
>> +{
>> + switch(type) {
>
> ^^
> space missing
Fixed.
>
>> + case SC_SPACE:
>> + case SC_FUNCTION:
>> + case SC_USER:
>> + case SC_ROLE:
>> + case SC_SEQUENCE:
>> + case SC_COLLATION:
>> + return type + 1;
>> + break;
>> + default:
>> + unreachable();
>> + }
>> +}
>> +
>> enum schema_object_type
>> schema_object_type(const char *name)
>> {
>> diff --git a/src/box/schema_def.h b/src/box/schema_def.h
>> index 2edb8d37f..9b5bd6864 100644
>> --- a/src/box/schema_def.h
>> +++ b/src/box/schema_def.h
>> @@ -218,19 +218,35 @@ enum {
>> *
>> * Use 0 for unknown to use the same index consistently
>> * even when there are more object types in the future.
>> + *
>> + * When adding new types please follow this rule:
>> + * SC_ENTITY_NEW_OBJECT = SC_NEW_OBJECT + 1
>> + * schema_entity_type() relies on this convention.
>> */
>> enum schema_object_type {
>> SC_UNKNOWN = 0,
>> SC_UNIVERSE = 1,
>> SC_SPACE = 2,
>> - SC_FUNCTION = 3,
>> - SC_USER = 4,
>> - SC_ROLE = 5,
>> - SC_SEQUENCE = 6,
>> - SC_COLLATION = 7,
>> - schema_object_type_MAX = 8
>> + SC_ENTITY_SPACE = 3,
>> + SC_FUNCTION = 4,
>> + SC_ENTITY_FUNCTION = 5,
>> + SC_USER = 6,
>> + SC_ENTITY_USER = 7,
>> + SC_ROLE = 8,
>> + SC_ENTITY_ROLE = 9,
>> + SC_SEQUENCE = 10,
>> + SC_ENTITY_SEQUENCE = 11,
>> + SC_COLLATION = 12,
>> + SC_ENTITY_COLLATION = 13,
>> + schema_object_type_MAX = 13
>> };
>
---
src/box/alter.cc | 27 +++++++++++++++++++-
src/box/bootstrap.snap | Bin 1540 -> 1556 bytes
src/box/lua/schema.lua | 58 ++++++++++++++++++++++++++-----------------
src/box/lua/upgrade.lua | 23 +++++++++++++++++
src/box/schema.cc | 11 ++++----
src/box/schema.h | 23 +++++++++--------
src/box/schema_def.c | 7 ++++++
src/box/schema_def.h | 18 +++++++++++++-
src/box/user.cc | 27 +++++++++++---------
test/box-py/bootstrap.result | 14 +++++------
test/box/access.result | 6 ++---
test/box/access_misc.result | 8 +++---
test/box/alter.result | 8 +++---
test/xlog/upgrade.result | 14 +++++------
14 files changed, 166 insertions(+), 78 deletions(-)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 3007a131d..f586a2695 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -2537,10 +2537,35 @@ priv_def_create_from_tuple(struct priv_def *priv, struct tuple *tuple)
{
priv->grantor_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_ID);
priv->grantee_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_UID);
+
const char *object_type =
tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_TYPE);
- priv->object_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_OBJECT_ID);
priv->object_type = schema_object_type(object_type);
+
+ const char *data = tuple_field(tuple, BOX_PRIV_FIELD_OBJECT_ID);
+ if (data == NULL) {
+ tnt_raise(ClientError, ER_NO_SUCH_FIELD,
+ BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE);
+ }
+ /*
+ * When granting or revoking privileges on a whole entity
+ * we pass empty string ('') to object_id to indicate
+ * grant on every object of that entity.
+ * So check for that first.
+ */
+ switch (mp_typeof(*data)) {
+ case MP_STR:
+ if (mp_decode_strl(&data) == 0) {
+ /* Entity-wide privilege. */
+ priv->object_id = 0;
+ priv->object_type = schema_entity_type(priv->object_type);
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ priv->object_id = tuple_field_u32_xc(tuple,
+ BOX_PRIV_FIELD_OBJECT_ID);
+ }
if (priv->object_type == SC_UNKNOWN) {
tnt_raise(ClientError, ER_UNKNOWN_SCHEMA_OBJECT,
object_type);
diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap
index b610828c9c9ae9a22acdd8c150c16c6838b7a273..44992b050e9d73d69608fb92782d1e965f6cdc51 100644
GIT binary patch
delta 1551
zcmV+q2JrcW43rFz7=JM>GB!9ZXE|m$WMeloGhzx!ZgX^DZewLSAT%>EG&o@}VJ$c{
zGcheRV>UP~VPZ03EipATVq!NoIX7cCWeQe9Y;R+0Iv{&}3JTS_3%bn(nE=k-$Bkd5
z0000004TLD{QyvfEC41w*h<hAaRLBeJb=_J{}F0FAgJ*mVt>V;#?6&k&og$Aul<dv
zv3Dv(N-{sS_S_R$=If$P=IFJ-Qc5dSF3)wMv;i7#PyNg>UnEmX0mA^f0L=io5sT!g
zD{Fnf#vxPKYgy*n?1AMVIy{=p9gia^hC=L0fWLuz8rC_P&bxEnm$jbL+0jvRI_+sG
zru|Ih;m)d9Ab%fU2!MAhTHBbGce$H&nf~2*&yFmHLT-w8E2;yCj1eht_F<%$wYjrA
z--_qmirxZNlbP>7cRjpY(I5*1%V7?t>8y7vDuOB;TVebwm5d3mRG{g<l`_3ftd)rc
zn_;zHClt(+{hgbmxU+pKw$>&pI!j<g$w35)6B;Hdw}0vc|76#A%XVkpWtdu!!EHY`
zQ473V(OEa~Z9g}|)Sgs&h}w*uq0W{Rc(<Zvf8ImXW-LrCDFM%iVB<2)IG&t`=^X0p
z%Yh$fD8!Boc(<bFh|kp4F)S=%TMBr$q8k55lCM#${Y=DS+Bfbz&A~d;aQkK7b>5ZV
zdG3dP6Mx6^(8sb6!1;Xg8sDAa&WZ-$y>W_Zn~dpXc#Nf8o1_ at R#?P at Ion`uUK3>En
z4|O&qz`GSKF%8FiNe275855I3zK&RX`$!^s><!J0t0shXfpC3jd1!TLaj at ww*s37t
z-HLiP9v};~La9)x)67Zcgesj%8+J-DBoj%4cYiCoL(1 at BuzjT$lI`Wf$ik??2xi9d
ztc3#01eTBGMdTtHiCXRru~^$q5*v~bieRnCyA at ptRojk|H*sWb>UR9^o~tSri06BO
z0Q-*j>z9Q*4+(#G7_m1GyjxLQ$D%fO4}ENn1MgPUw1qv^wQ}ZNwi<Z1qOu?JnRn at f
zM}I7Goln at sxA7u>0uPF;){6CdrBo=>OXh`5;7UxHP%|pfgijbup=MGrPps{8(Quhz
zWw^YXTN9%N1NEZh;%hNtVMQxeEKqt?SWV_GYBSbz?d=0?f`WpY*c$IvG*qAOKeIM_
zQh2wbDYx3&2cp<tnmn~GC&WCKzkjS};(teS=fpg|%u;9X?K_pwnFhnDwIsY-(GRlN
ztgP{o#>Rx0;YE$dsj=v%(gx?x*@*;&XWUfcndq})KR0uozbQ*?y?v(<-mNH&3>7#_
z#&nJefg`BVSY%8M%m4s at 04M+v21hAoRSyz?&^U^NFbZH021E!rh)xs$fZ#w_L4OfM
zEf at qq49vQeA))6t$8JsxhygJm2AP2;6jR1Ytzq>yuq)+j_YBuXSm^>oOc44oRR2+r
zfKn$8 at 9xdDJsnXgj8fvJX-OOEnOz2N82f7Vr6^tAcX*WFIPM{0Ntj!pLMS~2mv!oE
zRrM)J%oMN{r_N{V(s7_ah4$kjihs$6<OnC-Xy|vNdloebHTnit at EUCcD|n6OjV)em
zPC$*u2HNnREZ$rv)082si4 at Jx$$z3_Ifq*d0kp^Vv;;5qa1a|JkDvz!Y7ZzgZLtTG
znKqel_G}Nk_kmTD8UY2Zw|;97AY4LmR2{?0eUDLb#Sq+kdJS#-4;^$U>3_%%=)mhn
z2W|IQc+vMG<^-d?>WOsJ?wF5DwFGHVZ;5{eV6!P9un202v<JSzI-4XFWp2pfJ=}&9
z|B3!R7$^i;Ur3=7lANu}q6eAjK|>w!Z8R4d19B91M{)$#!E>qp7jG6HO>MyhU^@4T
z^f(MLmIX$FanP|HqB(=3bAPgI29$n(?koqvkkh_+Jdt&9kemV%zz>2&MdX*2g^(0B
zb3fr-G#O-Ux`l`P)LF58aj(U8%fMRlqE2MOof#G*F;Vmq(Um!gfT;c#$##_N2vs0b
zGn`~?u8)RY;W>4D58f)EMzh}yokR<1H8AM^(7KO=Ygngs1QB1+=m<%o!R6Hut?jEW
B)aL*I
delta 1534
zcmV<a1p)e$41^4j7=JJ=G%zh^V>dT4F*z~{Np5p=VQyn(Iv_b=V_`LAF*YqTV`gS8
zG-hTvEnzrjFfCy?W;Qf4VP!dGGGq!?Lu_wjYdRo%F*+bOeF_TIx(m9^1&9F7A|rpb
zr2qf`001bpFZ}>e{VM<lJ=RLl7I6XqUp$Ch%_7lYJ_Lj_ at PFoXP~+we(A76EO7~<&
z)F3;RA|;uhw(`4WgTRw>I&<{eU?~Ai$VOI~v629dx2JaIm at kx4N&&zCxB$xlBK}6v
zM#}nreKVfmYggvF>;bcooE<&pjzw|&ydgCd;B)Xi4C|Up=iRyONm;Mu=<J|49rmyj
z!~XSg?^aVP(0>n31mId~$~K1OP2OJJrGIzc!y|v*5Q}mxHFpG|K|%#jeQ^A;E^l>*
z3*Bp}NefgxX1+gm^KmUTgDMc1Jsb?P)oZC4!mL!?OgGcvU!7uNP_0u4V%4c@$$Tde
z<JJuBKo=+bJ1 at oWHsew%rA$(CR4!bhCq$aiEJ3j}Cx2ttc)M<~yh-n at 9Ru2aUZxgY
zOU+j=F>OCDy|bcHe0;hLW1g*=6kJQqvOo9n=`!@rT1v3PA=sEaGtUmrgF1V*+HwF$
z%o|ck2Ck)MDdN~U>lpNk)Rh9)Qd8p>$FU`TvVVQ}JNw3+pEy`&7|(v!cb#wKcU}Xc
zztr*E^M9!-1a3aZxQyRo-mQ)X;JxvQVS5a1E-Z#;*X8(mp!hlb(b=Wn_TxWHa?e&p
z0<NVdiD5jvlVdHR&M*6U`SOA at wvN<F<4PlXstt_|t42g+g<yeLeOP%|b(q;~x1wEl
zEj90~M>ms_NyVg8C=MtXRLX=hZO}2jlujiL*MCw|r<8%iFyl-urCG}bk_A!)lFN(Z
z*9rxd2`ZdQ%ZOz}8m(9>QmHeYBvm9q6rtA9wbTrW=uAh+mpZa8Z9M*WuhEnWw8OPP
z0Ken?`duE+M1Fc0sWuO;rRJ>TPnWxUKDEZdwbU$UUQcC(VtJFR2G>&aT`%TX-lUJ$
zzkkQk8h`!+Ak42Gb5O~I9X_GL4xhR(RGq@`<8YEmeGLBa%Ed{YaV#4wH7X6(wXrob
zRx(mCOfa|?Bo}qm;#z9jPz5?Ii>k-mKV61Bw$iw6MNm)>lUj2vHAVFK{#e#!kBV!l
ziDGG`ab1f2WXaFUg5t{}`TM8d6EBXt_J3uuRg$)9X&lOg&M*+4wU)S+njl=^i<EJZ
zX2ppwLyQ}LBXiMF<cgb*y<$jG_{C2oetkYX_VcpV`IoM<QW}RMaV<4zXt3a^V}T&3
z(OhIq3CsWhfB+}}AqGb&W<?JYfWSD4qc93!7zRWLI0_9I0RX{)ke~>l77Rj$ynhqj
zxeG%W18Ui|uoin^FOJH&6BE><l!R4e54%@5i^3tJ2=RjuhoRy}$qP!PWxP;CvBe2+
zB`AQ$m7GU4)NS at llAFhZ>1-;h#Us!zr2 at yPWOP}$xk=>TS*Ej6Q8ZgBx&}sXh}Wym
z;Yvs=Xm6s&oTIkS5VXc28)t^2+kc4qR4r1#;*gdpU~^0s$pG8pm?G)gVGer7p5*j@
zrQSOro_cGm&fR}<@b8h^=iXW!%4reE=RqJFW<g443Z&4$8`^`Azzc12c=p(Su(w)T
z1)jmCmtK6UOn at l~=HxoFllhK1;>sqt`1BcS0HC at As3ba#z^Ko9Pi8avYk$Oa!!S#&
zSx3_!A8xyrpfT#3Y0zk_Hi}Y>p%$pI61F+5M3N&%2xKJAC;$CDD}<6?=$#5uoTZ5Z
zCNj}EgB|fKv=$L at ag>MEJ_76DnN*W1Z`O`MZ9ptwx|K1yxMV1V1(Ltx%(4y7obk4E
zW?=^8GIQ=kv4A0`wS7N1*>`Z!opukPx!_g at c{8|RJi<`!QS!z#<&+X#nnV8V6uo^%
zFL^|hfwSZ-+|LAZ&d5i?Zt>-$tMH_1UnT!Yb{@SussOv at WfJ50JyfLCQd9Bw_N-dh
k2=V>Mm|$S01}gnuSl5<E4okR>OyKJnJxL~`9Mur5?adb1g8%>k
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index b9b8c9004..d347fd1e6 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1801,16 +1801,16 @@ local function privilege_name(privilege)
end
local function object_resolve(object_type, object_name)
+ if object_name ~= nil and type(object_name) ~= 'string'
+ and type(object_name) ~= 'number' then
+ box.error(box.error.ILLEGAL_PARAMS, "wrong object name type")
+ end
if object_type == 'universe' then
- if object_name ~= nil and type(object_name) ~= 'string'
- and type(object_name) ~= 'number' then
- box.error(box.error.ILLEGAL_PARAMS, "wrong object name type")
- end
return 0
end
if object_type == 'space' then
- if object_name == nil or object_name == 0 then
- return 0
+ if object_name == '' then
+ return ''
end
local space = box.space[object_name]
if space == nil then
@@ -1819,8 +1819,8 @@ local function object_resolve(object_type, object_name)
return space.id
end
if object_type == 'function' then
- if object_name == nil or object_name == 0 then
- return 0
+ if object_name == '' then
+ return ''
end
local _vfunc = box.space[box.schema.VFUNC_ID]
local func
@@ -1836,8 +1836,8 @@ local function object_resolve(object_type, object_name)
end
end
if object_type == 'sequence' then
- if object_name == nil or object_name == 0 then
- return 0
+ if object_name == '' then
+ return ''
end
local seq = sequence_resolve(object_name)
if seq == nil then
@@ -1864,7 +1864,7 @@ local function object_resolve(object_type, object_name)
end
local function object_name(object_type, object_id)
- if object_type == 'universe' then
+ if object_type == 'universe' or object_id == '' then
return ""
end
local space
@@ -2072,12 +2072,18 @@ local function grant(uid, name, privilege, object_type,
object_name, options)
-- From user point of view, role is the same thing
-- as a privilege. Allow syntax grant(user, role).
- if object_name == nil and object_type == nil then
- -- sic: avoid recursion, to not bother with roles
- -- named 'execute'
- object_type = 'role'
- object_name = privilege
- privilege = 'execute'
+ if object_name == nil then
+ if object_type == nil then
+ -- sic: avoid recursion, to not bother with roles
+ -- named 'execute'
+ object_type = 'role'
+ object_name = privilege
+ privilege = 'execute'
+ else
+ -- Allow syntax grant(user, priv, entity)
+ -- for entity grants.
+ object_name = ''
+ end
end
local privilege_hex = privilege_check(privilege, object_type)
@@ -2117,10 +2123,16 @@ end
local function revoke(uid, name, privilege, object_type, object_name, options)
-- From user point of view, role is the same thing
-- as a privilege. Allow syntax revoke(user, role).
- if object_name == nil and object_type == nil then
- object_type = 'role'
- object_name = privilege
- privilege = 'execute'
+ if object_name == nil then
+ if object_type == nil then
+ object_type = 'role'
+ object_name = privilege
+ privilege = 'execute'
+ else
+ -- Allow syntax revoke(user, privilege, entity)
+ -- to revoke entity privileges.
+ object_name = ''
+ end
end
local privilege_hex = privilege_check(privilege, object_type)
options = options or {}
@@ -2192,8 +2204,8 @@ local function drop(uid, opts)
local privs = _vpriv.index.primary:select{uid}
for k, tuple in pairs(privs) do
- -- we need an additional box.session.su() here, because of
- -- unnecessary check for privilege PRIV_REVOKE in priv_def_check()
+ -- we need an additional box.session.su() here, because of
+ -- unnecessary check for privilege PRIV_REVOKE in priv_def_check()
box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], tuple[4])
end
box.space[box.schema.USER_ID]:delete{uid}
diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index 0293f6ef8..091da2dc4 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -964,6 +964,28 @@ local function upgrade_to_1_10_0()
create_vsequence_space()
end
+--------------------------------------------------------------------------------
+--- Tarantool 1.10.2
+--------------------------------------------------------------------------------
+local function upgrade_space_priv_to_1_10_2()
+ local _priv = box.space._priv
+ local _vpriv = box.space._vpriv
+ local f = _priv:format()
+
+ f[4].type = 'scalar'
+ _priv:format(f)
+ f = _vpriv:format()
+ f[4].type = 'scalar'
+ _vpriv:format(f)
+ _priv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}
+ _vpriv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}
+ _priv.index.object:alter{parts={3, 'string', 4, 'scalar'}}
+ _vpriv.index.object:alter{parts={3, 'string', 4, 'scalar'}}
+end
+
+local function upgrade_to_1_10_2()
+ upgrade_space_priv_to_1_10_2()
+end
local function get_version()
local version = box.space._schema:get{'version'}
@@ -991,6 +1013,7 @@ local function upgrade(options)
{version = mkversion(1, 7, 6), func = upgrade_to_1_7_6, auto = false},
{version = mkversion(1, 7, 7), func = upgrade_to_1_7_7, auto = true},
{version = mkversion(1, 10, 0), func = upgrade_to_1_10_0, auto = true},
+ {version = mkversion(1, 10, 2), func = upgrade_to_1_10_2, auto = true},
}
for _, handler in ipairs(handlers) do
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 433f52c08..4502ca6dc 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -535,11 +535,14 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
{
switch (type) {
case SC_UNIVERSE:
+ case SC_ENTITY_SPACE:
+ case SC_ENTITY_FUNCTION:
+ case SC_ENTITY_SEQUENCE:
+ case SC_ENTITY_ROLE:
+ case SC_ENTITY_USER:
return "";
case SC_SPACE:
{
- if (object_id == 0)
- return "SPACE";
struct space *space = space_by_id(object_id);
if (space == NULL)
break;
@@ -547,8 +550,6 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
}
case SC_FUNCTION:
{
- if (object_id == 0)
- return "FUNCTION";
struct func *func = func_by_id(object_id);
if (func == NULL)
break;
@@ -556,8 +557,6 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
}
case SC_SEQUENCE:
{
- if (object_id == 0)
- return "SEQUENCE";
struct sequence *seq = sequence_by_id(object_id);
if (seq == NULL)
break;
diff --git a/src/box/schema.h b/src/box/schema.h
index 0822262d0..f1735ff34 100644
--- a/src/box/schema.h
+++ b/src/box/schema.h
@@ -250,16 +250,19 @@ static inline
struct access *
entity_access_get(enum schema_object_type type)
{
- switch (type) {
- case SC_SPACE:
- return entity_access.space;
- case SC_FUNCTION:
- return entity_access.function;
- case SC_SEQUENCE:
- return entity_access.sequence;
- default:
- return NULL;
- }
+ switch (type) {
+ case SC_SPACE:
+ case SC_ENTITY_SPACE:
+ return entity_access.space;
+ case SC_FUNCTION:
+ case SC_ENTITY_FUNCTION:
+ return entity_access.function;
+ case SC_SEQUENCE:
+ case SC_ENTITY_SEQUENCE:
+ return entity_access.sequence;
+ default:
+ return NULL;
+ }
}
#endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */
diff --git a/src/box/schema_def.c b/src/box/schema_def.c
index 97c074ab2..bbae046c3 100644
--- a/src/box/schema_def.c
+++ b/src/box/schema_def.c
@@ -41,6 +41,13 @@ static const char *object_type_strs[] = {
/* [SC_COLLATION] = */ "collation",
};
+enum schema_object_type
+schema_entity_type(enum schema_object_type type)
+{
+ assert((int) type < (int) schema_object_type_MAX);
+ return type + schema_object_type_MAX - 1;
+}
+
enum schema_object_type
schema_object_type(const char *name)
{
diff --git a/src/box/schema_def.h b/src/box/schema_def.h
index 2edb8d37f..5ece809f1 100644
--- a/src/box/schema_def.h
+++ b/src/box/schema_def.h
@@ -218,6 +218,10 @@ enum {
*
* Use 0 for unknown to use the same index consistently
* even when there are more object types in the future.
+ *
+ * When adding new types please keep the
+ * same order between objects and corresponding entity types.
+ * schema_entity_type() relies on this convention.
*/
enum schema_object_type {
SC_UNKNOWN = 0,
@@ -228,9 +232,21 @@ enum schema_object_type {
SC_ROLE = 5,
SC_SEQUENCE = 6,
SC_COLLATION = 7,
- schema_object_type_MAX = 8
+ schema_object_type_MAX = 8,
+ SC_ENTITY_SPACE,
+ SC_ENTITY_FUNCTION,
+ SC_ENTITY_USER,
+ SC_ENTITY_ROLE,
+ SC_ENTITY_SEQUENCE,
+ SC_ENTITY_COLLATION
};
+/**
+ * Given a object type, return an entity type it belongs to.
+ */
+enum schema_object_type
+schema_entity_type(enum schema_object_type type);
+
enum schema_object_type
schema_object_type(const char *name);
diff --git a/src/box/user.cc b/src/box/user.cc
index fbf06566a..eec785652 100644
--- a/src/box/user.cc
+++ b/src/box/user.cc
@@ -207,12 +207,23 @@ access_find(struct priv_def *priv)
access = universe.access;
break;
}
+ case SC_ENTITY_SPACE:
+ {
+ access = entity_access.space;
+ break;
+ }
+ case SC_ENTITY_FUNCTION:
+ {
+ access = entity_access.function;
+ break;
+ }
+ case SC_ENTITY_SEQUENCE:
+ {
+ access = entity_access.sequence;
+ break;
+ }
case SC_SPACE:
{
- if (priv->object_id == 0) {
- access = entity_access.space;
- break;
- }
struct space *space = space_by_id(priv->object_id);
if (space)
access = space->access;
@@ -220,10 +231,6 @@ access_find(struct priv_def *priv)
}
case SC_FUNCTION:
{
- if (priv->object_id == 0) {
- access = entity_access.function;
- break;
- }
struct func *func = func_by_id(priv->object_id);
if (func)
access = func->access;
@@ -231,10 +238,6 @@ access_find(struct priv_def *priv)
}
case SC_SEQUENCE:
{
- if (priv->object_id == 0) {
- access = entity_access.sequence;
- break;
- }
struct sequence *seq = sequence_by_id(priv->object_id);
if (seq)
access = seq->access;
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index 16c2027cf..cf8242de5 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -5,7 +5,7 @@ box.space._schema:select{}
---
- - ['cluster', '<cluster uuid>']
- ['max_id', 511]
- - ['version', 1, 10, 0]
+ - ['version', 1, 10, 2]
...
box.space._cluster:select{}
---
@@ -58,10 +58,10 @@ box.space._space:select{}
'type': 'string'}, {'name': 'auth', 'type': 'map'}]]
- [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {
'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
- {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]
+ {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
- [313, 1, '_vpriv', 'sysview', 0, {}, [{'name': 'grantor', 'type': 'unsigned'},
{'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
- {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]
+ {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
- [320, 1, '_cluster', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'uuid',
'type': 'string'}]]
- [330, 1, '_truncate', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'count',
@@ -104,13 +104,13 @@ box.space._index:select{}
- [305, 1, 'owner', 'tree', {'unique': false}, [[1, 'unsigned']]]
- [305, 2, 'name', 'tree', {'unique': true}, [[2, 'string']]]
- [312, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],
- [3, 'unsigned']]]
+ [3, 'scalar']]]
- [312, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]
- - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]
+ - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]
- [313, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],
- [3, 'unsigned']]]
+ [3, 'scalar']]]
- [313, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]
- - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]
+ - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]
- [320, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
- [320, 1, 'uuid', 'tree', {'unique': true}, [[1, 'string']]]
- [330, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
diff --git a/test/box/access.result b/test/box/access.result
index f4669a4a3..599500633 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -504,7 +504,7 @@ box.space._priv:select{id}
...
box.schema.user.grant('user', 'read', 'universe')
---
-- error: User 'user' already has read access on universe 'nil'
+- error: User 'user' already has read access on universe ''
...
box.space._priv:select{id}
---
@@ -690,7 +690,7 @@ box.schema.user.grant('guest', 'read,write,execute', 'universe')
...
box.schema.user.grant('guest', 'read,write,execute', 'universe')
---
-- error: User 'guest' already has read,write,execute access on universe 'nil'
+- error: User 'guest' already has read,write,execute access on universe ''
...
box.schema.user.grant('guest', 'read,write,execute', 'universe', '', { if_not_exists = true })
---
@@ -703,7 +703,7 @@ box.schema.user.revoke('guest', 'usage,session', 'universe')
...
box.schema.user.revoke('guest', 'read,write,execute', 'universe')
---
-- error: User 'guest' does not have read,write,execute access on universe 'nil'
+- error: User 'guest' does not have read,write,execute access on universe ''
...
box.schema.user.revoke('guest', 'read,write,execute', 'universe', '', { if_exists = true })
---
diff --git a/test/box/access_misc.result b/test/box/access_misc.result
index 2d87fa2d5..3061f1181 100644
--- a/test/box/access_misc.result
+++ b/test/box/access_misc.result
@@ -436,7 +436,7 @@ box.schema.user.revoke('testuser', 'usage,session', 'universe')
...
box.schema.user.revoke('testuser', 'read, write, execute', 'universe')
---
-- error: User 'testuser' does not have read, write, execute access on universe 'nil'
+- error: User 'testuser' does not have read, write, execute access on universe ''
...
box.schema.user.revoke('testuser', 'create', 'universe')
---
@@ -797,10 +797,10 @@ box.space._space:select()
'type': 'string'}, {'name': 'auth', 'type': 'map'}]]
- [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {
'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
- {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]
+ {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
- [313, 1, '_vpriv', 'sysview', 0, {}, [{'name': 'grantor', 'type': 'unsigned'},
{'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
- {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]
+ {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
- [320, 1, '_cluster', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'uuid',
'type': 'string'}]]
- [330, 1, '_truncate', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'count',
@@ -853,7 +853,7 @@ box.schema.user.grant('tester', 'read', 'universe')
-- error: the privilege is not granted
box.schema.user.revoke('tester', 'create', 'universe')
---
-- error: User 'tester' does not have create access on universe 'nil'
+- error: User 'tester' does not have create access on universe ''
...
-- no error: if_exists clause
box.schema.user.revoke('tester', 'create', 'universe', nil, { if_exists = true })
diff --git a/test/box/alter.result b/test/box/alter.result
index eb7014d8b..36bdb5fd3 100644
--- a/test/box/alter.result
+++ b/test/box/alter.result
@@ -214,13 +214,13 @@ _index:select{}
- [305, 1, 'owner', 'tree', {'unique': false}, [[1, 'unsigned']]]
- [305, 2, 'name', 'tree', {'unique': true}, [[2, 'string']]]
- [312, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],
- [3, 'unsigned']]]
+ [3, 'scalar']]]
- [312, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]
- - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]
+ - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]
- [313, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],
- [3, 'unsigned']]]
+ [3, 'scalar']]]
- [313, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]
- - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]
+ - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]
- [320, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
- [320, 1, 'uuid', 'tree', {'unique': true}, [[1, 'string']]]
- [330, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
diff --git a/test/xlog/upgrade.result b/test/xlog/upgrade.result
index f02996bba..76467baf1 100644
--- a/test/xlog/upgrade.result
+++ b/test/xlog/upgrade.result
@@ -36,7 +36,7 @@ box.space._schema:select()
---
- - ['cluster', '<server_uuid>']
- ['max_id', 513]
- - ['version', 1, 10, 0]
+ - ['version', 1, 10, 2]
...
box.space._space:select()
---
@@ -85,10 +85,10 @@ box.space._space:select()
'type': 'string'}, {'name': 'auth', 'type': 'map'}]]
- [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {
'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
- {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]
+ {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
- [313, 1, '_vpriv', 'sysview', 0, {}, [{'name': 'grantor', 'type': 'unsigned'},
{'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
- {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]
+ {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
- [320, 1, '_cluster', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'uuid',
'type': 'string'}]]
- [330, 1, '_truncate', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'count',
@@ -134,13 +134,13 @@ box.space._index:select()
- [305, 1, 'owner', 'tree', {'unique': false}, [[1, 'unsigned']]]
- [305, 2, 'name', 'tree', {'unique': true}, [[2, 'string']]]
- [312, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],
- [3, 'unsigned']]]
+ [3, 'scalar']]]
- [312, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]
- - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]
+ - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]
- [313, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],
- [3, 'unsigned']]]
+ [3, 'scalar']]]
- [313, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]
- - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]
+ - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]
- [320, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
- [320, 1, 'uuid', 'tree', {'unique': true}, [[1, 'string']]]
- [330, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
--
2.15.2 (Apple Git-101.1)
More information about the Tarantool-patches
mailing list