diff --git a/src/box/access.h b/src/box/access.h index ad53e9165230fc688572d1647093ba5f846714e1..9ee84785ac87f74b481970e751190526c3f46ea5 100644 --- a/src/box/access.h +++ b/src/box/access.h @@ -150,4 +150,17 @@ user_cache_init(); void user_cache_free(); +/** + * This is a clutch until there is a proper index in + * _priv space to look up by space id + */ +static inline bool +object_has_grants(uint8_t *access) +{ + for (int i = 0; i < BOX_USER_MAX; i++) + if (access[i]) + return true; + return false; +} + #endif /* INCLUDES_TARANTOOL_BOX_ACCESS_H */ diff --git a/src/box/alter.cc b/src/box/alter.cc index c702bc3ee8b6631b14c094915a51d8a948c3dfef..af6ee4cee813d56609c01e1cafcfadadd4b1196a 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -990,6 +990,11 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event) (unsigned) space_id(old_space), "the space has indexes"); } + if (object_has_grants(old_space->access)) { + tnt_raise(ClientError, ER_DROP_SPACE, + (unsigned) space_id(old_space), + "the space has grants"); + } /* @todo lock space metadata until commit. */ /* * dd_space_delete() can't fail, any such @@ -1268,6 +1273,8 @@ func_def_create_from_tuple(struct func_def *func, struct tuple *tuple) name, "function name is too long"); } snprintf(func->name, sizeof(func->name), "%s", name); + /** Nobody has access to the function but the owner. */ + memset(func->access, 0, sizeof(func->access)); } /** Remove a function from function cache */ @@ -1322,7 +1329,12 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event) * who created it or a superuser. */ access_check_ddl(func.uid); - /* @todo can only delete func if it has no grants */ + /* Can only delete func if it has no grants. */ + if (object_has_grants(old_func->access)) { + tnt_raise(ClientError, ER_DROP_FUNCTION, + (unsigned) func.uid, + "function has grants"); + } trigger_set(&txn->on_commit, &drop_func_trigger); } else { /* UPDATE, REPLACE */ func_def_create_from_tuple(&func, new_tuple); diff --git a/src/box/log_io.cc b/src/box/log_io.cc index b4268803b2ca03241e1e11c24844b99cd6045a34..297c052bfbca4f71ae3b65cd73af30c195ea953e 100644 --- a/src/box/log_io.cc +++ b/src/box/log_io.cc @@ -98,7 +98,8 @@ rb_gen(, log_dir_lsnmap_, log_dir_lsnmap_t, struct log_meta_lsn, link, #include "salad/mhash.h" int -log_dir_create(struct log_dir *dir) +log_dir_create(struct log_dir *dir, const char *dirname, + enum log_dir_type type) { memset(dir, 0, sizeof(*dir)); dir->nodeids = mh_nodeids_new(); @@ -106,6 +107,21 @@ log_dir_create(struct log_dir *dir) return -1; log_dir_map_new(&dir->map); log_dir_lsnmap_new(&dir->lsnmap); + /* Default mode. */ + dir->mode = 0660; + dir->dirname = strdup(dirname); + if (type == SNAP) { + strcpy(dir->open_wflags, "wxd"); + dir->filetype = "SNAP\n"; + dir->filename_ext = ".snap"; + dir->ignore_initial_setlsn = true; + dir->panic_if_error = true; + } else { + strcpy(dir->open_wflags, "wx"); + dir->sync_is_async = true; + dir->filetype = "XLOG\n"; + dir->filename_ext = ".xlog"; + } return 0; } diff --git a/src/box/log_io.h b/src/box/log_io.h index 03aea9d641af3590db2bf69d3a017f05df51b22d..6ab3244d5994a2ce2690f18546a5d9a9eab35b12 100644 --- a/src/box/log_io.h +++ b/src/box/log_io.h @@ -39,6 +39,11 @@ extern const uint32_t xlog_format; +enum log_dir_type { + SNAP, + XLOG +}; + enum log_mode { LOG_READ, LOG_WRITE @@ -113,7 +118,8 @@ struct log_dir { }; int -log_dir_create(struct log_dir *dir); +log_dir_create(struct log_dir *dir, const char *dirname, + enum log_dir_type type); void log_dir_destroy(struct log_dir *dir); diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index e3929413ac0bae359263ef07c73713cb6b00fc8a..2ee73e1b314990ec781c54f2949d7713042016fc 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -105,11 +105,18 @@ box.schema.create_space = box.schema.space.create box.schema.space.drop = function(space_id) local _space = box.space[box.schema.SPACE_ID] local _index = box.space[box.schema.INDEX_ID] + local _priv = box.space[box.schema.PRIV_ID] local keys = _index:select(space_id) for i = #keys, 1, -1 do local v = keys[i] _index:delete{v[0], v[1]} end + local privs = _priv:select{} + for k, tuple in pairs(privs) do + if tuple[2] == 'space' and tuple[3] == space_id then + box.schema.user.revoke(tuple[1], tuple[4], tuple[2], tuple[3]) + end + end if _space:delete{space_id} == nil then box.raise(box.error.NO_SUCH_SPACE, "Space "..space_id.." does not exist") @@ -323,7 +330,9 @@ function box.schema.space.bless(space) elseif box.index[opts.iterator] then itype = box.index[opts.iterator] elseif opts.iterator ~= nil then - error("Wrong iterator type: "..tostring(opts.iterator)) + box.raise(box.error.ITERATOR_TYPE, + "Unknown iterator type '".. + tostring(opts.iterator).."'") end end @@ -645,7 +654,14 @@ end box.schema.func.drop = function(name) local _func = box.space[box.schema.FUNC_ID] + local _priv = box.space[box.schema.PRIV_ID] local fid = object_resolve('function', name) + local privs = _priv:select{} + for k, tuple in pairs(privs) do + if tuple[2] == 'function' and tuple[3] == function_id then + box.schema.user.revoke(tuple[1], tuple[4], tuple[2], tuple[3]) + end + end _func:delete{fid} end @@ -700,7 +716,7 @@ box.schema.user.drop = function(name) box.space[tuple[0]]:drop() end local funcs = box.space[box.schema.FUNC_ID].index['owner']:select{uid} - for k, tuple in pairs(spaces) do + for k, tuple in pairs(funcs) do box.schema.func.drop(tuple[0]) end box.space[box.schema.USER_ID]:delete{uid} diff --git a/src/box/recovery.cc b/src/box/recovery.cc index c495a8262d54c9bee9dea81c0f02dc9bb3bec8d0..e833308ff39ee64ba0633bdb1ad5b87fefbc5b03 100644 --- a/src/box/recovery.cc +++ b/src/box/recovery.cc @@ -184,28 +184,13 @@ recovery_init(const char *snap_dirname, const char *wal_dirname, r->snapshot_handler = snapshot_handler; r->join_handler = join_handler; - log_dir_create(&r->snap_dir); - r->snap_dir.panic_if_error = false; - r->snap_dir.sync_is_async = false; - strcpy(r->snap_dir.open_wflags, "wxd"); - r->snap_dir.filetype = "SNAP\n"; - r->snap_dir.filename_ext = ".snap"; - r->snap_dir.dirname = strdup(snap_dirname); - r->snap_dir.mode = 0660; - r->snap_dir.ignore_initial_setlsn = true; - - log_dir_create(&r->wal_dir); - r->wal_dir.panic_if_error = false; - r->wal_dir.sync_is_async = true; - strcpy(r->wal_dir.open_wflags, "wx"); - r->wal_dir.filetype = "XLOG\n"; - r->wal_dir.filename_ext = ".xlog"; - r->wal_dir.dirname = strdup(wal_dirname); - r->wal_dir.mode = 0660; - - if (r->wal_mode == WAL_FSYNC) { + log_dir_create(&r->snap_dir, snap_dirname, SNAP); + + log_dir_create(&r->wal_dir, wal_dirname, XLOG); + + if (r->wal_mode == WAL_FSYNC) (void) strcat(r->wal_dir.open_wflags, "s"); - } + r->rows_per_wal = rows_per_wal; vclock_create(&r->vclock); diff --git a/src/cfg.cc b/src/cfg.cc index 25a5f10f250622cf6f8ecd240cf6f62491929810..4e01437ac4a218e00301101c1aeab6db0ca4a6fa 100644 --- a/src/cfg.cc +++ b/src/cfg.cc @@ -43,7 +43,11 @@ int cfg_geti(const char *param) { cfg_get(param); - int val = lua_tointeger(tarantool_L, -1); + int val; + if (lua_isboolean(tarantool_L, -1)) + val = lua_toboolean(tarantool_L, -1); + else + val = lua_tointeger(tarantool_L, -1); lua_pop(tarantool_L, 1); return val; } diff --git a/src/errcode.h b/src/errcode.h index 502968487dcbf4c59c79379fdd84383d72b39938..d7df99f96d9c18a61ab008a758538f5bc05c2e79 100644 --- a/src/errcode.h +++ b/src/errcode.h @@ -120,6 +120,8 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 68 */_(ER_INVALID_ORDER, 2, "Invalid LSN order for node %u: previous LSN = %llu, new lsn = %llu") \ /* 69 */_(ER_MISSING_REQUEST_FIELD, 2, "Missing mandatory field '%s' in request") \ /* 70 */_(ER_IDENTIFIER, 2, "Invalid identifier '%s' (expected [a-zA-Z_][a-zA-Z0-9_]*)") \ + /* 11 */_(ER_DROP_FUNCTION, 2, "Can't drop function %u: %s") \ + /* 11 */_(ER_ITERATOR_TYPE, 2, "Unknown iterator type %s") \ /* * !IMPORTANT! Please follow instructions at start of the file diff --git a/test/big/lua.result b/test/big/lua.result index e345fbf4999a8d0baf6f2af8601f9cca15c3ccd5..f4dc4c062d14f0ef619ad41ea130219b519da48d 100644 --- a/test/big/lua.result +++ b/test/big/lua.result @@ -472,7 +472,7 @@ t = {} ... index:pairs('sid_t', { iterator = 'wrong_iterator_type' }) --- -- error: '[string "-- schema.lua (internal file)..."]:326: Wrong iterator type: wrong_iterator_type' +- error: Unknown iterator type 'wrong_iterator_type' ... index = nil --- diff --git a/test/box/access.result b/test/box/access.result index 8d5ae014c8404652487740d05b8a7fde1f627138..192061551ad89ab55da5ee9b918141b3989aa21f 100644 --- a/test/box/access.result +++ b/test/box/access.result @@ -124,9 +124,6 @@ box.space['_user']:delete{uid} box.schema.user.drop('test') --- ... -session = nil ---- -... -------------------------------------------------------------------------------- -- #198: names like '' and 'x.y' and 5 and 'primary ' are legal -------------------------------------------------------------------------------- @@ -184,3 +181,57 @@ c:close() --- - true ... +-- Dropping a space recursively drops all grants - it's possible to +-- restore from a snapshot +box.schema.user.create('testus') +--- +... +s = box.schema.create_space('admin_space') +--- +... +s:create_index('primary', {type = 'hash', parts = {0, 'NUM'}}) +--- +... +box.schema.user.grant('testus', 'write', 'space', 'admin_space') +--- +... +s:drop() +--- +... +box.snapshot() +--- +- ok +... +--# stop server default +--# start server default +box.schema.user.drop('testus') +--- +... +-- ------------------------------------------------------------ +-- a test case for gh-289 +-- box.schema.user.drop() with cascade doesn't work +-- ------------------------------------------------------------ +session = require('session') +--- +... +box.schema.user.create('uniuser') +--- +... +box.schema.user.grant('uniuser', 'read, write, execute', 'universe') +--- +... +session.su('uniuser') +--- +... +us = box.schema.create_space('uniuser_space') +--- +... +session.su('admin') +--- +... +box.schema.user.drop('uniuser') +--- +... +session = nil +--- +... diff --git a/test/box/access.test.lua b/test/box/access.test.lua index a00ec016bb8e7bdb31a234c2e3ff04c00b925100..5f243f248e98750e4f9e832a9890fd03996e50a1 100644 --- a/test/box/access.test.lua +++ b/test/box/access.test.lua @@ -1,3 +1,4 @@ + session = require('session') -- user id for a Lua session is admin - 1 session.uid() @@ -57,7 +58,6 @@ box.space['_user']:delete{uid} box.schema.user.revoke('rich', 'read,write', 'universe') box.space['_user']:delete{uid} box.schema.user.drop('test') -session = nil -------------------------------------------------------------------------------- -- #198: names like '' and 'x.y' and 5 and 'primary ' are legal @@ -81,3 +81,26 @@ c:call('nosuchfunction') nosuchfunction = nil c:call('nosuchfunction') c:close() +-- Dropping a space recursively drops all grants - it's possible to +-- restore from a snapshot +box.schema.user.create('testus') +s = box.schema.create_space('admin_space') +s:create_index('primary', {type = 'hash', parts = {0, 'NUM'}}) +box.schema.user.grant('testus', 'write', 'space', 'admin_space') +s:drop() +box.snapshot() +--# stop server default +--# start server default +box.schema.user.drop('testus') +-- ------------------------------------------------------------ +-- a test case for gh-289 +-- box.schema.user.drop() with cascade doesn't work +-- ------------------------------------------------------------ +session = require('session') +box.schema.user.create('uniuser') +box.schema.user.grant('uniuser', 'read, write, execute', 'universe') +session.su('uniuser') +us = box.schema.create_space('uniuser_space') +session.su('admin') +box.schema.user.drop('uniuser') +session = nil diff --git a/test/box/admin.result b/test/box/admin.result index 9c6cb093d852fbe40c7bf991eb5750811bc50ef7..957102b1efa098463232bdd553a3b4e168189cfa 100644 --- a/test/box/admin.result +++ b/test/box/admin.result @@ -8,30 +8,6 @@ space:create_index('primary', { type = 'hash' }) ... --# push filter 'primary_port: .*' to 'primary_port: <number>' --# push filter 'admin_port: .*' to 'admin_port: <number>' -box.stat() ---- -- DELETE: - total: 35 - rps: 7 - SELECT: - total: 1 - rps: 0 - REPLACE: - total: 2 - rps: 0 - INSERT: - total: 35 - rps: 7 - AUTH: - total: 0 - rps: 0 - CALL: - total: 0 - rps: 0 - UPDATE: - total: 0 - rps: 0 -... help() --- - server admin commands @@ -68,30 +44,6 @@ box.cfg background: false wal_dir_rescan_delay: 0.1 ... -box.stat() ---- -- DELETE: - total: 35 - rps: 7 - SELECT: - total: 1 - rps: 0 - REPLACE: - total: 2 - rps: 0 - INSERT: - total: 35 - rps: 7 - AUTH: - total: 0 - rps: 0 - CALL: - total: 0 - rps: 0 - UPDATE: - total: 0 - rps: 0 -... space:insert{1, 'tuple'} --- - [1, 'tuple'] diff --git a/test/box/admin.test.lua b/test/box/admin.test.lua index 581833ae207fe152316a9ba2a8348c1b897a5d16..833819b918b01720f00854305496fe9e1eb0a87c 100644 --- a/test/box/admin.test.lua +++ b/test/box/admin.test.lua @@ -6,10 +6,8 @@ space:create_index('primary', { type = 'hash' }) --# push filter 'primary_port: .*' to 'primary_port: <number>' --# push filter 'admin_port: .*' to 'admin_port: <number>' -box.stat() help() box.cfg -box.stat() space:insert{1, 'tuple'} box.snapshot() space:delete{1} diff --git a/test/box/auth_access.result b/test/box/auth_access.result index 7da350e0320b04cf7a0d26e61554ec2b05afa641..86d2d3fa1b0113b81083ec6ba75160057a898916 100644 --- a/test/box/auth_access.result +++ b/test/box/auth_access.result @@ -305,11 +305,9 @@ box.schema.user.drop('uniuser_testus') ... box.schema.user.drop('uniuser') --- -- error: Function '513' does not exist ... box.space._user:delete(2) --- -- [2, '', 'uniuser', []] ... s:drop() --- @@ -400,55 +398,6 @@ box.space._index:insert{512, 1,'owner','tree', 1, 1, 0,'num'} session.su('admin') --- ... --- --- Check max function limit --- ---# setopt delimiter ';' -function func_limit() - local i = 1 - while true do - box.schema.func.create('func'..i) - i = i + 1 - end - return i -end; ---- -... -function drop_limit_func() - local i = 1 - while true do - box.schema.func.drop('func'..i) - i = i + 1 - end -end; ---- -... -func_limit(); ---- -- error: 'A limit on the total number of functions has been reached: 32000' -... -drop_limit_func(); ---- -- error: Function 'func32001' does not exist -... -box.schema.user.grant('testuser', 'read, write, execute', 'universe'); ---- -... -session.su('testuser'); ---- -... -func_limit(); ---- -- error: 'A limit on the total number of functions has been reached: 32000' -... -drop_limit_func(); ---- -- error: Function 'func32001' does not exist -... ---# setopt delimiter '' -session.su('admin') ---- -... box.schema.user.revoke('testuser', 'read, write, execute', 'universe') --- ... diff --git a/test/box/auth_access.test.lua b/test/box/auth_access.test.lua index b43e92e272485e0a5f3b3ec8a26464f8621a2cf0..6159ecc6ba6736663c7e9c92714bbbc1c6f04884 100644 --- a/test/box/auth_access.test.lua +++ b/test/box/auth_access.test.lua @@ -165,33 +165,6 @@ box.space._index:select(272) box.space._index:insert{512, 1,'owner','tree', 1, 1, 0,'num'} -session.su('admin') --- --- Check max function limit --- ---# setopt delimiter ';' -function func_limit() - local i = 1 - while true do - box.schema.func.create('func'..i) - i = i + 1 - end - return i -end; -function drop_limit_func() - local i = 1 - while true do - box.schema.func.drop('func'..i) - i = i + 1 - end -end; -func_limit(); -drop_limit_func(); -box.schema.user.grant('testuser', 'read, write, execute', 'universe'); -session.su('testuser'); -func_limit(); -drop_limit_func(); ---# setopt delimiter '' session.su('admin') box.schema.user.revoke('testuser', 'read, write, execute', 'universe') diff --git a/test/box/misc.result b/test/box/misc.result index a132936d199cc67d7f182f94302c2ac28d8dc1a5..997b8b00a7ae1f8f494ee2f204c38d4495dcec4b 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -203,11 +203,13 @@ t; - 'box.error.KEY_PART_COUNT : 31' - 'box.error.ALTER_SPACE : 12' - 'box.error.NODE_ID_IS_RO : 66' + - 'box.error.ITERATOR_TYPE : 72' - 'box.error.NONMASTER : 6' - 'box.error.SPACE_EXISTS : 10' + - 'box.error.MISSING_REQUEST_FIELD : 69' - 'box.error.IDENTIFIER : 70' - 'box.error.FIBER_STACK : 30' - - 'box.error.MISSING_REQUEST_FIELD : 69' + - 'box.error.DROP_FUNCTION : 71' - 'box.error.INVALID_ORDER : 68' - 'box.error.CFG : 59' - 'box.error.SPACE_FIELD_COUNT : 38' diff --git a/test/unit/log_dir.cc b/test/unit/log_dir.cc index ff7b569693b5b8a1f99fa5c8b62781134d179812..d0e58d5eae402ea930fa3105374bc201ba97c548 100644 --- a/test/unit/log_dir.cc +++ b/test/unit/log_dir.cc @@ -22,14 +22,11 @@ testset_create(struct log_dir *dir, int64_t *files, int files_n, int node_n) char tpl[] = "/tmp/fileXXXXXX"; struct fio_batch *batch = fio_batch_alloc(1024); - int create_res = log_dir_create(dir); + int create_res = log_dir_create(dir, mkdtemp(tpl), XLOG); assert(create_res == 0); (void)create_res; - strcpy(dir->open_wflags, "wx"); - dir->filetype = "XLOG\n"; - dir->filename_ext = ".xlog"; - dir->dirname = strdup(mkdtemp(tpl)); - dir->mode = 0660; + /* Avoid using libeio */ + dir->sync_is_async = false; for (int f = 0; f < files_n; f++) { struct vclock vclock; diff --git a/test/wal/func_max.result b/test/wal/func_max.result new file mode 100644 index 0000000000000000000000000000000000000000..3a0791da4e9d8366197693f916e05b31d46a8e27 --- /dev/null +++ b/test/wal/func_max.result @@ -0,0 +1,59 @@ +session = require('session') +--- +... +session.su('admin') +--- +... +-- +-- Check max function limit +-- +--# setopt delimiter ';' +function func_limit() + local i = 1 + while true do + box.schema.func.create('func'..i) + i = i + 1 + end + return i +end; +--- +... +function drop_limit_func() + local i = 1 + while true do + box.schema.func.drop('func'..i) + i = i + 1 + end +end; +--- +... +func_limit(); +--- +- error: 'A limit on the total number of functions has been reached: 32000' +... +drop_limit_func(); +--- +- error: Function 'func32001' does not exist +... +box.schema.user.create('testuser'); +--- +... +box.schema.user.grant('testuser', 'read, write, execute', 'universe'); +--- +... +session.su('testuser'); +--- +... +func_limit(); +--- +- error: 'A limit on the total number of functions has been reached: 32000' +... +drop_limit_func(); +--- +- error: Function 'func32001' does not exist +... +session.su('admin') +box.schema.user.drop('testuser'); +--- +... +--# setopt delimiter '' diff --git a/test/wal/func_max.test.lua b/test/wal/func_max.test.lua new file mode 100644 index 0000000000000000000000000000000000000000..1ede3870bb839b45110853c5c3ea301cf70cac08 --- /dev/null +++ b/test/wal/func_max.test.lua @@ -0,0 +1,31 @@ +session = require('session') +session.su('admin') +-- +-- Check max function limit +-- +--# setopt delimiter ';' +function func_limit() + local i = 1 + while true do + box.schema.func.create('func'..i) + i = i + 1 + end + return i +end; +function drop_limit_func() + local i = 1 + while true do + box.schema.func.drop('func'..i) + i = i + 1 + end +end; +func_limit(); +drop_limit_func(); +box.schema.user.create('testuser'); +box.schema.user.grant('testuser', 'read, write, execute', 'universe'); +session.su('testuser'); +func_limit(); +drop_limit_func(); +session.su('admin') +box.schema.user.drop('testuser'); +--# setopt delimiter ''