From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 11.5 \(3445.9.1\)) Subject: Re: [PATCH v2 1/4] Introduce separate entity object types for entity privileges. From: Serge Petrenko In-Reply-To: <6d03b3dad54d482d419fa4e61c35f37676a04da0.1534944662.git.sergepetrenko@tarantool.org> Date: Wed, 22 Aug 2018 18:42:07 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <34DD46B3-6FB8-423F-9FEC-AB47211C2FF8@tarantool.org> References: <6d03b3dad54d482d419fa4e61c35f37676a04da0.1534944662.git.sergepetrenko@tarantool.org> To: Vladimir Davydov Cc: kostja@tarantool.org, tarantool-patches@freelists.org List-ID: Sorry, forgot one minor change in priv_def_check(). No need to check for = object_id 0 here anymore. Here=E2=80=99s everything that=E2=80=99s changed. @@ -2583,10 +2623,8 @@ priv_def_check(struct priv_def *priv, enum = priv_type priv_type) break; case SC_SPACE: { - struct space *space =3D NULL; - if (priv->object_id !=3D 0) - space =3D space_cache_find_xc(priv->object_id); - if ((space =3D=3D NULL || space->def->uid !=3D = grantor->def->uid) && + struct space *space =3D = space_cache_find_xc(priv->object_id); + if (space->def->uid !=3D grantor->def->uid && grantor->def->uid !=3D ADMIN) { tnt_raise(AccessDeniedError, priv_name(priv_type), @@ -2597,10 +2635,8 @@ priv_def_check(struct priv_def *priv, enum = priv_type priv_type) } case SC_FUNCTION: { - struct func *func =3D NULL; - if (priv->object_id !=3D 0) - func =3D func_cache_find(priv->object_id); - if ((func =3D=3D NULL || func->def->uid !=3D = grantor->def->uid) && + struct func *func =3D func_cache_find(priv->object_id); + if (func->def->uid !=3D grantor->def->uid && grantor->def->uid !=3D ADMIN) { tnt_raise(AccessDeniedError, priv_name(priv_type), @@ -2611,10 +2647,8 @@ priv_def_check(struct priv_def *priv, enum = priv_type priv_type) } case SC_SEQUENCE: { - struct sequence *seq =3D NULL; - if (priv->object_id !=3D 0) - seq =3D sequence_cache_find(priv->object_id); - if ((seq =3D=3D NULL || seq->def->uid !=3D = grantor->def->uid) && + struct sequence *seq =3D = sequence_cache_find(priv->object_id); + if (seq->def->uid !=3D grantor->def->uid && grantor->def->uid !=3D ADMIN) { tnt_raise(AccessDeniedError, priv_name(priv_type), > 22 =D0=B0=D0=B2=D0=B3. 2018 =D0=B3., =D0=B2 16:39, Serge Petrenko = =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB(=D0= =B0): >=20 > When granting or revoking a privilege on an entire entity, id 0 was = used > to indicate the fact that we don't grant a privilege on a single = object, > but on a whole entity. This caused confusion, because for entity USER, > for example, id 0 is a valid object id (user 'guest' uses it). > Any non-zero id dedicated to this cause obviously may be confused as = well. > Fix this by creating separate schema_object_types for entities: > SC_ENTITY_SPACE, SC_ENTITY_SEQUENCE, etc. >=20 > Closes: #3574 > Prerequisite: #3524 > --- > src/box/alter.cc | 39 ++++++++++++++++++++++++++++- > src/box/bootstrap.snap | Bin 1540 -> 1556 bytes > src/box/lua/schema.lua | 58 = ++++++++++++++++++++++++++----------------- > src/box/lua/upgrade.lua | 23 +++++++++++++++++ > src/box/schema.cc | 9 +++---- > src/box/schema.h | 23 +++++++++-------- > src/box/schema_def.c | 17 +++++++++++++ > src/box/schema_def.h | 16 +++++++++++- > 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, 184 insertions(+), 78 deletions(-) >=20 > diff --git a/src/box/alter.cc b/src/box/alter.cc > index 3007a131d..8eba21a51 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 =3D tuple_field_u32_xc(tuple, = BOX_PRIV_FIELD_ID); > priv->grantee_id =3D tuple_field_u32_xc(tuple, = BOX_PRIV_FIELD_UID); > + > const char *object_type =3D > tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_TYPE); > - priv->object_id =3D tuple_field_u32_xc(tuple, = BOX_PRIV_FIELD_OBJECT_ID); > priv->object_type =3D schema_object_type(object_type); > + > + const char *data =3D tuple_field(tuple, = BOX_PRIV_FIELD_OBJECT_ID); > + if (data =3D=3D 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) =3D=3D 0) { > + /* Entity-wide privilege. */ > + priv->object_id =3D 0; > + priv->object_type =3D = schema_entity_type(priv->object_type); > + break; > + } > + FALLTHROUGH; > + default: > + priv->object_id =3D tuple_field_u32_xc(tuple, > + = BOX_PRIV_FIELD_OBJECT_ID); > + } > if (priv->object_type =3D=3D SC_UNKNOWN) { > tnt_raise(ClientError, ER_UNKNOWN_SCHEMA_OBJECT, > object_type); > @@ -2645,6 +2670,18 @@ priv_def_check(struct priv_def *priv, enum = priv_type priv_type) > } > /* Not necessary to do during revoke, but who cares. */ > role_check(grantee, role); > + break; > + } > + case SC_ENTITY_SPACE: > + case SC_ENTITY_FUNCTION: > + case SC_ENTITY_SEQUENCE: > + { > + /* Only admin may grant privileges on an entire entity. = */ > + if (grantor->def->uid !=3D ADMIN) { > + tnt_raise(AccessDeniedError, = priv_name(priv_type), > + schema_object_name(priv->object_type), = name, > + grantor->def->name); > + } > } > default: > break; > diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap > index = b610828c9c9ae9a22acdd8c150c16c6838b7a273..44992b050e9d73d69608fb92782d1e96= 5f6cdc51 100644 > GIT binary patch > delta 1551 > zcmV+q2JrcW43rFz7=3DJM>GB!9ZXE|m$WMeloGhzx!ZgX^DZewLSAT%>EG&o@}VJ$c{ > zGcheRV>UP~VPZ03EipATVq!NoIX7cCWeQe9Y;R+0Iv{&}3JTS_3%bn(nE=3Dk-$Bkd5 > z0000004TLD{QyvfEC41w*hV;#?6&k&og$Aul zv3Dv(N-{sS_S_R$=3DIf$P=3DIFJ-Qc5dSF3)wMv;i7#PyNg>UnEmX0mA^f0L=3Dio5sT!g= > zD{Fnf#vxPKYgy*n?1AMVIy{=3Dp9gia^hC=3DL0fWLuz8rC_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 zn_;zHClt(+{hgbmxU+pKw$>&pI!j zQ473V(OEa~Z9g}|)Sgs&h}w*uq0W{Rc( z%Yh$fD8!Boc(5ZV > zdG3dP6Mx6^(8sb6!1;Xg8sDAa&WZ-$y>W_Zn~dpXc#Nf8o1_@R#?P@Ion`uUK3>En > z4|O&qz`GSKF%8FiNe275855I3zK&RX`$!^s> z-HLiP9v};~La9)x)67Zcgesj%8+J-DBoj%4cYiCoL(1@BuzjT$lI`Wf$ik??2xi9d > ztc3#01eTBGMdTtHiCXRru~^$q5*v~bieRnCyA@ptRojk|H*sWb>UR9^o~tSri06BO > z0Q-*j>z9Q*4+(#G7_m1GyjxLQ$D%fO4}ENn1MgPUw1qv^wQ}ZNwi zM}I7Goln@sxA7u>0uPF;){6CdrBo=3D>OXh`5;7UxHP%|pfgijbup=3DMGrPps{8(Quhz > zWw^YXTN9%N1NEZh;%hNtVMQxeEKqt?SWV_GYBSbz?d=3D0?f`WpY*c$IvG*qAOKeIM_ > zQh2wbDYx3&2cp ztgP{o#>Rx0;YE$dsj=3Dv%(gx?x*@*;&XWUfcndq})KR0uozbQ*?y?v(<-mNH&3>7#_ > z#&nJefg`BVSY%8M%m4s@04M+v21hAoRSyz?&^U^NFbZH021E!rh)xs$fZ#w_L4OfM > zEf@qq49vQeA))6t$8JsxhygJm2AP2;6jR1Ytzq>yuq)+j_YBuXSm^>oOc44oRR2+r > zfKn$8@9xdDJsnXgj8fvJX-OOEnOz2N82f7Vr6^tAcX*WFIPM{0Ntj!pLMS~2mv!oE > zRrM)J%oMN{r_N{V(s7_ah4$kjihs$6 zPC$*u2HNnREZ$rv)082si4@Jx$$z3_Ifq*d0kp^Vv;;5qa1a|JkDvz!Y7ZzgZLtTG > znKqel_G}Nk_kmTD8UY2Zw|;97AY4LmR2{?0eUDLb#Sq+kdJS#-4;^$U>3_%%=3D)mhn > z2W|IQc+vMG<^-d?>WOsJ?wF5DwFGHVZ;5{eV6!P9un202v z|B3!R7$^i;Ur3=3D7lANu}q6eAjK|>w!Z8R4d19B91M{)$#!E>qp7jG6HO>MyhU^@4T > z^f(MLmIX$FanP|HqB(=3D3bAPgI29$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=3DYgngs1QB1+=3Dm<%o!R6Hut?jEW > B)aL*I >=20 > delta 1534 > zcmVdT4F*z~{Np5p=3DVQyn(Iv_b=3DV_`LAF*YqTV`g= S8 > zG-hTvEnzrjFfCy?W;Qf4VP!dGGGq!?Lu_wjYdRo%F*+bOeF_TIx(m9^1&9F7A|rpb > zr2qf`001bpFZ}>e{VM z)F3;RA|;uhw(`4WgTRw>I&<{eU?~Ai$VOI~v629dx2JaIm@kx4N&&zCxB$xlBK}6v > zM#}nreKVfmYggvF>;bcooE<&pjzw|&ydgCd;B)Xi4C|Up=3DiRyONm;Mu=3D 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 zOU+j=3DF>OCDy|bcHe0;hLW1g*=3D6kJQqvOo9n=3D`!@rT1v3PA=3DsEaGtUmrgF1V*+Hw= F$ > 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=3DWn_TxWHa?e&p > z0 zEj90~M>ms_NyVg8C=3DMtXRLX=3DhZO}2jlujiL*MCw|r<8%iFyl-urCG}bk_A!)lFN(Z > z*9rxd2`ZdQ%ZOz}8m(9>QmHeYBvm9q6rtA9wbTrW=3DuAh+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=3D^i zX2ppwLyQ}LBXiMF z(OhIq3CsWhfB+}}AqGb&Wl77Rj$ynhqj > zxeG%W18Ui|uoin^FOJH&6BE> zB`AQ$m7GU4)NS@llAFhZ>1-;h#Us!zr2@yPWOP}$xk=3D>TS*Ej6Q8ZgBx&}sXh}Wym > z;Yvs=3DXm6s&oTIkS5VXc28)t^2+kc4qR4r1#;*gdpU~^0s$pG8pm?G)gVGer7p5*j@ > zrQSOro_cGm&fR}<@b8h^=3DiXW!%4reE=3DRqJFW z1)jmCmtK6UOn@l~=3DHxoFllhK1;>sqt`1BcS0HC@As3ba#z^Ko9Pi8avYk$Oa!!S#& > zSx3_!A8xyrpfT#3Y0zk_Hi}Y>p%$pI61F+5M3N&%2xKJAC;$CDD}<6?=3D$#5uoTZ5Z > zCNj}EgB|fKv=3D$L@ag>MEJ_76DnN*W1Z`O`MZ9ptwx|K1yxMV1V1(Ltx%(4y7obk4E > zW?=3D^8GIQ=3Dkv4A0`wS7N1*>`Z!opukPx!_g@c{8|RJi<`!QS!z#<&+X#nnV8V6uo^% > zFL^|hfwSZ-+|LAZ&d5i?Zt>-$tMH_1UnT!Yb{@SussOv@WfJ50JyfLCQd9Bw_N-dh > k2=3DV>Mm|$S01}gnuSl5OyKJnJxL~`9Mur5?adb1g8%>k >=20 > 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 >=20 > local function object_resolve(object_type, object_name) > + if object_name ~=3D nil and type(object_name) ~=3D 'string' > + and type(object_name) ~=3D 'number' then > + box.error(box.error.ILLEGAL_PARAMS, "wrong object name type") > + end > if object_type =3D=3D 'universe' then > - if object_name ~=3D nil and type(object_name) ~=3D 'string' > - and type(object_name) ~=3D 'number' then > - box.error(box.error.ILLEGAL_PARAMS, "wrong object name = type") > - end > return 0 > end > if object_type =3D=3D 'space' then > - if object_name =3D=3D nil or object_name =3D=3D 0 then > - return 0 > + if object_name =3D=3D '' then > + return '' > end > local space =3D box.space[object_name] > if space =3D=3D nil then > @@ -1819,8 +1819,8 @@ local function object_resolve(object_type, = object_name) > return space.id > end > if object_type =3D=3D 'function' then > - if object_name =3D=3D nil or object_name =3D=3D 0 then > - return 0 > + if object_name =3D=3D '' then > + return '' > end > local _vfunc =3D 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 =3D=3D 'sequence' then > - if object_name =3D=3D nil or object_name =3D=3D 0 then > - return 0 > + if object_name =3D=3D '' then > + return '' > end > local seq =3D sequence_resolve(object_name) > if seq =3D=3D nil then > @@ -1864,7 +1864,7 @@ local function object_resolve(object_type, = object_name) > end >=20 > local function object_name(object_type, object_id) > - if object_type =3D=3D 'universe' then > + if object_type =3D=3D 'universe' or object_id =3D=3D '' then > return "" > end > local space > @@ -2072,12 +2072,18 @@ local function grant(uid, name, privilege, = object_type, > object_name, options) > -- =46rom user point of view, role is the same thing > -- as a privilege. Allow syntax grant(user, role). > - if object_name =3D=3D nil and object_type =3D=3D nil then > - -- sic: avoid recursion, to not bother with roles > - -- named 'execute' > - object_type =3D 'role' > - object_name =3D privilege > - privilege =3D 'execute' > + if object_name =3D=3D nil then > + if object_type =3D=3D nil then > + -- sic: avoid recursion, to not bother with roles > + -- named 'execute' > + object_type =3D 'role' > + object_name =3D privilege > + privilege =3D 'execute' > + else > + -- Allow syntax grant(user, priv, entity) > + -- for entity grants. > + object_name =3D '' > + end > end > local privilege_hex =3D privilege_check(privilege, object_type) >=20 > @@ -2117,10 +2123,16 @@ end > local function revoke(uid, name, privilege, object_type, object_name, = options) > -- =46rom user point of view, role is the same thing > -- as a privilege. Allow syntax revoke(user, role). > - if object_name =3D=3D nil and object_type =3D=3D nil then > - object_type =3D 'role' > - object_name =3D privilege > - privilege =3D 'execute' > + if object_name =3D=3D nil then > + if object_type =3D=3D nil then > + object_type =3D 'role' > + object_name =3D privilege > + privilege =3D 'execute' > + else > + -- Allow syntax revoke(user, privilege, entity) > + -- to revoke entity privileges. > + object_name =3D '' > + end > end > local privilege_hex =3D privilege_check(privilege, object_type) > options =3D options or {} > @@ -2192,8 +2204,8 @@ local function drop(uid, opts) > local privs =3D _vpriv.index.primary:select{uid} >=20 > 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..ec3826399 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 >=20 > = +-------------------------------------------------------------------------= ------- > +--- Tarantool 1.10.2 > = +-------------------------------------------------------------------------= ------- > +local function upgrade_priv_to_1_10_2() > + local _priv =3D box.space._priv > + local _vpriv =3D box.space._vpriv > + local format =3D _priv:format() > + > + format[4].type =3D 'scalar' > + _priv:format(format) > + format =3D _vpriv:format() > + format[4].type =3D 'scalar' > + _vpriv:format(format) > + _priv.index.primary:alter{parts=3D{2, 'unsigned', 3, 'string', 4, = 'scalar'}} > + _vpriv.index.primary:alter{parts=3D{2, 'unsigned', 3, 'string', = 4, 'scalar'}} > + _priv.index.object:alter{parts=3D{3, 'string', 4, 'scalar'}} > + _vpriv.index.object:alter{parts=3D{3, 'string', 4, 'scalar'}} > +end > + > +local function upgrade_to_1_10_2() > + upgrade_priv_to_1_10_2() > +end >=20 > local function get_version() > local version =3D box.space._schema:get{'version'} > @@ -991,6 +1013,7 @@ local function upgrade(options) > {version =3D mkversion(1, 7, 6), func =3D upgrade_to_1_7_6, = auto =3D false}, > {version =3D mkversion(1, 7, 7), func =3D upgrade_to_1_7_7, = auto =3D true}, > {version =3D mkversion(1, 10, 0), func =3D upgrade_to_1_10_0, = auto =3D true}, > + {version =3D mkversion(1, 10, 2), func =3D upgrade_to_1_10_2, = auto =3D true}, > } >=20 > for _, handler in ipairs(handlers) do > diff --git a/src/box/schema.cc b/src/box/schema.cc > index 433f52c08..aaa63a083 100644 > --- a/src/box/schema.cc > +++ b/src/box/schema.cc > @@ -535,11 +535,12 @@ 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: > return ""; > case SC_SPACE: > { > - if (object_id =3D=3D 0) > - return "SPACE"; > struct space *space =3D space_by_id(object_id); > if (space =3D=3D NULL) > break; > @@ -547,8 +548,6 @@ schema_find_name(enum schema_object_type type, = uint32_t object_id) > } > case SC_FUNCTION: > { > - if (object_id =3D=3D 0) > - return "FUNCTION"; > struct func *func =3D func_by_id(object_id); > if (func =3D=3D NULL) > break; > @@ -556,8 +555,6 @@ schema_find_name(enum schema_object_type type, = uint32_t object_id) > } > case SC_SEQUENCE: > { > - if (object_id =3D=3D 0) > - return "SEQUENCE"; > struct sequence *seq =3D = sequence_by_id(object_id); > if (seq =3D=3D 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; > + } > } >=20 > #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */ > diff --git a/src/box/schema_def.c b/src/box/schema_def.c > index 97c074ab2..9091af054 100644 > --- a/src/box/schema_def.c > +++ b/src/box/schema_def.c > @@ -41,6 +41,23 @@ static const char *object_type_strs[] =3D { > /* [SC_COLLATION] =3D */ "collation", > }; >=20 > +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; > + case SC_SEQUENCE: > + return SC_ENTITY_SEQUENCE; > + case SC_COLLATION: > + return SC_ENTITY_COLLATION; > + default: > + return SC_UNKNOWN; > + } > +} > + > 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..d2fc39b76 100644 > --- a/src/box/schema_def.h > +++ b/src/box/schema_def.h > @@ -228,9 +228,23 @@ enum schema_object_type { > SC_ROLE =3D 5, > SC_SEQUENCE =3D 6, > SC_COLLATION =3D 7, > - schema_object_type_MAX =3D 8 > + /* > + * All object types are supposed to be above this point, > + * all entity types - below. > + */ > + schema_object_type_MAX =3D 8, > + SC_ENTITY_SPACE, > + SC_ENTITY_FUNCTION, > + SC_ENTITY_SEQUENCE, > + SC_ENTITY_COLLATION > }; >=20 > +/** > + * 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); >=20 > 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 =3D universe.access; > break; > } > + case SC_ENTITY_SPACE: > + { > + access =3D entity_access.space; > + break; > + } > + case SC_ENTITY_FUNCTION: > + { > + access =3D entity_access.function; > + break; > + } > + case SC_ENTITY_SEQUENCE: > + { > + access =3D entity_access.sequence; > + break; > + } > case SC_SPACE: > { > - if (priv->object_id =3D=3D 0) { > - access =3D entity_access.space; > - break; > - } > struct space *space =3D space_by_id(priv->object_id); > if (space) > access =3D space->access; > @@ -220,10 +231,6 @@ access_find(struct priv_def *priv) > } > case SC_FUNCTION: > { > - if (priv->object_id =3D=3D 0) { > - access =3D entity_access.function; > - break; > - } > struct func *func =3D func_by_id(priv->object_id); > if (func) > access =3D func->access; > @@ -231,10 +238,6 @@ access_find(struct priv_def *priv) > } > case SC_SEQUENCE: > { > - if (priv->object_id =3D=3D 0) { > - access =3D entity_access.sequence; > - break; > - } > struct sequence *seq =3D = sequence_by_id(priv->object_id); > if (seq) > access =3D 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', ''] > - ['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 =3D 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 =3D 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 =3D 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', ''] > - ['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']]] > --=20 > 2.15.2 (Apple Git-101.1) >=20