mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add unzip/dir request handler to api v2
This commit is contained in:
parent
d9e405e56c
commit
27f6c4c926
@ -325,3 +325,12 @@ class FileHelpers:
|
||||
else:
|
||||
return "false"
|
||||
return
|
||||
|
||||
def unzip_server(self, zip_path, user_id):
|
||||
if Helpers.check_file_perms(zip_path):
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
||||
# extracts archive to temp directory
|
||||
zip_ref.extractall(temp_dir)
|
||||
if user_id:
|
||||
return temp_dir
|
||||
|
@ -1135,17 +1135,6 @@ class Helpers:
|
||||
</input></div><li>"""
|
||||
return output
|
||||
|
||||
def unzip_server(self, zip_path, user_id):
|
||||
if Helpers.check_file_perms(zip_path):
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
||||
# extracts archive to temp directory
|
||||
zip_ref.extractall(temp_dir)
|
||||
if user_id:
|
||||
self.websocket_helper.broadcast_user(
|
||||
user_id, "send_temp_path", {"path": temp_dir}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def unzip_backup_archive(backup_path, zip_name):
|
||||
zip_path = os.path.join(backup_path, zip_name)
|
||||
|
@ -41,10 +41,10 @@ scheduler_intervals = {
|
||||
class TasksManager:
|
||||
controller: Controller
|
||||
|
||||
def __init__(self, helper, controller):
|
||||
def __init__(self, helper, controller, file_helper):
|
||||
self.helper: Helpers = helper
|
||||
self.controller: Controller = controller
|
||||
self.tornado: Webserver = Webserver(helper, controller, self)
|
||||
self.tornado: Webserver = Webserver(helper, controller, self, file_helper)
|
||||
try:
|
||||
self.tz = get_localzone()
|
||||
except ZoneInfoNotFoundError as e:
|
||||
|
@ -9,7 +9,7 @@ import bleach
|
||||
import tornado.web
|
||||
import tornado.escape
|
||||
|
||||
from app.classes.shared.console import Console
|
||||
from app.classes.shared.file_helpers import FileHelpers
|
||||
from app.classes.shared.helpers import Helpers
|
||||
from app.classes.shared.server import ServerOutBuf
|
||||
from app.classes.web.base_handler import BaseHandler
|
||||
@ -148,32 +148,6 @@ class AjaxHandler(BaseHandler):
|
||||
self.controller.cached_login = "login_1.jpg"
|
||||
return
|
||||
|
||||
elif page == "unzip_server":
|
||||
path = urllib.parse.unquote(self.get_argument("path", ""))
|
||||
if not path:
|
||||
path = os.path.join(
|
||||
self.controller.project_root,
|
||||
"imports",
|
||||
urllib.parse.unquote(self.get_argument("file", "")),
|
||||
)
|
||||
if Helpers.check_file_exists(path):
|
||||
self.helper.unzip_server(path, exec_user["user_id"])
|
||||
else:
|
||||
user_id = exec_user["user_id"]
|
||||
if user_id:
|
||||
time.sleep(5)
|
||||
user_lang = self.controller.users.get_user_lang_by_id(user_id)
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
user_id,
|
||||
"send_start_error",
|
||||
{
|
||||
"error": self.helper.translation.translate(
|
||||
"error", "no-file", user_lang
|
||||
)
|
||||
},
|
||||
)
|
||||
return
|
||||
|
||||
elif page == "jar_cache":
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Not a super user")
|
||||
@ -208,25 +182,3 @@ class AjaxHandler(BaseHandler):
|
||||
new_dir = urllib.parse.unquote(self.get_argument("server_dir"))
|
||||
self.controller.update_master_server_dir(new_dir, exec_user["user_id"])
|
||||
return
|
||||
|
||||
def check_server_id(self, server_id, page_name):
|
||||
if server_id is None:
|
||||
logger.warning(
|
||||
f"Server ID not defined in {page_name} ajax call ({server_id})"
|
||||
)
|
||||
Console.warning(
|
||||
f"Server ID not defined in {page_name} ajax call ({server_id})"
|
||||
)
|
||||
return
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
# does this server id exist?
|
||||
if not self.controller.servers.server_id_exists(server_id):
|
||||
logger.warning(
|
||||
f"Server ID not found in {page_name} ajax call ({server_id})"
|
||||
)
|
||||
Console.warning(
|
||||
f"Server ID not found in {page_name} ajax call ({server_id})"
|
||||
)
|
||||
return
|
||||
return True
|
||||
|
@ -8,6 +8,7 @@ import tornado.web
|
||||
from app.classes.models.crafty_permissions import EnumPermissionsCrafty
|
||||
from app.classes.models.users import ApiKeys
|
||||
from app.classes.shared.helpers import Helpers
|
||||
from app.classes.shared.file_helpers import FileHelpers
|
||||
from app.classes.shared.main_controller import Controller
|
||||
from app.classes.shared.translation import Translation
|
||||
from app.classes.models.management import DatabaseShortcuts
|
||||
@ -24,15 +25,22 @@ class BaseHandler(tornado.web.RequestHandler):
|
||||
helper: Helpers
|
||||
controller: Controller
|
||||
translator: Translation
|
||||
file_helper: FileHelpers
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
def initialize(
|
||||
self, helper=None, controller=None, tasks_manager=None, translator=None
|
||||
self,
|
||||
helper=None,
|
||||
controller=None,
|
||||
tasks_manager=None,
|
||||
translator=None,
|
||||
file_helper=None,
|
||||
):
|
||||
self.helper = helper
|
||||
self.controller = controller
|
||||
self.tasks_manager = tasks_manager
|
||||
self.translator = translator
|
||||
self.file_helper = file_helper
|
||||
|
||||
def set_default_headers(self) -> None:
|
||||
"""
|
||||
|
@ -51,6 +51,7 @@ 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.clogs.index import ApiCraftyLogIndexHandler
|
||||
from app.classes.web.routes.api.crafty.imports.index import ApiImportFilesIndexHandler
|
||||
|
||||
|
||||
def api_handlers(handler_args):
|
||||
@ -76,6 +77,11 @@ def api_handlers(handler_args):
|
||||
ApiCraftyLogIndexHandler,
|
||||
handler_args,
|
||||
),
|
||||
(
|
||||
r"/api/v2/import/file/unzip/?",
|
||||
ApiImportFilesIndexHandler,
|
||||
handler_args,
|
||||
),
|
||||
# User routes
|
||||
(
|
||||
r"/api/v2/users/?",
|
||||
|
123
app/classes/web/routes/api/crafty/imports/index.py
Normal file
123
app/classes/web/routes/api/crafty/imports/index.py
Normal file
@ -0,0 +1,123 @@
|
||||
import os
|
||||
import logging
|
||||
import json
|
||||
import html
|
||||
from jsonschema import validate
|
||||
from jsonschema.exceptions import ValidationError
|
||||
from app.classes.models.crafty_permissions import EnumPermissionsCrafty
|
||||
from app.classes.shared.helpers import Helpers
|
||||
from app.classes.web.base_api_handler import BaseApiHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
files_get_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page": {"type": "string", "minLength": 1},
|
||||
"folder": {"type": "string"},
|
||||
"unzip": {"type": "boolean", "default": "True"},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"minProperties": 1,
|
||||
}
|
||||
|
||||
|
||||
class ApiImportFilesIndexHandler(BaseApiHandler):
|
||||
def post(self):
|
||||
auth_data = self.authenticate_user()
|
||||
if not auth_data:
|
||||
return
|
||||
|
||||
if (
|
||||
EnumPermissionsCrafty.SERVER_CREATION
|
||||
not in self.controller.crafty_perms.get_crafty_permissions_list(
|
||||
auth_data[4]["user_id"]
|
||||
)
|
||||
and not auth_data[4]["superuser"]
|
||||
):
|
||||
# if the user doesn't have Files or Backup permission, return an error
|
||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||
|
||||
try:
|
||||
data = json.loads(self.request.body)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
return self.finish_json(
|
||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||
)
|
||||
try:
|
||||
validate(data, files_get_schema)
|
||||
except ValidationError as e:
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
# TODO: limit some columns for specific permissions?
|
||||
folder = data["folder"]
|
||||
user_id = auth_data[4]["user_id"]
|
||||
root_path = False
|
||||
if data["unzip"]:
|
||||
if Helpers.check_file_exists(folder):
|
||||
folder = self.file_helper.unzip_server(folder, user_id)
|
||||
root_path = True
|
||||
else:
|
||||
if user_id:
|
||||
user_lang = self.controller.users.get_user_lang_by_id(user_id)
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
user_id,
|
||||
"send_start_error",
|
||||
{
|
||||
"error": self.helper.translation.translate(
|
||||
"error", "no-file", user_lang
|
||||
)
|
||||
},
|
||||
)
|
||||
else:
|
||||
if not self.helper.check_path_exists(folder):
|
||||
if user_id:
|
||||
user_lang = self.controller.users.get_user_lang_by_id(user_id)
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
user_id,
|
||||
"send_start_error",
|
||||
{
|
||||
"error": self.helper.translation.translate(
|
||||
"error", "no-file", user_lang
|
||||
)
|
||||
},
|
||||
)
|
||||
return_json = {
|
||||
"root_path": {
|
||||
"path": folder,
|
||||
"top": root_path,
|
||||
}
|
||||
}
|
||||
|
||||
dir_list = []
|
||||
unsorted_files = []
|
||||
file_list = os.listdir(folder)
|
||||
for item in file_list:
|
||||
if os.path.isdir(os.path.join(folder, item)):
|
||||
dir_list.append(item)
|
||||
else:
|
||||
unsorted_files.append(item)
|
||||
file_list = sorted(dir_list, key=str.casefold) + sorted(
|
||||
unsorted_files, key=str.casefold
|
||||
)
|
||||
for raw_filename in file_list:
|
||||
filename = html.escape(raw_filename)
|
||||
rel = os.path.join(folder, raw_filename)
|
||||
dpath = os.path.join(folder, filename)
|
||||
dpath = self.helper.wtol_path(dpath)
|
||||
if os.path.isdir(rel):
|
||||
return_json[filename] = {
|
||||
"path": dpath,
|
||||
"dir": True,
|
||||
}
|
||||
else:
|
||||
return_json[filename] = {
|
||||
"path": dpath,
|
||||
"dir": False,
|
||||
}
|
||||
self.finish_json(200, {"status": "ok", "data": return_json})
|
@ -48,13 +48,14 @@ class Webserver:
|
||||
controller: Controller
|
||||
helper: Helpers
|
||||
|
||||
def __init__(self, helper, controller, tasks_manager):
|
||||
def __init__(self, helper, controller, tasks_manager, file_helper):
|
||||
self.ioloop = None
|
||||
self.http_server = None
|
||||
self.https_server = None
|
||||
self.helper = helper
|
||||
self.controller = controller
|
||||
self.tasks_manager = tasks_manager
|
||||
self.file_helper = file_helper
|
||||
self._asyncio_patch()
|
||||
|
||||
@staticmethod
|
||||
@ -146,6 +147,7 @@ class Webserver:
|
||||
"controller": self.controller,
|
||||
"tasks_manager": self.tasks_manager,
|
||||
"translator": self.helper.translation,
|
||||
"file_helper": self.file_helper,
|
||||
}
|
||||
handlers = [
|
||||
(r"/", DefaultHandler, handler_args),
|
||||
|
@ -18,12 +18,18 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
|
||||
io_loop = None
|
||||
|
||||
def initialize(
|
||||
self, helper=None, controller=None, tasks_manager=None, translator=None
|
||||
self,
|
||||
helper=None,
|
||||
controller=None,
|
||||
tasks_manager=None,
|
||||
translator=None,
|
||||
file_helper=None,
|
||||
):
|
||||
self.helper = helper
|
||||
self.controller = controller
|
||||
self.tasks_manager = tasks_manager
|
||||
self.translator = translator
|
||||
self.file_helper = file_helper
|
||||
self.io_loop = tornado.ioloop.IOLoop.current()
|
||||
|
||||
def get_remote_ip(self):
|
||||
|
2
main.py
2
main.py
@ -171,7 +171,7 @@ if __name__ == "__main__":
|
||||
Console.info("Remote change complete.")
|
||||
|
||||
import3 = Import3(helper, controller)
|
||||
tasks_manager = TasksManager(helper, controller)
|
||||
tasks_manager = TasksManager(helper, controller, file_helper)
|
||||
tasks_manager.start_webserver()
|
||||
|
||||
def signal_handler(signum, _frame):
|
||||
|
Loading…
Reference in New Issue
Block a user