diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1245e3ff..4af8ce1f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,13 +1,15 @@
# Changelog
-## --- [4.1.4] - 2023/TBD
+## --- [4.2.0] - 2023/TBD
### New features
-TBD
+- Finish and Activate Arcadia notification backend ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/621))
### Bug fixes
- PWA: Removed the custom offline page in favour of browser default ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/607))
- Fix hidden servers appearing visible on public mobile status page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/612))
- Correctly handle if a server returns a string instead of json data on socket ping ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/614))
+- Bump tornado to resolve #269 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/623))
+- Bump crypto to resolve #267 & #268 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/622))
### Refactor
-- Refractor/Replace bleach with nh3 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/616))
+- Consolidate remaining frontend functions into API V2, and remove ajax internal API ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/585))
### Tweaks
- Polish/Enhance display for InApp Documentation ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/613))
- Add get_users command to Crafty's console ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/620))
diff --git a/README.md b/README.md
index eb3cd642..5d2379c8 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
[![Crafty Logo](app/frontend/static/assets/images/logo_long.svg)](https://craftycontrol.com)
-# Crafty Controller 4.1.4
+# Crafty Controller 4.2.0
> Python based Control Panel for your Minecraft Server
## What is Crafty Controller?
diff --git a/app/classes/controllers/management_controller.py b/app/classes/controllers/management_controller.py
index 7c423da9..cda74fea 100644
--- a/app/classes/controllers/management_controller.py
+++ b/app/classes/controllers/management_controller.py
@@ -79,8 +79,8 @@ class ManagementController:
# Audit_Log Methods
# **********************************************************************************
@staticmethod
- def get_actity_log():
- return HelpersManagement.get_actity_log()
+ def get_activity_log():
+ return HelpersManagement.get_activity_log()
def add_to_audit_log(self, user_id, log_msg, server_id=None, source_ip=None):
return self.management_helper.add_to_audit_log(
diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py
index 667e01b4..99147a63 100644
--- a/app/classes/controllers/users_controller.py
+++ b/app/classes/controllers/users_controller.py
@@ -31,7 +31,7 @@ class UsersController:
for permission in PermissionsCrafty.get_permissions_list()
],
},
- "quantity": {"type": "number", "minimum": 0},
+ "quantity": {"type": "number", "minimum": -1},
"enabled": {"type": "boolean"},
}
self.user_jsonschema_props: t.Final = {
@@ -46,7 +46,7 @@ class UsersController:
"password": {
"type": "string",
"maxLength": 20,
- "minLength": 4,
+ "minLength": 6,
"examples": ["crafty"],
"title": "Password",
},
@@ -73,6 +73,8 @@ class UsersController:
"examples": [False],
"title": "Superuser",
},
+ "manager": {"type": ["integer", "null"]},
+ "theme": {"type": "string"},
"permissions": {
"type": "array",
"items": {
@@ -84,7 +86,7 @@ class UsersController:
"roles": {
"type": "array",
"items": {
- "type": "string",
+ "type": "integer",
"minLength": 1,
},
},
diff --git a/app/classes/models/management.py b/app/classes/models/management.py
index 1213bda0..fc0a1eb6 100644
--- a/app/classes/models/management.py
+++ b/app/classes/models/management.py
@@ -146,7 +146,7 @@ class HelpersManagement:
# Audit_Log Methods
# **********************************************************************************
@staticmethod
- def get_actity_log():
+ def get_activity_log():
query = AuditLog.select()
return DatabaseShortcuts.return_db_rows(query)
diff --git a/app/classes/models/users.py b/app/classes/models/users.py
index b0612017..ccd8f1b0 100644
--- a/app/classes/models/users.py
+++ b/app/classes/models/users.py
@@ -45,6 +45,7 @@ class Users(BaseModel):
manager = IntegerField(default=None, null=True)
pfp = CharField(default="/static/assets/images/faces-clipart/pic-3.png")
theme = CharField(default="default")
+ cleared_notifs = CharField(default="default")
class Meta:
table_name = "users"
@@ -171,6 +172,7 @@ class HelperUsers:
"roles": [],
"servers": [],
"support_logs": "",
+ "cleared_notifs": "",
}
user = model_to_dict(Users.get(Users.user_id == user_id))
diff --git a/app/classes/shared/file_helpers.py b/app/classes/shared/file_helpers.py
index 53a5a56a..cc09dc4f 100644
--- a/app/classes/shared/file_helpers.py
+++ b/app/classes/shared/file_helpers.py
@@ -327,20 +327,11 @@ class FileHelpers:
return "false"
return
- # TODO Look if not redundant with the precendent function
- # TODO Prefixed ajax_ to differentiate and not broke things
-
- def ajax_unzip_server(self, zip_path, user_id):
+ 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:
- WebSocketManager().broadcast_user(
- user_id, "send_temp_path", {"path": temp_dir}
- )
-
- def ajax_backup_select(self, path, user_id):
- if user_id:
- WebSocketManager().broadcast_user(user_id, "send_temp_path", {"path": path})
+ return temp_dir
diff --git a/app/classes/shared/helpers.py b/app/classes/shared/helpers.py
index 30f70d3a..ba9c5a28 100644
--- a/app/classes/shared/helpers.py
+++ b/app/classes/shared/helpers.py
@@ -577,20 +577,16 @@ class Helpers:
return version_data
- @staticmethod
- def get_announcements():
- data = (
- '[{"id":"1","date":"Unknown",'
- '"title":"Error getting Announcements",'
- '"desc":"Error getting Announcements","link":""}]'
- )
-
+ def get_announcements(self):
+ data = []
try:
- response = requests.get("https://craftycontrol.com/notify.json", timeout=2)
+ response = requests.get("https://craftycontrol.com/notify", timeout=2)
data = json.loads(response.content)
except Exception as e:
logger.error(f"Failed to fetch notifications with error: {e}")
+ if self.update_available:
+ data.append(self.update_available)
return data
def get_version_string(self):
@@ -1090,87 +1086,6 @@ class Helpers:
return data
- def generate_tree(self, folder, output=""):
- 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)
- elif str(item) != self.ignored_names:
- 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)
- if os.path.isdir(rel):
- if filename not in self.ignored_names:
- output += f"""
- \n
-
-
-
- {filename}
-
-
- \n"""
- else:
- if filename not in self.ignored_names:
- output += f"""
- {filename}"""
- return output
-
- def generate_dir(self, folder, output=""):
- 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)
- elif str(item) != self.ignored_names:
- unsorted_files.append(item)
- file_list = sorted(dir_list, key=str.casefold) + sorted(
- unsorted_files, key=str.casefold
- )
- output += f""""""
- for raw_filename in file_list:
- filename = html.escape(raw_filename)
- dpath = os.path.join(folder, filename)
- rel = os.path.join(folder, raw_filename)
- if os.path.isdir(rel):
- if filename not in self.ignored_names:
- output += f"""-
- \n
-
-
-
- {filename}
-
-
- """
- else:
- if filename not in self.ignored_names:
- output += f"""
-
- {filename}
"""
- output += "
\n"
- return output
-
@staticmethod
def generate_zip_tree(folder, output=""):
file_list = os.listdir(folder)
diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py
index 2a299934..4100b21e 100644
--- a/app/classes/shared/main_controller.py
+++ b/app/classes/shared/main_controller.py
@@ -5,6 +5,7 @@ from datetime import datetime
import platform
import shutil
import time
+import json
import logging
import threading
from peewee import DoesNotExist
@@ -85,6 +86,17 @@ class Controller:
def set_project_root(self, root_dir):
self.project_root = root_dir
+ def set_config_json(self, data):
+ current_config = self.helper.get_all_settings()
+ for key in current_config:
+ if key in data:
+ current_config[key] = data[key]
+ keys = list(current_config.keys())
+ keys.sort()
+ sorted_data = {i: current_config[i] for i in keys}
+ with open(self.helper.settings_file, "w", encoding="utf-8") as f:
+ json.dump(sorted_data, f, indent=4)
+
def package_support_logs(self, exec_user):
if exec_user["preparing"]:
return
@@ -299,15 +311,6 @@ class Controller:
Helpers.ensure_dir_exists(new_server_path)
Helpers.ensure_dir_exists(backup_path)
- def _copy_import_dir_files(existing_server_path):
- existing_server_path = Helpers.get_os_understandable_path(
- existing_server_path
- )
- try:
- FileHelpers.copy_dir(existing_server_path, new_server_path, True)
- except shutil.Error as ex:
- logger.error(f"Server import failed with error: {ex}")
-
def _create_server_properties_if_needed(port, empty=False):
properties_file = os.path.join(new_server_path, "server.properties")
has_properties = os.path.exists(properties_file)
@@ -335,22 +338,25 @@ class Controller:
server_file = f"{create_data['type']}-{create_data['version']}.jar"
# Create an EULA file
- with open(
- os.path.join(new_server_path, "eula.txt"), "w", encoding="utf-8"
- ) as file:
- file.write(
- "eula=" + ("true" if create_data["agree_to_eula"] else "false")
- )
+ if "agree_to_eula" in create_data:
+ with open(
+ os.path.join(new_server_path, "eula.txt"), "w", encoding="utf-8"
+ ) as file:
+ file.write(
+ "eula="
+ + ("true" if create_data["agree_to_eula"] else "false")
+ )
elif root_create_data["create_type"] == "import_server":
- _copy_import_dir_files(create_data["existing_server_path"])
server_file = create_data["jarfile"]
elif root_create_data["create_type"] == "import_zip":
# TODO: Copy files from the zip file to the new server directory
server_file = create_data["jarfile"]
raise NotImplementedError("Not yet implemented")
- _create_server_properties_if_needed(
- create_data["server_properties_port"],
- )
+ # self.import_helper.import_java_zip_server()
+ if data["create_type"] == "minecraft_java":
+ _create_server_properties_if_needed(
+ create_data["server_properties_port"],
+ )
min_mem = create_data["mem_min"]
max_mem = create_data["mem_max"]
@@ -363,30 +369,72 @@ class Controller:
def _wrap_jar_if_windows():
return f'"{server_file}"' if Helpers.is_os_windows() else server_file
- server_command = (
- f"java -Xms{_gibs_to_mibs(min_mem)}M "
- f"-Xmx{_gibs_to_mibs(max_mem)}M "
- f"-jar {_wrap_jar_if_windows()} nogui"
- )
+ if root_create_data["create_type"] == "download_jar":
+ if Helpers.is_os_windows():
+ # Let's check for and setup for install server commands
+ if create_data["type"] == "forge":
+ server_command = (
+ f"java -Xms{Helpers.float_to_string(min_mem)}M "
+ f"-Xmx{Helpers.float_to_string(max_mem)}M "
+ f'-jar "{server_file}" --installServer'
+ )
+ else:
+ server_command = (
+ f"java -Xms{Helpers.float_to_string(min_mem)}M "
+ f"-Xmx{Helpers.float_to_string(max_mem)}M "
+ f'-jar "{server_file}" nogui'
+ )
+ else:
+ if create_data["type"] == "forge":
+ server_command = (
+ f"java -Xms{Helpers.float_to_string(min_mem)}M "
+ f"-Xmx{Helpers.float_to_string(max_mem)}M "
+ f"-jar {server_file} --installServer"
+ )
+ else:
+ server_command = (
+ f"java -Xms{Helpers.float_to_string(min_mem)}M "
+ f"-Xmx{Helpers.float_to_string(max_mem)}M "
+ f"-jar {server_file} nogui"
+ )
+ else:
+ server_command = (
+ f"java -Xms{_gibs_to_mibs(min_mem)}M "
+ f"-Xmx{_gibs_to_mibs(max_mem)}M "
+ f"-jar {_wrap_jar_if_windows()} nogui"
+ )
+
elif data["create_type"] == "minecraft_bedrock":
if root_create_data["create_type"] == "import_server":
existing_server_path = Helpers.get_os_understandable_path(
create_data["existing_server_path"]
)
- try:
- FileHelpers.copy_dir(existing_server_path, new_server_path, True)
- except shutil.Error as ex:
- logger.error(f"Server import failed with error: {ex}")
+ if Helpers.is_os_windows():
+ server_command = (
+ f'"{os.path.join(new_server_path, create_data["executable"])}"'
+ )
+ else:
+ server_command = f"./{create_data['executable']}"
+ logger.debug("command: " + server_command)
+ server_file = create_data["executable"]
elif root_create_data["create_type"] == "import_zip":
# TODO: Copy files from the zip file to the new server directory
raise NotImplementedError("Not yet implemented")
+ else:
+ server_file = "bedrock_server"
+ if Helpers.is_os_windows():
+ # if this is windows we will override the linux bedrock server name.
+ server_file = "bedrock_server.exe"
+ full_jar_path = os.path.join(new_server_path, server_file)
+
+ if self.helper.is_os_windows():
+ server_command = f'"{full_jar_path}"'
+ else:
+ server_command = f"./{server_file}"
_create_server_properties_if_needed(0, True)
- server_command = create_data["command"]
- server_file = (
- "./bedrock_server" # HACK: This is a hack to make the server start
- )
+ server_command = create_data.get("command", server_command)
elif data["create_type"] == "custom":
# TODO: working_directory, executable_update
if root_create_data["create_type"] == "raw_exec":
@@ -450,131 +498,85 @@ class Controller:
server_host=monitoring_host,
server_type=monitoring_type,
)
-
- if (
- data["create_type"] == "minecraft_java"
- and root_create_data["create_type"] == "download_jar"
- ):
- # modded update urls from server jars will only update the installer
- if create_data["category"] != "modded":
- server_obj = self.servers.get_server_obj(new_server_id)
- url = (
- f"https://serverjars.com/api/fetchJar/{create_data['category']}"
- f"/{create_data['type']}/{create_data['version']}"
+ if data["create_type"] == "minecraft_java":
+ if root_create_data["create_type"] == "download_jar":
+ # modded update urls from server jars will only update the installer
+ if create_data["category"] != "modded":
+ server_obj = self.servers.get_server_obj(new_server_id)
+ url = (
+ f"https://serverjars.com/api/fetchJar/{create_data['category']}"
+ f"/{create_data['type']}/{create_data['version']}"
+ )
+ server_obj.executable_update_url = url
+ self.servers.update_server(server_obj)
+ self.server_jars.download_jar(
+ create_data["category"],
+ create_data["type"],
+ create_data["version"],
+ full_jar_path,
+ new_server_id,
)
- server_obj.executable_update_url = url
- self.servers.update_server(server_obj)
- self.server_jars.download_jar(
- create_data["category"],
- create_data["type"],
- create_data["version"],
- full_jar_path,
- new_server_id,
- )
+ elif root_create_data["create_type"] == "import_server":
+ ServersController.set_import(new_server_id)
+ self.import_helper.import_jar_server(
+ create_data["existing_server_path"],
+ new_server_path,
+ monitoring_port,
+ new_server_id,
+ )
+ elif root_create_data["create_type"] == "import_zip":
+ ServersController.set_import(new_server_id)
+
+ elif data["create_type"] == "minecraft_bedrock":
+ if root_create_data["create_type"] == "download_exe":
+ ServersController.set_import(new_server_id)
+ self.import_helper.download_bedrock_server(
+ new_server_path, new_server_id
+ )
+ elif root_create_data["create_type"] == "import_server":
+ ServersController.set_import(new_server_id)
+ full_exe_path = os.path.join(new_server_path, create_data["executable"])
+ self.import_helper.import_bedrock_server(
+ create_data["existing_server_path"],
+ new_server_path,
+ monitoring_port,
+ full_exe_path,
+ new_server_id,
+ )
+ elif root_create_data["create_type"] == "import_zip":
+ ServersController.set_import(new_server_id)
+ full_exe_path = os.path.join(new_server_path, create_data["executable"])
+ self.import_helper.import_bedrock_zip_server(
+ create_data["zip_path"],
+ new_server_path,
+ os.path.join(create_data["zip_root"], create_data["executable"]),
+ monitoring_port,
+ new_server_id,
+ )
+
+ exec_user = self.users.get_user_by_id(int(user_id))
+ captured_roles = data.get("roles", [])
+ # These lines create a new Role for the Server with full permissions
+ # and add the user to it if he's not a superuser
+ if len(captured_roles) == 0:
+ if not exec_user["superuser"]:
+ new_server_uuid = self.servers.get_server_data_by_id(new_server_id).get(
+ "server_uuid"
+ )
+ role_id = self.roles.add_role(
+ f"Creator of Server with uuid={new_server_uuid}",
+ exec_user["user_id"],
+ )
+ self.server_perms.add_role_server(new_server_id, role_id, "11111111")
+ self.users.add_role_to_user(exec_user["user_id"], role_id)
+
+ else:
+ for role in captured_roles:
+ role_id = role
+ self.server_perms.add_role_server(new_server_id, role_id, "11111111")
return new_server_id, server_fs_uuid
- def create_jar_server(
- self,
- jar: str,
- server: str,
- version: str,
- name: str,
- min_mem: int,
- max_mem: int,
- port: int,
- user_id: int,
- ):
- server_id = Helpers.create_uuid()
- server_dir = os.path.join(self.helper.servers_dir, server_id)
- backup_path = os.path.join(self.helper.backup_path, server_id)
- if Helpers.is_os_windows():
- server_dir = Helpers.wtol_path(server_dir)
- backup_path = Helpers.wtol_path(backup_path)
- server_dir.replace(" ", "^ ")
- backup_path.replace(" ", "^ ")
-
- server_file = f"{server}-{version}.jar"
-
- # make the dir - perhaps a UUID?
- Helpers.ensure_dir_exists(server_dir)
- Helpers.ensure_dir_exists(backup_path)
-
- try:
- # do a eula.txt
- with open(
- os.path.join(server_dir, "eula.txt"), "w", encoding="utf-8"
- ) as file:
- file.write("eula=false")
- file.close()
-
- # setup server.properties with the port
- with open(
- os.path.join(server_dir, "server.properties"), "w", encoding="utf-8"
- ) as file:
- file.write(f"server-port={port}")
- file.close()
-
- except Exception as e:
- logger.error(f"Unable to create required server files due to :{e}")
- return False
-
- if Helpers.is_os_windows():
- # Let's check for and setup for install server commands
- if server == "forge":
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f'-jar "{server_file}" --installServer'
- )
- else:
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f'-jar "{server_file}" nogui'
- )
- else:
- if server == "forge":
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f"-jar {server_file} --installServer"
- )
- else:
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f"-jar {server_file} nogui"
- )
- server_log_file = "./logs/latest.log"
- server_stop = "stop"
-
- new_id = self.register_server(
- name,
- server_id,
- server_dir,
- backup_path,
- server_command,
- server_file,
- server_log_file,
- server_stop,
- port,
- user_id,
- server_type="minecraft-java",
- )
- # modded update urls from server jars will only update the installer
- if jar != "modded":
- server_obj = self.servers.get_server_obj(new_id)
- url = f"https://serverjars.com/api/fetchJar/{jar}/{server}/{version}"
- server_obj.executable_update_url = url
- self.servers.update_server(server_obj)
- # download the jar
- self.server_jars.download_jar(
- jar, server, version, os.path.join(server_dir, server_file), new_id
- )
-
- return new_id
-
@staticmethod
def verify_jar_server(server_path: str, server_jar: str):
server_path = Helpers.get_os_understandable_path(server_path)
@@ -592,123 +594,6 @@ class Controller:
return False
return True
- def import_jar_server(
- self,
- server_name: str,
- server_path: str,
- server_jar: str,
- min_mem: int,
- max_mem: int,
- port: int,
- user_id: int,
- ):
- server_id = Helpers.create_uuid()
- new_server_dir = os.path.join(self.helper.servers_dir, server_id)
- backup_path = os.path.join(self.helper.backup_path, server_id)
- if Helpers.is_os_windows():
- new_server_dir = Helpers.wtol_path(new_server_dir)
- backup_path = Helpers.wtol_path(backup_path)
- new_server_dir.replace(" ", "^ ")
- backup_path.replace(" ", "^ ")
-
- Helpers.ensure_dir_exists(new_server_dir)
- Helpers.ensure_dir_exists(backup_path)
- server_path = Helpers.get_os_understandable_path(server_path)
-
- full_jar_path = os.path.join(new_server_dir, server_jar)
-
- if Helpers.is_os_windows():
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f'-jar "{full_jar_path}" nogui'
- )
- else:
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f"-jar {full_jar_path} nogui"
- )
- server_log_file = "./logs/latest.log"
- server_stop = "stop"
-
- new_id = self.register_server(
- server_name,
- server_id,
- new_server_dir,
- backup_path,
- server_command,
- server_jar,
- server_log_file,
- server_stop,
- port,
- user_id,
- server_type="minecraft-java",
- )
- ServersController.set_import(new_id)
- self.import_helper.import_jar_server(server_path, new_server_dir, port, new_id)
- return new_id
-
- def import_zip_server(
- self,
- server_name: str,
- zip_path: str,
- server_jar: str,
- min_mem: int,
- max_mem: int,
- port: int,
- user_id: int,
- ):
- server_id = Helpers.create_uuid()
- new_server_dir = os.path.join(self.helper.servers_dir, server_id)
- backup_path = os.path.join(self.helper.backup_path, server_id)
- if Helpers.is_os_windows():
- new_server_dir = Helpers.wtol_path(new_server_dir)
- backup_path = Helpers.wtol_path(backup_path)
- new_server_dir.replace(" ", "^ ")
- backup_path.replace(" ", "^ ")
-
- temp_dir = Helpers.get_os_understandable_path(zip_path)
- Helpers.ensure_dir_exists(new_server_dir)
- Helpers.ensure_dir_exists(backup_path)
-
- full_jar_path = os.path.join(new_server_dir, server_jar)
-
- if Helpers.is_os_windows():
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f'-jar "{full_jar_path}" nogui'
- )
- else:
- server_command = (
- f"java -Xms{Helpers.float_to_string(min_mem)}M "
- f"-Xmx{Helpers.float_to_string(max_mem)}M "
- f"-jar {full_jar_path} nogui"
- )
- logger.debug("command: " + server_command)
- server_log_file = "./logs/latest.log"
- server_stop = "stop"
-
- new_id = self.register_server(
- server_name,
- server_id,
- new_server_dir,
- backup_path,
- server_command,
- server_jar,
- server_log_file,
- server_stop,
- port,
- user_id,
- server_type="minecraft-java",
- )
- ServersController.set_import(new_id)
- self.import_helper.import_java_zip_server(
- temp_dir, new_server_dir, port, new_id
- )
- return new_id
-
# **********************************************************************************
# BEDROCK IMPORTS
# **********************************************************************************
@@ -1065,6 +950,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/shared/tasks.py b/app/classes/shared/tasks.py
index d35cf8dd..3bb3336a 100644
--- a/app/classes/shared/tasks.py
+++ b/app/classes/shared/tasks.py
@@ -42,10 +42,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:
@@ -727,12 +727,21 @@ class TasksManager:
def check_for_updates(self):
logger.info("Checking for Crafty updates...")
self.helper.update_available = self.helper.check_remote_version()
+ remote = self.helper.update_available
if self.helper.update_available:
logger.info(f"Found new version {self.helper.update_available}")
else:
logger.info(
"No updates found! You are on the most up to date Crafty version."
)
+ if self.helper.update_available:
+ self.helper.update_available = {
+ "id": str(remote),
+ "title": f"{remote} Update Available",
+ "date": "",
+ "desc": "Release notes are available by clicking this notification.",
+ "link": "https://gitlab.com/crafty-controller/crafty-4/-/releases",
+ }
logger.info("Refreshing Gravatar PFPs...")
for user in HelperUsers.get_all_users():
if user.email:
diff --git a/app/classes/web/ajax_handler.py b/app/classes/web/ajax_handler.py
deleted file mode 100644
index 451f16d0..00000000
--- a/app/classes/web/ajax_handler.py
+++ /dev/null
@@ -1,700 +0,0 @@
-import os
-import html
-import pathlib
-import re
-import logging
-import time
-import urllib.parse
-import nh3
-import tornado.web
-import tornado.escape
-
-from app.classes.models.server_permissions import EnumPermissionsServer
-from app.classes.shared.console import Console
-from app.classes.shared.helpers import Helpers
-from app.classes.shared.file_helpers import FileHelpers
-from app.classes.shared.server import ServerOutBuf
-from app.classes.web.base_handler import BaseHandler
-from app.classes.shared.websocket_manager import WebSocketManager
-
-logger = logging.getLogger(__name__)
-
-
-class AjaxHandler(BaseHandler):
- def render_page(self, template, page_data):
- self.render(
- template,
- data=page_data,
- translate=self.translator.translate,
- )
-
- @tornado.web.authenticated
- def get(self, page):
- _, _, exec_user = self.current_user
- error = nh3.clean(self.get_argument("error", "WTF Error!"))
-
- template = "panel/denied.html"
-
- page_data = {"user_data": exec_user, "error": error}
-
- if page == "error":
- template = "public/error.html"
- self.render_page(template, page_data)
-
- elif page == "server_log":
- server_id = self.get_argument("id", None)
- full_log = self.get_argument("full", False)
-
- if server_id is None:
- logger.warning("Server ID not found in server_log ajax call")
- self.redirect("/panel/error?error=Server ID Not Found")
- return
-
- server_id = nh3.clean(server_id)
-
- server_data = self.controller.servers.get_server_data_by_id(server_id)
- if not server_data:
- logger.warning("Server Data not found in server_log ajax call")
- self.redirect("/panel/error?error=Server ID Not Found")
- return
-
- if not server_data["log_path"]:
- logger.warning(
- f"Log path not found in server_log ajax call ({server_id})"
- )
-
- if full_log:
- log_lines = self.helper.get_setting("max_log_lines")
- data = Helpers.tail_file(
- # If the log path is absolute it returns it as is
- # If it is relative it joins the paths below like normal
- pathlib.Path(server_data["path"], server_data["log_path"]),
- log_lines,
- )
- else:
- data = ServerOutBuf.lines.get(server_id, [])
-
- for line in data:
- try:
- line = re.sub("(\033\\[(0;)?[0-9]*[A-z]?(;[0-9])?m?)", "", line)
- line = re.sub("[A-z]{2}\b\b", "", line)
- line = self.helper.log_colors(html.escape(line))
- self.write(f"{line}
")
- # self.write(d.encode("utf-8"))
-
- except Exception as e:
- logger.warning(f"Skipping Log Line due to error: {e}")
-
- elif page == "announcements":
- data = Helpers.get_announcements()
- page_data["notify_data"] = data
- self.render_page("ajax/notify.html", page_data)
-
- elif page == "get_zip_tree":
- path = self.get_argument("path", None)
-
- self.write(
- Helpers.get_os_understandable_path(path)
- + "\n"
- + Helpers.generate_zip_tree(path)
- )
- self.finish()
-
- elif page == "get_zip_dir":
- path = self.get_argument("path", None)
-
- self.write(
- Helpers.get_os_understandable_path(path)
- + "\n"
- + Helpers.generate_zip_dir(path)
- )
- self.finish()
-
- elif page == "get_backup_tree":
- server_id = self.get_argument("id", None)
- folder = self.get_argument("path", None)
-
- output = ""
-
- 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
- )
- output += f"""