mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-12-05 01:10:15 +00:00
Merge branch 'dev' into bugfix/backup-download
This commit is contained in:
@@ -6,8 +6,12 @@ TBD
|
||||
- Change hour and minute intervals in APScheudler to fix incorrect triggers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/910))
|
||||
- Use asyncio locks to limit upload handler race condition ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/907))
|
||||
- Fix static fonts not working on some browsers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/906))
|
||||
- Fix import directory cleanup was not pointing to the proper directory ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/918))
|
||||
- Fix survey not appearing on first login ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/917))
|
||||
- Fix failue deleting server's DB files on server delete ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/916))
|
||||
- Fix server.properties overwritten in bedrock update ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/915))
|
||||
### Tweaks
|
||||
TBD
|
||||
- Provide better feedback on restore failures ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/914))
|
||||
### Lang
|
||||
TBD
|
||||
<br><br>
|
||||
|
||||
@@ -177,7 +177,9 @@ class ServersController(metaclass=Singleton):
|
||||
server_id,
|
||||
)
|
||||
self.file_helper.del_dirs(
|
||||
self.helper.root_dir, "app", "config", "db", "servers", str(server_id)
|
||||
pathlib.Path(
|
||||
self.helper.root_dir, "app", "config", "db", "servers", str(server_id)
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -126,6 +126,7 @@ class FileHelpers:
|
||||
@staticmethod
|
||||
def del_dirs(path):
|
||||
path = pathlib.Path(path)
|
||||
clean = True
|
||||
for sub in path.iterdir():
|
||||
if sub.is_dir():
|
||||
# Delete folder if it is a folder
|
||||
@@ -135,26 +136,29 @@ class FileHelpers:
|
||||
try:
|
||||
sub.unlink()
|
||||
except Exception as e:
|
||||
clean = False
|
||||
logger.error(f"Unable to delete file {sub}: {e}")
|
||||
try:
|
||||
# This removes the top-level folder:
|
||||
path.rmdir()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.error("Unable to remove top level")
|
||||
return e
|
||||
return True
|
||||
return False
|
||||
return clean
|
||||
|
||||
@staticmethod
|
||||
def del_file(path):
|
||||
path = pathlib.Path(path)
|
||||
clean = True
|
||||
try:
|
||||
logger.debug(f"Deleting file: {path}")
|
||||
# Remove the file
|
||||
os.remove(path)
|
||||
return True
|
||||
except (FileNotFoundError, PermissionError) as e:
|
||||
return clean
|
||||
except (FileNotFoundError, PermissionError):
|
||||
logger.error(f"Path specified is not a file or does not exist. {path}")
|
||||
return e
|
||||
clean = False
|
||||
return clean
|
||||
|
||||
def check_mime_types(self, file_path):
|
||||
m_type, _value = self.mime_types.guess_type(file_path)
|
||||
|
||||
@@ -45,6 +45,7 @@ class BackupManager:
|
||||
self, backup_config, backup_location, backup_file, svr_obj, in_place
|
||||
):
|
||||
server_path = svr_obj.settings["path"]
|
||||
error = False
|
||||
if Helpers.validate_traversal(backup_location, backup_file):
|
||||
if svr_obj.check_running():
|
||||
svr_obj.stop_server()
|
||||
@@ -58,10 +59,40 @@ class BackupManager:
|
||||
os.path.isdir(os.path.join(server_path, item))
|
||||
and item != "db_stats"
|
||||
):
|
||||
self.file_helper.del_dirs(os.path.join(server_path, item))
|
||||
result = self.file_helper.del_dirs(
|
||||
os.path.join(server_path, item)
|
||||
)
|
||||
if not result:
|
||||
error = True
|
||||
else:
|
||||
self.file_helper.del_file(os.path.join(server_path, item))
|
||||
result = self.file_helper.del_file(
|
||||
os.path.join(server_path, item)
|
||||
)
|
||||
if not result:
|
||||
error = True
|
||||
self.file_helper.restore_archive(backup_location, server_path)
|
||||
server_users = PermissionsServers.get_server_user_list(svr_obj.server_id)
|
||||
time.sleep(3)
|
||||
if error:
|
||||
for user in server_users:
|
||||
WebSocketManager().broadcast_user(
|
||||
user,
|
||||
"send_start_error",
|
||||
self.helper.translation.translate(
|
||||
"notify", "restoreFailed", HelperUsers.get_user_lang_by_id(user)
|
||||
),
|
||||
)
|
||||
else:
|
||||
for user in server_users:
|
||||
WebSocketManager().broadcast_user(
|
||||
user,
|
||||
"notification",
|
||||
self.helper.translation.translate(
|
||||
"notify",
|
||||
"restoreSuccess",
|
||||
HelperUsers.get_user_lang_by_id(user),
|
||||
),
|
||||
)
|
||||
|
||||
def backup_starter(self, backup_config, server):
|
||||
"""Notify users of backup starting, and start the backup.
|
||||
|
||||
@@ -244,7 +244,7 @@ class ImportHelpers:
|
||||
|
||||
unzip_path = self.helper.wtol_path(file_path)
|
||||
# unzips archive that was downloaded.
|
||||
self.file_helper.unzip_file(unzip_path)
|
||||
self.file_helper.unzip_file(unzip_path, True)
|
||||
# adjusts permissions for execution if os is not windows
|
||||
|
||||
if not self.helper.is_os_windows():
|
||||
|
||||
@@ -5,6 +5,7 @@ import threading
|
||||
import asyncio
|
||||
import datetime
|
||||
import json
|
||||
from pathlib import Path
|
||||
from zoneinfo import ZoneInfoNotFoundError
|
||||
from tzlocal import get_localzone
|
||||
from apscheduler.events import EVENT_JOB_EXECUTED
|
||||
@@ -815,15 +816,16 @@ class TasksManager:
|
||||
os.remove(os.path.join(file))
|
||||
except FileNotFoundError:
|
||||
logger.debug("Could not clear out file from temp directory")
|
||||
|
||||
for file in os.listdir(
|
||||
os.path.join(self.controller.project_root, "import", "upload")
|
||||
):
|
||||
if self.helper.is_file_older_than_x_days(
|
||||
os.path.join(self.controller.project_root, "import", "upload", file)
|
||||
):
|
||||
import_path = Path(self.controller.project_root, "import", "upload")
|
||||
for file in os.listdir(import_path):
|
||||
file_path = Path(import_path, file).resolve(strict=True)
|
||||
if not self.helper.validate_traversal(import_path, file_path):
|
||||
logger.error(
|
||||
"Traversal detected while deleting import file %s", file_path
|
||||
)
|
||||
if self.helper.is_file_older_than_x_days(file_path):
|
||||
try:
|
||||
os.remove(os.path.join(file))
|
||||
os.remove(file_path)
|
||||
except FileNotFoundError:
|
||||
logger.debug("Could not clear out file from import directory")
|
||||
|
||||
|
||||
@@ -283,6 +283,8 @@
|
||||
"finishedPreparing": "We've finished preparing your support logs. Please click download to download",
|
||||
"logout": "Logout",
|
||||
"preparingLogs": " Please wait while we prepare your logs... We`ll send a notification when they`re ready. This may take a while for large deployments.",
|
||||
"restoreFailed": "Backup restore failed. Could not delete files from server directory.",
|
||||
"restoreSuccess": "Server files restored successfully.",
|
||||
"schedule_desc": "We detected some or all of your scheduled tasks were not successfully transferred during the upgrade. Please confirm your schedules in the schedules tab.",
|
||||
"schedule_title": "Schedules Migration Warning",
|
||||
"supportLogs": "Support Logs"
|
||||
|
||||
3
main.py
3
main.py
@@ -21,6 +21,7 @@ from app.classes.logging.log_formatter import JsonFormatter
|
||||
|
||||
console = Console()
|
||||
helper = Helpers()
|
||||
first_login = False
|
||||
# Get the path our application is running on.
|
||||
if getattr(sys, "frozen", False):
|
||||
APPLICATION_PATH = os.path.dirname(sys.executable)
|
||||
@@ -388,6 +389,7 @@ if __name__ == "__main__":
|
||||
f"through your router/firewall if you would like to be able "
|
||||
f"to access Crafty remotely."
|
||||
)
|
||||
first_login = True
|
||||
PASSWORD = helper.create_pass()
|
||||
installer.default_settings(PASSWORD)
|
||||
with open(
|
||||
@@ -426,6 +428,7 @@ if __name__ == "__main__":
|
||||
import_helper = ImportHelpers(helper, file_helper)
|
||||
controller = Controller(database, helper, file_helper, import_helper)
|
||||
controller.set_project_root(APPLICATION_PATH)
|
||||
controller.first_login = first_login
|
||||
tasks_manager = TasksManager(helper, controller, file_helper)
|
||||
import3 = Import3(helper, controller)
|
||||
helper.migration_notifications = get_migration_notifications()
|
||||
|
||||
Reference in New Issue
Block a user