From b0934dffb511b022aa2ca56b6b79e967bbab1a27 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Fri, 7 Nov 2014 16:37:45 +0300
Subject: [PATCH] Refactor access check headers.

Make sure the tests pass under low memory and no memory overcommit.
---
 src/box/CMakeLists.txt               |  3 +-
 src/box/alter.cc                     | 24 ++++----
 src/box/authentication.cc            |  6 +-
 src/box/box.cc                       |  3 +-
 src/box/iproto.cc                    |  1 +
 src/box/lua/call.cc                  | 13 +++--
 src/box/lua/index.cc                 |  2 +-
 src/box/lua/session.cc               |  7 ++-
 src/box/request.cc                   |  3 +-
 src/box/schema.cc                    |  2 +-
 src/box/session.cc                   |  1 +
 src/box/session.h                    |  2 -
 src/box/space.cc                     |  6 +-
 src/box/{access.cc => user_cache.cc} | 35 +++++-------
 src/box/{access.h => user_cache.h}   | 82 ++++------------------------
 src/box/user_def.cc                  | 39 +++++++++++++
 src/box/user_def.h                   | 76 ++++++++++++++++++++++++++
 test/app/session.test.lua            |  2 +-
 test/app/trigger_atexit.test.lua     |  3 +-
 19 files changed, 184 insertions(+), 126 deletions(-)
 rename src/box/{access.cc => user_cache.cc} (89%)
 rename src/box/{access.h => user_cache.h} (58%)
 create mode 100644 src/box/user_def.cc
 create mode 100644 src/box/user_def.h

diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index bef3d92859..8cb6295982 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -41,7 +41,8 @@ add_library(box
     request.cc
     txn.cc
     box.cc
-    access.cc
+    user_def.cc
+    user_cache.cc
     authentication.cc
     vclock.c
     cluster.cc
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 7a1b19296c..464e074a16 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -28,7 +28,8 @@
  */
 #include "alter.h"
 #include "schema.h"
-#include "access.h"
+#include "user_def.h"
+#include "user_cache.h"
 #include "space.h"
 #include "txn.h"
 #include "tuple.h"
@@ -39,6 +40,7 @@
 #include <stdio.h> /* snprintf() */
 #include <ctype.h>
 #include "cluster.h" /* for cluster_set_uuid() */
+#include "session.h" /* to fetch the current user. */
 
 /** _space columns */
 #define ID               0
@@ -70,7 +72,7 @@
 void
 access_check_ddl(uint32_t owner_uid)
 {
-	struct user *user = user();
+	struct user_def *user = user();
 	/*
 	 * Only the creator of the space or superuser can modify
 	 * the space, since we don't have ALTER privilege.
@@ -1155,7 +1157,7 @@ user_has_data(uint32_t uid)
  */
 
 void
-user_fill_auth_data(struct user *user, const char *auth_data)
+user_fill_auth_data(struct user_def *user, const char *auth_data)
 {
 	uint8_t type = mp_typeof(*auth_data);
 	if (type == MP_ARRAY || type == MP_NIL) {
@@ -1199,7 +1201,7 @@ user_fill_auth_data(struct user *user, const char *auth_data)
 }
 
 void
-user_create_from_tuple(struct user *user, struct tuple *tuple)
+user_create_from_tuple(struct user_def *user, struct tuple *tuple)
 {
 	/* In case user password is empty, fill it with \0 */
 	memset(user, 0, sizeof(*user));
@@ -1252,7 +1254,7 @@ user_cache_alter_user(struct trigger * /* trigger */, void *event)
 {
 	struct txn *txn = (struct txn *) event;
 	struct txn_stmt *stmt = txn_stmt(txn);
-	struct user user;
+	struct user_def user;
 	user_create_from_tuple(&user, stmt->new_tuple);
 	user_cache_replace(&user);
 }
@@ -1271,9 +1273,9 @@ on_replace_dd_user(struct trigger * /* trigger */, void *event)
 
 	uint32_t uid = tuple_field_u32(old_tuple ?
 				       old_tuple : new_tuple, ID);
-	struct user *old_user = user_cache_find(uid);
+	struct user_def *old_user = user_cache_find(uid);
 	if (new_tuple != NULL && old_user == NULL) { /* INSERT */
-		struct user user;
+		struct user_def user;
 		user_create_from_tuple(&user, new_tuple);
 		(void) user_cache_replace(&user);
 		struct trigger *on_rollback =
@@ -1305,7 +1307,7 @@ on_replace_dd_user(struct trigger * /* trigger */, void *event)
 		 * password) but first check that the change is
 		 * correct.
 		 */
-		struct user user;
+		struct user_def user;
 		user_create_from_tuple(&user, new_tuple);
 		struct trigger *on_commit =
 			txn_alter_trigger_new(user_cache_alter_user, NULL);
@@ -1434,8 +1436,8 @@ priv_def_create_from_tuple(struct priv_def *priv, struct tuple *tuple)
 static void
 priv_def_check(struct priv_def *priv)
 {
-	struct user *grantor = user_cache_find(priv->grantor_id);
-	struct user *grantee = user_cache_find(priv->grantee_id);
+	struct user_def *grantor = user_cache_find(priv->grantor_id);
+	struct user_def *grantee = user_cache_find(priv->grantee_id);
 	if (grantor == NULL) {
 		tnt_raise(ClientError, ER_NO_SUCH_USER,
 			  int2str(priv->grantor_id));
@@ -1482,7 +1484,7 @@ priv_def_check(struct priv_def *priv)
 static void
 grant_or_revoke(struct priv_def *priv)
 {
-	struct user *grantee = user_cache_find(priv->grantee_id);
+	struct user_def *grantee = user_cache_find(priv->grantee_id);
 	if (grantee == NULL)
 		return;
 	struct access *access = NULL;
diff --git a/src/box/authentication.cc b/src/box/authentication.cc
index 89f03d5d47..7f83a3d606 100644
--- a/src/box/authentication.cc
+++ b/src/box/authentication.cc
@@ -26,13 +26,15 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include "access.h"
+#include "user_cache.h"
+#include "user_def.h"
+#include "session.h"
 
 void
 authenticate(const char *user_name, uint32_t len,
 	     const char *tuple, const char * /* tuple_end */)
 {
-	struct user *user = user_by_name(user_name, len);
+	struct user_def *user = user_by_name(user_name, len);
 	if (user == NULL) {
 		char name[BOX_NAME_MAX + 1];
 		/* \0 - to correctly print user name the error message. */
diff --git a/src/box/box.cc b/src/box/box.cc
index 5f079c7e81..559ce39a63 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -50,9 +50,10 @@
 #include "request.h"
 #include "txn.h"
 #include "fiber.h"
-#include "access.h"
+#include "user_cache.h"
 #include "cfg.h"
 #include "iobuf.h"
+#include "iproto_constants.h"
 
 static void process_ro(struct port *port, struct request *request);
 static void process_rw(struct port *port, struct request *request);
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 0c2470153e..21b3a91b3e 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -47,6 +47,7 @@
 #include "coio.h"
 #include "xrow.h"
 #include "iproto_constants.h"
+#include "user_def.h"
 
 class IprotoConnectionShutdown: public Exception
 {
diff --git a/src/box/lua/call.cc b/src/box/lua/call.cc
index 538bbe2945..bd1f187767 100644
--- a/src/box/lua/call.cc
+++ b/src/box/lua/call.cc
@@ -47,8 +47,11 @@
 #include "box/port.h"
 #include "box/request.h"
 #include "box/txn.h"
-#include "box/access.h"
+#include "box/user_def.h"
+#include "box/user_cache.h"
 #include "box/schema.h"
+#include "box/session.h"
+#include "box/iproto_constants.h"
 
 /* contents of box.lua, misc.lua, box.net.lua respectively */
 extern char session_lua[],
@@ -474,12 +477,12 @@ struct SetuidGuard
 	uint32_t orig_uid;
 
 	inline SetuidGuard(const char *name, uint32_t name_len,
-			   struct user *user, uint8_t access);
+			   struct user_def *user, uint8_t access);
 	inline ~SetuidGuard();
 };
 
 SetuidGuard::SetuidGuard(const char *name, uint32_t name_len,
-			 struct user *user, uint8_t access)
+			 struct user_def *user, uint8_t access)
 	:setuid(false)
 	,orig_auth_token(GUEST) /* silence gnu warning */
 	,orig_uid(GUEST)
@@ -521,7 +524,7 @@ SetuidGuard::SetuidGuard(const char *name, uint32_t name_len,
 		/** Remember and change the current user id. */
 		if (unlikely(func->auth_token >= BOX_USER_MAX)) {
 			/* Optimization: cache auth_token on first access */
-			struct user *owner = user_cache_find(func->uid);
+			struct user_def *owner = user_cache_find(func->uid);
 			assert(owner != NULL); /* checked by user_has_data() */
 			func->auth_token = owner->auth_token;
 			assert(owner->auth_token < BOX_USER_MAX);
@@ -546,7 +549,7 @@ SetuidGuard::~SetuidGuard()
 void
 box_lua_call(struct request *request, struct port *port)
 {
-	struct user *user = user();
+	struct user_def *user = user();
 	lua_State *L = lua_newthread(tarantool_L);
 	LuarefGuard coro_ref(tarantool_L);
 	const char *name = request->key;
diff --git a/src/box/lua/index.cc b/src/box/lua/index.cc
index 4f5424312b..9293cf8ae5 100644
--- a/src/box/lua/index.cc
+++ b/src/box/lua/index.cc
@@ -31,7 +31,7 @@
 #include "box/index.h"
 #include "box/space.h"
 #include "box/schema.h"
-#include "box/access.h"
+#include "box/user_def.h"
 #include "box/lua/tuple.h"
 #include "fiber.h"
 #include "tbuf.h"
diff --git a/src/box/lua/session.cc b/src/box/lua/session.cc
index f578178502..4d38251751 100644
--- a/src/box/lua/session.cc
+++ b/src/box/lua/session.cc
@@ -29,7 +29,8 @@
 #include "session.h"
 #include "lua/utils.h"
 #include "lua/trigger.h"
-#include "box/access.h"
+#include "box/user_cache.h"
+#include "box/user_def.h"
 
 extern "C" {
 #include <lua.h>
@@ -71,7 +72,7 @@ lbox_session_uid(struct lua_State *L)
 static int
 lbox_session_user(struct lua_State *L)
 {
-	struct user *user = user_cache_find(session()->uid);
+	struct user_def *user = user_cache_find(session()->uid);
 	if (user)
 		lua_pushstring(L, user->name);
 	else
@@ -88,7 +89,7 @@ lbox_session_su(struct lua_State *L)
 	struct session *session = session();
 	if (session == NULL)
 		luaL_error(L, "session.su(): session does not exit");
-	struct user *user;
+	struct user_def *user;
 	if (lua_type(L, 1) == LUA_TSTRING) {
 		size_t len;
 		const char *name = lua_tolstring(L, 1, &len);
diff --git a/src/box/request.cc b/src/box/request.cc
index f8a19d2aa5..e09e798d49 100644
--- a/src/box/request.cc
+++ b/src/box/request.cc
@@ -39,7 +39,8 @@
 #include <scoped_guard.h>
 #include <third_party/base64.h>
 #include "authentication.h"
-#include "access.h"
+#include "user_def.h"
+#include "iproto_constants.h"
 
 enum dup_replace_mode
 dup_replace_mode(uint32_t op)
diff --git a/src/box/schema.cc b/src/box/schema.cc
index fb9a9144de..6ce440d429 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include "schema.h"
-#include "access.h"
+#include "user_def.h"
 #include "engine.h"
 #include "space.h"
 #include "tuple.h"
diff --git a/src/box/session.cc b/src/box/session.cc
index c892a411f9..7f4189ddbe 100644
--- a/src/box/session.cc
+++ b/src/box/session.cc
@@ -35,6 +35,7 @@
 #include "exception.h"
 #include "random.h"
 #include <sys/socket.h>
+#include "user_def.h"
 
 static struct mh_i32ptr_t *session_registry;
 
diff --git a/src/box/session.h b/src/box/session.h
index a1d2157ec4..050512da6a 100644
--- a/src/box/session.h
+++ b/src/box/session.h
@@ -34,8 +34,6 @@
 #include "fiber.h"
 
 enum {	SESSION_SEED_SIZE = 32, SESSION_DELIM_SIZE = 16 };
-/** Predefined user ids. */
-enum { GUEST = 0, ADMIN =  1, PUBLIC = 2 /* role */ };
 
 /**
  * Abstraction of a single user session:
diff --git a/src/box/space.cc b/src/box/space.cc
index 7947cd3b0b..72f5f5490b 100644
--- a/src/box/space.cc
+++ b/src/box/space.cc
@@ -33,12 +33,14 @@
 #include "tuple.h"
 #include "scoped_guard.h"
 #include "trigger.h"
-#include "access.h"
+#include "user_def.h"
+#include "user_cache.h"
+#include "session.h"
 
 void
 access_check_space(struct space *space, uint8_t access)
 {
-	struct user *user = user();
+	struct user_def *user = user();
 	/*
 	 * If a user has a global permission, clear the respective
 	 * privilege from the list of privileges required
diff --git a/src/box/access.cc b/src/box/user_cache.cc
similarity index 89%
rename from src/box/access.cc
rename to src/box/user_cache.cc
index 1521b5f6e4..9d1a1c2861 100644
--- a/src/box/access.cc
+++ b/src/box/user_cache.cc
@@ -26,11 +26,12 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include "access.h"
+#include "user_cache.h"
+#include "user_def.h"
 #include "assoc.h"
 #include "schema.h"
 
-struct user users[BOX_USER_MAX];
+struct user_def users[BOX_USER_MAX];
 /** Bitmap type for used/unused authentication token map. */
 typedef unsigned long user_map_t;
 
@@ -69,7 +70,7 @@ user_map_get_slot()
 void
 user_map_put_slot(uint8_t auth_token)
 {
-	memset(users + auth_token, 0, sizeof(struct user));
+	memset(users + auth_token, 0, sizeof(struct user_def));
 	uint32_t bit_no = auth_token & (sizeof(user_map_t) * CHAR_BIT - 1);
 	auth_token /= sizeof(user_map_t) * CHAR_BIT;
 	user_map[auth_token] |= ((user_map_t) 1) << bit_no;
@@ -77,20 +78,10 @@ user_map_put_slot(uint8_t auth_token)
 		user_map_idx = auth_token;
 }
 
-const char *
-priv_name(uint8_t access)
-{
-	if (access & PRIV_R)
-		return "Read";
-	if (access & PRIV_W)
-		return "Write";
-	return "Execute";
-}
-
 void
-user_cache_replace(struct user *user)
+user_cache_replace(struct user_def *user)
 {
-	struct user *old = user_cache_find(user->uid);
+	struct user_def *old = user_cache_find(user->uid);
 	if (old == NULL) {
 		uint8_t auth_token = user_map_get_slot();
 		old = users + auth_token;
@@ -107,7 +98,7 @@ user_cache_replace(struct user *user)
 void
 user_cache_delete(uint32_t uid)
 {
-	struct user *old = user_cache_find(uid);
+	struct user_def *old = user_cache_find(uid);
 	if (old) {
 		assert(old->auth_token > ADMIN);
 		user_map_put_slot(old->auth_token);
@@ -118,21 +109,21 @@ user_cache_delete(uint32_t uid)
 }
 
 /** Find user by id. */
-struct user *
+struct user_def *
 user_cache_find(uint32_t uid)
 {
 	mh_int_t k = mh_i32ptr_find(user_registry, uid, NULL);
 	if (k == mh_end(user_registry))
 		return NULL;
-	return (struct user *) mh_i32ptr_node(user_registry, k)->val;
+	return (struct user_def *) mh_i32ptr_node(user_registry, k)->val;
 }
 
 /** Find user by name. */
-struct user *
+struct user_def *
 user_by_name(const char *name, uint32_t len)
 {
 	uint32_t uid = schema_find_id(SC_USER_ID, 2, name, len);
-	struct user *user = user_cache_find(uid);
+	struct user_def *user = user_cache_find(uid);
 	return user && user->type == SC_USER ? user : NULL;
 }
 
@@ -149,7 +140,7 @@ user_cache_init()
 	 * for 'guest' and 'admin' users here, they will be
 	 * updated with snapshot contents during recovery.
 	 */
-	struct user guest;
+	struct user_def guest;
 	memset(&guest, 0, sizeof(guest));
 	snprintf(guest.name, sizeof(guest.name), "guest");
 	guest.owner = ADMIN;
@@ -160,7 +151,7 @@ user_cache_init()
 	       guest.uid == GUEST &&
 	       users[guest.auth_token].uid == guest.uid);
 
-	struct user admin;
+	struct user_def admin;
 	memset(&admin, 0, sizeof(admin));
 	snprintf(admin.name, sizeof(admin.name), "admin");
 	admin.uid = admin.owner = ADMIN;
diff --git a/src/box/access.h b/src/box/user_cache.h
similarity index 58%
rename from src/box/access.h
rename to src/box/user_cache.h
index 385807aa4e..7097af372f 100644
--- a/src/box/access.h
+++ b/src/box/user_cache.h
@@ -1,5 +1,5 @@
-#ifndef INCLUDES_TARANTOOL_BOX_ACCESS_H
-#define INCLUDES_TARANTOOL_BOX_ACCESS_H
+#ifndef INCLUDES_TARANTOOL_BOX_USER_CACHE_H
+#define INCLUDES_TARANTOOL_BOX_USER_CACHE_H
 /*
  * Redistribution and use in source and binary forms, with or
  * without modification, are permitted provided that the following
@@ -28,51 +28,9 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include "iproto_constants.h"
-#include "key_def.h"
-#include "scramble.h"
-#include "fiber.h"
-#include "session.h"
-
-enum {
-	/* SELECT */
-	PRIV_R = 1,
-	/* INSERT, UPDATE, DELETE, REPLACE */
-	PRIV_W = 2,
-	/* CALL */
-	PRIV_X = 4,
-	/** Everything. */
-	PRIV_ALL = PRIV_R + PRIV_W + PRIV_X
-};
-
-/* Privilege name for error messages */
-const char *
-priv_name(uint8_t access);
-
-/**
- * A cache entry for an existing user. Entries for all existing
- * users are always present in the cache. The entry is maintained
- * in sync with _user and _priv system spaces by system space
- * triggers.
- * @sa alter.cc
- */
-struct user {
-	/** User id. */
-	uint32_t uid;
-	/** Creator of the user */
-	uint32_t owner;
-	/** 'user' or 'role' */
-	enum schema_object_type type;
-	/** User password - hash2 */
-	char hash2[SCRAMBLE_SIZE];
-	/** User name - for error messages and debugging */
-	char name[BOX_NAME_MAX + 1];
-	/** Global privileges this user has on the universe. */
-	struct access universal_access;
-	/** An id in users[] array to quickly find user */
-	uint8_t auth_token;
-};
+#include <stdint.h>
 
+struct user_def;
 /**
  * For best performance, all users are maintained in this array.
  * Position in the array is store in user->auth_token and also
@@ -84,7 +42,7 @@ struct user {
  * is also used to find out user privileges when accessing stored
  * objects, such as spaces and functions.
  */
-extern struct user users[];
+extern struct user_def users[];
 
 /*
  * Insert or update user object (a cache entry
@@ -99,7 +57,7 @@ extern struct user users[];
  * with an index in the users[] array.
  */
 void
-user_cache_replace(struct user *user);
+user_cache_replace(struct user_def *user);
 
 /**
  * Find a user by id and delete it from the
@@ -109,40 +67,20 @@ void
 user_cache_delete(uint32_t uid);
 
 /** Find user by id. */
-struct user *
+struct user_def *
 user_cache_find(uint32_t uid);
 
 /* Find a user by name. Used by authentication. */
-struct user *
+struct user_def *
 user_by_name(const char *name, uint32_t len);
 
 /**
  * Return the current user.
- *
- * @todo: this doesn't account for the case when a user
- * was dropped, its slot in users array was reused
- * for a new user, and some sessions exist which still
- * use the old auth_token. In this case, already
- * authenticated sessions use grants of the new user,
- * not the old one.
- *
- * This can be easily fixed by checking that uid of the
- * user found by means of auth_token matches the uid
- * stored in the session, and invalidating the session
- * auth_token when it doesn't.
- *
- * Alternatively, one could invalidate the session
- * auth_token whenever sc_version changes. Alternatively,
- * one could invalidate auth_token in all sessions whenever
- * any tuple in _user or _priv spaces is modified.
- *
- * None of these 3 solutions seems to be worth the while
- * at the moment.
  */
 #define user()							\
 ({								\
 	struct session *s = session();				\
-	struct user *u = &users[s->auth_token];			\
+	struct user_def *u = &users[s->auth_token];			\
 	if (u->auth_token != s->auth_token ||			\
 	    u->uid != s->uid) {					\
 		tnt_raise(ClientError, ER_NO_SUCH_USER,		\
@@ -159,4 +97,4 @@ user_cache_init();
 void
 user_cache_free();
 
-#endif /* INCLUDES_TARANTOOL_BOX_ACCESS_H */
+#endif /* INCLUDES_TARANTOOL_BOX_USER_CACHE_H */
diff --git a/src/box/user_def.cc b/src/box/user_def.cc
new file mode 100644
index 0000000000..5f178be766
--- /dev/null
+++ b/src/box/user_def.cc
@@ -0,0 +1,39 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "user_def.h"
+const char *
+priv_name(uint8_t access)
+{
+	if (access & PRIV_R)
+		return "Read";
+	if (access & PRIV_W)
+		return "Write";
+	return "Execute";
+}
+
diff --git a/src/box/user_def.h b/src/box/user_def.h
new file mode 100644
index 0000000000..31ac5c4905
--- /dev/null
+++ b/src/box/user_def.h
@@ -0,0 +1,76 @@
+#ifndef TARANTOOL_BOX_USER_DEF_H_INCLUDED
+#define TARANTOOL_BOX_USER_DEF_H_INCLUDED
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "key_def.h" /* for SCHEMA_OBJECT_TYPE */
+#include "scramble.h" /* for SCRAMBLE_SIZE */
+
+enum {
+	/* SELECT */
+	PRIV_R = 1,
+	/* INSERT, UPDATE, DELETE, REPLACE */
+	PRIV_W = 2,
+	/* CALL */
+	PRIV_X = 4,
+	/** Everything. */
+	PRIV_ALL = PRIV_R + PRIV_W + PRIV_X
+};
+
+/* Privilege name for error messages */
+const char *
+priv_name(uint8_t access);
+
+/**
+ * A cache entry for an existing user. Entries for all existing
+ * users are always present in the cache. The entry is maintained
+ * in sync with _user and _priv system spaces by system space
+ * triggers.
+ * @sa alter.cc
+ */
+struct user_def {
+	/** User id. */
+	uint32_t uid;
+	/** Creator of the user */
+	uint32_t owner;
+	/** 'user' or 'role' */
+	enum schema_object_type type;
+	/** User password - hash2 */
+	char hash2[SCRAMBLE_SIZE];
+	/** User name - for error messages and debugging */
+	char name[BOX_NAME_MAX + 1];
+	/** Global privileges this user has on the universe. */
+	struct access universal_access;
+	/** An id in users[] array to quickly find user */
+	uint8_t auth_token;
+};
+
+/** Predefined user ids. */
+enum { GUEST = 0, ADMIN =  1, PUBLIC = 2 /* role */ };
+
+#endif /* TARANTOOL_BOX_USER_DEF_H_INCLUDED */
diff --git a/test/app/session.test.lua b/test/app/session.test.lua
index d885b845ff..9c1a674bf1 100755
--- a/test/app/session.test.lua
+++ b/test/app/session.test.lua
@@ -3,7 +3,7 @@
 --
 -- Check that Tarantool creates ADMIN session for #! script
 --
-box.cfg{logger="tarantool.log"}
+box.cfg{logger="tarantool.log", slab_alloc_arena=0.1}
 print('session.id()', box.session.id())
 print('session.uid()', box.session.uid())
 os.exit(0)
diff --git a/test/app/trigger_atexit.test.lua b/test/app/trigger_atexit.test.lua
index 1e85558d9e..7ac54bd5e9 100755
--- a/test/app/trigger_atexit.test.lua
+++ b/test/app/trigger_atexit.test.lua
@@ -13,7 +13,8 @@ box.cfg {
     wal_dir = tempdir,
     snap_dir = tempdir,
     sophia_dir = tempdir,
-    logger      = fio.pathjoin(tempdir, 'tarantool.log')
+    logger      = fio.pathjoin(tempdir, 'tarantool.log'),
+    slab_alloc_arena=0.1 -- for small systems
 }
 
 local function test_replace(old_tuple, new_tuple)
-- 
GitLab