/* 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"); }