From 56d808e3e2c15f0c19eb5bbbb1d0ed223f305c93 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 7 Dec 2025 00:08:57 +0300 Subject: [PATCH] add 'write-to-user' permission & refactor checking for writeability --- src/devtools/Project.cpp | 11 ++++++++--- src/devtools/Project.hpp | 10 +++++++++- src/engine/Engine.cpp | 1 + src/engine/EnginePaths.cpp | 22 +++++++++++++++++++++- src/engine/EnginePaths.hpp | 8 ++++++++ src/logic/scripting/lua/libs/libfile.cpp | 13 +------------ 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/devtools/Project.cpp b/src/devtools/Project.cpp index f05b4a2d..86c73640 100644 --- a/src/devtools/Project.cpp +++ b/src/devtools/Project.cpp @@ -12,7 +12,7 @@ Project::~Project() = default; dv::value Project::serialize() const { auto permissionsList = dv::list(); - for (const auto& perm : permissions) { + for (const auto& perm : permissions.permissions) { permissionsList.add(perm); } return dv::object({ @@ -31,10 +31,11 @@ void Project::deserialize(const dv::value& src) { if (src.has("permissions")) { std::vector perms; dv::get(src, "permissions", perms); - permissions = std::set(perms.begin(), perms.end()); + permissions.permissions = + std::set(perms.begin(), perms.end()); } logger.info() << "permissions: "; - for (const auto& perm : permissions) { + for (const auto& perm : permissions.permissions) { logger.info() << " - " << perm; } } @@ -58,3 +59,7 @@ void Project::loadProjectStartScript() { logger.warning() << "project start script does not exists"; } } + +bool Permissions::has(const std::string& name) const { + return permissions.find(name) != permissions.end(); +} diff --git a/src/devtools/Project.hpp b/src/devtools/Project.hpp index c0646181..a07aec0c 100644 --- a/src/devtools/Project.hpp +++ b/src/devtools/Project.hpp @@ -12,13 +12,21 @@ namespace scripting { class IClientProjectScript; } +struct Permissions { + static inline std::string WRITE_TO_USER = "write-to-user"; + + std::set permissions; + + bool has(const std::string& name) const; +}; + struct Project : Serializable { std::string name; std::string title; std::vector basePacks; std::unique_ptr clientScript; std::unique_ptr setupCoroutine; - std::set permissions; + Permissions permissions; ~Project(); diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index f79fae75..4e38ac36 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -134,6 +134,7 @@ void Engine::initialize(CoreParameters coreParameters) { } paths = std::make_unique(params); loadProject(); + paths->setupProject(*project); editor = std::make_unique(*this); cmd = std::make_unique(); diff --git a/src/engine/EnginePaths.cpp b/src/engine/EnginePaths.cpp index 6c05614e..7cb71079 100644 --- a/src/engine/EnginePaths.cpp +++ b/src/engine/EnginePaths.cpp @@ -6,6 +6,7 @@ #include "io/devices/ZipFileDevice.hpp" #include "maths/util.hpp" #include "typedefs.hpp" +#include "devtools/Project.hpp" #include "util/platform.hpp" #include "util/random.hpp" #include "util/stringutil.hpp" @@ -43,7 +44,10 @@ static std::string generate_random_base64() { EnginePaths::EnginePaths(CoreParameters& params) : resourcesFolder(params.resFolder), userFilesFolder(params.userFolder), - projectFolder(params.projectFolder) { + projectFolder(params.projectFolder), + initiallyWriteables({ + "world", "export", "config" + }) { if (!params.scriptFile.empty()) { scriptFolder = params.scriptFile.parent_path(); io::set_device("script", std::make_shared(*scriptFolder)); @@ -239,6 +243,22 @@ void EnginePaths::setEntryPoints(std::vector entryPoints) { this->entryPoints = std::move(entryPoints); } +void EnginePaths::setupProject(const Project& project) { + if (project.permissions.has(Permissions::WRITE_TO_USER)) { + initiallyWriteables.insert("user"); + } +} + +bool EnginePaths::isWriteable(const std::string& entryPoint) const { + if (entryPoint.length() < 2) { + return false; + } + if (entryPoint.substr(0, 2) == "W.") { + return true; + } + return initiallyWriteables.find(entryPoint) != initiallyWriteables.end(); +} + std::tuple EnginePaths::parsePath(std::string_view path) { size_t separator = path.find(':'); if (separator == std::string::npos) { diff --git a/src/engine/EnginePaths.hpp b/src/engine/EnginePaths.hpp index 876394b4..a216ac45 100644 --- a/src/engine/EnginePaths.hpp +++ b/src/engine/EnginePaths.hpp @@ -9,6 +9,7 @@ #include #include #include +#include struct PathsRoot { std::string name; @@ -42,6 +43,8 @@ private: std::vector roots; }; +struct Project; + class EnginePaths { public: ResPaths resPaths; @@ -65,6 +68,10 @@ public: void setEntryPoints(std::vector entryPoints); + void setupProject(const Project& project); + + bool isWriteable(const std::string& entryPoint) const; + std::vector scanForWorlds() const; static std::tuple parsePath(std::string_view view); @@ -81,6 +88,7 @@ private: std::vector entryPoints; std::unordered_map writeables; std::vector mounted; + std::set initiallyWriteables; void cleanup(); }; diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index 197cd7db..68700815 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -39,18 +39,7 @@ static int l_read(lua::State* L) { ); } -static std::set writeable_entry_points { - "world", "export", "config" -}; - static bool is_writeable(const std::string& entryPoint) { - if (entryPoint.length() < 2) { - return false; - } - if (entryPoint.substr(0, 2) == "W.") { - return true; - } - // todo: do better auto device = io::get_device(entryPoint); if (device == nullptr) { return false; @@ -58,7 +47,7 @@ static bool is_writeable(const std::string& entryPoint) { if (dynamic_cast(device.get())) { return true; } - if (writeable_entry_points.find(entryPoint) != writeable_entry_points.end()) { + if (engine->getPaths().isWriteable(entryPoint)) { return true; } return false;