From 153fb211ac2342907eb766a79c1f41824f981ab5 Mon Sep 17 00:00:00 2001 From: Ben Deutsch Date: Sun, 5 Aug 2018 13:13:38 +0200 Subject: Replace auth.txt with SQLite auth database (#7279) * Replace auth.txt with SQLite auth database --- src/script/lua_api/l_auth.cpp | 216 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/script/lua_api/l_auth.cpp (limited to 'src/script/lua_api/l_auth.cpp') diff --git a/src/script/lua_api/l_auth.cpp b/src/script/lua_api/l_auth.cpp new file mode 100644 index 000000000..0fc57ba3a --- /dev/null +++ b/src/script/lua_api/l_auth.cpp @@ -0,0 +1,216 @@ +/* +Minetest +Copyright (C) 2018 bendeutsch, Ben Deutsch + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "lua_api/l_auth.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "cpp_api/s_base.h" +#include "server.h" +#include "environment.h" +#include "database/database.h" +#include + +// common start: ensure auth db +AuthDatabase *ModApiAuth::getAuthDb(lua_State *L) +{ + ServerEnvironment *server_environment = + dynamic_cast(getEnv(L)); + if (!server_environment) + return nullptr; + return server_environment->getAuthDatabase(); +} + +void ModApiAuth::pushAuthEntry(lua_State *L, const AuthEntry &authEntry) +{ + lua_newtable(L); + int table = lua_gettop(L); + // id + lua_pushnumber(L, authEntry.id); + lua_setfield(L, table, "id"); + // name + lua_pushstring(L, authEntry.name.c_str()); + lua_setfield(L, table, "name"); + // password + lua_pushstring(L, authEntry.password.c_str()); + lua_setfield(L, table, "password"); + // privileges + lua_newtable(L); + int privtable = lua_gettop(L); + for (const std::string &privs : authEntry.privileges) { + lua_pushboolean(L, true); + lua_setfield(L, privtable, privs.c_str()); + } + lua_setfield(L, table, "privileges"); + // last_login + lua_pushnumber(L, authEntry.last_login); + lua_setfield(L, table, "last_login"); + + lua_pushvalue(L, table); +} + +// auth_read(name) +int ModApiAuth::l_auth_read(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + AuthDatabase *auth_db = getAuthDb(L); + if (!auth_db) + return 0; + AuthEntry authEntry; + const char *name = luaL_checkstring(L, 1); + bool success = auth_db->getAuth(std::string(name), authEntry); + if (!success) + return 0; + + pushAuthEntry(L, authEntry); + return 1; +} + +// auth_save(table) +int ModApiAuth::l_auth_save(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + AuthDatabase *auth_db = getAuthDb(L); + if (!auth_db) + return 0; + luaL_checktype(L, 1, LUA_TTABLE); + int table = 1; + AuthEntry authEntry; + bool success; + success = getintfield(L, table, "id", authEntry.id); + success = success && getstringfield(L, table, "name", authEntry.name); + success = success && getstringfield(L, table, "password", authEntry.password); + lua_getfield(L, table, "privileges"); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2)) { + authEntry.privileges.emplace_back( + lua_tostring(L, -2)); // the key, not the value + lua_pop(L, 1); + } + } else { + success = false; + } + lua_pop(L, 1); // the table + success = success && getintfield(L, table, "last_login", authEntry.last_login); + + if (!success) { + lua_pushboolean(L, false); + return 1; + } + + lua_pushboolean(L, auth_db->saveAuth(authEntry)); + return 1; +} + +// auth_create(table) +int ModApiAuth::l_auth_create(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + AuthDatabase *auth_db = getAuthDb(L); + if (!auth_db) + return 0; + luaL_checktype(L, 1, LUA_TTABLE); + int table = 1; + AuthEntry authEntry; + bool success; + // no meaningful id field, we assume + success = getstringfield(L, table, "name", authEntry.name); + success = success && getstringfield(L, table, "password", authEntry.password); + lua_getfield(L, table, "privileges"); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2)) { + authEntry.privileges.emplace_back( + lua_tostring(L, -2)); // the key, not the value + lua_pop(L, 1); + } + } else { + success = false; + } + lua_pop(L, 1); // the table + success = success && getintfield(L, table, "last_login", authEntry.last_login); + + if (!success) + return 0; + + if (auth_db->createAuth(authEntry)) { + pushAuthEntry(L, authEntry); + return 1; + } + + return 0; +} + +// auth_delete(name) +int ModApiAuth::l_auth_delete(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + AuthDatabase *auth_db = getAuthDb(L); + if (!auth_db) + return 0; + std::string name(luaL_checkstring(L, 1)); + lua_pushboolean(L, auth_db->deleteAuth(name)); + return 1; +} + +// auth_list_names() +int ModApiAuth::l_auth_list_names(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + AuthDatabase *auth_db = getAuthDb(L); + if (!auth_db) + return 0; + std::vector names; + auth_db->listNames(names); + lua_createtable(L, names.size(), 0); + int table = lua_gettop(L); + int i = 1; + for (const std::string &name : names) { + lua_pushstring(L, name.c_str()); + lua_rawseti(L, table, i++); + } + return 1; +} + +// auth_reload() +int ModApiAuth::l_auth_reload(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + AuthDatabase *auth_db = getAuthDb(L); + if (auth_db) + auth_db->reload(); + return 0; +} + +void ModApiAuth::Initialize(lua_State *L, int top) +{ + + lua_newtable(L); + int auth_top = lua_gettop(L); + + registerFunction(L, "read", l_auth_read, auth_top); + registerFunction(L, "save", l_auth_save, auth_top); + registerFunction(L, "create", l_auth_create, auth_top); + registerFunction(L, "delete", l_auth_delete, auth_top); + registerFunction(L, "list_names", l_auth_list_names, auth_top); + registerFunction(L, "reload", l_auth_reload, auth_top); + + lua_setfield(L, top, "auth"); +} -- cgit v1.2.3