diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py index 52e98138..bc8daf1c 100644 --- a/app/classes/shared/main_controller.py +++ b/app/classes/shared/main_controller.py @@ -951,6 +951,8 @@ class Controller: "the new directory." }, ) + self.helper.dir_migration = False + return # set the cached serve dir self.helper.servers_dir = new_server_path diff --git a/app/classes/web/ajax_handler.py b/app/classes/web/ajax_handler.py index 8cd81b50..9a018539 100644 --- a/app/classes/web/ajax_handler.py +++ b/app/classes/web/ajax_handler.py @@ -127,30 +127,3 @@ class AjaxHandler(BaseHandler): self.controller.management.set_login_image("login_1.jpg") self.controller.cached_login = "login_1.jpg" return - - elif page == "update_server_dir": - if self.helper.dir_migration: - return - for server in self.controller.servers.get_all_servers_stats(): - if server["stats"]["running"]: - self.helper.websocket_helper.broadcast_user( - exec_user["user_id"], - "send_start_error", - { - "error": "You must stop all servers before " - "starting a storage migration." - }, - ) - return - if not superuser: - self.redirect("/panel/error?error=Not a super user") - return - if self.helper.is_env_docker(): - self.redirect( - "/panel/error?error=This feature is not" - " supported on docker environments" - ) - return - new_dir = urllib.parse.unquote(self.get_argument("server_dir")) - self.controller.update_master_server_dir(new_dir, exec_user["user_id"]) - return diff --git a/app/classes/web/routes/api/api_handlers.py b/app/classes/web/routes/api/api_handlers.py index 7294b931..2dc8c920 100644 --- a/app/classes/web/routes/api/api_handlers.py +++ b/app/classes/web/routes/api/api_handlers.py @@ -53,6 +53,9 @@ from app.classes.web.routes.api.users.user.api import ApiUsersUserKeyHandler from app.classes.web.routes.api.users.user.pfp import ApiUsersUserPfpHandler from app.classes.web.routes.api.users.user.public import ApiUsersUserPublicHandler from app.classes.web.routes.api.crafty.config.index import ApiCraftyConfigIndexHandler +from app.classes.web.routes.api.crafty.config.server_dir import ( + ApiCraftyConfigServerDirHandler, +) from app.classes.web.routes.api.crafty.clogs.index import ApiCraftyLogIndexHandler from app.classes.web.routes.api.crafty.imports.index import ApiImportFilesIndexHandler from app.classes.web.routes.api.crafty.exe_cache import ApiCraftyExeCacheIndexHandler @@ -76,6 +79,11 @@ def api_handlers(handler_args): ApiCraftyConfigIndexHandler, handler_args, ), + ( + r"/api/v2/crafty/config/servers_dir/?", + ApiCraftyConfigServerDirHandler, + handler_args, + ), ( r"/api/v2/crafty/logs/([a-z0-9_]+)/?", ApiCraftyLogIndexHandler, diff --git a/app/classes/web/routes/api/crafty/config/server_dir.py b/app/classes/web/routes/api/crafty/config/server_dir.py new file mode 100644 index 00000000..4e41be14 --- /dev/null +++ b/app/classes/web/routes/api/crafty/config/server_dir.py @@ -0,0 +1,115 @@ +from jsonschema import ValidationError, validate +import orjson +from playhouse.shortcuts import model_to_dict +from app.classes.web.base_api_handler import BaseApiHandler + +server_dir_schema = { + "type": "object", + "properties": { + "new_dir": {"type": "string"}, + }, + "additionalProperties": False, + "minProperties": 1, +} + + +class ApiCraftyConfigServerDirHandler(BaseApiHandler): + def get(self): + auth_data = self.authenticate_user() + if not auth_data: + return + ( + _, + _, + _, + superuser, + _, + ) = auth_data + + # GET /api/v2/roles?ids=true + get_only_ids = self.get_query_argument("ids", None) == "true" + + if not superuser: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + + self.finish_json( + 200, + { + "status": "ok", + "data": self.controller.roles.get_all_role_ids() + if get_only_ids + else [model_to_dict(r) for r in self.controller.roles.get_all_roles()], + }, + ) + + def patch(self): + auth_data = self.authenticate_user() + if not auth_data: + return + ( + _, + _, + _, + _, + _, + ) = auth_data + + if not auth_data: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + + if not auth_data[4]["superuser"]: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + if self.helper.is_env_docker(): + raise NotImplementedError + + try: + data = orjson.loads(self.request.body) + except orjson.decoder.JSONDecodeError as e: + return self.finish_json( + 400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)} + ) + + try: + validate(data, server_dir_schema) + except ValidationError as e: + return self.finish_json( + 400, + { + "status": "error", + "error": "INVALID_JSON_SCHEMA", + "error_data": str(e), + }, + ) + if self.helper.dir_migration: + return self.finish_json( + 400, + { + "status": "error", + "error": "IN PROGRESS", + "error_data": "Migration already in progress. Please be patient", + }, + ) + for server in self.controller.servers.get_all_servers_stats(): + if server["stats"]["running"]: + return self.finish_json( + 400, + { + "status": "error", + "error": "SERVER RUNNING", + }, + ) + + new_dir = data["new_dir"] + self.controller.update_master_server_dir(new_dir, auth_data[4]["user_id"]) + + self.controller.management.add_to_audit_log( + auth_data[4]["user_id"], + f"updated master servers dir to {new_dir}/servers", + server_id=0, + source_ip=self.get_remote_ip(), + ) + + self.finish_json( + 200, + {"status": "ok"}, + ) diff --git a/app/frontend/templates/panel/panel_config.html b/app/frontend/templates/panel/panel_config.html index 5dc8c253..898eb96f 100644 --- a/app/frontend/templates/panel/panel_config.html +++ b/app/frontend/templates/panel/panel_config.html @@ -326,24 +326,35 @@ }); } - $("#server-path").submit(function (e) { + $("#server-path").submit(async function (e) { var token = getCookie("_xsrf") e.preventDefault(); $("#submit-status").html(''); let path = $("#global_server_path").val(); - let encoded = encodeURIComponent(path); + path; console.log(path) - $.ajax({ - type: "POST", - headers: { 'X-XSRFToken': token }, - dataType: "text", - url: '/ajax/update_server_dir', - data: { - "server_dir": encoded, - }, - }); + var token = getCookie("_xsrf") + let res = await fetch(`/api/v2/crafty/config/servers_dir`, { + method: 'PATCH', + headers: { + 'X-XSRFToken': token + }, + body: JSON.stringify({"new_dir": path}), + }); + let responseData = await res.json(); + if (responseData.status === "ok") { + serverFileContent = text; + setSaveStatus(true) + + } else { + + bootbox.alert({ + title: responseData.status, + message: responseData.error + }); + } }); $(document).ready(function () {