diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 83e7283e..1996376a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -120,6 +120,9 @@ win-dev-build: --hidden-import apscheduler --collect-all tzlocal --collect-all tzdata + --collect-all pytz + --collect-all six + artifacts: name: "crafty-${CI_RUNNER_TAGS}-${CI_COMMIT_BRANCH}_${CI_COMMIT_SHORT_SHA}" paths: @@ -158,6 +161,9 @@ win-prod-build: --hidden-import apscheduler --collect-all tzlocal --collect-all tzdata + --collect-all pytz + --collect-all six + artifacts: name: "crafty-${CI_RUNNER_TAGS}-${CI_COMMIT_BRANCH}_${CI_COMMIT_SHORT_SHA}" paths: diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py index 8bf438a9..6cce0545 100644 --- a/app/classes/shared/main_controller.py +++ b/app/classes/shared/main_controller.py @@ -137,7 +137,6 @@ class Controller: def package_support_logs(self, exec_user): - time.sleep(5) websocket_helper.broadcast_user(exec_user['user_id'], 'notification', 'Preparing your support logs') tempDir = tempfile.mkdtemp() tempZipStorage = tempfile.mkdtemp() @@ -254,6 +253,11 @@ class Controller: server_id = helper.create_uuid() server_dir = os.path.join(helper.servers_dir, server_id) backup_path = os.path.join(helper.backup_path, server_id) + if helper.is_os_windows(): + server_dir = helper.wtol_path(server_dir) + backup_path = helper.wtol_path(backup_path) + server_dir.replace(' ', '^ ') + backup_path.replace(' ', '^ ') server_file = "{server}-{version}.jar".format(server=server, version=version) full_jar_path = os.path.join(server_dir, server_file) @@ -279,7 +283,7 @@ class Controller: server_command = 'java -Xms{}M -Xmx{}M -jar {} nogui'.format(helper.float_to_string(min_mem), helper.float_to_string(max_mem), - full_jar_path) + +'"'+full_jar_path+'"') server_log_file = "{}/logs/latest.log".format(server_dir) server_stop = "stop" @@ -310,6 +314,11 @@ class Controller: server_id = helper.create_uuid() new_server_dir = os.path.join(helper.servers_dir, server_id) backup_path = os.path.join(helper.backup_path, server_id) + if helper.is_os_windows(): + server_dir = helper.wtol_path(new_server_dir) + backup_path = helper.wtol_path(backup_path) + new_server_dir.replace(' ', '^ ') + backup_path.replace(' ', '^ ') helper.ensure_dir_exists(new_server_dir) helper.ensure_dir_exists(backup_path) @@ -327,9 +336,10 @@ class Controller: f.close() full_jar_path = os.path.join(new_server_dir, server_jar) + server_command = 'java -Xms{}M -Xmx{}M -jar {} nogui'.format(helper.float_to_string(min_mem), helper.float_to_string(max_mem), - full_jar_path) + +'"'+full_jar_path+'"') server_log_file = "{}/logs/latest.log".format(new_server_dir) server_stop = "stop" @@ -341,6 +351,12 @@ class Controller: server_id = helper.create_uuid() new_server_dir = os.path.join(helper.servers_dir, server_id) backup_path = os.path.join(helper.backup_path, server_id) + if helper.is_os_windows(): + new_server_dir = helper.wtol_path(new_server_dir) + backup_path = helper.wtol_path(backup_path) + new_server_dir.replace(' ', '^ ') + backup_path.replace(' ', '^ ') + tempDir = helper.get_os_understandable_path(zip_path) helper.ensure_dir_exists(new_server_dir) helper.ensure_dir_exists(backup_path) @@ -360,9 +376,10 @@ class Controller: f.close() full_jar_path = os.path.join(new_server_dir, server_jar) + server_command = 'java -Xms{}M -Xmx{}M -jar {} nogui'.format(helper.float_to_string(min_mem), helper.float_to_string(max_mem), - full_jar_path) + +'"'+full_jar_path+'"') logger.debug('command: ' + server_command) server_log_file = "{}/logs/latest.log".format(new_server_dir) server_stop = "stop" @@ -376,6 +393,9 @@ class Controller: old_bu_path = server_data['backup_path'] Server_Perms_Controller.backup_role_swap(old_server_id, new_server_id) backup_path = helper.validate_traversal(helper.backup_path, old_bu_path) + if helper.is_os_windows(): + backup_path = helper.wtol_path(backup_path) + backup_path.replace(' ', '^ ') backup_path_components = list(backup_path.parts) backup_path_components[-1] = new_uuid new_bu_path = pathlib.PurePath(os.path.join(*backup_path_components)) @@ -386,6 +406,7 @@ class Controller: def register_server(self, name: str, server_uuid: str, server_dir: str, backup_path: str, server_command: str, server_file: str, server_log_file: str, server_stop: str, server_port: int): # put data in the db + new_id = self.servers.create_server(name, server_uuid, server_dir, backup_path, server_command, server_file, server_log_file, server_stop, server_port) if not helper.check_file_exists(os.path.join(server_dir, "crafty_managed.txt")): try: diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index ea4af70a..56b3faad 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -119,6 +119,8 @@ class Server: self.restart_count = 0 self.crash_watcher_schedule = None self.stats = stats + tz = get_localzone() + self.server_scheduler = BackgroundScheduler(timezone=str(tz)) self.backup_thread = threading.Thread(target=self.a_backup_server, daemon=True, name=f"backup_{self.name}") self.is_backingup = False @@ -144,8 +146,6 @@ class Server: logger.info("Scheduling server {} to start in {} seconds".format(self.name, delay)) console.info("Scheduling server {} to start in {} seconds".format(self.name, delay)) - tz = get_localzone() - self.server_scheduler = BackgroundScheduler(timezone=str(tz)) self.server_scheduler.add_job(self.run_scheduled_server, 'interval', seconds=delay, id=str(self.server_id)) self.server_scheduler.start() @@ -300,7 +300,7 @@ class Server: logger.info("Server {} has crash detection enabled - starting watcher task".format(self.name)) console.info("Server {} has crash detection enabled - starting watcher task".format(self.name)) - self.crash_watcher_schedule = schedule.every(30).seconds.do(self.detect_crash).tag(self.name) + self.crash_watcher_schedule = self.server_scheduler.add_job(self.detect_crash, 'interval', seconds=30, id="crash_watcher") def check_internet_thread(self, user_id, user_lang): if user_id: diff --git a/app/classes/shared/tasks.py b/app/classes/shared/tasks.py index efc9e4a5..2bac6061 100644 --- a/app/classes/shared/tasks.py +++ b/app/classes/shared/tasks.py @@ -197,13 +197,19 @@ class TasksManager: for item in jobs: logger.info("JOB: {}".format(item)) + def remove_all_server_tasks(self, server_id): + schedules = management_helper.get_schedules_by_server(server_id) + for schedule in schedules: + self.remove_job(schedule.schedule_id) + def remove_job(self, sch_id): job = management_helper.get_scheduled_task_model(sch_id) management_helper.delete_scheduled_task(sch_id) if job.enabled: self.scheduler.remove_job(str(sch_id)) + logger.info("Job with ID {} was deleted.".format(sch_id)) else: - logger.info("Job with ID {} was deleted from DB, but was not enabled. Not going to try removing something that doesn't exist from active schedules.") + logger.info("Job with ID {} was deleted from DB, but was not enabled. Not going to try removing something that doesn't exist from active schedules.".format(sch_id)) def update_job(self, sch_id, job_data): management_helper.update_scheduled_task(sch_id, job_data) diff --git a/app/classes/web/ajax_handler.py b/app/classes/web/ajax_handler.py index df2da540..8133bc64 100644 --- a/app/classes/web/ajax_handler.py +++ b/app/classes/web/ajax_handler.py @@ -415,6 +415,16 @@ class AjaxHandler(BaseHandler): server_id = self.get_argument('id', None) logger.info( "Removing server from panel for server: {}".format(self.controller.servers.get_server_friendly_name(server_id))) + + server_data = self.controller.get_server_data(server_id) + server_name = server_data['server_name'] + + self.controller.management.add_to_audit_log(exec_user_id, + "Deleted server {} named {}".format(server_id, server_name), + server_id, + self.get_remote_ip()) + + self.tasks_manager.remove_all_server_tasks(server_id) self.controller.remove_server(server_id, False) elif page == "delete_server_files": @@ -425,6 +435,16 @@ class AjaxHandler(BaseHandler): server_id = self.get_argument('id', None) logger.info( "Removing server and all associated files for server: {}".format(self.controller.servers.get_server_friendly_name(server_id))) + + server_data = self.controller.get_server_data(server_id) + server_name = server_data['server_name'] + + self.controller.management.add_to_audit_log(exec_user_id, + "Deleted server {} named {}".format(server_id, server_name), + server_id, + self.get_remote_ip()) + + self.tasks_manager.remove_all_server_tasks(server_id) self.controller.remove_server(server_id, True) @tornado.web.authenticated diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 166ced27..270d8f1e 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -264,28 +264,6 @@ class PanelHandler(BaseHandler): elif page == 'contribute': template = "panel/contribute.html" - elif page == "remove_server": - server_id = self.get_argument('id', None) - - if not superuser: - self.redirect("/panel/error?error=Unauthorized access: not superuser") - return - elif server_id is None: - self.redirect("/panel/error?error=Invalid Server ID") - return - - server_data = self.controller.get_server_data(server_id) - server_name = server_data['server_name'] - - self.controller.management.add_to_audit_log(exec_user['user_id'], - "Deleted server {} named {}".format(server_id, server_name), - server_id, - self.get_remote_ip()) - - self.controller.remove_server(server_id) - self.redirect("/panel/dashboard") - return - elif page == 'dashboard': if superuser: # TODO: Figure out a better solution try: @@ -313,7 +291,10 @@ class PanelHandler(BaseHandler): logger.error("Failed to get server waiting to start: {} ".format(e)) data['stats']['waiting_start'] = False - page_data['num_players'] = 0 + try: + self.fetch_server_data(page_data) + except: + page_data['num_players'] = 0 IOLoop.current().add_callback(self.fetch_server_data, page_data) @@ -1093,7 +1074,7 @@ class PanelHandler(BaseHandler): "interval": '', "command": '', #We'll base every interval off of a midnight start time. - "start_time": '00:00', + "start_time": '', "command": command, "cron_string": cron_string, "enabled": enabled, @@ -1213,7 +1194,7 @@ class PanelHandler(BaseHandler): "interval": '', "command": '', #We'll base every interval off of a midnight start time. - "start_time": '00:00', + "start_time": '', "command": command, "cron_string": cron_string, "enabled": enabled, diff --git a/app/frontend/templates/base.html b/app/frontend/templates/base.html index cf1e7347..ab6d5656 100644 --- a/app/frontend/templates/base.html +++ b/app/frontend/templates/base.html @@ -21,6 +21,7 @@ + @@ -139,7 +140,6 @@ {% block js %} diff --git a/app/frontend/templates/notify.html b/app/frontend/templates/notify.html index 696e6b71..53881b10 100644 --- a/app/frontend/templates/notify.html +++ b/app/frontend/templates/notify.html @@ -32,11 +32,11 @@ {% end %}
Email: {{ data['user_data']['email'] }}
- Support Logs + {{ translate('notify', 'supportLogs', data['lang']) }} {% if data['superuser'] %} - Activity + {{ translate('notify', 'activityLog', data['lang']) }} {% end %} - Sign Out + {{ translate('notify', 'logout', data['lang']) }} \ No newline at end of file diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 29898b84..8ba0fe61 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -180,6 +180,14 @@ "cannotSee": "Not seeing everything?", "cannotSeeOnMobile": "Try clicking on a scheduled task for full details." }, + "notify":{ + "supportLogs": "Support Logs", + "activityLog": "Activity Logs", + "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.", + "downloadLogs": "Download Support Logs?", + "finishedPreparing": "We've finished preparing your support logs. Please click download to download" + }, "serverBackups": { "backupNow": "Backup Now!", "backupAtMidnight": "Auto-backup at midnight?", diff --git a/requirements.txt b/requirements.txt index 110e5c19..8b50f771 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,19 @@ -cryptography~=3.4 -argon2-cffi~=20.1 -bleach~=3.1 -colorama~=0.4 -cryptography~=3.4 -libgravatar~=1.0.0 -peewee~=3.13 -pexpect~=4.8 -psutil~=5.7 -pyOpenSSL~=19.1.0 +cryptography==3.4 +argon2-cffi==20.1 +bleach==3.1 +colorama==0.4 +cryptography==3.4 +libgravatar==1.0.0 +peewee==3.13 +pexpect==4.8 +psutil==5.7 +pyOpenSSL==19.1.0 PyYAML==5.3.1 -requests~=2.26 -termcolor~=1.1 -tornado~=6.0 +requests==2.26 +termcolor==1.1 +tornado==6.0 cached_property==1.5.2 -apscheduler~=3.8.1 -cron-validator~=1.0.3 -tzlocal~=4.1 -pyjwt~=2.3 +apscheduler==3.8.1 +cron-validator==1.0.3 +tzlocal==4.0 +pyjwt==2.3