Merge branch 'macgeek.db' into 'dev'

Macgeek database refactor

See merge request crafty-controller/crafty-commander!246
This commit is contained in:
Iain Powrie 2022-04-13 19:26:11 +00:00
commit 5d209b0827
47 changed files with 1883 additions and 1863 deletions

View File

@ -1,7 +1,7 @@
import logging import logging
from app.classes.models.crafty_permissions import ( from app.classes.models.crafty_permissions import (
crafty_permissions, Permissions_Crafty,
Enum_Permissions_Crafty, Enum_Permissions_Crafty,
) )
from app.classes.models.users import ApiKeys from app.classes.models.users import ApiKeys
@ -12,25 +12,25 @@ logger = logging.getLogger(__name__)
class Crafty_Perms_Controller: class Crafty_Perms_Controller:
@staticmethod @staticmethod
def list_defined_crafty_permissions(): def list_defined_crafty_permissions():
permissions_list = crafty_permissions.get_permissions_list() permissions_list = Permissions_Crafty.get_permissions_list()
return permissions_list return permissions_list
@staticmethod @staticmethod
def get_mask_crafty_permissions(user_id): def get_mask_crafty_permissions(user_id):
permissions_mask = crafty_permissions.get_crafty_permissions_mask(user_id) permissions_mask = Permissions_Crafty.get_crafty_permissions_mask(user_id)
return permissions_mask return permissions_mask
@staticmethod @staticmethod
def set_permission( def set_permission(
permission_mask, permission_tested: Enum_Permissions_Crafty, value permission_mask, permission_tested: Enum_Permissions_Crafty, value
): ):
return crafty_permissions.set_permission( return Permissions_Crafty.set_permission(
permission_mask, permission_tested, value permission_mask, permission_tested, value
) )
@staticmethod @staticmethod
def can_create_server(user_id): def can_create_server(user_id):
return crafty_permissions.can_add_in_crafty( return Permissions_Crafty.can_add_in_crafty(
user_id, Enum_Permissions_Crafty.Server_Creation user_id, Enum_Permissions_Crafty.Server_Creation
) )
@ -52,22 +52,22 @@ class Crafty_Perms_Controller:
@staticmethod @staticmethod
def list_all_crafty_permissions_quantity_limits(): def list_all_crafty_permissions_quantity_limits():
return crafty_permissions.get_all_permission_quantity_list() return Permissions_Crafty.get_all_permission_quantity_list()
@staticmethod @staticmethod
def list_crafty_permissions_quantity_limits(user_id): def list_crafty_permissions_quantity_limits(user_id):
return crafty_permissions.get_permission_quantity_list(user_id) return Permissions_Crafty.get_permission_quantity_list(user_id)
@staticmethod @staticmethod
def get_crafty_permissions_list(user_id): def get_crafty_permissions_list(user_id):
permissions_mask = crafty_permissions.get_crafty_permissions_mask(user_id) permissions_mask = Permissions_Crafty.get_crafty_permissions_mask(user_id)
permissions_list = crafty_permissions.get_permissions(permissions_mask) permissions_list = Permissions_Crafty.get_permissions(permissions_mask)
return permissions_list return permissions_list
@staticmethod @staticmethod
def add_server_creation(user_id): def add_server_creation(user_id):
return crafty_permissions.add_server_creation(user_id) return Permissions_Crafty.add_server_creation(user_id)
@staticmethod @staticmethod
def get_api_key_permissions_list(key: ApiKeys): def get_api_key_permissions_list(key: ApiKeys):
return crafty_permissions.get_api_key_permissions_list(key) return Permissions_Crafty.get_api_key_permissions_list(key)

View File

@ -1,60 +1,59 @@
import logging import logging
from app.classes.models.management import management_helper from app.classes.models.management import helpers_management
from app.classes.models.servers import servers_helper from app.classes.models.servers import helper_servers
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Management_Controller: class Management_Controller:
def __init__(self, management_helper):
self.management_helper = management_helper
# ********************************************************************************** # **********************************************************************************
# Host_Stats Methods # Host_Stats Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_latest_hosts_stats(): def get_latest_hosts_stats():
return management_helper.get_latest_hosts_stats() return helpers_management.get_latest_hosts_stats()
# ********************************************************************************** # **********************************************************************************
# Commands Methods # Commands Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_unactioned_commands(): def get_unactioned_commands():
return management_helper.get_unactioned_commands() return helpers_management.get_unactioned_commands()
@staticmethod def send_command(self, user_id, server_id, remote_ip, command):
def send_command(user_id, server_id, remote_ip, command): server_name = helper_servers.get_server_friendly_name(server_id)
server_name = servers_helper.get_server_friendly_name(server_id)
# Example: Admin issued command start_server for server Survival # Example: Admin issued command start_server for server Survival
management_helper.add_to_audit_log( self.management_helper.add_to_audit_log(
user_id, user_id,
f"issued command {command} for server {server_name}", f"issued command {command} for server {server_name}",
server_id, server_id,
remote_ip, remote_ip,
) )
management_helper.add_command(server_id, user_id, remote_ip, command) helpers_management.add_command(server_id, user_id, remote_ip, command)
@staticmethod @staticmethod
def mark_command_complete(command_id=None): def mark_command_complete(command_id=None):
return management_helper.mark_command_complete(command_id) return helpers_management.mark_command_complete(command_id)
# ********************************************************************************** # **********************************************************************************
# Audit_Log Methods # Audit_Log Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_actity_log(): def get_actity_log():
return management_helper.get_actity_log() return helpers_management.get_actity_log()
@staticmethod def add_to_audit_log(self, user_id, log_msg, server_id=None, source_ip=None):
def add_to_audit_log(user_id, log_msg, server_id=None, source_ip=None): return self.management_helper.add_to_audit_log(
return management_helper.add_to_audit_log(
user_id, log_msg, server_id, source_ip user_id, log_msg, server_id, source_ip
) )
@staticmethod def add_to_audit_log_raw(self, user_name, user_id, server_id, log_msg, source_ip):
def add_to_audit_log_raw(user_name, user_id, server_id, log_msg, source_ip): return self.management_helper.add_to_audit_log_raw(
return management_helper.add_to_audit_log_raw(
user_name, user_id, server_id, log_msg, source_ip user_name, user_id, server_id, log_msg, source_ip
) )
@ -72,7 +71,7 @@ class Management_Controller:
comment=None, comment=None,
enabled=True, enabled=True,
): ):
return management_helper.create_scheduled_task( return helpers_management.create_scheduled_task(
server_id, server_id,
action, action,
interval, interval,
@ -85,63 +84,61 @@ class Management_Controller:
@staticmethod @staticmethod
def delete_scheduled_task(schedule_id): def delete_scheduled_task(schedule_id):
return management_helper.delete_scheduled_task(schedule_id) return helpers_management.delete_scheduled_task(schedule_id)
@staticmethod @staticmethod
def update_scheduled_task(schedule_id, updates): def update_scheduled_task(schedule_id, updates):
return management_helper.update_scheduled_task(schedule_id, updates) return helpers_management.update_scheduled_task(schedule_id, updates)
@staticmethod @staticmethod
def get_scheduled_task(schedule_id): def get_scheduled_task(schedule_id):
return management_helper.get_scheduled_task(schedule_id) return helpers_management.get_scheduled_task(schedule_id)
@staticmethod @staticmethod
def get_scheduled_task_model(schedule_id): def get_scheduled_task_model(schedule_id):
return management_helper.get_scheduled_task_model(schedule_id) return helpers_management.get_scheduled_task_model(schedule_id)
@staticmethod @staticmethod
def get_child_schedules(sch_id): def get_child_schedules(sch_id):
return management_helper.get_child_schedules(sch_id) return helpers_management.get_child_schedules(sch_id)
@staticmethod @staticmethod
def get_schedules_by_server(server_id): def get_schedules_by_server(server_id):
return management_helper.get_schedules_by_server(server_id) return helpers_management.get_schedules_by_server(server_id)
@staticmethod @staticmethod
def get_schedules_all(): def get_schedules_all():
return management_helper.get_schedules_all() return helpers_management.get_schedules_all()
@staticmethod @staticmethod
def get_schedules_enabled(): def get_schedules_enabled():
return management_helper.get_schedules_enabled() return helpers_management.get_schedules_enabled()
# ********************************************************************************** # **********************************************************************************
# Backups Methods # Backups Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_backup_config(server_id): def get_backup_config(server_id):
return management_helper.get_backup_config(server_id) return helpers_management.get_backup_config(server_id)
@staticmethod
def set_backup_config( def set_backup_config(
self,
server_id: int, server_id: int,
backup_path: str = None, backup_path: str = None,
max_backups: int = None, max_backups: int = None,
excluded_dirs: list = None, excluded_dirs: list = None,
compress: bool = False, compress: bool = False,
): ):
return management_helper.set_backup_config( return self.management_helper.set_backup_config(
server_id, backup_path, max_backups, excluded_dirs, compress server_id, backup_path, max_backups, excluded_dirs, compress
) )
@staticmethod @staticmethod
def get_excluded_backup_dirs(server_id: int): def get_excluded_backup_dirs(server_id: int):
return management_helper.get_excluded_backup_dirs(server_id) return helpers_management.get_excluded_backup_dirs(server_id)
@staticmethod def add_excluded_backup_dir(self, server_id: int, dir_to_add: str):
def add_excluded_backup_dir(server_id: int, dir_to_add: str): self.management_helper.add_excluded_backup_dir(server_id, dir_to_add)
management_helper.add_excluded_backup_dir(server_id, dir_to_add)
@staticmethod def del_excluded_backup_dir(self, server_id: int, dir_to_del: str):
def del_excluded_backup_dir(server_id: int, dir_to_del: str): self.management_helper.del_excluded_backup_dir(server_id, dir_to_del)
management_helper.del_excluded_backup_dir(server_id, dir_to_del)

View File

@ -1,25 +1,28 @@
import logging import logging
from app.classes.models.roles import roles_helper from app.classes.models.roles import helper_roles
from app.classes.models.server_permissions import server_permissions from app.classes.models.server_permissions import Permissions_Servers
from app.classes.models.users import users_helper from app.classes.shared.helpers import Helpers
from app.classes.shared.helpers import helper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Roles_Controller: class Roles_Controller:
def __init__(self, users_helper, roles_helper):
self.users_helper = users_helper
self.roles_helper = roles_helper
@staticmethod @staticmethod
def get_all_roles(): def get_all_roles():
return roles_helper.get_all_roles() return helper_roles.get_all_roles()
@staticmethod @staticmethod
def get_roleid_by_name(role_name): def get_roleid_by_name(role_name):
return roles_helper.get_roleid_by_name(role_name) return helper_roles.get_roleid_by_name(role_name)
@staticmethod @staticmethod
def get_role(role_id): def get_role(role_id):
return roles_helper.get_role(role_id) return helper_roles.get_role(role_id)
@staticmethod @staticmethod
def update_role(role_id: str, role_data=None, permissions_mask: str = "00000000"): def update_role(role_id: str, role_data=None, permissions_mask: str = "00000000"):
@ -37,41 +40,42 @@ class Roles_Controller:
removed_servers = base_data["servers"].difference(role_data["servers"]) removed_servers = base_data["servers"].difference(role_data["servers"])
elif base_data[key] != role_data[key]: elif base_data[key] != role_data[key]:
up_data[key] = role_data[key] up_data[key] = role_data[key]
up_data["last_update"] = helper.get_time_as_string() up_data["last_update"] = Helpers.get_time_as_string()
logger.debug( logger.debug(
f"role: {role_data} +server:{added_servers} -server{removed_servers}" f"role: {role_data} +server:{added_servers} -server{removed_servers}"
) )
for server in added_servers: for server in added_servers:
server_permissions.get_or_create(role_id, server, permissions_mask) Permissions_Servers.get_or_create(role_id, server, permissions_mask)
for server in base_data["servers"]: for server in base_data["servers"]:
server_permissions.update_role_permission(role_id, server, permissions_mask) Permissions_Servers.update_role_permission(
role_id, server, permissions_mask
)
# TODO: This is horribly inefficient and we should be using bulk queries # TODO: This is horribly inefficient and we should be using bulk queries
# but im going for functionality at this point # but im going for functionality at this point
server_permissions.delete_roles_permissions(role_id, removed_servers) Permissions_Servers.delete_roles_permissions(role_id, removed_servers)
if up_data: if up_data:
roles_helper.update_role(role_id, up_data) helper_roles.update_role(role_id, up_data)
@staticmethod @staticmethod
def add_role(role_name): def add_role(role_name):
return roles_helper.add_role(role_name) return helper_roles.add_role(role_name)
@staticmethod def remove_role(self, role_id):
def remove_role(role_id):
role_data = Roles_Controller.get_role_with_servers(role_id) role_data = Roles_Controller.get_role_with_servers(role_id)
server_permissions.delete_roles_permissions(role_id, role_data["servers"]) Permissions_Servers.delete_roles_permissions(role_id, role_data["servers"])
users_helper.remove_roles_from_role_id(role_id) self.users_helper.remove_roles_from_role_id(role_id)
return roles_helper.remove_role(role_id) return self.roles_helper.remove_role(role_id)
@staticmethod @staticmethod
def role_id_exists(role_id): def role_id_exists(role_id):
return roles_helper.role_id_exists(role_id) return helper_roles.role_id_exists(role_id)
@staticmethod @staticmethod
def get_role_with_servers(role_id): def get_role_with_servers(role_id):
role = roles_helper.get_role(role_id) role = helper_roles.get_role(role_id)
if role: if role:
servers_query = server_permissions.get_servers_from_role(role_id) servers_query = Permissions_Servers.get_servers_from_role(role_id)
# TODO: this query needs to be narrower # TODO: this query needs to be narrower
servers = set() servers = set()
for s in servers_query: for s in servers_query:

View File

@ -1,13 +1,13 @@
import logging import logging
from app.classes.models.server_permissions import ( from app.classes.models.server_permissions import (
server_permissions, Permissions_Servers,
Enum_Permissions_Server, Enum_Permissions_Server,
) )
from app.classes.models.users import users_helper, ApiKeys from app.classes.models.users import helper_users, ApiKeys
from app.classes.models.roles import roles_helper from app.classes.models.roles import helper_roles
from app.classes.models.servers import servers_helper from app.classes.models.servers import helper_servers
from app.classes.shared.main_models import db_helper from app.classes.shared.main_models import db_shortcuts
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -15,100 +15,102 @@ logger = logging.getLogger(__name__)
class Server_Perms_Controller: class Server_Perms_Controller:
@staticmethod @staticmethod
def get_server_user_list(server_id): def get_server_user_list(server_id):
return server_permissions.get_server_user_list(server_id) return Permissions_Servers.get_server_user_list(server_id)
@staticmethod @staticmethod
def list_defined_permissions(): def list_defined_permissions():
permissions_list = server_permissions.get_permissions_list() permissions_list = Permissions_Servers.get_permissions_list()
return permissions_list return permissions_list
@staticmethod @staticmethod
def get_mask_permissions(role_id, server_id): def get_mask_permissions(role_id, server_id):
permissions_mask = server_permissions.get_permissions_mask(role_id, server_id) permissions_mask = Permissions_Servers.get_permissions_mask(role_id, server_id)
return permissions_mask return permissions_mask
@staticmethod @staticmethod
def get_role_permissions(role_id): def get_role_permissions(role_id):
permissions_list = server_permissions.get_role_permissions_list(role_id) permissions_list = Permissions_Servers.get_role_permissions_list(role_id)
return permissions_list return permissions_list
@staticmethod @staticmethod
def add_role_server(server_id, role_id, rs_permissions="00000000"): def add_role_server(server_id, role_id, rs_permissions="00000000"):
return server_permissions.add_role_server(server_id, role_id, rs_permissions) return Permissions_Servers.add_role_server(server_id, role_id, rs_permissions)
@staticmethod @staticmethod
def get_server_roles(server_id): def get_server_roles(server_id):
return server_permissions.get_server_roles(server_id) return Permissions_Servers.get_server_roles(server_id)
@staticmethod @staticmethod
def backup_role_swap(old_server_id, new_server_id): def backup_role_swap(old_server_id, new_server_id):
role_list = server_permissions.get_server_roles(old_server_id) role_list = Permissions_Servers.get_server_roles(old_server_id)
for role in role_list: for role in role_list:
server_permissions.add_role_server( Permissions_Servers.add_role_server(
new_server_id, new_server_id,
role.role_id, role.role_id,
server_permissions.get_permissions_mask( Permissions_Servers.get_permissions_mask(
int(role.role_id), int(old_server_id) int(role.role_id), int(old_server_id)
), ),
) )
# server_permissions.add_role_server(new_server_id, role.role_id,"00001000") # Permissions_Servers.add_role_server(
# new_server_id, role.role_id, "00001000"
# )
# ********************************************************************************** # **********************************************************************************
# Servers Permissions Methods # Servers Permissions Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_permissions_mask(role_id, server_id): def get_permissions_mask(role_id, server_id):
return server_permissions.get_permissions_mask(role_id, server_id) return Permissions_Servers.get_permissions_mask(role_id, server_id)
@staticmethod @staticmethod
def set_permission( def set_permission(
permission_mask, permission_tested: Enum_Permissions_Server, value permission_mask, permission_tested: Enum_Permissions_Server, value
): ):
return server_permissions.set_permission( return Permissions_Servers.set_permission(
permission_mask, permission_tested, value permission_mask, permission_tested, value
) )
@staticmethod @staticmethod
def get_role_permissions_list(role_id): def get_role_permissions_list(role_id):
return server_permissions.get_role_permissions_list(role_id) return Permissions_Servers.get_role_permissions_list(role_id)
@staticmethod @staticmethod
def get_user_id_permissions_list(user_id: str, server_id: str): def get_user_id_permissions_list(user_id: str, server_id: str):
return server_permissions.get_user_id_permissions_list(user_id, server_id) return Permissions_Servers.get_user_id_permissions_list(user_id, server_id)
@staticmethod @staticmethod
def get_api_key_id_permissions_list(key_id: str, server_id: str): def get_api_key_id_permissions_list(key_id: str, server_id: str):
key = users_helper.get_user_api_key(key_id) key = helper_users.get_user_api_key(key_id)
return server_permissions.get_api_key_permissions_list(key, server_id) return Permissions_Servers.get_api_key_permissions_list(key, server_id)
@staticmethod @staticmethod
def get_api_key_permissions_list(key: ApiKeys, server_id: str): def get_api_key_permissions_list(key: ApiKeys, server_id: str):
return server_permissions.get_api_key_permissions_list(key, server_id) return Permissions_Servers.get_api_key_permissions_list(key, server_id)
@staticmethod @staticmethod
def get_authorized_servers_stats_from_roles(user_id): def get_authorized_servers_stats_from_roles(user_id):
user_roles = users_helper.get_user_roles_id(user_id) user_roles = helper_users.get_user_roles_id(user_id)
roles_list = [] roles_list = []
role_server = [] role_server = []
authorized_servers = [] authorized_servers = []
server_data = [] server_data = []
for u in user_roles: for u in user_roles:
roles_list.append(roles_helper.get_role(u.role_id)) roles_list.append(helper_roles.get_role(u.role_id))
for r in roles_list: for r in roles_list:
role_test = server_permissions.get_role_servers_from_role_id( role_test = Permissions_Servers.get_role_servers_from_role_id(
r.get("role_id") r.get("role_id")
) )
for t in role_test: for t in role_test:
role_server.append(t) role_server.append(t)
for s in role_server: for s in role_server:
authorized_servers.append(servers_helper.get_server_data_by_id(s.server_id)) authorized_servers.append(helper_servers.get_server_data_by_id(s.server_id))
for s in authorized_servers: for s in authorized_servers:
latest = servers_helper.get_latest_server_stats(s.get("server_id")) latest = helper_servers.get_latest_server_stats(s.get("server_id"))
server_data.append( server_data.append(
{"server_data": s, "stats": db_helper.return_rows(latest)[0]} {"server_data": s, "stats": db_shortcuts.return_rows(latest)[0]}
) )
return server_data return server_data

View File

@ -3,25 +3,27 @@ import logging
import json import json
from app.classes.controllers.roles_controller import Roles_Controller from app.classes.controllers.roles_controller import Roles_Controller
from app.classes.models.servers import servers_helper from app.classes.models.servers import helper_servers
from app.classes.models.users import users_helper, ApiKeys from app.classes.models.users import helper_users, ApiKeys
from app.classes.models.server_permissions import ( from app.classes.models.server_permissions import (
server_permissions, Permissions_Servers,
Enum_Permissions_Server, Enum_Permissions_Server,
) )
from app.classes.shared.helpers import helper from app.classes.shared.helpers import Helpers
from app.classes.shared.main_models import db_helper from app.classes.shared.main_models import db_shortcuts
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Servers_Controller: class Servers_Controller:
def __init__(self, servers_helper):
self.servers_helper = servers_helper
# ********************************************************************************** # **********************************************************************************
# Generic Servers Methods # Generic Servers Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod
def create_server( def create_server(
self,
name: str, name: str,
server_uuid: str, server_uuid: str,
server_dir: str, server_dir: str,
@ -33,7 +35,7 @@ class Servers_Controller:
server_type: str, server_type: str,
server_port=25565, server_port=25565,
): ):
return servers_helper.create_server( return self.servers_helper.create_server(
name, name,
server_uuid, server_uuid,
server_dir, server_dir,
@ -48,60 +50,59 @@ class Servers_Controller:
@staticmethod @staticmethod
def get_server_obj(server_id): def get_server_obj(server_id):
return servers_helper.get_server_obj(server_id) return helper_servers.get_server_obj(server_id)
@staticmethod @staticmethod
def update_server(server_obj): def update_server(server_obj):
return servers_helper.update_server(server_obj) return helper_servers.update_server(server_obj)
@staticmethod @staticmethod
def set_download(server_id): def set_download(server_id):
return servers_helper.set_download(server_id) return helper_servers.set_download(server_id)
@staticmethod @staticmethod
def finish_download(server_id): def finish_download(server_id):
return servers_helper.finish_download(server_id) return helper_servers.finish_download(server_id)
@staticmethod @staticmethod
def get_download_status(server_id): def get_download_status(server_id):
return servers_helper.get_download_status(server_id) return helper_servers.get_download_status(server_id)
@staticmethod def remove_server(self, server_id):
def remove_server(server_id): roles_list = Permissions_Servers.get_roles_from_server(server_id)
roles_list = server_permissions.get_roles_from_server(server_id)
for role in roles_list: for role in roles_list:
role_id = role.role_id role_id = role.role_id
role_data = Roles_Controller.get_role_with_servers(role_id) role_data = Roles_Controller.get_role_with_servers(role_id)
role_data["servers"] = {server_id} role_data["servers"] = {server_id}
server_permissions.delete_roles_permissions(role_id, role_data["servers"]) Permissions_Servers.delete_roles_permissions(role_id, role_data["servers"])
server_permissions.remove_roles_of_server(server_id) Permissions_Servers.remove_roles_of_server(server_id)
servers_helper.remove_server(server_id) self.servers_helper.remove_server(server_id)
@staticmethod @staticmethod
def get_server_data_by_id(server_id): def get_server_data_by_id(server_id):
return servers_helper.get_server_data_by_id(server_id) return helper_servers.get_server_data_by_id(server_id)
# ********************************************************************************** # **********************************************************************************
# Servers Methods # Servers Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_all_defined_servers(): def get_all_defined_servers():
return servers_helper.get_all_defined_servers() return helper_servers.get_all_defined_servers()
@staticmethod @staticmethod
def get_authorized_servers(user_id): def get_authorized_servers(user_id):
server_data = [] server_data = []
user_roles = users_helper.user_role_query(user_id) user_roles = helper_users.user_role_query(user_id)
for us in user_roles: for us in user_roles:
role_servers = server_permissions.get_role_servers_from_role_id(us.role_id) role_servers = Permissions_Servers.get_role_servers_from_role_id(us.role_id)
for role in role_servers: for role in role_servers:
server_data.append(servers_helper.get_server_data_by_id(role.server_id)) server_data.append(helper_servers.get_server_data_by_id(role.server_id))
return server_data return server_data
@staticmethod @staticmethod
def get_all_servers_stats(): def get_all_servers_stats():
return servers_helper.get_all_servers_stats() return helper_servers.get_all_servers_stats()
@staticmethod @staticmethod
def get_authorized_servers_stats_api_key(api_key: ApiKeys): def get_authorized_servers_stats_api_key(api_key: ApiKeys):
@ -111,8 +112,8 @@ class Servers_Controller:
) )
for s in authorized_servers: for s in authorized_servers:
latest = servers_helper.get_latest_server_stats(s.get("server_id")) latest = helper_servers.get_latest_server_stats(s.get("server_id"))
key_permissions = server_permissions.get_api_key_permissions_list( key_permissions = Permissions_Servers.get_api_key_permissions_list(
api_key, s.get("server_id") api_key, s.get("server_id")
) )
if Enum_Permissions_Server.Commands in key_permissions: if Enum_Permissions_Server.Commands in key_permissions:
@ -122,7 +123,7 @@ class Servers_Controller:
server_data.append( server_data.append(
{ {
"server_data": s, "server_data": s,
"stats": db_helper.return_rows(latest)[0], "stats": db_shortcuts.return_rows(latest)[0],
"user_command_permission": user_command_permission, "user_command_permission": user_command_permission,
} }
) )
@ -134,9 +135,9 @@ class Servers_Controller:
authorized_servers = Servers_Controller.get_authorized_servers(user_id) authorized_servers = Servers_Controller.get_authorized_servers(user_id)
for s in authorized_servers: for s in authorized_servers:
latest = servers_helper.get_latest_server_stats(s.get("server_id")) latest = helper_servers.get_latest_server_stats(s.get("server_id"))
# TODO # TODO
user_permissions = server_permissions.get_user_id_permissions_list( user_permissions = Permissions_Servers.get_user_id_permissions_list(
user_id, s.get("server_id") user_id, s.get("server_id")
) )
if Enum_Permissions_Server.Commands in user_permissions: if Enum_Permissions_Server.Commands in user_permissions:
@ -146,7 +147,7 @@ class Servers_Controller:
server_data.append( server_data.append(
{ {
"server_data": s, "server_data": s,
"stats": db_helper.return_rows(latest)[0], "stats": db_shortcuts.return_rows(latest)[0],
"user_command_permission": user_command_permission, "user_command_permission": user_command_permission,
} }
) )
@ -155,28 +156,28 @@ class Servers_Controller:
@staticmethod @staticmethod
def get_server_friendly_name(server_id): def get_server_friendly_name(server_id):
return servers_helper.get_server_friendly_name(server_id) return helper_servers.get_server_friendly_name(server_id)
# ********************************************************************************** # **********************************************************************************
# Servers_Stats Methods # Servers_Stats Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_server_stats_by_id(server_id): def get_server_stats_by_id(server_id):
return servers_helper.get_server_stats_by_id(server_id) return helper_servers.get_server_stats_by_id(server_id)
@staticmethod @staticmethod
def server_id_exists(server_id): def server_id_exists(server_id):
return servers_helper.server_id_exists(server_id) return helper_servers.server_id_exists(server_id)
@staticmethod @staticmethod
def get_server_type_by_id(server_id): def get_server_type_by_id(server_id):
return servers_helper.get_server_type_by_id(server_id) return helper_servers.get_server_type_by_id(server_id)
@staticmethod @staticmethod
def server_id_authorized(server_id_a, user_id): def server_id_authorized(server_id_a, user_id):
user_roles = users_helper.user_role_query(user_id) user_roles = helper_users.user_role_query(user_id)
for role in user_roles: for role in user_roles:
for server_id_b in server_permissions.get_role_servers_from_role_id( for server_id_b in Permissions_Servers.get_role_servers_from_role_id(
role.role_id role.role_id
): ):
if str(server_id_a) == str(server_id_b.server_id): if str(server_id_a) == str(server_id_b.server_id):
@ -185,7 +186,7 @@ class Servers_Controller:
@staticmethod @staticmethod
def is_crashed(server_id): def is_crashed(server_id):
return servers_helper.is_crashed(server_id) return helper_servers.is_crashed(server_id)
@staticmethod @staticmethod
def server_id_authorized_api_key(server_id: str, api_key: ApiKeys) -> bool: def server_id_authorized_api_key(server_id: str, api_key: ApiKeys) -> bool:
@ -194,42 +195,40 @@ class Servers_Controller:
# There is no view server permission # There is no view server permission
# permission_helper.both_have_perm(api_key) # permission_helper.both_have_perm(api_key)
@staticmethod def set_update(self, server_id, value):
def set_update(server_id, value): return self.servers_helper.set_update(server_id, value)
return servers_helper.set_update(server_id, value)
@staticmethod @staticmethod
def get_TTL_without_player(server_id): def get_TTL_without_player(server_id):
return servers_helper.get_TTL_without_player(server_id) return helper_servers.get_TTL_without_player(server_id)
@staticmethod @staticmethod
def can_stop_no_players(server_id, time_limit): def can_stop_no_players(server_id, time_limit):
return servers_helper.can_stop_no_players(server_id, time_limit) return helper_servers.can_stop_no_players(server_id, time_limit)
@staticmethod def set_waiting_start(self, server_id, value):
def set_waiting_start(server_id, value): self.servers_helper.set_waiting_start(server_id, value)
servers_helper.set_waiting_start(server_id, value)
@staticmethod @staticmethod
def get_waiting_start(server_id): def get_waiting_start(server_id):
return servers_helper.get_waiting_start(server_id) return helper_servers.get_waiting_start(server_id)
@staticmethod @staticmethod
def get_update_status(server_id): def get_update_status(server_id):
return servers_helper.get_update_status(server_id) return helper_servers.get_update_status(server_id)
# ********************************************************************************** # **********************************************************************************
# Servers Helpers Methods # Servers Helpers Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_banned_players(server_id): def get_banned_players(server_id):
stats = servers_helper.get_server_stats_by_id(server_id) stats = helper_servers.get_server_stats_by_id(server_id)
server_path = stats["server_id"]["path"] server_path = stats["server_id"]["path"]
path = os.path.join(server_path, "banned-players.json") path = os.path.join(server_path, "banned-players.json")
try: try:
with open( with open(
helper.get_os_understandable_path(path), encoding="utf-8" Helpers.get_os_understandable_path(path), encoding="utf-8"
) as file: ) as file:
content = file.read() content = file.read()
file.close() file.close()
@ -240,7 +239,7 @@ class Servers_Controller:
return json.loads(content) return json.loads(content)
def check_for_old_logs(self): def check_for_old_logs(self):
servers = servers_helper.get_all_defined_servers() servers = helper_servers.get_all_defined_servers()
for server in servers: for server in servers:
logs_path = os.path.split(server["log_path"])[0] logs_path = os.path.split(server["log_path"])[0]
latest_log_file = os.path.split(server["log_path"])[1] latest_log_file = os.path.split(server["log_path"])[1]
@ -253,9 +252,9 @@ class Servers_Controller:
) )
for log_file in log_files: for log_file in log_files:
log_file_path = os.path.join(logs_path, log_file) log_file_path = os.path.join(logs_path, log_file)
if helper.check_file_exists( if Helpers.check_file_exists(
log_file_path log_file_path
) and helper.is_file_older_than_x_days( ) and Helpers.is_file_older_than_x_days(
log_file_path, logs_delete_after log_file_path, logs_delete_after
): ):
os.remove(log_file_path) os.remove(log_file_path)

View File

@ -1,61 +1,62 @@
import logging import logging
from typing import Optional from typing import Optional
from app.classes.models.users import users_helper from app.classes.models.users import helper_users
from app.classes.models.crafty_permissions import ( from app.classes.models.crafty_permissions import (
crafty_permissions, Permissions_Crafty,
Enum_Permissions_Crafty, Enum_Permissions_Crafty,
) )
from app.classes.shared.helpers import helper
from app.classes.shared.authentication import authentication
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Users_Controller: class Users_Controller:
def __init__(self, helper, users_helper, authentication):
self.helper = helper
self.users_helper = users_helper
self.authentication = authentication
# ********************************************************************************** # **********************************************************************************
# Users Methods # Users Methods
# ********************************************************************************** # **********************************************************************************
@staticmethod @staticmethod
def get_all_users(): def get_all_users():
return users_helper.get_all_users() return helper_users.get_all_users()
@staticmethod @staticmethod
def get_id_by_name(username): def get_id_by_name(username):
return users_helper.get_user_id_by_name(username) return helper_users.get_user_id_by_name(username)
@staticmethod @staticmethod
def get_user_lang_by_id(user_id): def get_user_lang_by_id(user_id):
return users_helper.get_user_lang_by_id(user_id) return helper_users.get_user_lang_by_id(user_id)
@staticmethod @staticmethod
def get_user_by_id(user_id): def get_user_by_id(user_id):
return users_helper.get_user(user_id) return helper_users.get_user(user_id)
@staticmethod @staticmethod
def update_server_order(user_id, user_server_order): def update_server_order(user_id, user_server_order):
users_helper.update_server_order(user_id, user_server_order) helper_users.update_server_order(user_id, user_server_order)
@staticmethod @staticmethod
def get_server_order(user_id): def get_server_order(user_id):
return users_helper.get_server_order(user_id) return helper_users.get_server_order(user_id)
@staticmethod @staticmethod
def user_query(user_id): def user_query(user_id):
return users_helper.user_query(user_id) return helper_users.user_query(user_id)
@staticmethod @staticmethod
def set_support_path(user_id, support_path): def set_support_path(user_id, support_path):
users_helper.set_support_path(user_id, support_path) helper_users.set_support_path(user_id, support_path)
@staticmethod def update_user(self, user_id: str, user_data=None, user_crafty_data=None):
def update_user(user_id: str, user_data=None, user_crafty_data=None):
if user_crafty_data is None: if user_crafty_data is None:
user_crafty_data = {} user_crafty_data = {}
if user_data is None: if user_data is None:
user_data = {} user_data = {}
base_data = users_helper.get_user(user_id) base_data = helper_users.get_user(user_id)
up_data = {} up_data = {}
added_roles = set() added_roles = set()
removed_roles = set() removed_roles = set()
@ -67,15 +68,15 @@ class Users_Controller:
removed_roles = base_data["roles"].difference(user_data["roles"]) removed_roles = base_data["roles"].difference(user_data["roles"])
elif key == "password": elif key == "password":
if user_data["password"] is not None and user_data["password"] != "": if user_data["password"] is not None and user_data["password"] != "":
up_data["password"] = helper.encode_pass(user_data["password"]) up_data["password"] = self.helper.encode_pass(user_data["password"])
elif base_data[key] != user_data[key]: elif base_data[key] != user_data[key]:
up_data[key] = user_data[key] up_data[key] = user_data[key]
up_data["last_update"] = helper.get_time_as_string() up_data["last_update"] = self.helper.get_time_as_string()
up_data["lang"] = user_data["lang"] up_data["lang"] = user_data["lang"]
up_data["hints"] = user_data["hints"] up_data["hints"] = user_data["hints"]
logger.debug(f"user: {user_data} +role:{added_roles} -role:{removed_roles}") logger.debug(f"user: {user_data} +role:{added_roles} -role:{removed_roles}")
for role in added_roles: for role in added_roles:
users_helper.get_or_create(user_id=user_id, role_id=role) helper_users.get_or_create(user_id=user_id, role_id=role)
permissions_mask = user_crafty_data.get("permissions_mask", "000") permissions_mask = user_crafty_data.get("permissions_mask", "000")
if "server_quantity" in user_crafty_data: if "server_quantity" in user_crafty_data:
@ -94,7 +95,7 @@ class Users_Controller:
limit_user_creation = 0 limit_user_creation = 0
limit_role_creation = 0 limit_role_creation = 0
crafty_permissions.add_or_update_user( Permissions_Crafty.add_or_update_user(
user_id, user_id,
permissions_mask, permissions_mask,
limit_server_creation, limit_server_creation,
@ -102,19 +103,19 @@ class Users_Controller:
limit_role_creation, limit_role_creation,
) )
users_helper.delete_user_roles(user_id, removed_roles) self.users_helper.delete_user_roles(user_id, removed_roles)
users_helper.update_user(user_id, up_data) self.users_helper.update_user(user_id, up_data)
@staticmethod
def add_user( def add_user(
self,
username, username,
password, password,
email="default@example.com", email="default@example.com",
enabled: bool = True, enabled: bool = True,
superuser: bool = False, superuser: bool = False,
): ):
return users_helper.add_user( return self.users_helper.add_user(
username, username,
password=password, password=password,
email=email, email=email,
@ -130,7 +131,7 @@ class Users_Controller:
enabled: bool = True, enabled: bool = True,
superuser: bool = False, superuser: bool = False,
): ):
return users_helper.add_rawpass_user( return helper_users.add_rawpass_user(
username, username,
password=password, password=password,
email=email, email=email,
@ -138,35 +139,31 @@ class Users_Controller:
superuser=superuser, superuser=superuser,
) )
@staticmethod def remove_user(self, user_id):
def remove_user(user_id): return self.users_helper.remove_user(user_id)
return users_helper.remove_user(user_id)
@staticmethod @staticmethod
def user_id_exists(user_id): def user_id_exists(user_id):
return users_helper.user_id_exists(user_id) return helper_users.user_id_exists(user_id)
@staticmethod @staticmethod
def set_prepare(user_id): def set_prepare(user_id):
return users_helper.set_prepare(user_id) return helper_users.set_prepare(user_id)
@staticmethod @staticmethod
def stop_prepare(user_id): def stop_prepare(user_id):
return users_helper.stop_prepare(user_id) return helper_users.stop_prepare(user_id)
@staticmethod def get_user_id_by_api_token(self, token: str) -> str:
def get_user_id_by_api_token(token: str) -> str: token_data = self.authentication.check_no_iat(token)
token_data = authentication.check_no_iat(token)
return token_data["user_id"] return token_data["user_id"]
@staticmethod def get_user_by_api_token(self, token: str):
def get_user_by_api_token(token: str): _, _, user = self.authentication.check(token)
_, _, user = authentication.check(token)
return user return user
@staticmethod def get_api_key_by_token(self, token: str):
def get_api_key_by_token(token: str): key, _, _ = self.authentication.check(token)
key, _, _ = authentication.check(token)
return key return key
# ********************************************************************************** # **********************************************************************************
@ -175,23 +172,21 @@ class Users_Controller:
@staticmethod @staticmethod
def get_user_roles_id(user_id): def get_user_roles_id(user_id):
return users_helper.get_user_roles_id(user_id) return helper_users.get_user_roles_id(user_id)
@staticmethod @staticmethod
def get_user_roles_names(user_id): def get_user_roles_names(user_id):
return users_helper.get_user_roles_names(user_id) return helper_users.get_user_roles_names(user_id)
@staticmethod def add_role_to_user(self, user_id, role_id):
def add_role_to_user(user_id, role_id): return self.users_helper.add_role_to_user(user_id, role_id)
return users_helper.add_role_to_user(user_id, role_id)
@staticmethod def add_user_roles(self, user):
def add_user_roles(user): return self.users_helper.add_user_roles(user)
return users_helper.add_user_roles(user)
@staticmethod @staticmethod
def user_role_query(user_id): def user_role_query(user_id):
return users_helper.user_role_query(user_id) return helper_users.user_role_query(user_id)
# ********************************************************************************** # **********************************************************************************
# Api Keys Methods # Api Keys Methods
@ -199,28 +194,26 @@ class Users_Controller:
@staticmethod @staticmethod
def get_user_api_keys(user_id: str): def get_user_api_keys(user_id: str):
return users_helper.get_user_api_keys(user_id) return helper_users.get_user_api_keys(user_id)
@staticmethod @staticmethod
def get_user_api_key(key_id: str): def get_user_api_key(key_id: str):
return users_helper.get_user_api_key(key_id) return helper_users.get_user_api_key(key_id)
@staticmethod
def add_user_api_key( def add_user_api_key(
self,
name: str, name: str,
user_id: str, user_id: str,
superuser: bool = False, superuser: bool = False,
server_permissions_mask: Optional[str] = None, server_permissions_mask: Optional[str] = None,
crafty_permissions_mask: Optional[str] = None, crafty_permissions_mask: Optional[str] = None,
): ):
return users_helper.add_user_api_key( return self.users_helper.add_user_api_key(
name, user_id, superuser, server_permissions_mask, crafty_permissions_mask name, user_id, superuser, server_permissions_mask, crafty_permissions_mask
) )
@staticmethod def delete_user_api_keys(self, user_id: str):
def delete_user_api_keys(user_id: str): return self.users_helper.delete_user_api_keys(user_id)
return users_helper.delete_user_api_keys(user_id)
@staticmethod def delete_user_api_key(self, key_id: str):
def delete_user_api_key(key_id: str): return self.users_helper.delete_user_api_key(key_id)
return users_helper.delete_user_api_key(key_id)

View File

@ -9,7 +9,7 @@ import uuid
import random import random
from app.classes.minecraft.bedrock_ping import BedrockPing from app.classes.minecraft.bedrock_ping import BedrockPing
from app.classes.shared.console import console from app.classes.shared.console import Console
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -106,14 +106,14 @@ def get_code_format(format_name):
return data.get(format_name) return data.get(format_name)
else: else:
logger.error(f"Format MOTD Error: format name {format_name} does not exist") logger.error(f"Format MOTD Error: format name {format_name} does not exist")
console.error( Console.error(
f"Format MOTD Error: format name {format_name} does not exist" f"Format MOTD Error: format name {format_name} does not exist"
) )
return "" return ""
except Exception as e: except Exception as e:
logger.critical(f"Config File Error: Unable to read {format_file} due to {e}") logger.critical(f"Config File Error: Unable to read {format_file} due to {e}")
console.critical(f"Config File Error: Unable to read {format_file} due to {e}") Console.critical(f"Config File Error: Unable to read {format_file} due to {e}")
return "" return ""

View File

@ -4,23 +4,17 @@ import time
import shutil import shutil
import logging import logging
from datetime import datetime from datetime import datetime
import requests
from app.classes.controllers.servers_controller import Servers_Controller from app.classes.controllers.servers_controller import Servers_Controller
from app.classes.models.server_permissions import server_permissions from app.classes.models.server_permissions import Permissions_Servers
from app.classes.shared.helpers import helper
from app.classes.web.websocket_helper import websocket_helper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
try:
import requests
except ModuleNotFoundError as err:
helper.auto_installer_fix(err)
class ServerJars: class ServerJars:
def __init__(self): def __init__(self, helper):
self.helper = helper
self.base_url = "https://serverjars.com" self.base_url = "https://serverjars.com"
def _get_api_result(self, call_url: str): def _get_api_result(self, call_url: str):
@ -50,9 +44,8 @@ class ServerJars:
return api_response return api_response
@staticmethod def _read_cache(self):
def _read_cache(): cache_file = self.helper.serverjar_cache
cache_file = helper.serverjar_cache
cache = {} cache = {}
try: try:
with open(cache_file, "r", encoding="utf-8") as f: with open(cache_file, "r", encoding="utf-8") as f:
@ -109,8 +102,8 @@ class ServerJars:
def refresh_cache(self): def refresh_cache(self):
cache_file = helper.serverjar_cache cache_file = self.helper.serverjar_cache
cache_old = helper.is_file_older_than_x_days(cache_file) cache_old = self.helper.is_file_older_than_x_days(cache_file)
# debug override # debug override
# cache_old = True # cache_old = True
@ -166,6 +159,7 @@ class ServerJars:
def download_jar(self, server, version, path, server_id): def download_jar(self, server, version, path, server_id):
update_thread = threading.Thread( update_thread = threading.Thread(
name=f"server_download-{server_id}-{server}-{version}",
target=self.a_download_jar, target=self.a_download_jar,
daemon=True, daemon=True,
args=(server, version, path, server_id), args=(server, version, path, server_id),
@ -176,7 +170,7 @@ class ServerJars:
# delaying download for server register to finish # delaying download for server register to finish
time.sleep(3) time.sleep(3)
fetch_url = f"{self.base_url}/api/fetchJar/{server}/{version}" fetch_url = f"{self.base_url}/api/fetchJar/{server}/{version}"
server_users = server_permissions.get_server_user_list(server_id) server_users = Permissions_Servers.get_server_user_list(server_id)
# We need to make sure the server is registered before # We need to make sure the server is registered before
# we submit a db update for it's stats. # we submit a db update for it's stats.
@ -184,11 +178,13 @@ class ServerJars:
try: try:
Servers_Controller.set_download(server_id) Servers_Controller.set_download(server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user(user, "send_start_reload", {}) self.helper.websocket_helper.broadcast_user(
user, "send_start_reload", {}
)
break break
except: except Exception as ex:
logger.debug("server not registered yet. Delaying download.") logger.debug(f"server not registered yet. Delaying download - {ex}")
# open a file stream # open a file stream
with requests.get(fetch_url, timeout=2, stream=True) as r: with requests.get(fetch_url, timeout=2, stream=True) as r:
@ -198,24 +194,25 @@ class ServerJars:
Servers_Controller.finish_download(server_id) Servers_Controller.finish_download(server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, "notification", "Executable download finished" user, "notification", "Executable download finished"
) )
time.sleep(3) time.sleep(3)
websocket_helper.broadcast_user(user, "send_start_reload", {}) self.helper.websocket_helper.broadcast_user(
user, "send_start_reload", {}
)
return True return True
except Exception as e: except Exception as e:
logger.error(f"Unable to save jar to {path} due to error:{e}") logger.error(f"Unable to save jar to {path} due to error:{e}")
Servers_Controller.finish_download(server_id) Servers_Controller.finish_download(server_id)
server_users = server_permissions.get_server_user_list(server_id) server_users = Permissions_Servers.get_server_user_list(server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, "notification", "Executable download finished" user, "notification", "Executable download finished"
) )
time.sleep(3) time.sleep(3)
websocket_helper.broadcast_user(user, "send_start_reload", {}) self.helper.websocket_helper.broadcast_user(
user, "send_start_reload", {}
)
return False return False
server_jar_obj = ServerJars()

View File

@ -6,14 +6,15 @@ import psutil
from app.classes.minecraft.mc_ping import ping from app.classes.minecraft.mc_ping import ping
from app.classes.models.management import Host_Stats from app.classes.models.management import Host_Stats
from app.classes.models.servers import servers_helper from app.classes.models.servers import helper_servers
from app.classes.shared.helpers import helper from app.classes.shared.helpers import Helpers
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Stats: class Stats:
def __init__(self, controller): def __init__(self, helper, controller):
self.helper = helper
self.controller = controller self.controller = controller
def get_node_stats(self): def get_node_stats(self):
@ -30,8 +31,8 @@ class Stats:
"cpu_cur_freq": round(cpu_freq[0], 2), "cpu_cur_freq": round(cpu_freq[0], 2),
"cpu_max_freq": cpu_freq[2], "cpu_max_freq": cpu_freq[2],
"mem_percent": psutil.virtual_memory()[2], "mem_percent": psutil.virtual_memory()[2],
"mem_usage": helper.human_readable_file_size(psutil.virtual_memory()[3]), "mem_usage": Helpers.human_readable_file_size(psutil.virtual_memory()[3]),
"mem_total": helper.human_readable_file_size(psutil.virtual_memory()[0]), "mem_total": Helpers.human_readable_file_size(psutil.virtual_memory()[0]),
"disk_data": self._all_disk_usage(), "disk_data": self._all_disk_usage(),
} }
# server_stats = self.get_servers_stats() # server_stats = self.get_servers_stats()
@ -60,7 +61,9 @@ class Stats:
with p.oneshot(): with p.oneshot():
process_stats = { process_stats = {
"cpu_usage": real_cpu, "cpu_usage": real_cpu,
"memory_usage": helper.human_readable_file_size(p.memory_info()[0]), "memory_usage": Helpers.human_readable_file_size(
p.memory_info()[0]
),
"mem_percentage": round(p.memory_percent(), 0), "mem_percentage": round(p.memory_percent(), 0),
} }
return process_stats return process_stats
@ -84,7 +87,7 @@ class Stats:
# print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type","Mount")) # print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type","Mount"))
for part in psutil.disk_partitions(all=False): for part in psutil.disk_partitions(all=False):
if helper.is_os_windows(): if Helpers.is_os_windows():
if "cdrom" in part.opts or part.fstype == "": if "cdrom" in part.opts or part.fstype == "":
# skip cd-rom drives with no disk in it; they may raise # skip cd-rom drives with no disk in it; they may raise
# ENOENT, pop-up a Windows GUI error for a non-ready # ENOENT, pop-up a Windows GUI error for a non-ready
@ -94,9 +97,9 @@ class Stats:
disk_data.append( disk_data.append(
{ {
"device": part.device, "device": part.device,
"total": helper.human_readable_file_size(usage.total), "total": Helpers.human_readable_file_size(usage.total),
"used": helper.human_readable_file_size(usage.used), "used": Helpers.human_readable_file_size(usage.used),
"free": helper.human_readable_file_size(usage.free), "free": Helpers.human_readable_file_size(usage.free),
"percent_used": int(usage.percent), "percent_used": int(usage.percent),
"fs": part.fstype, "fs": part.fstype,
"mount": part.mountpoint, "mount": part.mountpoint,
@ -110,15 +113,15 @@ class Stats:
total_size = 0 total_size = 0
total_size = helper.get_dir_size(server_path) total_size = Helpers.get_dir_size(server_path)
level_total_size = helper.human_readable_file_size(total_size) level_total_size = Helpers.human_readable_file_size(total_size)
return level_total_size return level_total_size
def get_server_players(self, server_id): def get_server_players(self, server_id):
server = servers_helper.get_server_data_by_id(server_id) server = helper_servers.get_server_data_by_id(server_id)
logger.info(f"Getting players for server {server}") logger.info(f"Getting players for server {server}")
@ -130,8 +133,8 @@ class Stats:
internal_ip = server["server_ip"] internal_ip = server["server_ip"]
server_port = server["server_port"] server_port = server["server_port"]
logger.debug("Pinging {internal_ip} on port {server_port}") logger.debug(f"Pinging {internal_ip} on port {server_port}")
if servers_helper.get_server_type_by_id(server_id) != "minecraft-bedrock": if helper_servers.get_server_type_by_id(server_id) != "minecraft-bedrock":
int_mc_ping = ping(internal_ip, int(server_port)) int_mc_ping = ping(internal_ip, int(server_port))
ping_data = {} ping_data = {}
@ -232,7 +235,7 @@ class Stats:
# ).execute() # ).execute()
# delete old data # delete old data
max_age = helper.get_setting("history_max_age") max_age = self.helper.get_setting("history_max_age")
now = datetime.datetime.now() now = datetime.datetime.now()
last_week = now.day - max_age last_week = now.day - max_age

View File

@ -0,0 +1,8 @@
import peewee
database_proxy = peewee.DatabaseProxy()
class BaseModel(peewee.Model):
class Meta:
database = database_proxy

View File

@ -1,35 +1,22 @@
import logging import logging
from enum import Enum
from app.classes.shared.helpers import helper from peewee import (
from app.classes.shared.permission_helper import permission_helper
from app.classes.models.users import Users, ApiKeys, users_helper
try:
from peewee import (
SqliteDatabase,
Model,
ForeignKeyField, ForeignKeyField,
CharField, CharField,
IntegerField, IntegerField,
DoesNotExist, DoesNotExist,
)
from enum import Enum
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
) )
from app.classes.models.base_model import BaseModel
from app.classes.models.users import Users, ApiKeys, helper_users
from app.classes.shared.permission_helper import PermissionHelper
logger = logging.getLogger(__name__)
# ********************************************************************************** # **********************************************************************************
# User_Crafty Class # User_Crafty Class
# ********************************************************************************** # **********************************************************************************
class User_Crafty(Model): class User_Crafty(BaseModel):
user_id = ForeignKeyField(Users, backref="users_crafty") user_id = ForeignKeyField(Users, backref="users_crafty")
permissions = CharField(default="00000000") permissions = CharField(default="00000000")
limit_server_creation = IntegerField(default=-1) limit_server_creation = IntegerField(default=-1)
@ -41,7 +28,6 @@ class User_Crafty(Model):
class Meta: class Meta:
table_name = "user_crafty" table_name = "user_crafty"
database = database
# ********************************************************************************** # **********************************************************************************
@ -68,7 +54,7 @@ class Permissions_Crafty:
def get_permissions(permissions_mask): def get_permissions(permissions_mask):
permissions_list = [] permissions_list = []
for member in Enum_Permissions_Crafty.__members__.items(): for member in Enum_Permissions_Crafty.__members__.items():
if crafty_permissions.has_permission(permissions_mask, member[1]): if Permissions_Crafty.has_permission(permissions_mask, member[1]):
permissions_list.append(member[1]) permissions_list.append(member[1])
return permissions_list return permissions_list
@ -95,7 +81,7 @@ class Permissions_Crafty:
@staticmethod @staticmethod
def get_crafty_permissions_mask(user_id): def get_crafty_permissions_mask(user_id):
permissions_mask = "" permissions_mask = ""
user_crafty = crafty_permissions.get_User_Crafty(user_id) user_crafty = Permissions_Crafty.get_User_Crafty(user_id)
permissions_mask = user_crafty.permissions permissions_mask = user_crafty.permissions
return permissions_mask return permissions_mask
@ -110,7 +96,7 @@ class Permissions_Crafty:
@staticmethod @staticmethod
def get_permission_quantity_list(user_id): def get_permission_quantity_list(user_id):
user_crafty = crafty_permissions.get_User_Crafty(user_id) user_crafty = Permissions_Crafty.get_User_Crafty(user_id)
quantity_list = { quantity_list = {
Enum_Permissions_Crafty.Server_Creation.name: user_crafty.limit_server_creation, # pylint: disable=line-too-long Enum_Permissions_Crafty.Server_Creation.name: user_crafty.limit_server_creation, # pylint: disable=line-too-long
Enum_Permissions_Crafty.User_Config.name: user_crafty.limit_user_creation, Enum_Permissions_Crafty.User_Config.name: user_crafty.limit_user_creation,
@ -140,7 +126,7 @@ class Permissions_Crafty:
User_Crafty.created_role: 0, User_Crafty.created_role: 0,
} }
).execute() ).execute()
user_crafty = crafty_permissions.get_User_Crafty(user_id) user_crafty = Permissions_Crafty.get_User_Crafty(user_id)
return user_crafty return user_crafty
@staticmethod @staticmethod
@ -180,7 +166,7 @@ class Permissions_Crafty:
@staticmethod @staticmethod
def get_created_quantity_list(user_id): def get_created_quantity_list(user_id):
user_crafty = crafty_permissions.get_User_Crafty(user_id) user_crafty = Permissions_Crafty.get_User_Crafty(user_id)
quantity_list = { quantity_list = {
Enum_Permissions_Crafty.Server_Creation.name: user_crafty.created_server, Enum_Permissions_Crafty.Server_Creation.name: user_crafty.created_server,
Enum_Permissions_Crafty.User_Config.name: user_crafty.created_user, Enum_Permissions_Crafty.User_Config.name: user_crafty.created_user,
@ -190,15 +176,15 @@ class Permissions_Crafty:
@staticmethod @staticmethod
def get_crafty_limit_value(user_id, permission): def get_crafty_limit_value(user_id, permission):
quantity_list = crafty_permissions.get_permission_quantity_list(user_id) quantity_list = Permissions_Crafty.get_permission_quantity_list(user_id)
return quantity_list[permission] return quantity_list[permission]
@staticmethod @staticmethod
def can_add_in_crafty(user_id, permission): def can_add_in_crafty(user_id, permission):
user_crafty = crafty_permissions.get_User_Crafty(user_id) user_crafty = Permissions_Crafty.get_User_Crafty(user_id)
can = crafty_permissions.has_permission(user_crafty.permissions, permission) can = Permissions_Crafty.has_permission(user_crafty.permissions, permission)
limit_list = crafty_permissions.get_permission_quantity_list(user_id) limit_list = Permissions_Crafty.get_permission_quantity_list(user_id)
quantity_list = crafty_permissions.get_created_quantity_list(user_id) quantity_list = Permissions_Crafty.get_created_quantity_list(user_id)
return can and ( return can and (
(quantity_list[permission.name] < limit_list[permission.name]) (quantity_list[permission.name] < limit_list[permission.name])
or limit_list[permission.name] == -1 or limit_list[permission.name] == -1
@ -206,29 +192,26 @@ class Permissions_Crafty:
@staticmethod @staticmethod
def add_server_creation(user_id): def add_server_creation(user_id):
user_crafty = crafty_permissions.get_User_Crafty(user_id) user_crafty = Permissions_Crafty.get_User_Crafty(user_id)
user_crafty.created_server += 1 user_crafty.created_server += 1
User_Crafty.save(user_crafty) User_Crafty.save(user_crafty)
return user_crafty.created_server return user_crafty.created_server
@staticmethod @staticmethod
def get_api_key_permissions_list(key: ApiKeys): def get_api_key_permissions_list(key: ApiKeys):
user = users_helper.get_user(key.user_id) user = helper_users.get_user(key.user_id)
if user["superuser"] and key.superuser: if user["superuser"] and key.superuser:
return crafty_permissions.get_permissions_list() return Permissions_Crafty.get_permissions_list()
else: else:
if user["superuser"]: if user["superuser"]:
user_permissions_mask = "111" user_permissions_mask = "111"
else: else:
user_permissions_mask = crafty_permissions.get_crafty_permissions_mask( user_permissions_mask = Permissions_Crafty.get_crafty_permissions_mask(
user["user_id"] user["user_id"]
) )
key_permissions_mask: str = key.crafty_permissions key_permissions_mask: str = key.crafty_permissions
permissions_mask = permission_helper.combine_masks( permissions_mask = PermissionHelper.combine_masks(
user_permissions_mask, key_permissions_mask user_permissions_mask, key_permissions_mask
) )
permissions_list = crafty_permissions.get_permissions(permissions_mask) permissions_list = Permissions_Crafty.get_permissions(permissions_mask)
return permissions_list return permissions_list
crafty_permissions = Permissions_Crafty()

View File

@ -1,17 +1,6 @@
import logging import logging
import datetime import datetime
from peewee import (
from app.classes.models.users import Users, users_helper
from app.classes.models.servers import Servers
from app.classes.models.server_permissions import server_permissions
from app.classes.shared.helpers import helper
from app.classes.shared.main_models import db_helper
from app.classes.web.websocket_helper import websocket_helper
try:
from peewee import (
SqliteDatabase,
Model,
ForeignKeyField, ForeignKeyField,
CharField, CharField,
IntegerField, IntegerField,
@ -20,23 +9,21 @@ try:
TextField, TextField,
AutoField, AutoField,
BooleanField, BooleanField,
) )
from playhouse.shortcuts import model_to_dict from playhouse.shortcuts import model_to_dict
except ModuleNotFoundError as e: from app.classes.models.base_model import BaseModel
helper.auto_installer_fix(e) from app.classes.models.users import Users, helper_users
from app.classes.models.servers import Servers
from app.classes.models.server_permissions import Permissions_Servers
from app.classes.shared.main_models import db_shortcuts
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
# ********************************************************************************** # **********************************************************************************
# Audit_Log Class # Audit_Log Class
# ********************************************************************************** # **********************************************************************************
class Audit_Log(Model): class Audit_Log(BaseModel):
audit_id = AutoField() audit_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
user_name = CharField(default="") user_name = CharField(default="")
@ -47,14 +34,11 @@ class Audit_Log(Model):
) # When auditing global events, use server ID 0 ) # When auditing global events, use server ID 0
log_msg = TextField(default="") log_msg = TextField(default="")
class Meta:
database = database
# ********************************************************************************** # **********************************************************************************
# Host_Stats Class # Host_Stats Class
# ********************************************************************************** # **********************************************************************************
class Host_Stats(Model): class Host_Stats(BaseModel):
time = DateTimeField(default=datetime.datetime.now, index=True) time = DateTimeField(default=datetime.datetime.now, index=True)
boot_time = CharField(default="") boot_time = CharField(default="")
cpu_usage = FloatField(default=0) cpu_usage = FloatField(default=0)
@ -68,13 +52,12 @@ class Host_Stats(Model):
class Meta: class Meta:
table_name = "host_stats" table_name = "host_stats"
database = database
# ********************************************************************************** # **********************************************************************************
# Commands Class # Commands Class
# ********************************************************************************** # **********************************************************************************
class Commands(Model): class Commands(BaseModel):
command_id = AutoField() command_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
server_id = ForeignKeyField(Servers, backref="server", index=True) server_id = ForeignKeyField(Servers, backref="server", index=True)
@ -85,13 +68,12 @@ class Commands(Model):
class Meta: class Meta:
table_name = "commands" table_name = "commands"
database = database
# ********************************************************************************** # **********************************************************************************
# Webhooks Class # Webhooks Class
# ********************************************************************************** # **********************************************************************************
class Webhooks(Model): class Webhooks(BaseModel):
id = AutoField() id = AutoField()
name = CharField(max_length=64, unique=True, index=True) name = CharField(max_length=64, unique=True, index=True)
method = CharField(default="POST") method = CharField(default="POST")
@ -101,13 +83,12 @@ class Webhooks(Model):
class Meta: class Meta:
table_name = "webhooks" table_name = "webhooks"
database = database
# ********************************************************************************** # **********************************************************************************
# Schedules Class # Schedules Class
# ********************************************************************************** # **********************************************************************************
class Schedules(Model): class Schedules(BaseModel):
schedule_id = IntegerField(unique=True, primary_key=True) schedule_id = IntegerField(unique=True, primary_key=True)
server_id = ForeignKeyField(Servers, backref="schedule_server") server_id = ForeignKeyField(Servers, backref="schedule_server")
enabled = BooleanField() enabled = BooleanField()
@ -124,13 +105,12 @@ class Schedules(Model):
class Meta: class Meta:
table_name = "schedules" table_name = "schedules"
database = database
# ********************************************************************************** # **********************************************************************************
# Backups Class # Backups Class
# ********************************************************************************** # **********************************************************************************
class Backups(Model): class Backups(BaseModel):
excluded_dirs = CharField(null=True) excluded_dirs = CharField(null=True)
max_backups = IntegerField() max_backups = IntegerField()
server_id = ForeignKeyField(Servers, backref="backups_server") server_id = ForeignKeyField(Servers, backref="backups_server")
@ -138,10 +118,12 @@ class Backups(Model):
class Meta: class Meta:
table_name = "backups" table_name = "backups"
database = database
class helpers_management: class helpers_management:
def __init__(self, database, helper):
self.database = database
self.helper = helper
# ********************************************************************************** # **********************************************************************************
# Host_Stats Methods # Host_Stats Methods
@ -185,18 +167,17 @@ class helpers_management:
@staticmethod @staticmethod
def get_actity_log(): def get_actity_log():
q = Audit_Log.select() q = Audit_Log.select()
return db_helper.return_db_rows(q) return db_shortcuts.return_db_rows(q)
@staticmethod def add_to_audit_log(self, user_id, log_msg, server_id=None, source_ip=None):
def add_to_audit_log(user_id, log_msg, server_id=None, source_ip=None):
logger.debug(f"Adding to audit log User:{user_id} - Message: {log_msg} ") logger.debug(f"Adding to audit log User:{user_id} - Message: {log_msg} ")
user_data = users_helper.get_user(user_id) user_data = helper_users.get_user(user_id)
audit_msg = f"{str(user_data['username']).capitalize()} {log_msg}" audit_msg = f"{str(user_data['username']).capitalize()} {log_msg}"
server_users = server_permissions.get_server_user_list(server_id) server_users = Permissions_Servers.get_server_user_list(server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user(user, "notification", audit_msg) self.helper.websocket_helper.broadcast_user(user, "notification", audit_msg)
Audit_Log.insert( Audit_Log.insert(
{ {
@ -210,17 +191,16 @@ class helpers_management:
# deletes records when they're more than 100 # deletes records when they're more than 100
ordered = Audit_Log.select().order_by(+Audit_Log.created) ordered = Audit_Log.select().order_by(+Audit_Log.created)
for item in ordered: for item in ordered:
if not helper.get_setting("max_audit_entries"): if not self.helper.get_setting("max_audit_entries"):
max_entries = 300 max_entries = 300
else: else:
max_entries = helper.get_setting("max_audit_entries") max_entries = self.helper.get_setting("max_audit_entries")
if Audit_Log.select().count() > max_entries: if Audit_Log.select().count() > max_entries:
Audit_Log.delete().where(Audit_Log.audit_id == item.audit_id).execute() Audit_Log.delete().where(Audit_Log.audit_id == item.audit_id).execute()
else: else:
return return
@staticmethod def add_to_audit_log_raw(self, user_name, user_id, server_id, log_msg, source_ip):
def add_to_audit_log_raw(user_name, user_id, server_id, log_msg, source_ip):
Audit_Log.insert( Audit_Log.insert(
{ {
Audit_Log.user_name: user_name, Audit_Log.user_name: user_name,
@ -234,10 +214,10 @@ class helpers_management:
ordered = Audit_Log.select().order_by(+Audit_Log.created) ordered = Audit_Log.select().order_by(+Audit_Log.created)
for item in ordered: for item in ordered:
# configurable through app/config/config.json # configurable through app/config/config.json
if not helper.get_setting("max_audit_entries"): if not self.helper.get_setting("max_audit_entries"):
max_entries = 300 max_entries = 300
else: else:
max_entries = helper.get_setting("max_audit_entries") max_entries = self.helper.get_setting("max_audit_entries")
if Audit_Log.select().count() > max_entries: if Audit_Log.select().count() > max_entries:
Audit_Log.delete().where(Audit_Log.audit_id == item.audit_id).execute() Audit_Log.delete().where(Audit_Log.audit_id == item.audit_id).execute()
else: else:
@ -354,8 +334,8 @@ class helpers_management:
} }
return conf return conf
@staticmethod
def set_backup_config( def set_backup_config(
self,
server_id: int, server_id: int,
backup_path: str = None, backup_path: str = None,
max_backups: int = None, max_backups: int = None,
@ -381,7 +361,7 @@ class helpers_management:
conf["excluded_dirs"] = dirs_to_exclude conf["excluded_dirs"] = dirs_to_exclude
conf["compress"] = compress conf["compress"] = compress
if not new_row: if not new_row:
with database.atomic(): with self.database.atomic():
if backup_path is not None: if backup_path is not None:
u1 = ( u1 = (
Servers.update(backup_path=backup_path) Servers.update(backup_path=backup_path)
@ -395,7 +375,7 @@ class helpers_management:
) )
logger.debug(f"Updating existing backup record. {u1}+{u2} rows affected") logger.debug(f"Updating existing backup record. {u1}+{u2} rows affected")
else: else:
with database.atomic(): with self.database.atomic():
conf["server_id"] = server_id conf["server_id"] = server_id
if backup_path is not None: if backup_path is not None:
Servers.update(backup_path=backup_path).where( Servers.update(backup_path=backup_path).where(
@ -404,8 +384,9 @@ class helpers_management:
Backups.create(**conf) Backups.create(**conf)
logger.debug("Creating new backup record.") logger.debug("Creating new backup record.")
def get_excluded_backup_dirs(self, server_id: int): @staticmethod
excluded_dirs = self.get_backup_config(server_id)["excluded_dirs"] def get_excluded_backup_dirs(server_id: int):
excluded_dirs = helpers_management.get_backup_config(server_id)["excluded_dirs"]
if excluded_dirs is not None and excluded_dirs != "": if excluded_dirs is not None and excluded_dirs != "":
dir_list = excluded_dirs.split(",") dir_list = excluded_dirs.split(",")
else: else:
@ -441,6 +422,3 @@ class helpers_management:
Commands.update({Commands.executed: True}).where( Commands.update({Commands.executed: True}).where(
Commands.executed == False # pylint: disable=singleton-comparison Commands.executed == False # pylint: disable=singleton-comparison
).execute() ).execute()
management_helper = helpers_management()

View File

@ -1,33 +1,22 @@
import logging import logging
import datetime import datetime
from peewee import (
from app.classes.shared.helpers import helper
try:
from peewee import (
SqliteDatabase,
Model,
CharField, CharField,
DoesNotExist, DoesNotExist,
AutoField, AutoField,
DateTimeField, DateTimeField,
) )
from playhouse.shortcuts import model_to_dict from playhouse.shortcuts import model_to_dict
except ModuleNotFoundError as e: from app.classes.models.base_model import BaseModel
helper.auto_installer_fix(e) from app.classes.shared.helpers import Helpers
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
# ********************************************************************************** # **********************************************************************************
# Roles Class # Roles Class
# ********************************************************************************** # **********************************************************************************
class Roles(Model): class Roles(BaseModel):
role_id = AutoField() role_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
last_update = DateTimeField(default=datetime.datetime.now) last_update = DateTimeField(default=datetime.datetime.now)
@ -35,13 +24,15 @@ class Roles(Model):
class Meta: class Meta:
table_name = "roles" table_name = "roles"
database = database
# ********************************************************************************** # **********************************************************************************
# Roles Helpers # Roles Helpers
# ********************************************************************************** # **********************************************************************************
class helper_roles: class helper_roles:
def __init__(self, database):
self.database = database
@staticmethod @staticmethod
def get_all_roles(): def get_all_roles():
query = Roles.select() query = Roles.select()
@ -63,7 +54,7 @@ class helper_roles:
role_id = Roles.insert( role_id = Roles.insert(
{ {
Roles.role_name: role_name.lower(), Roles.role_name: role_name.lower(),
Roles.created: helper.get_time_as_string(), Roles.created: Helpers.get_time_as_string(),
} }
).execute() ).execute()
return role_id return role_id
@ -72,17 +63,13 @@ class helper_roles:
def update_role(role_id, up_data): def update_role(role_id, up_data):
return Roles.update(up_data).where(Roles.role_id == role_id).execute() return Roles.update(up_data).where(Roles.role_id == role_id).execute()
@staticmethod def remove_role(self, role_id):
def remove_role(role_id): with self.database.atomic():
with database.atomic():
role = Roles.get(Roles.role_id == role_id) role = Roles.get(Roles.role_id == role_id)
return role.delete_instance() return role.delete_instance()
@staticmethod @staticmethod
def role_id_exists(role_id): def role_id_exists(role_id):
if not roles_helper.get_role(role_id): if not helper_roles.get_role(role_id):
return False return False
return True return True
roles_helper = helper_roles()

View File

@ -1,36 +1,24 @@
from enum import Enum
import logging import logging
from peewee import (
from app.classes.models.servers import Servers
from app.classes.models.roles import Roles
from app.classes.models.users import User_Roles, users_helper, ApiKeys, Users
from app.classes.shared.helpers import helper
from app.classes.shared.permission_helper import permission_helper
try:
from peewee import (
SqliteDatabase,
Model,
ForeignKeyField, ForeignKeyField,
CharField, CharField,
CompositeKey, CompositeKey,
JOIN, JOIN,
) )
from enum import Enum
except ModuleNotFoundError as e: from app.classes.models.base_model import BaseModel
helper.auto_installer_fix(e) from app.classes.models.servers import Servers
from app.classes.models.roles import Roles
from app.classes.models.users import User_Roles, helper_users, ApiKeys, Users
from app.classes.shared.permission_helper import PermissionHelper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
# ********************************************************************************** # **********************************************************************************
# Role Servers Class # Role Servers Class
# ********************************************************************************** # **********************************************************************************
class Role_Servers(Model): class Role_Servers(BaseModel):
role_id = ForeignKeyField(Roles, backref="role_server") role_id = ForeignKeyField(Roles, backref="role_server")
server_id = ForeignKeyField(Servers, backref="role_server") server_id = ForeignKeyField(Servers, backref="role_server")
permissions = CharField(default="00000000") permissions = CharField(default="00000000")
@ -38,7 +26,6 @@ class Role_Servers(Model):
class Meta: class Meta:
table_name = "role_servers" table_name = "role_servers"
primary_key = CompositeKey("role_id", "server_id") primary_key = CompositeKey("role_id", "server_id")
database = database
# ********************************************************************************** # **********************************************************************************
@ -73,7 +60,7 @@ class Permissions_Servers:
def get_permissions(permissions_mask): def get_permissions(permissions_mask):
permissions_list = [] permissions_list = []
for member in Enum_Permissions_Server.__members__.items(): for member in Enum_Permissions_Server.__members__.items():
if server_permissions.has_permission(permissions_mask, member[1]): if Permissions_Servers.has_permission(permissions_mask, member[1]):
permissions_list.append(member[1]) permissions_list.append(member[1])
return permissions_list return permissions_list
@ -98,7 +85,7 @@ class Permissions_Servers:
def get_token_permissions(permissions_mask, api_permissions_mask): def get_token_permissions(permissions_mask, api_permissions_mask):
permissions_list = [] permissions_list = []
for member in Enum_Permissions_Server.__members__.items(): for member in Enum_Permissions_Server.__members__.items():
if permission_helper.both_have_perm( if PermissionHelper.both_have_perm(
permissions_mask, api_permissions_mask, member[1] permissions_mask, api_permissions_mask, member[1]
): ):
permissions_list.append(member[1]) permissions_list.append(member[1])
@ -166,7 +153,7 @@ class Permissions_Servers:
role_server = Role_Servers.get_or_none(Role_Servers.role_id == role_id) role_server = Role_Servers.get_or_none(Role_Servers.role_id == role_id)
if role_server is not None: if role_server is not None:
permissions_mask = role_server.permissions permissions_mask = role_server.permissions
permissions_list = server_permissions.get_permissions(permissions_mask) permissions_list = Permissions_Servers.get_permissions(permissions_mask)
return permissions_list return permissions_list
@staticmethod @staticmethod
@ -193,24 +180,21 @@ class Permissions_Servers:
@staticmethod @staticmethod
def remove_roles_of_server(server_id): def remove_roles_of_server(server_id):
with database.atomic():
return ( return (
Role_Servers.delete() Role_Servers.delete().where(Role_Servers.server_id == server_id).execute()
.where(Role_Servers.server_id == server_id)
.execute()
) )
@staticmethod @staticmethod
def get_user_id_permissions_mask(user_id, server_id: str): def get_user_id_permissions_mask(user_id, server_id: str):
user = users_helper.get_user_model(user_id) user = helper_users.get_user_model(user_id)
return server_permissions.get_user_permissions_mask(user, server_id) return Permissions_Servers.get_user_permissions_mask(user, server_id)
@staticmethod @staticmethod
def get_user_permissions_mask(user: Users, server_id: str): def get_user_permissions_mask(user: Users, server_id: str):
if user.superuser: if user.superuser:
permissions_mask = "1" * len(server_permissions.get_permissions_list()) permissions_mask = "1" * len(Permissions_Servers.get_permissions_list())
else: else:
roles_list = users_helper.get_user_roles_id(user.user_id) roles_list = helper_users.get_user_roles_id(user.user_id)
role_server = ( role_server = (
Role_Servers.select() Role_Servers.select()
.where(Role_Servers.role_id.in_(roles_list)) .where(Role_Servers.role_id.in_(roles_list))
@ -220,7 +204,7 @@ class Permissions_Servers:
try: try:
permissions_mask = role_server[0].permissions permissions_mask = role_server[0].permissions
except IndexError: except IndexError:
permissions_mask = "0" * len(server_permissions.get_permissions_list()) permissions_mask = "0" * len(Permissions_Servers.get_permissions_list())
return permissions_mask return permissions_mask
@staticmethod @staticmethod
@ -242,45 +226,48 @@ class Permissions_Servers:
@staticmethod @staticmethod
def get_user_id_permissions_list(user_id, server_id: str): def get_user_id_permissions_list(user_id, server_id: str):
user = users_helper.get_user_model(user_id) user = helper_users.get_user_model(user_id)
return server_permissions.get_user_permissions_list(user, server_id) return Permissions_Servers.get_user_permissions_list(user, server_id)
@staticmethod @staticmethod
def get_user_permissions_list(user: Users, server_id: str): def get_user_permissions_list(user: Users, server_id: str):
if user.superuser: if user.superuser:
permissions_list = server_permissions.get_permissions_list() permissions_list = Permissions_Servers.get_permissions_list()
else: else:
permissions_mask = server_permissions.get_user_permissions_mask( permissions_mask = Permissions_Servers.get_user_permissions_mask(
user, server_id user, server_id
) )
permissions_list = server_permissions.get_permissions(permissions_mask) permissions_list = Permissions_Servers.get_permissions(permissions_mask)
return permissions_list return permissions_list
@staticmethod @staticmethod
def get_api_key_id_permissions_list(key_id, server_id: str): def get_api_key_id_permissions_list(key_id, server_id: str):
key = ApiKeys.get(ApiKeys.token_id == key_id) key = ApiKeys.get(ApiKeys.token_id == key_id)
return server_permissions.get_api_key_permissions_list(key, server_id) return Permissions_Servers.get_api_key_permissions_list(key, server_id)
@staticmethod @staticmethod
def get_api_key_permissions_list(key: ApiKeys, server_id: str): def get_api_key_permissions_list(key: ApiKeys, server_id: str):
user = users_helper.get_user(key.user_id) user = helper_users.get_user(key.user_id)
if user["superuser"] and key.superuser: if user["superuser"] and key.superuser:
return server_permissions.get_permissions_list() return Permissions_Servers.get_permissions_list()
else: else:
roles_list = users_helper.get_user_roles_id(user["user_id"]) roles_list = helper_users.get_user_roles_id(user["user_id"])
role_server = ( role_server = (
Role_Servers.select() Role_Servers.select()
.where(Role_Servers.role_id.in_(roles_list)) .where(Role_Servers.role_id.in_(roles_list))
.where(Role_Servers.server_id == server_id) .where(Role_Servers.server_id == server_id)
.execute() .execute()
) )
try:
user_permissions_mask = role_server[0].permissions user_permissions_mask = role_server[0].permissions
except:
if user["superuser"]:
user_permissions_mask = "11111111"
else:
user_permissions_mask = "00000000"
key_permissions_mask = key.server_permissions key_permissions_mask = key.server_permissions
permissions_mask = permission_helper.combine_masks( permissions_mask = PermissionHelper.combine_masks(
user_permissions_mask, key_permissions_mask user_permissions_mask, key_permissions_mask
) )
permissions_list = server_permissions.get_permissions(permissions_mask) permissions_list = Permissions_Servers.get_permissions(permissions_mask)
return permissions_list return permissions_list
server_permissions = Permissions_Servers()

View File

@ -1,13 +1,6 @@
import logging import logging
import datetime import datetime
from peewee import (
from app.classes.shared.helpers import helper
from app.classes.shared.main_models import db_helper
try:
from peewee import (
SqliteDatabase,
Model,
ForeignKeyField, ForeignKeyField,
CharField, CharField,
AutoField, AutoField,
@ -15,22 +8,17 @@ try:
BooleanField, BooleanField,
IntegerField, IntegerField,
FloatField, FloatField,
) )
except ModuleNotFoundError as e: from app.classes.shared.main_models import db_shortcuts
helper.auto_installer_fix(e) from app.classes.models.base_model import BaseModel
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
# ********************************************************************************** # **********************************************************************************
# Servers Class # Servers Class
# ********************************************************************************** # **********************************************************************************
class Servers(Model): class Servers(BaseModel):
server_id = AutoField() server_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
server_uuid = CharField(default="", index=True) server_uuid = CharField(default="", index=True)
@ -52,13 +40,12 @@ class Servers(Model):
class Meta: class Meta:
table_name = "servers" table_name = "servers"
database = database
# ********************************************************************************** # **********************************************************************************
# Servers Stats Class # Servers Stats Class
# ********************************************************************************** # **********************************************************************************
class Server_Stats(Model): class Server_Stats(BaseModel):
stats_id = AutoField() stats_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
server_id = ForeignKeyField(Servers, backref="server", index=True) server_id = ForeignKeyField(Servers, backref="server", index=True)
@ -84,13 +71,14 @@ class Server_Stats(Model):
class Meta: class Meta:
table_name = "server_stats" table_name = "server_stats"
database = database
# ********************************************************************************** # **********************************************************************************
# Servers Class # Servers Class
# ********************************************************************************** # **********************************************************************************
class helper_servers: class helper_servers:
def __init__(self, database):
self.database = database
# ********************************************************************************** # **********************************************************************************
# Generic Servers Methods # Generic Servers Methods
@ -139,16 +127,15 @@ class helper_servers:
def update_server(server_obj): def update_server(server_obj):
return server_obj.save() return server_obj.save()
@staticmethod def remove_server(self, server_id):
def remove_server(server_id): with self.database.atomic():
with database.atomic():
Servers.delete().where(Servers.server_id == server_id).execute() Servers.delete().where(Servers.server_id == server_id).execute()
@staticmethod @staticmethod
def get_server_data_by_id(server_id): def get_server_data_by_id(server_id):
query = Servers.select().where(Servers.server_id == server_id).limit(1) query = Servers.select().where(Servers.server_id == server_id).limit(1)
try: try:
return db_helper.return_rows(query)[0] return db_shortcuts.return_rows(query)[0]
except IndexError: except IndexError:
return {} return {}
@ -158,11 +145,11 @@ class helper_servers:
@staticmethod @staticmethod
def get_all_defined_servers(): def get_all_defined_servers():
query = Servers.select() query = Servers.select()
return db_helper.return_rows(query) return db_shortcuts.return_rows(query)
@staticmethod @staticmethod
def get_all_servers_stats(): def get_all_servers_stats():
servers = servers_helper.get_all_defined_servers() servers = helper_servers.get_all_defined_servers()
server_data = [] server_data = []
try: try:
for s in servers: for s in servers:
@ -175,7 +162,7 @@ class helper_servers:
server_data.append( server_data.append(
{ {
"server_data": s, "server_data": s,
"stats": db_helper.return_rows(latest)[0], "stats": db_shortcuts.return_rows(latest)[0],
"user_command_permission": True, "user_command_permission": True,
} }
) )
@ -187,7 +174,7 @@ class helper_servers:
@staticmethod @staticmethod
def get_server_friendly_name(server_id): def get_server_friendly_name(server_id):
server_data = servers_helper.get_server_data_by_id(server_id) server_data = helper_servers.get_server_data_by_id(server_id)
friendly_name = ( friendly_name = (
f"{server_data.get('server_name', None)} " f"{server_data.get('server_name', None)} "
f"with ID: {server_data.get('server_id', 0)}" f"with ID: {server_data.get('server_id', 0)}"
@ -214,31 +201,28 @@ class helper_servers:
.order_by(Server_Stats.created.desc()) .order_by(Server_Stats.created.desc())
.limit(1) .limit(1)
) )
return db_helper.return_rows(stats)[0] return db_shortcuts.return_rows(stats)[0]
@staticmethod @staticmethod
def server_id_exists(server_id): def server_id_exists(server_id):
if not servers_helper.get_server_data_by_id(server_id): if not helper_servers.get_server_data_by_id(server_id):
return False return False
return True return True
@staticmethod @staticmethod
def sever_crashed(server_id): def sever_crashed(server_id):
with database.atomic():
Server_Stats.update(crashed=True).where( Server_Stats.update(crashed=True).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@staticmethod @staticmethod
def set_download(server_id): def set_download(server_id):
with database.atomic():
Server_Stats.update(downloading=True).where( Server_Stats.update(downloading=True).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@staticmethod @staticmethod
def finish_download(server_id): def finish_download(server_id):
with database.atomic():
Server_Stats.update(downloading=False).where( Server_Stats.update(downloading=False).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@ -252,7 +236,6 @@ class helper_servers:
@staticmethod @staticmethod
def server_crash_reset(server_id): def server_crash_reset(server_id):
with database.atomic():
Server_Stats.update(crashed=False).where( Server_Stats.update(crashed=False).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@ -272,7 +255,6 @@ class helper_servers:
Server_Stats.select().where(Server_Stats.server_id == server_id) Server_Stats.select().where(Server_Stats.server_id == server_id)
except Exception as ex: except Exception as ex:
logger.error(f"Database entry not found! {ex}") logger.error(f"Database entry not found! {ex}")
with database.atomic():
Server_Stats.update(updating=value).where( Server_Stats.update(updating=value).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@ -293,7 +275,6 @@ class helper_servers:
except Exception as ex: except Exception as ex:
logger.error(f"Database entry not found! {ex}") logger.error(f"Database entry not found! {ex}")
return return
with database.atomic():
Server_Stats.update(first_run=False).where( Server_Stats.update(first_run=False).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@ -325,7 +306,7 @@ class helper_servers:
@staticmethod @staticmethod
def can_stop_no_players(server_id, time_limit): def can_stop_no_players(server_id, time_limit):
can = False can = False
ttl_no_players = servers_helper.get_TTL_without_player(server_id) ttl_no_players = helper_servers.get_TTL_without_player(server_id)
if (time_limit == -1) or (ttl_no_players > time_limit): if (time_limit == -1) or (ttl_no_players > time_limit):
can = True can = True
return can return can
@ -337,7 +318,6 @@ class helper_servers:
Server_Stats.select().where(Server_Stats.server_id == server_id) Server_Stats.select().where(Server_Stats.server_id == server_id)
except Exception as ex: except Exception as ex:
logger.error(f"Database entry not found! {ex}") logger.error(f"Database entry not found! {ex}")
with database.atomic():
Server_Stats.update(waiting_start=value).where( Server_Stats.update(waiting_start=value).where(
Server_Stats.server_id == server_id Server_Stats.server_id == server_id
).execute() ).execute()
@ -348,6 +328,3 @@ class helper_servers:
Server_Stats.select().where(Server_Stats.server_id == server_id).get() Server_Stats.select().where(Server_Stats.server_id == server_id).get()
) )
return waiting_start.waiting_start return waiting_start.waiting_start
servers_helper = helper_servers()

View File

@ -2,13 +2,7 @@ import logging
import datetime import datetime
from typing import Optional, Union from typing import Optional, Union
from app.classes.models.roles import Roles, roles_helper from peewee import (
from app.classes.shared.helpers import helper
try:
from peewee import (
SqliteDatabase,
Model,
ForeignKeyField, ForeignKeyField,
CharField, CharField,
AutoField, AutoField,
@ -17,23 +11,19 @@ try:
CompositeKey, CompositeKey,
DoesNotExist, DoesNotExist,
JOIN, JOIN,
) )
from playhouse.shortcuts import model_to_dict from playhouse.shortcuts import model_to_dict
except ModuleNotFoundError as e: from app.classes.shared.helpers import Helpers
helper.auto_installer_fix(e) from app.classes.models.base_model import BaseModel
from app.classes.models.roles import Roles, helper_roles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
# ********************************************************************************** # **********************************************************************************
# Users Class # Users Class
# ********************************************************************************** # **********************************************************************************
class Users(Model): class Users(BaseModel):
user_id = AutoField() user_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
last_login = DateTimeField(default=datetime.datetime.now) last_login = DateTimeField(default=datetime.datetime.now)
@ -53,13 +43,12 @@ class Users(Model):
class Meta: class Meta:
table_name = "users" table_name = "users"
database = database
# ********************************************************************************** # **********************************************************************************
# API Keys Class # API Keys Class
# ********************************************************************************** # **********************************************************************************
class ApiKeys(Model): class ApiKeys(BaseModel):
token_id = AutoField() token_id = AutoField()
name = CharField(default="", unique=True, index=True) name = CharField(default="", unique=True, index=True)
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
@ -70,26 +59,28 @@ class ApiKeys(Model):
class Meta: class Meta:
table_name = "api_keys" table_name = "api_keys"
database = database
# ********************************************************************************** # **********************************************************************************
# User Roles Class # User Roles Class
# ********************************************************************************** # **********************************************************************************
class User_Roles(Model): class User_Roles(BaseModel):
user_id = ForeignKeyField(Users, backref="user_role") user_id = ForeignKeyField(Users, backref="user_role")
role_id = ForeignKeyField(Roles, backref="user_role") role_id = ForeignKeyField(Roles, backref="user_role")
class Meta: class Meta:
table_name = "user_roles" table_name = "user_roles"
primary_key = CompositeKey("user_id", "role_id") primary_key = CompositeKey("user_id", "role_id")
database = database
# ********************************************************************************** # **********************************************************************************
# Users Helpers # Users Helpers
# ********************************************************************************** # **********************************************************************************
class helper_users: class helper_users:
def __init__(self, database, helper):
self.database = database
self.helper = helper
@staticmethod @staticmethod
def get_by_id(user_id): def get_by_id(user_id):
return Users.get_by_id(user_id) return Users.get_by_id(user_id)
@ -137,7 +128,7 @@ class helper_users:
if user: if user:
# I know it should apply it without setting it but I'm just making sure # I know it should apply it without setting it but I'm just making sure
user = users_helper.add_user_roles(user) user = helper_users.add_user_roles(user)
return user return user
else: else:
# logger.debug("user: ({}) {}".format(user_id, {})) # logger.debug("user: ({}) {}".format(user_id, {}))
@ -155,11 +146,11 @@ class helper_users:
@staticmethod @staticmethod
def get_user_model(user_id: str) -> Users: def get_user_model(user_id: str) -> Users:
user = Users.get(Users.user_id == user_id) user = Users.get(Users.user_id == user_id)
user = users_helper.add_user_roles(user) user = helper_users.add_user_roles(user)
return user return user
@staticmethod
def add_user( def add_user(
self,
username: str, username: str,
password: str = None, password: str = None,
email: Optional[str] = None, email: Optional[str] = None,
@ -167,7 +158,7 @@ class helper_users:
superuser: bool = False, superuser: bool = False,
) -> str: ) -> str:
if password is not None: if password is not None:
pw_enc = helper.encode_pass(password) pw_enc = self.helper.encode_pass(password)
else: else:
pw_enc = None pw_enc = None
user_id = Users.insert( user_id = Users.insert(
@ -177,7 +168,7 @@ class helper_users:
Users.email: email, Users.email: email,
Users.enabled: enabled, Users.enabled: enabled,
Users.superuser: superuser, Users.superuser: superuser,
Users.created: helper.get_time_as_string(), Users.created: Helpers.get_time_as_string(),
} }
).execute() ).execute()
return user_id return user_id
@ -197,7 +188,7 @@ class helper_users:
Users.email: email, Users.email: email,
Users.enabled: enabled, Users.enabled: enabled,
Users.superuser: superuser, Users.superuser: superuser,
Users.created: helper.get_time_as_string(), Users.created: Helpers.get_time_as_string(),
} }
).execute() ).execute()
return user_id return user_id
@ -230,9 +221,8 @@ class helper_users:
final_users.append(suser.user_id) final_users.append(suser.user_id)
return final_users return final_users
@staticmethod def remove_user(self, user_id):
def remove_user(user_id): with self.database.atomic():
with database.atomic():
User_Roles.delete().where(User_Roles.user_id == user_id).execute() User_Roles.delete().where(User_Roles.user_id == user_id).execute()
user = Users.get(Users.user_id == user_id) user = Users.get(Users.user_id == user_id)
return user.delete_instance() return user.delete_instance()
@ -259,7 +249,7 @@ class helper_users:
@staticmethod @staticmethod
def user_id_exists(user_id): def user_id_exists(user_id):
if not users_helper.get_user(user_id): if not helper_users.get_user(user_id):
return False return False
return True return True
@ -276,7 +266,7 @@ class helper_users:
roles_list = [] roles_list = []
roles = User_Roles.select().where(User_Roles.user_id == user_id) roles = User_Roles.select().where(User_Roles.user_id == user_id)
for r in roles: for r in roles:
roles_list.append(roles_helper.get_role(r.role_id)["role_id"]) roles_list.append(helper_roles.get_role(r.role_id)["role_id"])
return roles_list return roles_list
@staticmethod @staticmethod
@ -284,7 +274,7 @@ class helper_users:
roles_list = [] roles_list = []
roles = User_Roles.select().where(User_Roles.user_id == user_id) roles = User_Roles.select().where(User_Roles.user_id == user_id)
for r in roles: for r in roles:
roles_list.append(roles_helper.get_role(r.role_id)["role_name"]) roles_list.append(helper_roles.get_role(r.role_id)["role_name"])
return roles_list return roles_list
@staticmethod @staticmethod
@ -384,6 +374,3 @@ class helper_users:
@staticmethod @staticmethod
def delete_user_api_key(key_id: str): def delete_user_api_key(key_id: str):
ApiKeys.delete().where(ApiKeys.token_id == key_id).execute() ApiKeys.delete().where(ApiKeys.token_id == key_id).execute()
users_helper = helper_users()

View File

@ -1,58 +1,50 @@
import logging import logging
import time import time
from typing import Optional, Dict, Any, Tuple from typing import Optional, Dict, Any, Tuple
import jwt
from jwt import PyJWTError
from app.classes.models.users import users_helper, ApiKeys from app.classes.models.users import helper_users, ApiKeys
from app.classes.shared.helpers import helper
try:
import jwt
from jwt import PyJWTError
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Authentication: class Authentication:
def __init__(self): def __init__(self, helper):
self.helper = helper
self.secret = "my secret" self.secret = "my secret"
self.secret = helper.get_setting("apikey_secret", None) self.secret = self.helper.get_setting("apikey_secret", None)
if self.secret is None or self.secret == "random": if self.secret is None or self.secret == "random":
self.secret = helper.random_string_generator(64) self.secret = self.helper.random_string_generator(64)
helper.set_setting("apikey_secret", self.secret) self.helper.set_setting("apikey_secret", self.secret)
@staticmethod def generate(self, user_id, extra=None):
def generate(user_id, extra=None):
if extra is None: if extra is None:
extra = {} extra = {}
jwt_encoded = jwt.encode( jwt_encoded = jwt.encode(
{"user_id": user_id, "iat": int(time.time()), **extra}, {"user_id": user_id, "iat": int(time.time()), **extra},
authentication.secret, self.secret,
algorithm="HS256", algorithm="HS256",
) )
return jwt_encoded return jwt_encoded
@staticmethod def read(self, token):
def read(token): return jwt.decode(token, self.secret, algorithms=["HS256"])
return jwt.decode(token, authentication.secret, algorithms=["HS256"])
@staticmethod def check_no_iat(self, token) -> Optional[Dict[str, Any]]:
def check_no_iat(token) -> Optional[Dict[str, Any]]:
try: try:
return jwt.decode(token, authentication.secret, algorithms=["HS256"]) return jwt.decode(token, self.secret, algorithms=["HS256"])
except PyJWTError as error: except PyJWTError as error:
logger.debug("Error while checking JWT token: ", exc_info=error) logger.debug("Error while checking JWT token: ", exc_info=error)
return None return None
@staticmethod
def check( def check(
self,
token, token,
) -> Optional[Tuple[Optional[ApiKeys], Dict[str, Any], Dict[str, Any]]]: ) -> Optional[Tuple[Optional[ApiKeys], Dict[str, Any], Dict[str, Any]]]:
try: try:
data = jwt.decode(token, authentication.secret, algorithms=["HS256"]) data = jwt.decode(token, self.secret, algorithms=["HS256"])
except PyJWTError as error: except PyJWTError as error:
logger.debug("Error while checking JWT token: ", exc_info=error) logger.debug("Error while checking JWT token: ", exc_info=error)
return None return None
@ -60,11 +52,11 @@ class Authentication:
key: Optional[ApiKeys] = None key: Optional[ApiKeys] = None
if "token_id" in data: if "token_id" in data:
key_id = data["token_id"] key_id = data["token_id"]
key = users_helper.get_user_api_key(key_id) key = helper_users.get_user_api_key(key_id)
if key is None: if key is None:
return None return None
user_id: str = data["user_id"] user_id: str = data["user_id"]
user = users_helper.get_user(user_id) user = helper_users.get_user(user_id)
# TODO: Have a cache or something so we don't constantly # TODO: Have a cache or something so we don't constantly
# have to query the database # have to query the database
if int(user.get("valid_tokens_from").timestamp()) < iat: if int(user.get("valid_tokens_from").timestamp()) < iat:
@ -73,9 +65,5 @@ class Authentication:
else: else:
return None return None
@staticmethod def check_bool(self, token) -> bool:
def check_bool(token) -> bool: return self.check(token) is not None
return authentication.check(token) is not None
authentication = Authentication()

View File

@ -3,23 +3,21 @@ import cmd
import time import time
import threading import threading
import logging import logging
from app.classes.shared.console import Console
from app.classes.shared.console import console
from app.classes.shared.helpers import helper
from app.classes.shared.import3 import import3 from app.classes.shared.import3 import import3
from app.classes.web.websocket_helper import websocket_helper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class MainPrompt(cmd.Cmd): class MainPrompt(cmd.Cmd):
def __init__(self, tasks_manager, migration_manager): def __init__(self, helper, tasks_manager, migration_manager):
super().__init__() super().__init__()
self.helper = helper
self.tasks_manager = tasks_manager self.tasks_manager = tasks_manager
self.migration_manager = migration_manager self.migration_manager = migration_manager
# overrides the default Prompt # overrides the default Prompt
prompt = f"Crafty Controller v{helper.get_version_string()} > " self.prompt = f"Crafty Controller v{self.helper.get_version_string()} > "
# see MR !233 for pylint exemptino reason # see MR !233 for pylint exemptino reason
@staticmethod @staticmethod
@ -36,20 +34,20 @@ class MainPrompt(cmd.Cmd):
elif line == "down": elif line == "down":
self.migration_manager.down() self.migration_manager.down()
elif line == "done": elif line == "done":
console.info(self.migration_manager.done) Console.info(self.migration_manager.done)
elif line == "todo": elif line == "todo":
console.info(self.migration_manager.todo) Console.info(self.migration_manager.todo)
elif line == "diff": elif line == "diff":
console.info(self.migration_manager.diff) Console.info(self.migration_manager.diff)
elif line == "info": elif line == "info":
console.info(f"Done: {self.migration_manager.done}") Console.info(f"Done: {self.migration_manager.done}")
console.info(f"FS: {self.migration_manager.todo}") Console.info(f"FS: {self.migration_manager.todo}")
console.info(f"Todo: {self.migration_manager.diff}") Console.info(f"Todo: {self.migration_manager.diff}")
elif line.startswith("add "): elif line.startswith("add "):
migration_name = line[len("add ") :] migration_name = line[len("add ") :]
self.migration_manager.create(migration_name, False) self.migration_manager.create(migration_name, False)
else: else:
console.info("Unknown migration command") Console.info("Unknown migration command")
@staticmethod @staticmethod
def do_threads(_line): def do_threads(_line):
@ -67,24 +65,21 @@ class MainPrompt(cmd.Cmd):
def universal_exit(self): def universal_exit(self):
logger.info("Stopping all server daemons / threads") logger.info("Stopping all server daemons / threads")
console.info( Console.info(
"Stopping all server daemons / threads - This may take a few seconds" "Stopping all server daemons / threads - This may take a few seconds"
) )
websocket_helper.disconnect_all() self.helper.websocket_helper.disconnect_all()
console.info("Waiting for main thread to stop") Console.info("Waiting for main thread to stop")
while True: while True:
if self.tasks_manager.get_main_thread_run_status(): if self.tasks_manager.get_main_thread_run_status():
sys.exit(0) sys.exit(0)
time.sleep(1) time.sleep(1)
@staticmethod def help_exit(self):
def help_exit(): Console.help("Stops the server if running, Exits the program")
console.help("Stops the server if running, Exits the program")
@staticmethod def help_migrations(self):
def help_migrations(): Console.help("Only for advanced users. Use with caution")
console.help("Only for advanced users. Use with caution")
@staticmethod def help_import3(self):
def help_import3(): Console.help("Import users and servers from Crafty 3")
console.help("Import users and servers from Crafty 3")

View File

@ -28,47 +28,56 @@ class Console:
else: else:
print(message) print(message)
def magenta(self, message): @staticmethod
self.do_print(message, "magenta") def magenta(message):
Console.do_print(message, "magenta")
def cyan(self, message): @staticmethod
self.do_print(message, "cyan") def cyan(message):
Console.do_print(message, "cyan")
def yellow(self, message): @staticmethod
self.do_print(message, "yellow") def yellow(message):
Console.do_print(message, "yellow")
def red(self, message): @staticmethod
self.do_print(message, "red") def red(message):
Console.do_print(message, "red")
def green(self, message): @staticmethod
self.do_print(message, "green") def green(message):
Console.do_print(message, "green")
def white(self, message): @staticmethod
self.do_print(message, "white") def white(message):
Console.do_print(message, "white")
def debug(self, message): @staticmethod
def debug(message):
dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p") dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
self.magenta(f"[+] Crafty: {dt} - DEBUG:\t{message}") Console.magenta(f"[+] Crafty: {dt} - DEBUG:\t{message}")
def info(self, message): @staticmethod
def info(message):
dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p") dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
self.white(f"[+] Crafty: {dt} - INFO:\t{message}") Console.white(f"[+] Crafty: {dt} - INFO:\t{message}")
def warning(self, message): @staticmethod
def warning(message):
dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p") dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
self.cyan(f"[+] Crafty: {dt} - WARNING:\t{message}") Console.cyan(f"[+] Crafty: {dt} - WARNING:\t{message}")
def error(self, message): @staticmethod
def error(message):
dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p") dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
self.yellow(f"[+] Crafty: {dt} - ERROR:\t{message}") Console.yellow(f"[+] Crafty: {dt} - ERROR:\t{message}")
def critical(self, message): @staticmethod
def critical(message):
dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p") dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
self.red(f"[+] Crafty: {dt} - CRITICAL:\t{message}") Console.red(f"[+] Crafty: {dt} - CRITICAL:\t{message}")
def help(self, message): @staticmethod
def help(message):
dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p") dt = datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
self.green(f"[+] Crafty: {dt} - HELP:\t{message}") Console.green(f"[+] Crafty: {dt} - HELP:\t{message}")
console = Console()

View File

@ -10,12 +10,13 @@ logger = logging.getLogger(__name__)
class FileHelpers: class FileHelpers:
allowed_quotes = ['"', "'", "`"] allowed_quotes = ['"', "'", "`"]
def del_dirs(self, path): @staticmethod
def del_dirs(path):
path = pathlib.Path(path) path = pathlib.Path(path)
for sub in path.iterdir(): for sub in path.iterdir():
if sub.is_dir(): if sub.is_dir():
# Delete folder if it is a folder # Delete folder if it is a folder
self.del_dirs(sub) FileHelpers.del_dirs(sub)
else: else:
# Delete file if it is a file: # Delete file if it is a file:
sub.unlink() sub.unlink()
@ -45,13 +46,15 @@ class FileHelpers:
def copy_file(src_path, dest_path): def copy_file(src_path, dest_path):
shutil.copy(src_path, dest_path) shutil.copy(src_path, dest_path)
def move_dir(self, src_path, dest_path): @staticmethod
self.copy_dir(src_path, dest_path) def move_dir(src_path, dest_path):
self.del_dirs(src_path) FileHelpers.copy_dir(src_path, dest_path)
FileHelpers.del_dirs(src_path)
def move_file(self, src_path, dest_path): @staticmethod
self.copy_file(src_path, dest_path) def move_file(src_path, dest_path):
self.del_file(src_path) FileHelpers.copy_file(src_path, dest_path)
FileHelpers.del_file(src_path)
@staticmethod @staticmethod
def make_archive(path_to_destination, path_to_zip): def make_archive(path_to_destination, path_to_zip):
@ -110,6 +113,3 @@ class FileHelpers:
) )
return True return True
file_helper = FileHelpers()

View File

@ -19,10 +19,11 @@ from socket import gethostname
from contextlib import suppress from contextlib import suppress
import psutil import psutil
from app.classes.shared.console import console from app.classes.shared.console import Console
from app.classes.shared.installer import installer from app.classes.shared.installer import installer
from app.classes.shared.file_helpers import file_helper from app.classes.shared.file_helpers import FileHelpers
from app.classes.web.websocket_helper import websocket_helper from app.classes.shared.translation import Translation
from app.classes.web.websocket_helper import WebSocketHelper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -61,17 +62,22 @@ class Helpers:
self.passhasher = PasswordHasher() self.passhasher = PasswordHasher()
self.exiting = False self.exiting = False
self.websocket_helper = WebSocketHelper(self)
self.translation = Translation(self)
@staticmethod @staticmethod
def auto_installer_fix(ex): def auto_installer_fix(ex):
logger.critical(f"Import Error: Unable to load {ex.name} module", exc_info=True) logger.critical(f"Import Error: Unable to load {ex.name} module", exc_info=True)
print(f"Import Error: Unable to load {ex.name} module") print(f"Import Error: Unable to load {ex.name} module")
installer.do_install() installer.do_install()
def float_to_string(self, gbs: int): @staticmethod
def float_to_string(gbs: int):
s = str(float(gbs) * 1000).rstrip("0").rstrip(".") s = str(float(gbs) * 1000).rstrip("0").rstrip(".")
return s return s
def check_file_perms(self, path): @staticmethod
def check_file_perms(path):
try: try:
open(path, "r", encoding="utf-8").close() open(path, "r", encoding="utf-8").close()
logger.info(f"{path} is readable") logger.info(f"{path} is readable")
@ -79,8 +85,9 @@ class Helpers:
except PermissionError: except PermissionError:
return False return False
def is_file_older_than_x_days(self, file, days=1): @staticmethod
if self.check_file_exists(file): def is_file_older_than_x_days(file, days=1):
if Helpers.check_file_exists(file):
file_time = os.path.getmtime(file) file_time = os.path.getmtime(file)
# Check against 24 hours # Check against 24 hours
if (time.time() - file_time) / 3600 > 24 * days: if (time.time() - file_time) / 3600 > 24 * days:
@ -193,14 +200,14 @@ class Helpers:
else: else:
logger.error(f"Config File Error: setting {key} does not exist") logger.error(f"Config File Error: setting {key} does not exist")
console.error(f"Config File Error: setting {key} does not exist") Console.error(f"Config File Error: setting {key} does not exist")
return default_return return default_return
except Exception as e: except Exception as e:
logger.critical( logger.critical(
f"Config File Error: Unable to read {self.settings_file} due to {e}" f"Config File Error: Unable to read {self.settings_file} due to {e}"
) )
console.critical( Console.critical(
f"Config File Error: Unable to read {self.settings_file} due to {e}" f"Config File Error: Unable to read {self.settings_file} due to {e}"
) )
@ -217,7 +224,7 @@ class Helpers:
else: else:
logger.error(f"Config File Error: setting {key} does not exist") logger.error(f"Config File Error: setting {key} does not exist")
console.error(f"Config File Error: setting {key} does not exist") Console.error(f"Config File Error: setting {key} does not exist")
return default_return return default_return
with open(self.settings_file, "w", encoding="utf-8") as f: with open(self.settings_file, "w", encoding="utf-8") as f:
@ -227,11 +234,12 @@ class Helpers:
logger.critical( logger.critical(
f"Config File Error: Unable to read {self.settings_file} due to {e}" f"Config File Error: Unable to read {self.settings_file} due to {e}"
) )
console.critical( Console.critical(
f"Config File Error: Unable to read {self.settings_file} due to {e}" f"Config File Error: Unable to read {self.settings_file} due to {e}"
) )
def get_local_ip(self): @staticmethod
def get_local_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try: try:
# doesn't even have to be reachable # doesn't even have to be reachable
@ -252,7 +260,7 @@ class Helpers:
version_data = json.load(f) version_data = json.load(f)
except Exception as e: except Exception as e:
console.critical(f"Unable to get version data! \n{e}") Console.critical(f"Unable to get version data! \n{e}")
return version_data return version_data
@ -274,7 +282,6 @@ class Helpers:
return data return data
def get_version_string(self): def get_version_string(self):
version_data = self.get_version() version_data = self.get_version()
major = version_data.get("major", "?") major = version_data.get("major", "?")
minor = version_data.get("minor", "?") minor = version_data.get("minor", "?")
@ -331,7 +338,8 @@ class Helpers:
return line return line
def validate_traversal(self, base_path, filename): @staticmethod
def validate_traversal(base_path, filename):
logger.debug(f'Validating traversal ("{base_path}", "{filename}")') logger.debug(f'Validating traversal ("{base_path}", "{filename}")')
base = pathlib.Path(base_path).resolve() base = pathlib.Path(base_path).resolve()
file = pathlib.Path(filename) file = pathlib.Path(filename)
@ -342,8 +350,9 @@ class Helpers:
else: else:
raise ValueError("Path traversal detected") raise ValueError("Path traversal detected")
def tail_file(self, file_name, number_lines=20): @staticmethod
if not self.check_file_exists(file_name): def tail_file(file_name, number_lines=20):
if not Helpers.check_file_exists(file_name):
logger.warning(f"Unable to find file to tail: {file_name}") logger.warning(f"Unable to find file to tail: {file_name}")
return [f"Unable to find file to tail: {file_name}"] return [f"Unable to find file to tail: {file_name}"]
@ -392,8 +401,9 @@ class Helpers:
logger.critical(f"Unable to write to {path} - Error: {e}") logger.critical(f"Unable to write to {path} - Error: {e}")
return False return False
def checkRoot(self): @staticmethod
if self.is_os_windows(): def checkRoot():
if Helpers.is_os_windows():
if ctypes.windll.shell32.IsUserAnAdmin() == 1: if ctypes.windll.shell32.IsUserAnAdmin() == 1:
return True return True
else: else:
@ -404,7 +414,8 @@ class Helpers:
else: else:
return False return False
def unzipFile(self, zip_path): @staticmethod
def unzipFile(zip_path):
new_dir_list = zip_path.split("/") new_dir_list = zip_path.split("/")
new_dir = "" new_dir = ""
for i in range(len(new_dir_list) - 1): for i in range(len(new_dir_list) - 1):
@ -413,8 +424,8 @@ class Helpers:
else: else:
new_dir += "/" + new_dir_list[i] new_dir += "/" + new_dir_list[i]
if helper.check_file_perms(zip_path) and os.path.isfile(zip_path): if Helpers.check_file_perms(zip_path) and os.path.isfile(zip_path):
helper.ensure_dir_exists(new_dir) Helpers.ensure_dir_exists(new_dir)
tempDir = tempfile.mkdtemp() tempDir = tempfile.mkdtemp()
try: try:
with zipfile.ZipFile(zip_path, "r") as zip_ref: with zipfile.ZipFile(zip_path, "r") as zip_ref:
@ -429,7 +440,7 @@ class Helpers:
for item in os.listdir(full_root_path): for item in os.listdir(full_root_path):
try: try:
file_helper.move_dir( FileHelpers.move_dir(
os.path.join(full_root_path, item), os.path.join(full_root_path, item),
os.path.join(new_dir, item), os.path.join(new_dir, item),
) )
@ -447,7 +458,7 @@ class Helpers:
logger.info("Checking app directory writable") logger.info("Checking app directory writable")
writeable = self.check_writeable(self.root_dir) writeable = Helpers.check_writeable(self.root_dir)
# if not writeable, let's bomb out # if not writeable, let's bomb out
if not writeable: if not writeable:
@ -459,13 +470,13 @@ class Helpers:
with suppress(FileExistsError): with suppress(FileExistsError):
os.makedirs(os.path.join(self.root_dir, "logs")) os.makedirs(os.path.join(self.root_dir, "logs"))
except Exception as e: except Exception as e:
console.error(f"Failed to make logs directory with error: {e} ") Console.error(f"Failed to make logs directory with error: {e} ")
# ensure the log file is there # ensure the log file is there
try: try:
open(log_file, "a", encoding="utf-8").close() open(log_file, "a", encoding="utf-8").close()
except Exception as e: except Exception as e:
console.critical(f"Unable to open log file! {e}") Console.critical(f"Unable to open log file! {e}")
sys.exit(1) sys.exit(1)
# del any old session.lock file as this is a new session # del any old session.lock file as this is a new session
@ -565,7 +576,7 @@ class Helpers:
pid = data.get("pid") pid = data.get("pid")
started = data.get("started") started = data.get("started")
if psutil.pid_exists(pid): if psutil.pid_exists(pid):
console.critical( Console.critical(
f"Another Crafty Controller agent seems to be running..." f"Another Crafty Controller agent seems to be running..."
f"\npid: {pid} \nstarted on: {started}" f"\npid: {pid} \nstarted on: {started}"
) )
@ -580,7 +591,7 @@ class Helpers:
except Exception as e: except Exception as e:
logger.error(f"Failed to locate existing session.lock with error: {e} ") logger.error(f"Failed to locate existing session.lock with error: {e} ")
console.error( Console.error(
f"Failed to locate existing session.lock with error: {e} " f"Failed to locate existing session.lock with error: {e} "
) )
@ -595,11 +606,12 @@ class Helpers:
# because this is a recursive function, we will return bytes, # because this is a recursive function, we will return bytes,
# and set human readable later # and set human readable later
def get_dir_size(self, path: str): @staticmethod
def get_dir_size(path: str):
total = 0 total = 0
for entry in os.scandir(path): for entry in os.scandir(path):
if entry.is_dir(follow_symlinks=False): if entry.is_dir(follow_symlinks=False):
total += self.get_dir_size(entry.path) total += Helpers.get_dir_size(entry.path)
else: else:
total += entry.stat(follow_symlinks=False).st_size total += entry.stat(follow_symlinks=False).st_size
return total return total
@ -613,11 +625,15 @@ class Helpers:
) )
] ]
def get_human_readable_files_sizes(self, paths: list): @staticmethod
def get_human_readable_files_sizes(paths: list):
sizes = [] sizes = []
for p in paths: for p in paths:
sizes.append( sizes.append(
{"path": p, "size": self.human_readable_file_size(os.stat(p).st_size)} {
"path": p,
"size": Helpers.human_readable_file_size(os.stat(p).st_size),
}
) )
return sizes return sizes
@ -633,10 +649,12 @@ class Helpers:
b64_bytes = base64.decodebytes(s_bytes) b64_bytes = base64.decodebytes(s_bytes)
return b64_bytes.decode("utf-8") return b64_bytes.decode("utf-8")
def create_uuid(self): @staticmethod
def create_uuid():
return str(uuid.uuid4()) return str(uuid.uuid4())
def ensure_dir_exists(self, path): @staticmethod
def ensure_dir_exists(path):
""" """
ensures a directory exists ensures a directory exists
@ -662,7 +680,7 @@ class Helpers:
cert_dir = os.path.join(self.config_dir, "web", "certs") cert_dir = os.path.join(self.config_dir, "web", "certs")
# create a directory if needed # create a directory if needed
self.ensure_dir_exists(cert_dir) Helpers.ensure_dir_exists(cert_dir)
cert_file = os.path.join(cert_dir, "commander.cert.pem") cert_file = os.path.join(cert_dir, "commander.cert.pem")
key_file = os.path.join(cert_dir, "commander.key.pem") key_file = os.path.join(cert_dir, "commander.key.pem")
@ -671,16 +689,16 @@ class Helpers:
logger.info(f"SSL Key File is set to: {key_file}") logger.info(f"SSL Key File is set to: {key_file}")
# don't create new files if we already have them. # don't create new files if we already have them.
if self.check_file_exists(cert_file) and self.check_file_exists(key_file): if Helpers.check_file_exists(cert_file) and Helpers.check_file_exists(key_file):
logger.info("Cert and Key files already exists, not creating them.") logger.info("Cert and Key files already exists, not creating them.")
return True return True
console.info("Generating a self signed SSL") Console.info("Generating a self signed SSL")
logger.info("Generating a self signed SSL") logger.info("Generating a self signed SSL")
# create a key pair # create a key pair
logger.info("Generating a key pair. This might take a moment.") logger.info("Generating a key pair. This might take a moment.")
console.info("Generating a key pair. This might take a moment.") Console.info("Generating a key pair. This might take a moment.")
k = crypto.PKey() k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 4096) k.generate_key(crypto.TYPE_RSA, 4096)
@ -756,11 +774,11 @@ class Helpers:
default_file = os.path.join(self.root_dir, "default.json") default_file = os.path.join(self.root_dir, "default.json")
data = {} data = {}
if self.check_file_exists(default_file): if Helpers.check_file_exists(default_file):
with open(default_file, "r", encoding="utf-8") as f: with open(default_file, "r", encoding="utf-8") as f:
data = json.load(f) data = json.load(f)
del_json = helper.get_setting("delete_default_json") del_json = self.get_setting("delete_default_json")
if del_json: if del_json:
os.remove(default_file) os.remove(default_file)
@ -885,27 +903,27 @@ class Helpers:
</input></div><li>""" </input></div><li>"""
return output return output
@staticmethod def unzipServer(self, zip_path, user_id):
def unzipServer(zip_path, user_id): if Helpers.check_file_perms(zip_path):
if helper.check_file_perms(zip_path):
tempDir = tempfile.mkdtemp() tempDir = tempfile.mkdtemp()
with zipfile.ZipFile(zip_path, "r") as zip_ref: with zipfile.ZipFile(zip_path, "r") as zip_ref:
# extracts archive to temp directory # extracts archive to temp directory
zip_ref.extractall(tempDir) zip_ref.extractall(tempDir)
if user_id: if user_id:
websocket_helper.broadcast_user( self.websocket_helper.broadcast_user(
user_id, "send_temp_path", {"path": tempDir} user_id, "send_temp_path", {"path": tempDir}
) )
@staticmethod def backup_select(self, path, user_id):
def backup_select(path, user_id):
if user_id: if user_id:
websocket_helper.broadcast_user(user_id, "send_temp_path", {"path": path}) self.websocket_helper.broadcast_user(
user_id, "send_temp_path", {"path": path}
)
@staticmethod @staticmethod
def unzip_backup_archive(backup_path, zip_name): def unzip_backup_archive(backup_path, zip_name):
zip_path = os.path.join(backup_path, zip_name) zip_path = os.path.join(backup_path, zip_name)
if helper.check_file_perms(zip_path): if Helpers.check_file_perms(zip_path):
tempDir = tempfile.mkdtemp() tempDir = tempfile.mkdtemp()
with zipfile.ZipFile(zip_path, "r") as zip_ref: with zipfile.ZipFile(zip_path, "r") as zip_ref:
# extracts archive to temp directory # extracts archive to temp directory
@ -937,7 +955,7 @@ class Helpers:
@staticmethod @staticmethod
def copy_files(source, dest): def copy_files(source, dest):
if os.path.isfile(source): if os.path.isfile(source):
file_helper.copy_file(source, dest) FileHelpers.copy_file(source, dest)
logger.info("Copying jar %s to %s", source, dest) logger.info("Copying jar %s to %s", source, dest)
else: else:
logger.info("Source jar does not exist.") logger.info("Source jar does not exist.")
@ -974,6 +992,3 @@ class Helpers:
return "en" return "en"
else: else:
return lang + "-" + region return lang + "-" + region
helper = Helpers()

View File

@ -2,16 +2,16 @@ import json
import os import os
import logging import logging
from app.classes.controllers.users_controller import users_helper from app.classes.controllers.users_controller import helper_users
from app.classes.shared.main_controller import Controller from app.classes.shared.console import Console
from app.classes.shared.console import console
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class import3: class import3:
def __init__(self): def __init__(self, helper, controller):
self.controller = Controller() self.helper = helper
self.controller = controller
def start_import(self): def start_import(self):
folder = os.path.normpath( folder = os.path.normpath(
@ -21,11 +21,11 @@ class import3:
) )
) )
if not os.path.exists(folder): if not os.path.exists(folder):
console.info( Console.info(
"Crafty cannot find the path you entered. " "Crafty cannot find the path you entered. "
"Does Crafty's user have permission to access it?" "Does Crafty's user have permission to access it?"
) )
console.info("Please run the import3 command again and enter a valid path.") Console.info("Please run the import3 command again and enter a valid path.")
else: else:
with open(os.path.join(folder, "users.json"), encoding="utf-8") as f: with open(os.path.join(folder, "users.json"), encoding="utf-8") as f:
user_json = json.loads(f.read()) user_json = json.loads(f.read())
@ -34,16 +34,15 @@ class import3:
self.import_users(user_json) self.import_users(user_json)
self.import_servers(servers_json, self.controller) self.import_servers(servers_json, self.controller)
@staticmethod def import_users(self, json_data):
def import_users(json_data):
# If there is only one user to import json needs to call the data differently # If there is only one user to import json needs to call the data differently
if isinstance(json_data, list): if isinstance(json_data, list):
for user in json_data: for user in json_data:
users_helper.add_rawpass_user(user["username"], user["password"]) helper_users.add_rawpass_user(user["username"], user["password"])
console.info(f"Imported user {user['username']} from Crafty 3") Console.info(f"Imported user {user['username']} from Crafty 3")
logger.info(f"Imported user {user['username']} from Crafty 3") logger.info(f"Imported user {user['username']} from Crafty 3")
else: else:
console.info( Console.info(
"There is only one user detected. " "There is only one user detected. "
"Cannot create duplicate Admin account." "Cannot create duplicate Admin account."
) )
@ -52,8 +51,7 @@ class import3:
"Cannot create duplicate Admin account." "Cannot create duplicate Admin account."
) )
@staticmethod def import_servers(self, json_data, controller):
def import_servers(json_data, controller):
# If there is only one server to import json needs to call the data differently # If there is only one server to import json needs to call the data differently
if isinstance(json_data, list): if isinstance(json_data, list):
for server in json_data: for server in json_data:
@ -65,7 +63,7 @@ class import3:
max_mem=(int(server["memory_max"]) / 1000), max_mem=(int(server["memory_max"]) / 1000),
port=server["server_port"], port=server["server_port"],
) )
console.info( Console.info(
f"Imported server {server['server_name']}[{server['id']}] " f"Imported server {server['server_name']}[{server['id']}] "
f"from Crafty 3 to new server id {new_server_id}" f"from Crafty 3 to new server id {new_server_id}"
) )
@ -82,7 +80,7 @@ class import3:
max_mem=(int(json_data["memory_max"]) / 1000), max_mem=(int(json_data["memory_max"]) / 1000),
port=json_data["server_port"], port=json_data["server_port"],
) )
console.info( Console.info(
f"Imported server {json_data['server_name']}[{json_data['id']}] " f"Imported server {json_data['server_name']}[{json_data['id']}] "
f"from Crafty 3 to new server id {new_server_id}" f"from Crafty 3 to new server id {new_server_id}"
) )
@ -90,6 +88,3 @@ class import3:
f"Imported server {json_data['server_name']}[{json_data['id']}] " f"Imported server {json_data['server_name']}[{json_data['id']}] "
f"from Crafty 3 to new server id {new_server_id}" f"from Crafty 3 to new server id {new_server_id}"
) )
import3 = import3()

View File

@ -6,6 +6,11 @@ import time
import logging import logging
import tempfile import tempfile
from typing import Union from typing import Union
from peewee import DoesNotExist
# TZLocal is set as a hidden import on win pipeline
from tzlocal import get_localzone
from apscheduler.schedulers.background import BackgroundScheduler
from app.classes.controllers.crafty_perms_controller import Crafty_Perms_Controller from app.classes.controllers.crafty_perms_controller import Crafty_Perms_Controller
from app.classes.controllers.management_controller import Management_Controller from app.classes.controllers.management_controller import Management_Controller
@ -15,40 +20,40 @@ from app.classes.controllers.server_perms_controller import Server_Perms_Control
from app.classes.controllers.servers_controller import Servers_Controller from app.classes.controllers.servers_controller import Servers_Controller
from app.classes.models.server_permissions import Enum_Permissions_Server from app.classes.models.server_permissions import Enum_Permissions_Server
from app.classes.models.users import helper_users from app.classes.models.users import helper_users
from app.classes.models.roles import helper_roles
from app.classes.models.management import helpers_management from app.classes.models.management import helpers_management
from app.classes.models.servers import servers_helper from app.classes.models.servers import helper_servers
from app.classes.shared.console import console from app.classes.shared.authentication import Authentication
from app.classes.shared.helpers import helper from app.classes.shared.console import Console
from app.classes.shared.helpers import Helpers
from app.classes.shared.server import Server from app.classes.shared.server import Server
from app.classes.shared.file_helpers import file_helper from app.classes.shared.file_helpers import FileHelpers
from app.classes.minecraft.server_props import ServerProps from app.classes.minecraft.server_props import ServerProps
from app.classes.minecraft.serverjars import server_jar_obj from app.classes.minecraft.serverjars import ServerJars
from app.classes.minecraft.stats import Stats from app.classes.minecraft.stats import Stats
from app.classes.web.websocket_helper import websocket_helper
try:
from peewee import DoesNotExist
# TZLocal is set as a hidden import on win pipeline
from tzlocal import get_localzone
from apscheduler.schedulers.background import BackgroundScheduler
except ModuleNotFoundError as err:
helper.auto_installer_fix(err)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Controller: class Controller:
def __init__(self): def __init__(self, database, helper):
self.helper = helper
self.server_jars = ServerJars(helper)
self.users_helper = helper_users(database, self.helper)
self.roles_helper = helper_roles(database)
self.servers_helper = helper_servers(database)
self.management_helper = helpers_management(database, self.helper)
self.authentication = Authentication(self.helper)
self.servers_list = [] self.servers_list = []
self.stats = Stats(self) self.stats = Stats(self.helper, self)
self.crafty_perms = Crafty_Perms_Controller() self.crafty_perms = Crafty_Perms_Controller()
self.management = Management_Controller() self.management = Management_Controller(self.management_helper)
self.roles = Roles_Controller() self.roles = Roles_Controller(self.users_helper, self.roles_helper)
self.server_perms = Server_Perms_Controller() self.server_perms = Server_Perms_Controller()
self.servers = Servers_Controller() self.servers = Servers_Controller(self.servers_helper)
self.users = Users_Controller() self.users = Users_Controller(
self.helper, self.users_helper, self.authentication
)
tz = get_localzone() tz = get_localzone()
self.support_scheduler = BackgroundScheduler(timezone=str(tz)) self.support_scheduler = BackgroundScheduler(timezone=str(tz))
self.support_scheduler.start() self.support_scheduler.start()
@ -83,28 +88,28 @@ class Controller:
continue continue
# if this server path no longer exists - let's warn and bomb out # if this server path no longer exists - let's warn and bomb out
if not helper.check_path_exists( if not Helpers.check_path_exists(
helper.get_os_understandable_path(s["path"]) Helpers.get_os_understandable_path(s["path"])
): ):
logger.warning( logger.warning(
f"Unable to find server {s['server_name']} at path {s['path']}. " f"Unable to find server {s['server_name']} at path {s['path']}. "
f"Skipping this server" f"Skipping this server"
) )
console.warning( Console.warning(
f"Unable to find server {s['server_name']} at path {s['path']}. " f"Unable to find server {s['server_name']} at path {s['path']}. "
f"Skipping this server" f"Skipping this server"
) )
continue continue
settings_file = os.path.join( settings_file = os.path.join(
helper.get_os_understandable_path(s["path"]), "server.properties" Helpers.get_os_understandable_path(s["path"]), "server.properties"
) )
# if the properties file isn't there, let's warn # if the properties file isn't there, let's warn
if not helper.check_file_exists(settings_file): if not Helpers.check_file_exists(settings_file):
logger.error(f"Unable to find {settings_file}. Skipping this server.") logger.error(f"Unable to find {settings_file}. Skipping this server.")
console.error(f"Unable to find {settings_file}. Skipping this server.") Console.error(f"Unable to find {settings_file}. Skipping this server.")
continue continue
settings = ServerProps(settings_file) settings = ServerProps(settings_file)
@ -112,7 +117,7 @@ class Controller:
temp_server_dict = { temp_server_dict = {
"server_id": s.get("server_id"), "server_id": s.get("server_id"),
"server_data_obj": s, "server_data_obj": s,
"server_obj": Server(self.stats), "server_obj": Server(self.helper, self.management_helper, self.stats),
"server_settings": settings.props, "server_settings": settings.props,
} }
@ -127,7 +132,7 @@ class Controller:
self.refresh_server_settings(s["server_id"]) self.refresh_server_settings(s["server_id"])
console.info( Console.info(
f"Loaded Server: ID {s['server_id']}" f"Loaded Server: ID {s['server_id']}"
+ f" | Name: {s['server_name']}" + f" | Name: {s['server_name']}"
+ f" | Autostart: {s['auto_start']}" + f" | Autostart: {s['auto_start']}"
@ -154,7 +159,7 @@ class Controller:
self.users.set_prepare(exec_user["user_id"]) self.users.set_prepare(exec_user["user_id"])
# pausing so on screen notifications can run for user # pausing so on screen notifications can run for user
time.sleep(7) time.sleep(7)
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
exec_user["user_id"], "notification", "Preparing your support logs" exec_user["user_id"], "notification", "Preparing your support logs"
) )
tempDir = tempfile.mkdtemp() tempDir = tempfile.mkdtemp()
@ -195,12 +200,12 @@ class Controller:
final_path += "_" + server["server_uuid"] final_path += "_" + server["server_uuid"]
os.mkdir(final_path) os.mkdir(final_path)
try: try:
file_helper.copy_file(server["log_path"], final_path) FileHelpers.copy_file(server["log_path"], final_path)
except Exception as e: except Exception as e:
logger.warning(f"Failed to copy file with error: {e}") logger.warning(f"Failed to copy file with error: {e}")
# Copy crafty logs to archive dir # Copy crafty logs to archive dir
full_log_name = os.path.join(crafty_path, "logs") full_log_name = os.path.join(crafty_path, "logs")
file_helper.copy_dir(os.path.join(self.project_root, "logs"), full_log_name) FileHelpers.copy_dir(os.path.join(self.project_root, "logs"), full_log_name)
self.support_scheduler.add_job( self.support_scheduler.add_job(
self.log_status, self.log_status,
"interval", "interval",
@ -208,17 +213,19 @@ class Controller:
id="logs_" + str(exec_user["user_id"]), id="logs_" + str(exec_user["user_id"]),
args=[full_temp, tempZipStorage + ".zip", exec_user], args=[full_temp, tempZipStorage + ".zip", exec_user],
) )
file_helper.make_archive(tempZipStorage, tempDir) FileHelpers.make_archive(tempZipStorage, tempDir)
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
exec_user["user_id"], exec_user["user_id"],
"support_status_update", "support_status_update",
helper.calc_percent(full_temp, tempZipStorage + ".zip"), Helpers.calc_percent(full_temp, tempZipStorage + ".zip"),
) )
tempZipStorage += ".zip" tempZipStorage += ".zip"
websocket_helper.broadcast_user(exec_user["user_id"], "send_logs_bootbox", {}) self.helper.websocket_helper.broadcast_user(
exec_user["user_id"], "send_logs_bootbox", {}
)
self.users.set_support_path(exec_user["user_id"], tempZipStorage) self.users.set_support_path(exec_user["user_id"], tempZipStorage)
@ -229,7 +236,7 @@ class Controller:
def add_system_user(): def add_system_user():
helper_users.add_user( helper_users.add_user(
"system", "system",
helper.random_string_generator(64), Helpers.random_string_generator(64),
"default@example.com", "default@example.com",
False, False,
False, False,
@ -254,11 +261,11 @@ class Controller:
svr.stop_crash_detection() svr.stop_crash_detection()
def log_status(self, source_path, dest_path, exec_user): def log_status(self, source_path, dest_path, exec_user):
results = helper.calc_percent(source_path, dest_path) results = Helpers.calc_percent(source_path, dest_path)
self.log_stats = results self.log_stats = results
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
exec_user["user_id"], "support_status_update", results exec_user["user_id"], "support_status_update", results
) )
@ -286,7 +293,7 @@ class Controller:
@staticmethod @staticmethod
def list_defined_servers(): def list_defined_servers():
servers = servers_helper.get_all_defined_servers() servers = helper_servers.get_all_defined_servers()
return servers return servers
def list_running_servers(self): def list_running_servers(self):
@ -307,14 +314,14 @@ class Controller:
def stop_all_servers(self): def stop_all_servers(self):
servers = self.list_running_servers() servers = self.list_running_servers()
logger.info(f"Found {len(servers)} running server(s)") logger.info(f"Found {len(servers)} running server(s)")
console.info(f"Found {len(servers)} running server(s)") Console.info(f"Found {len(servers)} running server(s)")
logger.info("Stopping All Servers") logger.info("Stopping All Servers")
console.info("Stopping All Servers") Console.info("Stopping All Servers")
for s in servers: for s in servers:
logger.info(f"Stopping Server ID {s['id']} - {s['name']}") logger.info(f"Stopping Server ID {s['id']} - {s['name']}")
console.info(f"Stopping Server ID {s['id']} - {s['name']}") Console.info(f"Stopping Server ID {s['id']} - {s['name']}")
self.stop_server(s["id"]) self.stop_server(s["id"])
@ -322,7 +329,7 @@ class Controller:
time.sleep(2) time.sleep(2)
logger.info("All Servers Stopped") logger.info("All Servers Stopped")
console.info("All Servers Stopped") Console.info("All Servers Stopped")
def stop_server(self, server_id): def stop_server(self, server_id):
# issue the stop command # issue the stop command
@ -338,12 +345,12 @@ class Controller:
max_mem: int, max_mem: int,
port: int, port: int,
): ):
server_id = helper.create_uuid() server_id = Helpers.create_uuid()
server_dir = os.path.join(helper.servers_dir, server_id) server_dir = os.path.join(self.helper.servers_dir, server_id)
backup_path = os.path.join(helper.backup_path, server_id) backup_path = os.path.join(self.helper.backup_path, server_id)
if helper.is_os_windows(): if Helpers.is_os_windows():
server_dir = helper.wtol_path(server_dir) server_dir = Helpers.wtol_path(server_dir)
backup_path = helper.wtol_path(backup_path) backup_path = Helpers.wtol_path(backup_path)
server_dir.replace(" ", "^ ") server_dir.replace(" ", "^ ")
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
@ -351,8 +358,8 @@ class Controller:
full_jar_path = os.path.join(server_dir, server_file) full_jar_path = os.path.join(server_dir, server_file)
# make the dir - perhaps a UUID? # make the dir - perhaps a UUID?
helper.ensure_dir_exists(server_dir) Helpers.ensure_dir_exists(server_dir)
helper.ensure_dir_exists(backup_path) Helpers.ensure_dir_exists(backup_path)
try: try:
# do a eula.txt # do a eula.txt
@ -371,16 +378,16 @@ class Controller:
logger.error(f"Unable to create required server files due to :{e}") logger.error(f"Unable to create required server files due to :{e}")
return False return False
if helper.is_os_windows(): if Helpers.is_os_windows():
server_command = ( server_command = (
f"java -Xms{helper.float_to_string(min_mem)}M " f"java -Xms{Helpers.float_to_string(min_mem)}M "
f"-Xmx{helper.float_to_string(max_mem)}M " f"-Xmx{Helpers.float_to_string(max_mem)}M "
f'-jar "{full_jar_path}" nogui' f'-jar "{full_jar_path}" nogui'
) )
else: else:
server_command = ( server_command = (
f"java -Xms{helper.float_to_string(min_mem)}M " f"java -Xms{Helpers.float_to_string(min_mem)}M "
f"-Xmx{helper.float_to_string(max_mem)}M " f"-Xmx{Helpers.float_to_string(max_mem)}M "
f"-jar {full_jar_path} nogui" f"-jar {full_jar_path} nogui"
) )
server_log_file = f"{server_dir}/logs/latest.log" server_log_file = f"{server_dir}/logs/latest.log"
@ -400,23 +407,23 @@ class Controller:
) )
# download the jar # download the jar
server_jar_obj.download_jar(server, version, full_jar_path, new_id) self.server_jars.download_jar(server, version, full_jar_path, new_id)
return new_id return new_id
@staticmethod @staticmethod
def verify_jar_server(server_path: str, server_jar: str): def verify_jar_server(server_path: str, server_jar: str):
server_path = helper.get_os_understandable_path(server_path) server_path = Helpers.get_os_understandable_path(server_path)
path_check = helper.check_path_exists(server_path) path_check = Helpers.check_path_exists(server_path)
jar_check = helper.check_file_exists(os.path.join(server_path, server_jar)) jar_check = Helpers.check_file_exists(os.path.join(server_path, server_jar))
if not path_check or not jar_check: if not path_check or not jar_check:
return False return False
return True return True
@staticmethod @staticmethod
def verify_zip_server(zip_path: str): def verify_zip_server(zip_path: str):
zip_path = helper.get_os_understandable_path(zip_path) zip_path = Helpers.get_os_understandable_path(zip_path)
zip_check = helper.check_file_exists(zip_path) zip_check = Helpers.check_file_exists(zip_path)
if not zip_check: if not zip_check:
return False return False
return True return True
@ -430,20 +437,20 @@ class Controller:
max_mem: int, max_mem: int,
port: int, port: int,
): ):
server_id = helper.create_uuid() server_id = Helpers.create_uuid()
new_server_dir = os.path.join(helper.servers_dir, server_id) new_server_dir = os.path.join(self.helper.servers_dir, server_id)
backup_path = os.path.join(helper.backup_path, server_id) backup_path = os.path.join(self.helper.backup_path, server_id)
if helper.is_os_windows(): if Helpers.is_os_windows():
new_server_dir = helper.wtol_path(new_server_dir) new_server_dir = Helpers.wtol_path(new_server_dir)
backup_path = helper.wtol_path(backup_path) backup_path = Helpers.wtol_path(backup_path)
new_server_dir.replace(" ", "^ ") new_server_dir.replace(" ", "^ ")
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
helper.ensure_dir_exists(new_server_dir) Helpers.ensure_dir_exists(new_server_dir)
helper.ensure_dir_exists(backup_path) Helpers.ensure_dir_exists(backup_path)
server_path = helper.get_os_understandable_path(server_path) server_path = Helpers.get_os_understandable_path(server_path)
try: try:
file_helper.copy_dir(server_path, new_server_dir, True) FileHelpers.copy_dir(server_path, new_server_dir, True)
except shutil.Error as ex: except shutil.Error as ex:
logger.error(f"Server import failed with error: {ex}") logger.error(f"Server import failed with error: {ex}")
@ -464,16 +471,16 @@ class Controller:
full_jar_path = os.path.join(new_server_dir, server_jar) full_jar_path = os.path.join(new_server_dir, server_jar)
if helper.is_os_windows(): if Helpers.is_os_windows():
server_command = ( server_command = (
f"java -Xms{helper.float_to_string(min_mem)}M " f"java -Xms{Helpers.float_to_string(min_mem)}M "
f"-Xmx{helper.float_to_string(max_mem)}M " f"-Xmx{Helpers.float_to_string(max_mem)}M "
f'-jar "{full_jar_path}" nogui' f'-jar "{full_jar_path}" nogui'
) )
else: else:
server_command = ( server_command = (
f"java -Xms{helper.float_to_string(min_mem)}M " f"java -Xms{Helpers.float_to_string(min_mem)}M "
f"-Xmx{helper.float_to_string(max_mem)}M " f"-Xmx{Helpers.float_to_string(max_mem)}M "
f"-jar {full_jar_path} nogui" f"-jar {full_jar_path} nogui"
) )
server_log_file = f"{new_server_dir}/logs/latest.log" server_log_file = f"{new_server_dir}/logs/latest.log"
@ -502,18 +509,18 @@ class Controller:
max_mem: int, max_mem: int,
port: int, port: int,
): ):
server_id = helper.create_uuid() server_id = Helpers.create_uuid()
new_server_dir = os.path.join(helper.servers_dir, server_id) new_server_dir = os.path.join(self.helper.servers_dir, server_id)
backup_path = os.path.join(helper.backup_path, server_id) backup_path = os.path.join(self.helper.backup_path, server_id)
if helper.is_os_windows(): if Helpers.is_os_windows():
new_server_dir = helper.wtol_path(new_server_dir) new_server_dir = Helpers.wtol_path(new_server_dir)
backup_path = helper.wtol_path(backup_path) backup_path = Helpers.wtol_path(backup_path)
new_server_dir.replace(" ", "^ ") new_server_dir.replace(" ", "^ ")
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
tempDir = helper.get_os_understandable_path(zip_path) tempDir = Helpers.get_os_understandable_path(zip_path)
helper.ensure_dir_exists(new_server_dir) Helpers.ensure_dir_exists(new_server_dir)
helper.ensure_dir_exists(backup_path) Helpers.ensure_dir_exists(backup_path)
has_properties = False has_properties = False
# extracts archive to temp directory # extracts archive to temp directory
for item in os.listdir(tempDir): for item in os.listdir(tempDir):
@ -521,11 +528,11 @@ class Controller:
has_properties = True has_properties = True
try: try:
if not os.path.isdir(os.path.join(tempDir, item)): if not os.path.isdir(os.path.join(tempDir, item)):
file_helper.move_file( FileHelpers.move_file(
os.path.join(tempDir, item), os.path.join(new_server_dir, item) os.path.join(tempDir, item), os.path.join(new_server_dir, item)
) )
else: else:
file_helper.move_dir( FileHelpers.move_dir(
os.path.join(tempDir, item), os.path.join(new_server_dir, item) os.path.join(tempDir, item), os.path.join(new_server_dir, item)
) )
except Exception as ex: except Exception as ex:
@ -543,16 +550,16 @@ class Controller:
full_jar_path = os.path.join(new_server_dir, server_jar) full_jar_path = os.path.join(new_server_dir, server_jar)
if helper.is_os_windows(): if Helpers.is_os_windows():
server_command = ( server_command = (
f"java -Xms{helper.float_to_string(min_mem)}M " f"java -Xms{Helpers.float_to_string(min_mem)}M "
f"-Xmx{helper.float_to_string(max_mem)}M " f"-Xmx{Helpers.float_to_string(max_mem)}M "
f'-jar "{full_jar_path}" nogui' f'-jar "{full_jar_path}" nogui'
) )
else: else:
server_command = ( server_command = (
f"java -Xms{helper.float_to_string(min_mem)}M " f"java -Xms{Helpers.float_to_string(min_mem)}M "
f"-Xmx{helper.float_to_string(max_mem)}M " f"-Xmx{Helpers.float_to_string(max_mem)}M "
f"-jar {full_jar_path} nogui" f"-jar {full_jar_path} nogui"
) )
logger.debug("command: " + server_command) logger.debug("command: " + server_command)
@ -580,20 +587,20 @@ class Controller:
def import_bedrock_server( def import_bedrock_server(
self, server_name: str, server_path: str, server_exe: str, port: int self, server_name: str, server_path: str, server_exe: str, port: int
): ):
server_id = helper.create_uuid() server_id = Helpers.create_uuid()
new_server_dir = os.path.join(helper.servers_dir, server_id) new_server_dir = os.path.join(self.helper.servers_dir, server_id)
backup_path = os.path.join(helper.backup_path, server_id) backup_path = os.path.join(self.helper.backup_path, server_id)
if helper.is_os_windows(): if Helpers.is_os_windows():
new_server_dir = helper.wtol_path(new_server_dir) new_server_dir = Helpers.wtol_path(new_server_dir)
backup_path = helper.wtol_path(backup_path) backup_path = Helpers.wtol_path(backup_path)
new_server_dir.replace(" ", "^ ") new_server_dir.replace(" ", "^ ")
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
helper.ensure_dir_exists(new_server_dir) Helpers.ensure_dir_exists(new_server_dir)
helper.ensure_dir_exists(backup_path) Helpers.ensure_dir_exists(backup_path)
server_path = helper.get_os_understandable_path(server_path) server_path = Helpers.get_os_understandable_path(server_path)
try: try:
file_helper.copy_dir(server_path, new_server_dir, True) FileHelpers.copy_dir(server_path, new_server_dir, True)
except shutil.Error as ex: except shutil.Error as ex:
logger.error(f"Server import failed with error: {ex}") logger.error(f"Server import failed with error: {ex}")
@ -614,7 +621,7 @@ class Controller:
full_jar_path = os.path.join(new_server_dir, server_exe) full_jar_path = os.path.join(new_server_dir, server_exe)
if helper.is_os_windows(): if Helpers.is_os_windows():
server_command = f'"{full_jar_path}"' server_command = f'"{full_jar_path}"'
else: else:
server_command = f"./{server_exe}" server_command = f"./{server_exe}"
@ -635,25 +642,25 @@ class Controller:
server_type="minecraft-bedrock", server_type="minecraft-bedrock",
) )
if os.name != "nt": if os.name != "nt":
if helper.check_file_exists(full_jar_path): if Helpers.check_file_exists(full_jar_path):
os.chmod(full_jar_path, 0o2775) os.chmod(full_jar_path, 0o2775)
return new_id return new_id
def import_bedrock_zip_server( def import_bedrock_zip_server(
self, server_name: str, zip_path: str, server_exe: str, port: int self, server_name: str, zip_path: str, server_exe: str, port: int
): ):
server_id = helper.create_uuid() server_id = Helpers.create_uuid()
new_server_dir = os.path.join(helper.servers_dir, server_id) new_server_dir = os.path.join(self.helper.servers_dir, server_id)
backup_path = os.path.join(helper.backup_path, server_id) backup_path = os.path.join(self.helper.backup_path, server_id)
if helper.is_os_windows(): if Helpers.is_os_windows():
new_server_dir = helper.wtol_path(new_server_dir) new_server_dir = Helpers.wtol_path(new_server_dir)
backup_path = helper.wtol_path(backup_path) backup_path = Helpers.wtol_path(backup_path)
new_server_dir.replace(" ", "^ ") new_server_dir.replace(" ", "^ ")
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
tempDir = helper.get_os_understandable_path(zip_path) tempDir = Helpers.get_os_understandable_path(zip_path)
helper.ensure_dir_exists(new_server_dir) Helpers.ensure_dir_exists(new_server_dir)
helper.ensure_dir_exists(backup_path) Helpers.ensure_dir_exists(backup_path)
has_properties = False has_properties = False
# extracts archive to temp directory # extracts archive to temp directory
for item in os.listdir(tempDir): for item in os.listdir(tempDir):
@ -661,11 +668,11 @@ class Controller:
has_properties = True has_properties = True
try: try:
if not os.path.isdir(os.path.join(tempDir, item)): if not os.path.isdir(os.path.join(tempDir, item)):
file_helper.move_file( FileHelpers.move_file(
os.path.join(tempDir, item), os.path.join(new_server_dir, item) os.path.join(tempDir, item), os.path.join(new_server_dir, item)
) )
else: else:
file_helper.move_dir( FileHelpers.move_dir(
os.path.join(tempDir, item), os.path.join(new_server_dir, item) os.path.join(tempDir, item), os.path.join(new_server_dir, item)
) )
except Exception as ex: except Exception as ex:
@ -683,7 +690,7 @@ class Controller:
full_jar_path = os.path.join(new_server_dir, server_exe) full_jar_path = os.path.join(new_server_dir, server_exe)
if helper.is_os_windows(): if Helpers.is_os_windows():
server_command = f'"{full_jar_path}"' server_command = f'"{full_jar_path}"'
else: else:
server_command = f"./{server_exe}" server_command = f"./{server_exe}"
@ -704,7 +711,7 @@ class Controller:
server_type="minecraft-bedrock", server_type="minecraft-bedrock",
) )
if os.name != "nt": if os.name != "nt":
if helper.check_file_exists(full_jar_path): if Helpers.check_file_exists(full_jar_path):
os.chmod(full_jar_path, 0o2775) os.chmod(full_jar_path, 0o2775)
return new_id return new_id
@ -717,20 +724,23 @@ class Controller:
server_data = self.servers.get_server_data_by_id(old_server_id) server_data = self.servers.get_server_data_by_id(old_server_id)
old_bu_path = server_data["backup_path"] old_bu_path = server_data["backup_path"]
Server_Perms_Controller.backup_role_swap(old_server_id, new_server_id) Server_Perms_Controller.backup_role_swap(old_server_id, new_server_id)
if not helper.is_os_windows(): if not Helpers.is_os_windows():
backup_path = helper.validate_traversal(helper.backup_path, old_bu_path) backup_path = Helpers.validate_traversal(
if helper.is_os_windows(): self.helper.backup_path, old_bu_path
backup_path = helper.validate_traversal(
helper.wtol_path(helper.backup_path), helper.wtol_path(old_bu_path)
) )
backup_path = helper.wtol_path(str(backup_path)) if Helpers.is_os_windows():
backup_path = Helpers.validate_traversal(
Helpers.wtol_path(self.helper.backup_path),
Helpers.wtol_path(old_bu_path),
)
backup_path = Helpers.wtol_path(str(backup_path))
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
backup_path = Path(backup_path) backup_path = Path(backup_path)
backup_path_components = list(backup_path.parts) backup_path_components = list(backup_path.parts)
backup_path_components[-1] = new_uuid backup_path_components[-1] = new_uuid
new_bu_path = pathlib.PurePath(os.path.join(*backup_path_components)) new_bu_path = pathlib.PurePath(os.path.join(*backup_path_components))
if os.path.isdir(new_bu_path): if os.path.isdir(new_bu_path):
if helper.validate_traversal(helper.backup_path, new_bu_path): if Helpers.validate_traversal(self.helper.backup_path, new_bu_path):
os.rmdir(new_bu_path) os.rmdir(new_bu_path)
backup_path.rename(new_bu_path) backup_path.rename(new_bu_path)
@ -762,7 +772,9 @@ class Controller:
server_port, server_port,
) )
if not helper.check_file_exists(os.path.join(server_dir, "crafty_managed.txt")): if not Helpers.check_file_exists(
os.path.join(server_dir, "crafty_managed.txt")
):
try: try:
# place a file in the dir saying it's owned by crafty # place a file in the dir saying it's owned by crafty
with open( with open(
@ -795,7 +807,7 @@ class Controller:
server_name = server_data["server_name"] server_name = server_data["server_name"]
logger.info(f"Deleting Server: ID {server_id} | Name: {server_name} ") logger.info(f"Deleting Server: ID {server_id} | Name: {server_name} ")
console.info(f"Deleting Server: ID {server_id} | Name: {server_name} ") Console.info(f"Deleting Server: ID {server_id} | Name: {server_name} ")
srv_obj = s["server_obj"] srv_obj = s["server_obj"]
running = srv_obj.check_running() running = srv_obj.check_running()
@ -804,8 +816,8 @@ class Controller:
self.stop_server(server_id) self.stop_server(server_id)
if files: if files:
try: try:
file_helper.del_dirs( FileHelpers.del_dirs(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.servers.get_server_data_by_id(server_id)["path"] self.servers.get_server_data_by_id(server_id)["path"]
) )
) )
@ -814,11 +826,11 @@ class Controller:
f"Unable to delete server files for server with ID: " f"Unable to delete server files for server with ID: "
f"{server_id} with error logged: {e}" f"{server_id} with error logged: {e}"
) )
if helper.check_path_exists( if Helpers.check_path_exists(
self.servers.get_server_data_by_id(server_id)["backup_path"] self.servers.get_server_data_by_id(server_id)["backup_path"]
): ):
file_helper.del_dirs( FileHelpers.del_dirs(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.servers.get_server_data_by_id(server_id)[ self.servers.get_server_data_by_id(server_id)[
"backup_path" "backup_path"
] ]

View File

@ -1,54 +1,36 @@
import logging import logging
from playhouse.shortcuts import model_to_dict
from app.classes.models.users import Users, users_helper # pylint: disable=unused-import
from app.classes.shared.helpers import helper from app.classes.shared.helpers import Helpers
from app.classes.shared.console import console
# To disable warning about unused import ; Users is imported from here in other places
# pylint: disable=self-assigning-variable
Users = Users
try:
# pylint: disable=unused-import
from peewee import SqliteDatabase, fn
from playhouse.shortcuts import model_to_dict
except ModuleNotFoundError as err:
helper.auto_installer_fix(err)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
database = SqliteDatabase(
helper.db_path
# This is commented out after presenting issues when
# moving from SQLiteDatabase to SqliteQueueDatabase
# //TODO Enable tuning
# pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
class db_builder: class db_builder:
@staticmethod def __init__(self, database, helper, users_helper):
def default_settings(): self.database = database
self.helper = helper
self.users_helper = users_helper
def default_settings(self):
logger.info("Fresh Install Detected - Creating Default Settings") logger.info("Fresh Install Detected - Creating Default Settings")
console.info("Fresh Install Detected - Creating Default Settings") self.helper.console.info("Fresh Install Detected - Creating Default Settings")
default_data = helper.find_default_password() default_data = self.helper.find_default_password()
username = default_data.get("username", "admin") username = default_data.get("username", "admin")
password = default_data.get("password", "crafty") password = default_data.get("password", "crafty")
users_helper.add_user( self.users_helper.add_user(
username=username, username=username,
password=password, password=password,
email="default@example.com", email="default@example.com",
superuser=True, superuser=True,
) )
@staticmethod def is_fresh_install(self):
def is_fresh_install():
try: try:
user = users_helper.get_by_id(1) user = self.users_helper.get_by_id(1)
if user: if user:
return False return False
except: except:
@ -56,7 +38,6 @@ class db_builder:
class db_shortcuts: class db_shortcuts:
# ********************************************************************************** # **********************************************************************************
# Generic Databse Methods # Generic Databse Methods
# ********************************************************************************** # **********************************************************************************
@ -77,10 +58,3 @@ class db_shortcuts:
def return_db_rows(model): def return_db_rows(model):
data = [model_to_dict(row) for row in model] data = [model_to_dict(row) for row in model]
return data return data
# **********************************************************************************
# Static Accessors
# **********************************************************************************
installer = db_builder()
db_helper = db_shortcuts()

View File

@ -7,22 +7,17 @@ import os
import re import re
from functools import wraps from functools import wraps
from functools import cached_property from functools import cached_property
import peewee
from app.classes.shared.helpers import helper from playhouse.migrate import (
from app.classes.shared.console import console
try:
import peewee
from playhouse.migrate import (
SqliteMigrator, SqliteMigrator,
Operation, Operation,
SQL, SQL,
SqliteDatabase, SqliteDatabase,
make_index_name, make_index_name,
) )
except ModuleNotFoundError as e: from app.classes.shared.console import Console
helper.auto_installer_fix(e) from app.classes.shared.helpers import Helpers
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -303,13 +298,14 @@ class Migrator(object):
class MigrationManager(object): class MigrationManager(object):
filemask = re.compile(r"[\d]+_[^\.]+\.py$") filemask = re.compile(r"[\d]+_[^\.]+\.py$")
def __init__(self, database: t.Union[peewee.Database, peewee.Proxy]): def __init__(self, database: t.Union[peewee.Database, peewee.Proxy], helper):
""" """
Initializes the migration manager. Initializes the migration manager.
""" """
if not isinstance(database, (peewee.Database, peewee.Proxy)): if not isinstance(database, (peewee.Database, peewee.Proxy)):
raise RuntimeError("Invalid database: {}".format(database)) raise RuntimeError("Invalid database: {}".format(database))
self.database = database self.database = database
self.helper = helper
@cached_property @cached_property
def model(self) -> t.Type[MigrateHistory]: def model(self) -> t.Type[MigrateHistory]:
@ -334,13 +330,17 @@ class MigrationManager(object):
""" """
Scans migrations in the file system. Scans migrations in the file system.
""" """
if not os.path.exists(helper.migration_dir): if not os.path.exists(self.helper.migration_dir):
logger.warning( logger.warning(
"Migration directory: {} does not exist.".format(helper.migration_dir) "Migration directory: {} does not exist.".format(
self.helper.migration_dir
) )
os.makedirs(helper.migration_dir) )
os.makedirs(self.helper.migration_dir)
return sorted( return sorted(
f[:-3] for f in os.listdir(helper.migration_dir) if self.filemask.match(f) f[:-3]
for f in os.listdir(self.helper.migration_dir)
if self.filemask.match(f)
) )
@property @property
@ -367,7 +367,7 @@ class MigrationManager(object):
""" """
name = datetime.utcnow().strftime("%Y%m%d%H%M%S") + "_" + name name = datetime.utcnow().strftime("%Y%m%d%H%M%S") + "_" + name
filename = name + ".py" filename = name + ".py"
path = os.path.join(helper.migration_dir, filename) path = os.path.join(self.helper.migration_dir, filename)
with open(path, "w") as f: with open(path, "w") as f:
f.write( f.write(
MIGRATE_TEMPLATE.format( MIGRATE_TEMPLATE.format(
@ -399,13 +399,13 @@ class MigrationManager(object):
Runs all unapplied migrations. Runs all unapplied migrations.
""" """
logger.info("Starting migrations") logger.info("Starting migrations")
console.info("Starting migrations") Console.info("Starting migrations")
done = [] done = []
diff = self.diff diff = self.diff
if not diff: if not diff:
logger.info("There is nothing to migrate") logger.info("There is nothing to migrate")
console.info("There is nothing to migrate") Console.info("There is nothing to migrate")
return done return done
migrator = self.migrator migrator = self.migrator
@ -421,10 +421,12 @@ class MigrationManager(object):
Reads a migration from a file. Reads a migration from a file.
""" """
call_params = dict() call_params = dict()
if helper.is_os_windows() and sys.version_info >= (3, 0): if Helpers.is_os_windows() and sys.version_info >= (3, 0):
# if system is windows - force utf-8 encoding # if system is windows - force utf-8 encoding
call_params["encoding"] = "utf-8" call_params["encoding"] = "utf-8"
with open(os.path.join(helper.migration_dir, name + ".py"), **call_params) as f: with open(
os.path.join(self.helper.migration_dir, name + ".py"), **call_params
) as f:
code = f.read() code = f.read()
scope = {} scope = {}
code = compile(code, "<string>", "exec", dont_inherit=True) code = compile(code, "<string>", "exec", dont_inherit=True)

View File

@ -4,7 +4,7 @@ from enum import Enum
class PermissionHelper: class PermissionHelper:
@staticmethod @staticmethod
def both_have_perm(a: str, b: str, permission_tested: Enum): def both_have_perm(a: str, b: str, permission_tested: Enum):
return permission_helper.combine_perm_bool( return PermissionHelper.combine_perm_bool(
a[permission_tested.value], b[permission_tested.value] a[permission_tested.value], b[permission_tested.value]
) )
@ -20,8 +20,5 @@ class PermissionHelper:
def combine_masks(permission_mask_a: str, permission_mask_b: str) -> str: def combine_masks(permission_mask_a: str, permission_mask_b: str) -> str:
both_masks = zip(list(permission_mask_a), list(permission_mask_b)) both_masks = zip(list(permission_mask_a), list(permission_mask_b))
return "".join( return "".join(
map(lambda x: permission_helper.combine_perm(x[0], x[1]), both_masks) map(lambda x: PermissionHelper.combine_perm(x[0], x[1]), both_masks)
) )
permission_helper = PermissionHelper()

View File

@ -8,28 +8,22 @@ import logging.config
import subprocess import subprocess
import html import html
import tempfile import tempfile
import psutil
from psutil import NoSuchProcess
# TZLocal is set as a hidden import on win pipeline
from tzlocal import get_localzone
from apscheduler.schedulers.background import BackgroundScheduler
from app.classes.minecraft.stats import Stats from app.classes.minecraft.stats import Stats
from app.classes.minecraft.mc_ping import ping, ping_bedrock from app.classes.minecraft.mc_ping import ping, ping_bedrock
from app.classes.models.servers import Server_Stats, servers_helper from app.classes.models.servers import Server_Stats, helper_servers
from app.classes.models.management import management_helper from app.classes.models.management import helpers_management
from app.classes.models.users import users_helper from app.classes.models.users import helper_users
from app.classes.models.server_permissions import server_permissions from app.classes.models.server_permissions import Permissions_Servers
from app.classes.shared.helpers import helper from app.classes.shared.console import Console
from app.classes.shared.console import console from app.classes.shared.helpers import Helpers
from app.classes.shared.translation import translation from app.classes.shared.file_helpers import FileHelpers
from app.classes.shared.file_helpers import file_helper
from app.classes.web.websocket_helper import websocket_helper
try:
import psutil
# TZLocal is set as a hidden import on win pipeline
from tzlocal import get_localzone
from apscheduler.schedulers.background import BackgroundScheduler
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -37,11 +31,12 @@ logger = logging.getLogger(__name__)
class ServerOutBuf: class ServerOutBuf:
lines = {} lines = {}
def __init__(self, proc, server_id): def __init__(self, helper, proc, server_id):
self.helper = helper
self.proc = proc self.proc = proc
self.server_id = str(server_id) self.server_id = str(server_id)
# Buffers text for virtual_terminal_lines config number of lines # Buffers text for virtual_terminal_lines config number of lines
self.max_lines = helper.get_setting("virtual_terminal_lines") self.max_lines = self.helper.get_setting("virtual_terminal_lines")
self.line_buffer = "" self.line_buffer = ""
ServerOutBuf.lines[self.server_id] = [] ServerOutBuf.lines[self.server_id] = []
self.lsi = 0 self.lsi = 0
@ -79,13 +74,13 @@ class ServerOutBuf:
def new_line_handler(self, new_line): def new_line_handler(self, new_line):
new_line = re.sub("(\033\\[(0;)?[0-9]*[A-z]?(;[0-9])?m?)", " ", new_line) new_line = re.sub("(\033\\[(0;)?[0-9]*[A-z]?(;[0-9])?m?)", " ", new_line)
new_line = re.sub("[A-z]{2}\b\b", "", new_line) new_line = re.sub("[A-z]{2}\b\b", "", new_line)
highlighted = helper.log_colors(html.escape(new_line)) highlighted = self.helper.log_colors(html.escape(new_line))
logger.debug("Broadcasting new virtual terminal line") logger.debug("Broadcasting new virtual terminal line")
# TODO: Do not send data to clients who do not have permission to view # TODO: Do not send data to clients who do not have permission to view
# this server's console # this server's console
websocket_helper.broadcast_page_params( self.helper.websocket_helper.broadcast_page_params(
"/panel/server_detail", "/panel/server_detail",
{"id": self.server_id}, {"id": self.server_id},
"vterm_new_line", "vterm_new_line",
@ -97,7 +92,9 @@ class ServerOutBuf:
# Minecraft Server Class # Minecraft Server Class
# ********************************************************************************** # **********************************************************************************
class Server: class Server:
def __init__(self, stats): def __init__(self, helper, management_helper, stats):
self.helper = helper
self.management_helper = management_helper
# holders for our process # holders for our process
self.process = None self.process = None
self.line = False self.line = False
@ -121,14 +118,14 @@ class Server:
) )
self.is_backingup = False self.is_backingup = False
# Reset crash and update at initialization # Reset crash and update at initialization
servers_helper.server_crash_reset(self.server_id) helper_servers.server_crash_reset(self.server_id)
servers_helper.set_update(self.server_id, False) helper_servers.set_update(self.server_id, False)
# ********************************************************************************** # **********************************************************************************
# Minecraft Server Management # Minecraft Server Management
# ********************************************************************************** # **********************************************************************************
def reload_server_settings(self): def reload_server_settings(self):
server_data = servers_helper.get_server_data_by_id(self.server_id) server_data = helper_servers.get_server_data_by_id(self.server_id)
self.settings = server_data self.settings = server_data
def do_server_setup(self, server_data_obj): def do_server_setup(self, server_data_obj):
@ -153,7 +150,7 @@ class Server:
delay = int(self.settings["auto_start_delay"]) delay = int(self.settings["auto_start_delay"])
logger.info(f"Scheduling server {self.name} to start in {delay} seconds") logger.info(f"Scheduling server {self.name} to start in {delay} seconds")
console.info(f"Scheduling server {self.name} to start in {delay} seconds") Console.info(f"Scheduling server {self.name} to start in {delay} seconds")
self.server_scheduler.add_job( self.server_scheduler.add_job(
self.run_scheduled_server, self.run_scheduled_server,
@ -163,10 +160,10 @@ class Server:
) )
def run_scheduled_server(self): def run_scheduled_server(self):
console.info(f"Starting server ID: {self.server_id} - {self.name}") Console.info(f"Starting server ID: {self.server_id} - {self.name}")
logger.info(f"Starting server ID: {self.server_id} - {self.name}") logger.info(f"Starting server ID: {self.server_id} - {self.name}")
# Sets waiting start to false since we're attempting to start the server. # Sets waiting start to false since we're attempting to start the server.
servers_helper.set_waiting_start(self.server_id, False) helper_servers.set_waiting_start(self.server_id, False)
self.run_threaded_server(None) self.run_threaded_server(None)
# remove the scheduled job since it's ran # remove the scheduled job since it's ran
@ -184,7 +181,7 @@ class Server:
# Register an shedule for polling server stats when running # Register an shedule for polling server stats when running
logger.info(f"Polling server statistics {self.name} every {5} seconds") logger.info(f"Polling server statistics {self.name} every {5} seconds")
console.info(f"Polling server statistics {self.name} every {5} seconds") Console.info(f"Polling server statistics {self.name} every {5} seconds")
try: try:
self.server_scheduler.add_job( self.server_scheduler.add_job(
self.realtime_stats, self.realtime_stats,
@ -203,43 +200,43 @@ class Server:
def setup_server_run_command(self): def setup_server_run_command(self):
# configure the server # configure the server
server_exec_path = helper.get_os_understandable_path( server_exec_path = Helpers.get_os_understandable_path(
self.settings["executable"] self.settings["executable"]
) )
self.server_command = helper.cmdparse(self.settings["execution_command"]) self.server_command = Helpers.cmdparse(self.settings["execution_command"])
self.server_path = helper.get_os_understandable_path(self.settings["path"]) self.server_path = Helpers.get_os_understandable_path(self.settings["path"])
# let's do some quick checking to make sure things actually exists # let's do some quick checking to make sure things actually exists
full_path = os.path.join(self.server_path, server_exec_path) full_path = os.path.join(self.server_path, server_exec_path)
if not helper.check_file_exists(full_path): if not Helpers.check_file_exists(full_path):
logger.critical( logger.critical(
f"Server executable path: {full_path} does not seem to exist" f"Server executable path: {full_path} does not seem to exist"
) )
console.critical( Console.critical(
f"Server executable path: {full_path} does not seem to exist" f"Server executable path: {full_path} does not seem to exist"
) )
if not helper.check_path_exists(self.server_path): if not Helpers.check_path_exists(self.server_path):
logger.critical(f"Server path: {self.server_path} does not seem to exits") logger.critical(f"Server path: {self.server_path} does not seem to exits")
console.critical(f"Server path: {self.server_path} does not seem to exits") Console.critical(f"Server path: {self.server_path} does not seem to exits")
if not helper.check_writeable(self.server_path): if not Helpers.check_writeable(self.server_path):
logger.critical(f"Unable to write/access {self.server_path}") logger.critical(f"Unable to write/access {self.server_path}")
console.warning(f"Unable to write/access {self.server_path}") Console.critical(f"Unable to write/access {self.server_path}")
def start_server(self, user_id): def start_server(self, user_id):
if not user_id: if not user_id:
user_lang = helper.get_setting("language") user_lang = self.helper.get_setting("language")
else: else:
user_lang = users_helper.get_user_lang_by_id(user_id) user_lang = helper_users.get_user_lang_by_id(user_id)
if servers_helper.get_download_status(self.server_id): if helper_servers.get_download_status(self.server_id):
if user_id: if user_id:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "not-downloaded", user_lang "error", "not-downloaded", user_lang
) )
}, },
@ -253,18 +250,18 @@ class Server:
# fail safe in case we try to start something already running # fail safe in case we try to start something already running
if self.check_running(): if self.check_running():
logger.error("Server is already running - Cancelling Startup") logger.error("Server is already running - Cancelling Startup")
console.error("Server is already running - Cancelling Startup") Console.error("Server is already running - Cancelling Startup")
return False return False
if self.check_update(): if self.check_update():
logger.error("Server is updating. Terminating startup.") logger.error("Server is updating. Terminating startup.")
return False return False
logger.info(f"Launching Server {self.name} with command {self.server_command}") logger.info(f"Launching Server {self.name} with command {self.server_command}")
console.info(f"Launching Server {self.name} with command {self.server_command}") Console.info(f"Launching Server {self.name} with command {self.server_command}")
# Checks for eula. Creates one if none detected. # Checks for eula. Creates one if none detected.
# If EULA is detected and not set to true we offer to set it true. # If EULA is detected and not set to true we offer to set it true.
if helper.check_file_exists(os.path.join(self.settings["path"], "eula.txt")): if Helpers.check_file_exists(os.path.join(self.settings["path"], "eula.txt")):
f = open( f = open(
os.path.join(self.settings["path"], "eula.txt"), "r", encoding="utf-8" os.path.join(self.settings["path"], "eula.txt"), "r", encoding="utf-8"
) )
@ -288,7 +285,7 @@ class Server:
if not e_flag: if not e_flag:
if user_id: if user_id:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, "send_eula_bootbox", {"id": self.server_id} user_id, "send_eula_bootbox", {"id": self.server_id}
) )
else: else:
@ -299,7 +296,7 @@ class Server:
return False return False
return False return False
f.close() f.close()
if helper.is_os_windows(): if Helpers.is_os_windows():
logger.info("Windows Detected") logger.info("Windows Detected")
else: else:
logger.info("Unix Detected") logger.info("Unix Detected")
@ -313,7 +310,7 @@ class Server:
f = open( f = open(
os.path.join( os.path.join(
self.server_path, self.server_path,
servers_helper.get_server_data_by_id(self.server_id)["executable"], helper_servers.get_server_data_by_id(self.server_id)["executable"],
), ),
"r", "r",
encoding="utf-8", encoding="utf-8",
@ -322,11 +319,11 @@ class Server:
except: except:
if user_id: if user_id:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "not-downloaded", user_lang "error", "not-downloaded", user_lang
) )
}, },
@ -334,8 +331,8 @@ class Server:
return return
if ( if (
not helper.is_os_windows() not Helpers.is_os_windows()
and servers_helper.get_server_type_by_id(self.server_id) and helper_servers.get_server_type_by_id(self.server_id)
== "minecraft-bedrock" == "minecraft-bedrock"
): ):
logger.info( logger.info(
@ -358,11 +355,11 @@ class Server:
f"Server {self.name} failed to start with error code: {ex}" f"Server {self.name} failed to start with error code: {ex}"
) )
if user_id: if user_id:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "start-error", user_lang "error", "start-error", user_lang
).format(self.name, ex) ).format(self.name, ex)
}, },
@ -382,11 +379,11 @@ class Server:
# Checks for java on initial fail # Checks for java on initial fail
if os.system("java -version") == 32512: if os.system("java -version") == 32512:
if user_id: if user_id:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "noJava", user_lang "error", "noJava", user_lang
).format(self.name) ).format(self.name)
}, },
@ -397,18 +394,18 @@ class Server:
f"Server {self.name} failed to start with error code: {ex}" f"Server {self.name} failed to start with error code: {ex}"
) )
if user_id: if user_id:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "start-error", user_lang "error", "start-error", user_lang
).format(self.name, ex) ).format(self.name, ex)
}, },
) )
return False return False
out_buf = ServerOutBuf(self.process, self.server_id) out_buf = ServerOutBuf(self.helper, self.process, self.server_id)
logger.debug(f"Starting virtual terminal listener for server {self.name}") logger.debug(f"Starting virtual terminal listener for server {self.name}")
threading.Thread( threading.Thread(
@ -416,15 +413,15 @@ class Server:
).start() ).start()
self.is_crashed = False self.is_crashed = False
servers_helper.server_crash_reset(self.server_id) helper_servers.server_crash_reset(self.server_id)
self.start_time = str(datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")) self.start_time = str(datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"))
if self.process.poll() is None: if self.process.poll() is None:
logger.info(f"Server {self.name} running with PID {self.process.pid}") logger.info(f"Server {self.name} running with PID {self.process.pid}")
console.info(f"Server {self.name} running with PID {self.process.pid}") Console.info(f"Server {self.name} running with PID {self.process.pid}")
self.is_crashed = False self.is_crashed = False
servers_helper.server_crash_reset(self.server_id) helper_servers.server_crash_reset(self.server_id)
self.record_server_stats() self.record_server_stats()
check_internet_thread = threading.Thread( check_internet_thread = threading.Thread(
target=self.check_internet_thread, target=self.check_internet_thread,
@ -437,35 +434,39 @@ class Server:
) )
check_internet_thread.start() check_internet_thread.start()
# Checks if this is the servers first run. # Checks if this is the servers first run.
if servers_helper.get_first_run(self.server_id): if helper_servers.get_first_run(self.server_id):
servers_helper.set_first_run(self.server_id) helper_servers.set_first_run(self.server_id)
loc_server_port = servers_helper.get_server_stats_by_id(self.server_id)[ loc_server_port = helper_servers.get_server_stats_by_id(self.server_id)[
"server_port" "server_port"
] ]
# Sends port reminder message. # Sends port reminder message.
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "portReminder", user_lang "error", "portReminder", user_lang
).format(self.name, loc_server_port) ).format(self.name, loc_server_port)
}, },
) )
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
for user in server_users: for user in server_users:
if user != user_id: if user != user_id:
websocket_helper.broadcast_user(user, "send_start_reload", {}) self.helper.websocket_helper.broadcast_user(
user, "send_start_reload", {}
)
else: else:
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user(user, "send_start_reload", {}) self.helper.websocket_helper.broadcast_user(
user, "send_start_reload", {}
)
else: else:
logger.warning( logger.warning(
f"Server PID {self.process.pid} died right after starting " f"Server PID {self.process.pid} died right after starting "
f"- is this a server config issue?" f"- is this a server config issue?"
) )
console.warning( Console.critical(
f"Server PID {self.process.pid} died right after starting " f"Server PID {self.process.pid} died right after starting "
f"- is this a server config issue?" f"- is this a server config issue?"
) )
@ -475,7 +476,7 @@ class Server:
f"Server {self.name} has crash detection enabled " f"Server {self.name} has crash detection enabled "
f"- starting watcher task" f"- starting watcher task"
) )
console.info( Console.info(
f"Server {self.name} has crash detection enabled " f"Server {self.name} has crash detection enabled "
f"- starting watcher task" f"- starting watcher task"
) )
@ -486,11 +487,15 @@ class Server:
def check_internet_thread(self, user_id, user_lang): def check_internet_thread(self, user_id, user_lang):
if user_id: if user_id:
if not helper.check_internet(): if not Helpers.check_internet():
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{"error": translation.translate("error", "internet", user_lang)}, {
"error": self.helper.translation.translate(
"error", "internet", user_lang
)
},
) )
def stop_crash_detection(self): def stop_crash_detection(self):
@ -514,7 +519,7 @@ class Server:
f"Server {self.name} has crash detection enabled " f"Server {self.name} has crash detection enabled "
f"- starting watcher task" f"- starting watcher task"
) )
console.info( Console.info(
f"Server {self.name} has crash detection enabled " f"Server {self.name} has crash detection enabled "
"- starting watcher task" "- starting watcher task"
) )
@ -547,7 +552,7 @@ class Server:
running = self.check_running() running = self.check_running()
if not running: if not running:
logger.info(f"Can't stop server {self.name} if it's not running") logger.info(f"Can't stop server {self.name} if it's not running")
console.info(f"Can't stop server {self.name} if it's not running") Console.info(f"Can't stop server {self.name} if it's not running")
return return
x = 0 x = 0
@ -563,7 +568,7 @@ class Server:
f"seconds until force close)" f"seconds until force close)"
) )
logger.info(logstr) logger.info(logstr)
console.info(logstr) Console.info(logstr)
running = self.check_running() running = self.check_running()
time.sleep(2) time.sleep(2)
@ -572,17 +577,17 @@ class Server:
logger.info( logger.info(
f"Server {server_name} is still running - Forcing the process down" f"Server {server_name} is still running - Forcing the process down"
) )
console.info( Console.info(
f"Server {server_name} is still running - Forcing the process down" f"Server {server_name} is still running - Forcing the process down"
) )
self.kill() self.kill()
logger.info(f"Stopped Server {server_name} with PID {server_pid}") logger.info(f"Stopped Server {server_name} with PID {server_pid}")
console.info(f"Stopped Server {server_name} with PID {server_pid}") Console.info(f"Stopped Server {server_name} with PID {server_pid}")
# massive resetting of variables # massive resetting of variables
self.cleanup_server_object() self.cleanup_server_object()
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
# remove the stats polling job since server is stopped # remove the stats polling job since server is stopped
self.server_scheduler.remove_job("stats_" + str(self.server_id)) self.server_scheduler.remove_job("stats_" + str(self.server_id))
@ -590,7 +595,7 @@ class Server:
self.record_server_stats() self.record_server_stats()
for user in server_users: for user in server_users:
websocket_helper.broadcast_user(user, "send_start_reload", {}) self.helper.websocket_helper.broadcast_user(user, "send_start_reload", {})
def restart_threaded_server(self, user_id): def restart_threaded_server(self, user_id):
# if not already running, let's just start # if not already running, let's just start
@ -623,7 +628,7 @@ class Server:
if not self.check_running() and command.lower() != "start": if not self.check_running() and command.lower() != "start":
logger.warning(f'Server not running, unable to send command "{command}"') logger.warning(f'Server not running, unable to send command "{command}"')
return False return False
console.info(f"COMMAND TIME: {command}") Console.info(f"COMMAND TIME: {command}")
logger.debug(f"Sending command {command} to server") logger.debug(f"Sending command {command} to server")
# send it # send it
@ -647,7 +652,7 @@ class Server:
f"The server {name} has crashed and will be restarted. " f"The server {name} has crashed and will be restarted. "
f"Restarting server" f"Restarting server"
) )
console.warning( Console.critical(
f"The server {name} has crashed and will be restarted. " f"The server {name} has crashed and will be restarted. "
f"Restarting server" f"Restarting server"
) )
@ -658,7 +663,7 @@ class Server:
f"The server {name} has crashed, " f"The server {name} has crashed, "
f"crash detection is disabled and it will not be restarted" f"crash detection is disabled and it will not be restarted"
) )
console.critical( Console.critical(
f"The server {name} has crashed, " f"The server {name} has crashed, "
f"crash detection is disabled and it will not be restarted" f"crash detection is disabled and it will not be restarted"
) )
@ -666,8 +671,11 @@ class Server:
def kill(self): def kill(self):
logger.info(f"Terminating server {self.server_id} and all child processes") logger.info(f"Terminating server {self.server_id} and all child processes")
try:
process = psutil.Process(self.process.pid) process = psutil.Process(self.process.pid)
except NoSuchProcess:
logger.info(f"Cannot kill {self.process.pid} as we cannot find that pid.")
return
# for every sub process... # for every sub process...
for proc in process.children(recursive=True): for proc in process.children(recursive=True):
# kill all the child processes # kill all the child processes
@ -710,7 +718,7 @@ class Server:
self.server_scheduler.remove_job("c_" + str(self.server_id)) self.server_scheduler.remove_job("c_" + str(self.server_id))
return return
servers_helper.sever_crashed(self.server_id) helper_servers.sever_crashed(self.server_id)
# if we haven't tried to restart more 3 or more times # if we haven't tried to restart more 3 or more times
if self.restart_count <= 3: if self.restart_count <= 3:
@ -727,21 +735,21 @@ class Server:
f"Server {self.name} has been restarted {self.restart_count}" f"Server {self.name} has been restarted {self.restart_count}"
f" times. It has crashed, not restarting." f" times. It has crashed, not restarting."
) )
console.critical( Console.critical(
f"Server {self.name} has been restarted {self.restart_count}" f"Server {self.name} has been restarted {self.restart_count}"
f" times. It has crashed, not restarting." f" times. It has crashed, not restarting."
) )
self.restart_count = 0 self.restart_count = 0
self.is_crashed = True self.is_crashed = True
servers_helper.sever_crashed(self.server_id) helper_servers.sever_crashed(self.server_id)
# cancel the watcher task # cancel the watcher task
self.server_scheduler.remove_job("c_" + str(self.server_id)) self.server_scheduler.remove_job("c_" + str(self.server_id))
def remove_watcher_thread(self): def remove_watcher_thread(self):
logger.info("Removing old crash detection watcher thread") logger.info("Removing old crash detection watcher thread")
console.info("Removing old crash detection watcher thread") Console.info("Removing old crash detection watcher thread")
self.server_scheduler.remove_job("c_" + str(self.server_id)) self.server_scheduler.remove_job("c_" + str(self.server_id))
def agree_eula(self, user_id): def agree_eula(self, user_id):
@ -758,6 +766,9 @@ class Server:
return False return False
def backup_server(self): def backup_server(self):
if self.settings["backup_path"] == "":
logger.critical("Backup path is None. Canceling Backup!")
return
backup_thread = threading.Thread( backup_thread = threading.Thread(
target=self.a_backup_server, daemon=True, name=f"backup_{self.name}" target=self.a_backup_server, daemon=True, name=f"backup_{self.name}"
) )
@ -765,7 +776,7 @@ class Server:
f"Starting Backup Thread for server {self.settings['server_name']}." f"Starting Backup Thread for server {self.settings['server_name']}."
) )
if self.server_path is None: if self.server_path is None:
self.server_path = helper.get_os_understandable_path(self.settings["path"]) self.server_path = Helpers.get_os_understandable_path(self.settings["path"])
logger.info( logger.info(
"Backup Thread - Local server path not defined. " "Backup Thread - Local server path not defined. "
"Setting local server path variable." "Setting local server path variable."
@ -787,26 +798,26 @@ class Server:
logger.info(f"Backup Thread started for server {self.settings['server_name']}.") logger.info(f"Backup Thread started for server {self.settings['server_name']}.")
def a_backup_server(self): def a_backup_server(self):
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_page_params( self.helper.websocket_helper.broadcast_page_params(
"/panel/server_detail", "/panel/server_detail",
{"id": str(self.server_id)}, {"id": str(self.server_id)},
"backup_reload", "backup_reload",
{"percent": 0, "total_files": 0}, {"percent": 0, "total_files": 0},
) )
logger.info(f"Starting server {self.name} (ID {self.server_id}) backup") logger.info(f"Starting server {self.name} (ID {self.server_id}) backup")
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, user,
"notification", "notification",
translation.translate( self.helper.translation.translate(
"notify", "backupStarted", users_helper.get_user_lang_by_id(user) "notify", "backupStarted", helper_users.get_user_lang_by_id(user)
).format(self.name), ).format(self.name),
) )
time.sleep(3) time.sleep(3)
conf = management_helper.get_backup_config(self.server_id) conf = helpers_management.get_backup_config(self.server_id)
helper.ensure_dir_exists(self.settings["backup_path"]) self.helper.ensure_dir_exists(self.settings["backup_path"])
try: try:
backup_filename = ( backup_filename = (
f"{self.settings['backup_path']}/" f"{self.settings['backup_path']}/"
@ -827,23 +838,23 @@ class Server:
args=[tempDir + "/", backup_filename + ".zip"], args=[tempDir + "/", backup_filename + ".zip"],
) )
# pylint: disable=unexpected-keyword-arg # pylint: disable=unexpected-keyword-arg
file_helper.copy_dir(self.server_path, tempDir, dirs_exist_ok=True) FileHelpers.copy_dir(self.server_path, tempDir, dirs_exist_ok=True)
excluded_dirs = management_helper.get_excluded_backup_dirs(self.server_id) excluded_dirs = helpers_management.get_excluded_backup_dirs(self.server_id)
server_dir = helper.get_os_understandable_path(self.settings["path"]) server_dir = Helpers.get_os_understandable_path(self.settings["path"])
for my_dir in excluded_dirs: for my_dir in excluded_dirs:
# Take the full path of the excluded dir and replace the # Take the full path of the excluded dir and replace the
# server path with the temp path, this is so that we're # server path with the temp path, this is so that we're
# only deleting excluded dirs from the temp path # only deleting excluded dirs from the temp path
# and not the server path # and not the server path
excluded_dir = helper.get_os_understandable_path(my_dir).replace( excluded_dir = Helpers.get_os_understandable_path(my_dir).replace(
server_dir, helper.get_os_understandable_path(tempDir) server_dir, Helpers.get_os_understandable_path(tempDir)
) )
# Next, check to see if it is a directory # Next, check to see if it is a directory
if os.path.isdir(excluded_dir): if os.path.isdir(excluded_dir):
# If it is a directory, # If it is a directory,
# recursively delete the entire directory from the backup # recursively delete the entire directory from the backup
file_helper.del_dirs(excluded_dir) FileHelpers.del_dirs(excluded_dir)
else: else:
# If not, just remove the file # If not, just remove the file
os.remove(excluded_dir) os.remove(excluded_dir)
@ -851,15 +862,15 @@ class Server:
logger.debug( logger.debug(
"Found compress backup to be true. Calling compressed archive" "Found compress backup to be true. Calling compressed archive"
) )
file_helper.make_compressed_archive( FileHelpers.make_compressed_archive(
helper.get_os_understandable_path(backup_filename), tempDir Helpers.get_os_understandable_path(backup_filename), tempDir
) )
else: else:
logger.debug( logger.debug(
"Found compress backup to be false. Calling NON-compressed archive" "Found compress backup to be false. Calling NON-compressed archive"
) )
file_helper.make_archive( FileHelpers.make_archive(
helper.get_os_understandable_path(backup_filename), tempDir Helpers.get_os_understandable_path(backup_filename), tempDir
) )
while ( while (
@ -870,29 +881,29 @@ class Server:
oldfile = backup_list[0] oldfile = backup_list[0]
oldfile_path = f"{conf['backup_path']}/{oldfile['path']}" oldfile_path = f"{conf['backup_path']}/{oldfile['path']}"
logger.info(f"Removing old backup '{oldfile['path']}'") logger.info(f"Removing old backup '{oldfile['path']}'")
os.remove(helper.get_os_understandable_path(oldfile_path)) os.remove(Helpers.get_os_understandable_path(oldfile_path))
self.is_backingup = False self.is_backingup = False
file_helper.del_dirs(tempDir) FileHelpers.del_dirs(tempDir)
logger.info(f"Backup of server: {self.name} completed") logger.info(f"Backup of server: {self.name} completed")
self.server_scheduler.remove_job("backup_" + str(self.server_id)) self.server_scheduler.remove_job("backup_" + str(self.server_id))
results = {"percent": 100, "total_files": 0, "current_file": 0} results = {"percent": 100, "total_files": 0, "current_file": 0}
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_page_params( self.helper.websocket_helper.broadcast_page_params(
"/panel/server_detail", "/panel/server_detail",
{"id": str(self.server_id)}, {"id": str(self.server_id)},
"backup_status", "backup_status",
results, results,
) )
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, user,
"notification", "notification",
translation.translate( self.helper.translation.translate(
"notify", "notify",
"backupComplete", "backupComplete",
users_helper.get_user_lang_by_id(user), helper_users.get_user_lang_by_id(user),
).format(self.name), ).format(self.name),
) )
time.sleep(3) time.sleep(3)
@ -903,8 +914,8 @@ class Server:
) )
self.server_scheduler.remove_job("backup_" + str(self.server_id)) self.server_scheduler.remove_job("backup_" + str(self.server_id))
results = {"percent": 100, "total_files": 0, "current_file": 0} results = {"percent": 100, "total_files": 0, "current_file": 0}
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_page_params( self.helper.websocket_helper.broadcast_page_params(
"/panel/server_detail", "/panel/server_detail",
{"id": str(self.server_id)}, {"id": str(self.server_id)},
"backup_status", "backup_status",
@ -914,10 +925,10 @@ class Server:
return return
def backup_status(self, source_path, dest_path): def backup_status(self, source_path, dest_path):
results = helper.calc_percent(source_path, dest_path) results = Helpers.calc_percent(source_path, dest_path)
self.backup_stats = results self.backup_stats = results
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_page_params( self.helper.websocket_helper.broadcast_page_params(
"/panel/server_detail", "/panel/server_detail",
{"id": str(self.server_id)}, {"id": str(self.server_id)},
"backup_status", "backup_status",
@ -932,19 +943,19 @@ class Server:
def list_backups(self): def list_backups(self):
if self.settings["backup_path"]: if self.settings["backup_path"]:
if helper.check_path_exists( if Helpers.check_path_exists(
helper.get_os_understandable_path(self.settings["backup_path"]) Helpers.get_os_understandable_path(self.settings["backup_path"])
): ):
files = helper.get_human_readable_files_sizes( files = Helpers.get_human_readable_files_sizes(
helper.list_dir_by_date( Helpers.list_dir_by_date(
helper.get_os_understandable_path(self.settings["backup_path"]) Helpers.get_os_understandable_path(self.settings["backup_path"])
) )
) )
return [ return [
{ {
"path": os.path.relpath( "path": os.path.relpath(
f["path"], f["path"],
start=helper.get_os_understandable_path( start=Helpers.get_os_understandable_path(
self.settings["backup_path"] self.settings["backup_path"]
), ),
), ),
@ -961,7 +972,7 @@ class Server:
return [] return []
def jar_update(self): def jar_update(self):
servers_helper.set_update(self.server_id, True) helper_servers.set_update(self.server_id, True)
update_thread = threading.Thread( update_thread = threading.Thread(
target=self.a_jar_update, daemon=True, name=f"exe_update_{self.name}" target=self.a_jar_update, daemon=True, name=f"exe_update_{self.name}"
) )
@ -969,7 +980,7 @@ class Server:
def check_update(self): def check_update(self):
if servers_helper.get_server_stats_by_id(self.server_id)["updating"]: if helper_servers.get_server_stats_by_id(self.server_id)["updating"]:
return True return True
else: else:
return False return False
@ -987,13 +998,13 @@ class Server:
self.stop_threaded_server() self.stop_threaded_server()
else: else:
wasStarted = False wasStarted = False
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
# There are clients # There are clients
self.check_update() self.check_update()
message = ( message = (
'<a data-id="' + str(self.server_id) + '" class=""> UPDATING...</i></a>' '<a data-id="' + str(self.server_id) + '" class=""> UPDATING...</i></a>'
) )
websocket_helper.broadcast_page( self.helper.websocket_helper.broadcast_page(
"/panel/server_detail", "/panel/server_detail",
"update_button_status", "update_button_status",
{ {
@ -1003,9 +1014,11 @@ class Server:
"string": message, "string": message,
}, },
) )
websocket_helper.broadcast_page("/panel/dashboard", "send_start_reload", {}) self.helper.websocket_helper.broadcast_page(
"/panel/dashboard", "send_start_reload", {}
)
backup_dir = os.path.join( backup_dir = os.path.join(
helper.get_os_understandable_path(self.settings["path"]), Helpers.get_os_understandable_path(self.settings["path"]),
"crafty_executable_backups", "crafty_executable_backups",
) )
# checks if backup directory already exists # checks if backup directory already exists
@ -1028,37 +1041,37 @@ class Server:
logger.info(f"No old backups found for server: {self.name}") logger.info(f"No old backups found for server: {self.name}")
current_executable = os.path.join( current_executable = os.path.join(
helper.get_os_understandable_path(self.settings["path"]), Helpers.get_os_understandable_path(self.settings["path"]),
self.settings["executable"], self.settings["executable"],
) )
# copies to backup dir # copies to backup dir
helper.copy_files(current_executable, backup_executable) Helpers.copy_files(current_executable, backup_executable)
# boolean returns true for false for success # boolean returns true for false for success
downloaded = helper.download_file( downloaded = Helpers.download_file(
self.settings["executable_update_url"], current_executable self.settings["executable_update_url"], current_executable
) )
while servers_helper.get_server_stats_by_id(self.server_id)["updating"]: while helper_servers.get_server_stats_by_id(self.server_id)["updating"]:
if downloaded and not self.is_backingup: if downloaded and not self.is_backingup:
logger.info("Executable updated successfully. Starting Server") logger.info("Executable updated successfully. Starting Server")
servers_helper.set_update(self.server_id, False) helper_servers.set_update(self.server_id, False)
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
# There are clients # There are clients
self.check_update() self.check_update()
server_users = server_permissions.get_server_user_list( server_users = Permissions_Servers.get_server_user_list(
self.server_id self.server_id
) )
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, user,
"notification", "notification",
"Executable update finished for " + self.name, "Executable update finished for " + self.name,
) )
time.sleep(3) time.sleep(3)
websocket_helper.broadcast_page( self.helper.websocket_helper.broadcast_page(
"/panel/server_detail", "/panel/server_detail",
"update_button_status", "update_button_status",
{ {
@ -1067,18 +1080,18 @@ class Server:
"wasRunning": wasStarted, "wasRunning": wasStarted,
}, },
) )
websocket_helper.broadcast_page( self.helper.websocket_helper.broadcast_page(
"/panel/dashboard", "send_start_reload", {} "/panel/dashboard", "send_start_reload", {}
) )
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, user,
"notification", "notification",
"Executable update finished for " + self.name, "Executable update finished for " + self.name,
) )
management_helper.add_to_audit_log_raw( self.management_helper.add_to_audit_log_raw(
"Alert", "Alert",
"-1", "-1",
self.server_id, self.server_id,
@ -1089,9 +1102,9 @@ class Server:
self.start_server() self.start_server()
elif not downloaded and not self.is_backingup: elif not downloaded and not self.is_backingup:
time.sleep(5) time.sleep(5)
server_users = server_permissions.get_server_user_list(self.server_id) server_users = Permissions_Servers.get_server_user_list(self.server_id)
for user in server_users: for user in server_users:
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user, user,
"notification", "notification",
"Executable update failed for " "Executable update failed for "
@ -1134,8 +1147,8 @@ class Server:
"icon": raw_ping_result.get("icon"), "icon": raw_ping_result.get("icon"),
} }
) )
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
websocket_helper.broadcast_page_params( self.helper.websocket_helper.broadcast_page_params(
"/panel/server_detail", "/panel/server_detail",
{"id": str(self.server_id)}, {"id": str(self.server_id)},
"update_server_details", "update_server_details",
@ -1163,16 +1176,16 @@ class Server:
self.record_server_stats() self.record_server_stats()
if (len(servers_ping) > 0) & (len(websocket_helper.clients) > 0): if (len(servers_ping) > 0) & (len(self.helper.websocket_helper.clients) > 0):
try: try:
websocket_helper.broadcast_page( self.helper.websocket_helper.broadcast_page(
"/panel/dashboard", "update_server_status", servers_ping "/panel/dashboard", "update_server_status", servers_ping
) )
websocket_helper.broadcast_page( self.helper.websocket_helper.broadcast_page(
"/status", "update_server_status", servers_ping "/status", "update_server_status", servers_ping
) )
except: except:
console.warning("Can't broadcast server status to websocket") Console.critical("Can't broadcast server status to websocket")
def get_servers_stats(self): def get_servers_stats(self):
@ -1181,7 +1194,7 @@ class Server:
logger.info("Getting Stats for Server " + self.name + " ...") logger.info("Getting Stats for Server " + self.name + " ...")
server_id = self.server_id server_id = self.server_id
server = servers_helper.get_server_data_by_id(server_id) server = helper_servers.get_server_data_by_id(server_id)
logger.debug(f"Getting stats for server: {server_id}") logger.debug(f"Getting stats for server: {server_id}")
@ -1199,8 +1212,8 @@ class Server:
server_port = server["server_port"] server_port = server["server_port"]
server_name = server.get("server_name", f"ID#{server_id}") server_name = server.get("server_name", f"ID#{server_id}")
logger.debug("Pinging server '{server}' on {internal_ip}:{server_port}") logger.debug(f"Pinging server '{server}' on {internal_ip}:{server_port}")
if servers_helper.get_server_type_by_id(server_id) == "minecraft-bedrock": if helper_servers.get_server_type_by_id(server_id) == "minecraft-bedrock":
int_mc_ping = ping_bedrock(internal_ip, int(server_port)) int_mc_ping = ping_bedrock(internal_ip, int(server_port))
else: else:
int_mc_ping = ping(internal_ip, int(server_port)) int_mc_ping = ping(internal_ip, int(server_port))
@ -1212,7 +1225,7 @@ class Server:
if int_mc_ping: if int_mc_ping:
int_data = True int_data = True
if ( if (
servers_helper.get_server_type_by_id(server["server_id"]) helper_servers.get_server_type_by_id(server["server_id"])
== "minecraft-bedrock" == "minecraft-bedrock"
): ):
ping_data = Stats.parse_server_RakNet_ping(int_mc_ping) ping_data = Stats.parse_server_RakNet_ping(int_mc_ping)
@ -1261,7 +1274,7 @@ class Server:
def get_server_players(self): def get_server_players(self):
server = servers_helper.get_server_data_by_id(self.server_id) server = helper_servers.get_server_data_by_id(self.server_id)
logger.info(f"Getting players for server {server}") logger.info(f"Getting players for server {server}")
@ -1273,8 +1286,8 @@ class Server:
internal_ip = server["server_ip"] internal_ip = server["server_ip"]
server_port = server["server_port"] server_port = server["server_port"]
logger.debug("Pinging {internal_ip} on port {server_port}") logger.debug(f"Pinging {internal_ip} on port {server_port}")
if servers_helper.get_server_type_by_id(self.server_id) != "minecraft-bedrock": if helper_servers.get_server_type_by_id(self.server_id) != "minecraft-bedrock":
int_mc_ping = ping(internal_ip, int(server_port)) int_mc_ping = ping(internal_ip, int(server_port))
ping_data = {} ping_data = {}
@ -1288,7 +1301,7 @@ class Server:
def get_raw_server_stats(self, server_id): def get_raw_server_stats(self, server_id):
try: try:
server = servers_helper.get_server_obj(server_id) server = helper_servers.get_server_obj(server_id)
except: except:
return { return {
"id": server_id, "id": server_id,
@ -1310,10 +1323,10 @@ class Server:
} }
server_stats = {} server_stats = {}
server = servers_helper.get_server_obj(server_id) server = helper_servers.get_server_obj(server_id)
if not server: if not server:
return {} return {}
server_dt = servers_helper.get_server_data_by_id(server_id) server_dt = helper_servers.get_server_data_by_id(server_id)
logger.debug(f"Getting stats for server: {server_id}") logger.debug(f"Getting stats for server: {server_id}")
@ -1334,7 +1347,7 @@ class Server:
server_port = server_dt["server_port"] server_port = server_dt["server_port"]
logger.debug(f"Pinging server '{self.name}' on {internal_ip}:{server_port}") logger.debug(f"Pinging server '{self.name}' on {internal_ip}:{server_port}")
if servers_helper.get_server_type_by_id(server_id) == "minecraft-bedrock": if helper_servers.get_server_type_by_id(server_id) == "minecraft-bedrock":
int_mc_ping = ping_bedrock(internal_ip, int(server_port)) int_mc_ping = ping_bedrock(internal_ip, int(server_port))
else: else:
int_mc_ping = ping(internal_ip, int(server_port)) int_mc_ping = ping(internal_ip, int(server_port))
@ -1345,7 +1358,7 @@ class Server:
# otherwise people have gotten confused. # otherwise people have gotten confused.
if self.check_running(): if self.check_running():
# if we got a good ping return, let's parse it # if we got a good ping return, let's parse it
if servers_helper.get_server_type_by_id(server_id) != "minecraft-bedrock": if helper_servers.get_server_type_by_id(server_id) != "minecraft-bedrock":
if int_mc_ping: if int_mc_ping:
int_data = True int_data = True
ping_data = Stats.parse_server_ping(int_mc_ping) ping_data = Stats.parse_server_ping(int_mc_ping)
@ -1461,7 +1474,7 @@ class Server:
).execute() ).execute()
# delete old data # delete old data
max_age = helper.get_setting("history_max_age") max_age = self.helper.get_setting("history_max_age")
now = datetime.datetime.now() now = datetime.datetime.now()
last_week = now.day - max_age last_week = now.day - max_age

View File

@ -4,24 +4,15 @@ import logging
import threading import threading
import asyncio import asyncio
import datetime import datetime
from tzlocal import get_localzone
from apscheduler.events import EVENT_JOB_EXECUTED
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from app.classes.controllers.users_controller import Users_Controller from app.classes.models.management import helpers_management
from app.classes.minecraft.serverjars import server_jar_obj from app.classes.models.users import helper_users
from app.classes.models.management import management_helper from app.classes.shared.console import Console
from app.classes.models.users import users_helper
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
from app.classes.web.tornado_handler import Webserver from app.classes.web.tornado_handler import Webserver
from app.classes.web.websocket_helper import websocket_helper
try:
from tzlocal import get_localzone
from apscheduler.events import EVENT_JOB_EXECUTED
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
except ModuleNotFoundError as err:
helper.auto_installer_fix(err)
logger = logging.getLogger("apscheduler") logger = logging.getLogger("apscheduler")
scheduler_intervals = { scheduler_intervals = {
@ -41,14 +32,15 @@ scheduler_intervals = {
class TasksManager: class TasksManager:
def __init__(self, controller): def __init__(self, helper, controller):
self.helper = helper
self.controller = controller self.controller = controller
self.tornado = Webserver(controller, self) self.tornado = Webserver(helper, controller, self)
self.tz = get_localzone() self.tz = get_localzone()
self.scheduler = BackgroundScheduler(timezone=str(self.tz)) self.scheduler = BackgroundScheduler(timezone=str(self.tz))
self.users_controller = Users_Controller() self.users_controller = self.controller.users
self.webserver_thread = threading.Thread( self.webserver_thread = threading.Thread(
target=self.tornado.run_tornado, daemon=True, name="tornado_thread" target=self.tornado.run_tornado, daemon=True, name="tornado_thread"
@ -78,7 +70,7 @@ class TasksManager:
return self.main_thread_exiting return self.main_thread_exiting
def reload_schedule_from_db(self): def reload_schedule_from_db(self):
jobs = management_helper.get_schedules_enabled() jobs = helpers_management.get_schedules_enabled()
logger.info("Reload from DB called. Current enabled schedules: ") logger.info("Reload from DB called. Current enabled schedules: ")
for item in jobs: for item in jobs:
logger.info(f"JOB: {item}") logger.info(f"JOB: {item}")
@ -86,7 +78,7 @@ class TasksManager:
def command_watcher(self): def command_watcher(self):
while True: while True:
# select any commands waiting to be processed # select any commands waiting to be processed
commands = management_helper.get_unactioned_commands() commands = helpers_management.get_unactioned_commands()
for c in commands: for c in commands:
try: try:
svr = self.controller.get_server_obj(c.server_id) svr = self.controller.get_server_obj(c.server_id)
@ -95,7 +87,7 @@ class TasksManager:
"Server value requested does note exist! " "Server value requested does note exist! "
"Purging item from waiting commands." "Purging item from waiting commands."
) )
management_helper.mark_command_complete(c.command_id) helpers_management.mark_command_complete(c.command_id)
user_id = c.user_id user_id = c.user_id
command = c.command command = c.command
@ -116,19 +108,19 @@ class TasksManager:
svr.jar_update() svr.jar_update()
else: else:
svr.send_command(command) svr.send_command(command)
management_helper.mark_command_complete(c.command_id) helpers_management.mark_command_complete(c.command_id)
time.sleep(1) time.sleep(1)
def _main_graceful_exit(self): def _main_graceful_exit(self):
try: try:
os.remove(helper.session_file) os.remove(self.helper.session_file)
self.controller.stop_all_servers() self.controller.stop_all_servers()
except: except:
logger.info("Caught error during shutdown", exc_info=True) logger.info("Caught error during shutdown", exc_info=True)
logger.info("***** Crafty Shutting Down *****\n\n") logger.info("***** Crafty Shutting Down *****\n\n")
console.info("***** Crafty Shutting Down *****\n\n") Console.info("***** Crafty Shutting Down *****\n\n")
self.main_thread_exiting = True self.main_thread_exiting = True
def start_webserver(self): def start_webserver(self):
@ -136,7 +128,7 @@ class TasksManager:
def reload_webserver(self): def reload_webserver(self):
self.tornado.stop_web_server() self.tornado.stop_web_server()
console.info("Waiting 3 seconds") Console.info("Waiting 3 seconds")
time.sleep(3) time.sleep(3)
self.webserver_thread = threading.Thread( self.webserver_thread = threading.Thread(
target=self.tornado.run_tornado, daemon=True, name="tornado_thread" target=self.tornado.run_tornado, daemon=True, name="tornado_thread"
@ -148,20 +140,20 @@ class TasksManager:
def start_scheduler(self): def start_scheduler(self):
logger.info("Launching Scheduler Thread...") logger.info("Launching Scheduler Thread...")
console.info("Launching Scheduler Thread...") Console.info("Launching Scheduler Thread...")
self.schedule_thread.start() self.schedule_thread.start()
logger.info("Launching command thread...") logger.info("Launching command thread...")
console.info("Launching command thread...") Console.info("Launching command thread...")
self.command_thread.start() self.command_thread.start()
logger.info("Launching log watcher...") logger.info("Launching log watcher...")
console.info("Launching log watcher...") Console.info("Launching log watcher...")
self.log_watcher_thread.start() self.log_watcher_thread.start()
logger.info("Launching realtime thread...") logger.info("Launching realtime thread...")
console.info("Launching realtime thread...") Console.info("Launching realtime thread...")
self.realtime_thread.start() self.realtime_thread.start()
def scheduler_thread(self): def scheduler_thread(self):
schedules = management_helper.get_schedules_enabled() schedules = helpers_management.get_schedules_enabled()
self.scheduler.add_listener(self.schedule_watcher, mask=EVENT_JOB_EXECUTED) self.scheduler.add_listener(self.schedule_watcher, mask=EVENT_JOB_EXECUTED)
# self.scheduler.add_job( # self.scheduler.add_job(
# self.scheduler.print_jobs, "interval", seconds=10, id="-1" # self.scheduler.print_jobs, "interval", seconds=10, id="-1"
@ -173,7 +165,7 @@ class TasksManager:
if schedule.cron_string != "": if schedule.cron_string != "":
try: try:
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
CronTrigger.from_crontab( CronTrigger.from_crontab(
schedule.cron_string, timezone=str(self.tz) schedule.cron_string, timezone=str(self.tz)
), ),
@ -186,16 +178,18 @@ class TasksManager:
], ],
) )
except Exception as e: except Exception as e:
console.error(f"Failed to schedule task with error: {e}.") Console.error(f"Failed to schedule task with error: {e}.")
console.warning("Removing failed task from DB.") Console.warning("Removing failed task from DB.")
logger.error(f"Failed to schedule task with error: {e}.") logger.error(f"Failed to schedule task with error: {e}.")
logger.warning("Removing failed task from DB.") logger.warning("Removing failed task from DB.")
# remove items from DB if task fails to add to apscheduler # remove items from DB if task fails to add to apscheduler
management_helper.delete_scheduled_task(schedule.schedule_id) self.controller.management_helper.delete_scheduled_task(
schedule.schedule_id
)
else: else:
if schedule.interval_type == "hours": if schedule.interval_type == "hours":
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
minute=0, minute=0,
hour="*/" + str(schedule.interval), hour="*/" + str(schedule.interval),
@ -209,7 +203,7 @@ class TasksManager:
) )
elif schedule.interval_type == "minutes": elif schedule.interval_type == "minutes":
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
minute="*/" + str(schedule.interval), minute="*/" + str(schedule.interval),
id=str(schedule.schedule_id), id=str(schedule.schedule_id),
@ -223,7 +217,7 @@ class TasksManager:
elif schedule.interval_type == "days": elif schedule.interval_type == "days":
curr_time = schedule.start_time.split(":") curr_time = schedule.start_time.split(":")
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
day="*/" + str(schedule.interval), day="*/" + str(schedule.interval),
hour=curr_time[0], hour=curr_time[0],
@ -243,7 +237,7 @@ class TasksManager:
logger.info(f"JOB: {item}") logger.info(f"JOB: {item}")
def schedule_job(self, job_data): def schedule_job(self, job_data):
sch_id = management_helper.create_scheduled_task( sch_id = helpers_management.create_scheduled_task(
job_data["server_id"], job_data["server_id"],
job_data["action"], job_data["action"],
job_data["interval"], job_data["interval"],
@ -260,13 +254,13 @@ class TasksManager:
# Checks to make sure some doofus didn't actually make the newly # Checks to make sure some doofus didn't actually make the newly
# created task a child of itself. # created task a child of itself.
if str(job_data["parent"]) == str(sch_id): if str(job_data["parent"]) == str(sch_id):
management_helper.update_scheduled_task(sch_id, {"parent": None}) helpers_management.update_scheduled_task(sch_id, {"parent": None})
# Check to see if it's enabled and is not a chain reaction. # Check to see if it's enabled and is not a chain reaction.
if job_data["enabled"] and job_data["interval_type"] != "reaction": if job_data["enabled"] and job_data["interval_type"] != "reaction":
if job_data["cron_string"] != "": if job_data["cron_string"] != "":
try: try:
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
CronTrigger.from_crontab( CronTrigger.from_crontab(
job_data["cron_string"], timezone=str(self.tz) job_data["cron_string"], timezone=str(self.tz)
), ),
@ -279,16 +273,16 @@ class TasksManager:
], ],
) )
except Exception as e: except Exception as e:
console.error(f"Failed to schedule task with error: {e}.") Console.error(f"Failed to schedule task with error: {e}.")
console.warning("Removing failed task from DB.") Console.warning("Removing failed task from DB.")
logger.error(f"Failed to schedule task with error: {e}.") logger.error(f"Failed to schedule task with error: {e}.")
logger.warning("Removing failed task from DB.") logger.warning("Removing failed task from DB.")
# remove items from DB if task fails to add to apscheduler # remove items from DB if task fails to add to apscheduler
management_helper.delete_scheduled_task(sch_id) self.controller.management_helper.delete_scheduled_task(sch_id)
else: else:
if job_data["interval_type"] == "hours": if job_data["interval_type"] == "hours":
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
minute=0, minute=0,
hour="*/" + str(job_data["interval"]), hour="*/" + str(job_data["interval"]),
@ -302,7 +296,7 @@ class TasksManager:
) )
elif job_data["interval_type"] == "minutes": elif job_data["interval_type"] == "minutes":
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
minute="*/" + str(job_data["interval"]), minute="*/" + str(job_data["interval"]),
id=str(sch_id), id=str(sch_id),
@ -316,7 +310,7 @@ class TasksManager:
elif job_data["interval_type"] == "days": elif job_data["interval_type"] == "days":
curr_time = job_data["start_time"].split(":") curr_time = job_data["start_time"].split(":")
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
day="*/" + str(job_data["interval"]), day="*/" + str(job_data["interval"]),
hour=curr_time[0], hour=curr_time[0],
@ -335,18 +329,18 @@ class TasksManager:
logger.info(f"JOB: {item}") logger.info(f"JOB: {item}")
def remove_all_server_tasks(self, server_id): def remove_all_server_tasks(self, server_id):
schedules = management_helper.get_schedules_by_server(server_id) schedules = helpers_management.get_schedules_by_server(server_id)
for schedule in schedules: for schedule in schedules:
if schedule.interval != "reaction": if schedule.interval != "reaction":
self.remove_job(schedule.schedule_id) self.remove_job(schedule.schedule_id)
def remove_job(self, sch_id): def remove_job(self, sch_id):
job = management_helper.get_scheduled_task_model(sch_id) job = helpers_management.get_scheduled_task_model(sch_id)
for schedule in management_helper.get_child_schedules(sch_id): for schedule in helpers_management.get_child_schedules(sch_id):
management_helper.update_scheduled_task( self.controller.management_helper.update_scheduled_task(
schedule.schedule_id, {"parent": None} schedule.schedule_id, {"parent": None}
) )
management_helper.delete_scheduled_task(sch_id) self.controller.management_helper.delete_scheduled_task(sch_id)
if job.enabled and job.interval_type != "reaction": if job.enabled and job.interval_type != "reaction":
self.scheduler.remove_job(str(sch_id)) self.scheduler.remove_job(str(sch_id))
logger.info(f"Job with ID {sch_id} was deleted.") logger.info(f"Job with ID {sch_id} was deleted.")
@ -358,11 +352,11 @@ class TasksManager:
) )
def update_job(self, sch_id, job_data): def update_job(self, sch_id, job_data):
management_helper.update_scheduled_task(sch_id, job_data) helpers_management.update_scheduled_task(sch_id, job_data)
# Checks to make sure some doofus didn't actually make the newly # Checks to make sure some doofus didn't actually make the newly
# created task a child of itself. # created task a child of itself.
if str(job_data["parent"]) == str(sch_id): if str(job_data["parent"]) == str(sch_id):
management_helper.update_scheduled_task(sch_id, {"parent": None}) helpers_management.update_scheduled_task(sch_id, {"parent": None})
try: try:
if job_data["interval"] != "reaction": if job_data["interval"] != "reaction":
self.scheduler.remove_job(str(sch_id)) self.scheduler.remove_job(str(sch_id))
@ -377,7 +371,7 @@ class TasksManager:
if job_data["cron_string"] != "": if job_data["cron_string"] != "":
try: try:
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
CronTrigger.from_crontab( CronTrigger.from_crontab(
job_data["cron_string"], timezone=str(self.tz) job_data["cron_string"], timezone=str(self.tz)
), ),
@ -390,13 +384,13 @@ class TasksManager:
], ],
) )
except Exception as e: except Exception as e:
console.error(f"Failed to schedule task with error: {e}.") Console.error(f"Failed to schedule task with error: {e}.")
console.info("Removing failed task from DB.") Console.info("Removing failed task from DB.")
management_helper.delete_scheduled_task(sch_id) self.controller.management_helper.delete_scheduled_task(sch_id)
else: else:
if job_data["interval_type"] == "hours": if job_data["interval_type"] == "hours":
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
minute=0, minute=0,
hour="*/" + str(job_data["interval"]), hour="*/" + str(job_data["interval"]),
@ -410,7 +404,7 @@ class TasksManager:
) )
elif job_data["interval_type"] == "minutes": elif job_data["interval_type"] == "minutes":
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
minute="*/" + str(job_data["interval"]), minute="*/" + str(job_data["interval"]),
id=str(sch_id), id=str(sch_id),
@ -424,7 +418,7 @@ class TasksManager:
elif job_data["interval_type"] == "days": elif job_data["interval_type"] == "days":
curr_time = job_data["start_time"].split(":") curr_time = job_data["start_time"].split(":")
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"cron", "cron",
day="*/" + str(job_data["interval"]), day="*/" + str(job_data["interval"]),
hour=curr_time[0], hour=curr_time[0],
@ -450,10 +444,12 @@ class TasksManager:
def schedule_watcher(self, event): def schedule_watcher(self, event):
if not event.exception: if not event.exception:
if str(event.job_id).isnumeric(): if str(event.job_id).isnumeric():
task = management_helper.get_scheduled_task_model(int(event.job_id)) task = self.controller.management.get_scheduled_task_model(
management_helper.add_to_audit_log_raw( int(event.job_id)
)
self.controller.management.add_to_audit_log_raw(
"system", "system",
users_helper.get_user_id_by_name("system"), helper_users.get_user_id_by_name("system"),
task.server_id, task.server_id,
f"Task with id {task.schedule_id} completed successfully", f"Task with id {task.schedule_id} completed successfully",
"127.0.0.1", "127.0.0.1",
@ -465,7 +461,7 @@ class TasksManager:
# check for any child tasks for this. It's kind of backward, # check for any child tasks for this. It's kind of backward,
# but this makes DB management a lot easier. One to one # but this makes DB management a lot easier. One to one
# instead of one to many. # instead of one to many.
for schedule in management_helper.get_child_schedules_by_server( for schedule in helpers_management.get_child_schedules_by_server(
task.schedule_id, task.server_id task.schedule_id, task.server_id
): ):
# event job ID's are strings so we need to look at # event job ID's are strings so we need to look at
@ -476,7 +472,7 @@ class TasksManager:
seconds=schedule.delay seconds=schedule.delay
) )
self.scheduler.add_job( self.scheduler.add_job(
management_helper.add_command, helpers_management.add_command,
"date", "date",
run_date=delaytime, run_date=delaytime,
id=str(schedule.schedule_id), id=str(schedule.schedule_id),
@ -496,11 +492,11 @@ class TasksManager:
logger.error(f"Task failed with error: {event.exception}") logger.error(f"Task failed with error: {event.exception}")
def start_stats_recording(self): def start_stats_recording(self):
stats_update_frequency = helper.get_setting("stats_update_frequency") stats_update_frequency = self.helper.get_setting("stats_update_frequency")
logger.info( logger.info(
f"Stats collection frequency set to {stats_update_frequency} seconds" f"Stats collection frequency set to {stats_update_frequency} seconds"
) )
console.info( Console.info(
f"Stats collection frequency set to {stats_update_frequency} seconds" f"Stats collection frequency set to {stats_update_frequency} seconds"
) )
@ -516,36 +512,39 @@ class TasksManager:
def serverjar_cache_refresher(self): def serverjar_cache_refresher(self):
logger.info("Refreshing serverjars.com cache on start") logger.info("Refreshing serverjars.com cache on start")
server_jar_obj.refresh_cache() self.controller.server_jars.refresh_cache()
logger.info("Scheduling Serverjars.com cache refresh service every 12 hours") logger.info("Scheduling Serverjars.com cache refresh service every 12 hours")
self.scheduler.add_job( self.scheduler.add_job(
server_jar_obj.refresh_cache, "interval", hours=12, id="serverjars" self.controller.server_jars.refresh_cache,
"interval",
hours=12,
id="serverjars",
) )
def realtime(self): def realtime(self):
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
host_stats = management_helper.get_latest_hosts_stats() host_stats = helpers_management.get_latest_hosts_stats()
while True: while True:
if host_stats.get( if host_stats.get(
"cpu_usage" "cpu_usage"
) != management_helper.get_latest_hosts_stats().get( ) != helpers_management.get_latest_hosts_stats().get(
"cpu_usage" "cpu_usage"
) or host_stats.get( ) or host_stats.get(
"mem_percent" "mem_percent"
) != management_helper.get_latest_hosts_stats().get( ) != helpers_management.get_latest_hosts_stats().get(
"mem_percent" "mem_percent"
): ):
# Stats are different # Stats are different
host_stats = management_helper.get_latest_hosts_stats() host_stats = helpers_management.get_latest_hosts_stats()
if len(websocket_helper.clients) > 0: if len(self.helper.websocket_helper.clients) > 0:
# There are clients # There are clients
websocket_helper.broadcast_page( self.helper.websocket_helper.broadcast_page(
"/panel/dashboard", "/panel/dashboard",
"update_host_stats", "update_host_stats",
{ {

View File

@ -3,15 +3,17 @@ import logging
import os import os
import typing as t import typing as t
from app.classes.shared.console import console from app.classes.shared.console import Console
from app.classes.shared.helpers import helper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Translation: class Translation:
def __init__(self): def __init__(self, helper):
self.translations_path = os.path.join(helper.root_dir, "app", "translations") self.helper = helper
self.translations_path = os.path.join(
self.helper.root_dir, "app", "translations"
)
self.cached_translation = None self.cached_translation = None
self.cached_translation_lang = None self.cached_translation_lang = None
@ -59,7 +61,7 @@ class Translation:
f"Translation File Error: page {page} " f"Translation File Error: page {page} "
f"does not exist for lang {language}" f"does not exist for lang {language}"
) )
console.error( Console.error(
f"Translation File Error: page {page} " f"Translation File Error: page {page} "
f"does not exist for lang {language}" f"does not exist for lang {language}"
) )
@ -73,7 +75,7 @@ class Translation:
f"Translation File Error: word {word} does not exist on page " f"Translation File Error: word {word} does not exist on page "
f"{page} for lang {language}" f"{page} for lang {language}"
) )
console.error( Console.error(
f"Translation File Error: word {word} does not exist on page " f"Translation File Error: word {word} does not exist on page "
f"{page} for lang {language}" f"{page} for lang {language}"
) )
@ -83,10 +85,7 @@ class Translation:
logger.critical( logger.critical(
f"Translation File Error: Unable to read {language_file} due to {e}" f"Translation File Error: Unable to read {language_file} due to {e}"
) )
console.critical( Console.critical(
f"Translation File Error: Unable to read {language_file} due to {e}" f"Translation File Error: Unable to read {language_file} due to {e}"
) )
return None return None
translation = Translation()

View File

@ -3,23 +3,16 @@ import html
import re import re
import logging import logging
import time import time
import bleach
import tornado.web
import tornado.escape
from app.classes.models.server_permissions import Enum_Permissions_Server from app.classes.models.server_permissions import Enum_Permissions_Server
from app.classes.shared.console import console from app.classes.shared.console import Console
from app.classes.shared.helpers import helper from app.classes.shared.helpers import Helpers
from app.classes.shared.translation import translation
from app.classes.shared.server import ServerOutBuf from app.classes.shared.server import ServerOutBuf
from app.classes.web.websocket_helper import websocket_helper
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
try:
import bleach
import tornado.web
import tornado.escape
except ModuleNotFoundError as ex:
helper.auto_installer_fix(ex)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -67,9 +60,9 @@ class AjaxHandler(BaseHandler):
) )
if full_log: if full_log:
log_lines = helper.get_setting("max_log_lines") log_lines = self.helper.get_setting("max_log_lines")
data = helper.tail_file( data = Helpers.tail_file(
helper.get_os_understandable_path(server_data["log_path"]), Helpers.get_os_understandable_path(server_data["log_path"]),
log_lines, log_lines,
) )
else: else:
@ -79,7 +72,7 @@ class AjaxHandler(BaseHandler):
try: try:
d = re.sub("(\033\\[(0;)?[0-9]*[A-z]?(;[0-9])?m?)|(> )", "", d) d = re.sub("(\033\\[(0;)?[0-9]*[A-z]?(;[0-9])?m?)|(> )", "", d)
d = re.sub("[A-z]{2}\b\b", "", d) d = re.sub("[A-z]{2}\b\b", "", d)
line = helper.log_colors(html.escape(d)) line = self.helper.log_colors(html.escape(d))
self.write(f"{line}<br />") self.write(f"{line}<br />")
# self.write(d.encode("utf-8")) # self.write(d.encode("utf-8"))
@ -87,7 +80,7 @@ class AjaxHandler(BaseHandler):
logger.warning(f"Skipping Log Line due to error: {e}") logger.warning(f"Skipping Log Line due to error: {e}")
elif page == "announcements": elif page == "announcements":
data = helper.get_announcements() data = Helpers.get_announcements()
page_data["notify_data"] = data page_data["notify_data"] = data
self.render_page("ajax/notify.html", page_data) self.render_page("ajax/notify.html", page_data)
@ -95,9 +88,9 @@ class AjaxHandler(BaseHandler):
path = self.get_argument("path", None) path = self.get_argument("path", None)
self.write( self.write(
helper.get_os_understandable_path(path) Helpers.get_os_understandable_path(path)
+ "\n" + "\n"
+ helper.generate_zip_tree(path) + Helpers.generate_zip_tree(path)
) )
self.finish() self.finish()
@ -105,9 +98,9 @@ class AjaxHandler(BaseHandler):
path = self.get_argument("path", None) path = self.get_argument("path", None)
self.write( self.write(
helper.get_os_understandable_path(path) Helpers.get_os_understandable_path(path)
+ "\n" + "\n"
+ helper.generate_zip_dir(path) + Helpers.generate_zip_dir(path)
) )
self.finish() self.finish()
@ -175,7 +168,7 @@ class AjaxHandler(BaseHandler):
onclick=""><input type='checkbox' class="checkBoxClass" name='root_path' value="{dpath}"> onclick=""><input type='checkbox' class="checkBoxClass" name='root_path' value="{dpath}">
<span style="margin-right: 6px;"><i class="far fa-file"> <span style="margin-right: 6px;"><i class="far fa-file">
</i></span></input>{filename}</li>""" </i></span></input>{filename}</li>"""
self.write(helper.get_os_understandable_path(folder) + "\n" + output) self.write(Helpers.get_os_understandable_path(folder) + "\n" + output)
self.finish() self.finish()
elif page == "get_backup_dir": elif page == "get_backup_dir":
@ -240,7 +233,7 @@ class AjaxHandler(BaseHandler):
<span style="margin-right: 6px;"><i class="far fa-file"> <span style="margin-right: 6px;"><i class="far fa-file">
</i></span></input>{filename}</li>""" </i></span></input>{filename}</li>"""
self.write(helper.get_os_understandable_path(folder) + "\n" + output) self.write(Helpers.get_os_understandable_path(folder) + "\n" + output)
self.finish() self.finish()
elif page == "get_dir": elif page == "get_dir":
@ -252,13 +245,13 @@ class AjaxHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if helper.validate_traversal( if Helpers.validate_traversal(
self.controller.servers.get_server_data_by_id(server_id)["path"], path self.controller.servers.get_server_data_by_id(server_id)["path"], path
): ):
self.write( self.write(
helper.get_os_understandable_path(path) Helpers.get_os_understandable_path(path)
+ "\n" + "\n"
+ helper.generate_dir(path) + Helpers.generate_dir(path)
) )
self.finish() self.finish()
@ -291,7 +284,7 @@ class AjaxHandler(BaseHandler):
if server_id is None: if server_id is None:
logger.warning("Server ID not found in send_command ajax call") logger.warning("Server ID not found in send_command ajax call")
console.warning("Server ID not found in send_command ajax call") Console.warning("Server ID not found in send_command ajax call")
srv_obj = self.controller.get_server_obj(server_id) srv_obj = self.controller.get_server_obj(server_id)
@ -390,8 +383,8 @@ class AjaxHandler(BaseHandler):
server_data = self.controller.servers.get_server_data_by_id(server_id) server_data = self.controller.servers.get_server_data_by_id(server_id)
if server_data["type"] == "minecraft-java": if server_data["type"] == "minecraft-java":
backup_path = svr_obj.backup_path backup_path = svr_obj.backup_path
if helper.validate_traversal(backup_path, zip_name): if Helpers.validate_traversal(backup_path, zip_name):
tempDir = helper.unzip_backup_archive(backup_path, zip_name) tempDir = Helpers.unzip_backup_archive(backup_path, zip_name)
new_server = self.controller.import_zip_server( new_server = self.controller.import_zip_server(
svr_obj.server_name, svr_obj.server_name,
tempDir, tempDir,
@ -410,8 +403,8 @@ class AjaxHandler(BaseHandler):
else: else:
backup_path = svr_obj.backup_path backup_path = svr_obj.backup_path
if helper.validate_traversal(backup_path, zip_name): if Helpers.validate_traversal(backup_path, zip_name):
tempDir = helper.unzip_backup_archive(backup_path, zip_name) tempDir = Helpers.unzip_backup_archive(backup_path, zip_name)
new_server = self.controller.import_bedrock_zip_server( new_server = self.controller.import_bedrock_zip_server(
svr_obj.server_name, svr_obj.server_name,
tempDir, tempDir,
@ -428,23 +421,27 @@ class AjaxHandler(BaseHandler):
elif page == "unzip_server": elif page == "unzip_server":
path = self.get_argument("path", None) path = self.get_argument("path", None)
if helper.check_file_exists(path): if Helpers.check_file_exists(path):
helper.unzipServer(path, exec_user["user_id"]) self.helper.unzipServer(path, exec_user["user_id"])
else: else:
user_id = exec_user["user_id"] user_id = exec_user["user_id"]
if user_id: if user_id:
time.sleep(5) time.sleep(5)
user_lang = self.controller.users.get_user_lang_by_id(user_id) user_lang = self.controller.users.get_user_lang_by_id(user_id)
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{"error": translation.translate("error", "no-file", user_lang)}, {
"error": self.helper.translation.translate(
"error", "no-file", user_lang
)
},
) )
return return
elif page == "backup_select": elif page == "backup_select":
path = self.get_argument("path", None) path = self.get_argument("path", None)
helper.backup_select(path, exec_user["user_id"]) self.helper.backup_select(path, exec_user["user_id"])
return return
@tornado.web.authenticated @tornado.web.authenticated
@ -481,12 +478,12 @@ class AjaxHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Backups") self.redirect("/panel/error?error=Unauthorized access to Backups")
return return
file_path = helper.get_os_understandable_path( file_path = Helpers.get_os_understandable_path(
self.get_body_argument("file_path", default=None, strip=True) self.get_body_argument("file_path", default=None, strip=True)
) )
server_id = self.get_argument("id", None) server_id = self.get_argument("id", None)
console.warning(f"Delete {file_path} for server {server_id}") Console.warning(f"Delete {file_path} for server {server_id}")
if not self.check_server_id(server_id, "del_backup"): if not self.check_server_id(server_id, "del_backup"):
return return
@ -495,21 +492,22 @@ class AjaxHandler(BaseHandler):
server_info = self.controller.servers.get_server_data_by_id(server_id) server_info = self.controller.servers.get_server_data_by_id(server_id)
if not ( if not (
helper.in_path( Helpers.in_path(
helper.get_os_understandable_path(server_info["path"]), file_path Helpers.get_os_understandable_path(server_info["path"]), file_path
) )
or helper.in_path( or Helpers.in_path(
helper.get_os_understandable_path(server_info["backup_path"]), Helpers.get_os_understandable_path(server_info["backup_path"]),
file_path, file_path,
) )
) or not helper.check_file_exists(os.path.abspath(file_path)): ) or not Helpers.check_file_exists(os.path.abspath(file_path)):
logger.warning(f"Invalid path in del_backup ajax call ({file_path})") logger.warning(f"Invalid path in del_backup ajax call ({file_path})")
console.warning(f"Invalid path in del_backup ajax call ({file_path})") Console.warning(f"Invalid path in del_backup ajax call ({file_path})")
return return
# Delete the file # Delete the file
if helper.validate_traversal( if Helpers.validate_traversal(
helper.get_os_understandable_path(server_info["backup_path"]), file_path Helpers.get_os_understandable_path(server_info["backup_path"]),
file_path,
): ):
os.remove(file_path) os.remove(file_path)
@ -566,7 +564,7 @@ class AjaxHandler(BaseHandler):
logger.warning( logger.warning(
f"Server ID not defined in {page_name} ajax call ({server_id})" f"Server ID not defined in {page_name} ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Server ID not defined in {page_name} ajax call ({server_id})" f"Server ID not defined in {page_name} ajax call ({server_id})"
) )
return return
@ -578,7 +576,7 @@ class AjaxHandler(BaseHandler):
logger.warning( logger.warning(
f"Server ID not found in {page_name} ajax call ({server_id})" f"Server ID not found in {page_name} ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Server ID not found in {page_name} ajax call ({server_id})" f"Server ID not found in {page_name} ajax call ({server_id})"
) )
return return

View File

@ -135,16 +135,28 @@ class SendCommand(ApiHandler):
def post(self): def post(self):
user = self.authenticate_user() user = self.authenticate_user()
user_obj = self.controller.users.get_user_by_api_token(self.api_token)
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
server_id = self.get_argument("id") server_id = self.get_argument("id")
if (
not user_obj["user_id"]
in self.controller.server_perms.get_server_user_list(server_id)
and not user_obj["superuser"]
):
self.access_denied("unknown")
return
if not self.permissions[ if not self.permissions[
"Commands" "Commands"
] in self.controller.server_perms.get_api_key_permissions_list( ] in self.controller.server_perms.get_api_key_permissions_list(
self.controller.users.get_api_key_by_token(self.api_token), server_id self.controller.users.get_api_key_by_token(self.api_token), server_id
): ):
self.access_denied(user) self.access_denied(user)
return
command = self.get_argument("command", default=None, strip=True) command = self.get_argument("command", default=None, strip=True)
server_id = self.get_argument("id") server_id = self.get_argument("id")
@ -163,16 +175,28 @@ class ServerBackup(ApiHandler):
def post(self): def post(self):
user = self.authenticate_user() user = self.authenticate_user()
user_obj = self.controller.users.get_user_by_api_token(self.api_token)
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
server_id = self.get_argument("id") server_id = self.get_argument("id")
if (
not user_obj["user_id"]
in self.controller.server_perms.get_server_user_list(server_id)
and not user_obj["superuser"]
):
self.access_denied("unknown")
return
if not self.permissions[ if not self.permissions[
"Backup" "Backup"
] in self.controller.server_perms.get_api_key_permissions_list( ] in self.controller.server_perms.get_api_key_permissions_list(
self.controller.users.get_api_key_by_token(self.api_token), server_id self.controller.users.get_api_key_by_token(self.api_token), server_id
): ):
self.access_denied(user) self.access_denied(user)
return
server = self.controller.get_server_obj(server_id) server = self.controller.get_server_obj(server_id)
@ -190,15 +214,23 @@ class StartServer(ApiHandler):
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
server_id = self.get_argument("id") server_id = self.get_argument("id")
if not self.permissions[ if (
not user_obj["user_id"]
in self.controller.server_perms.get_server_user_list(server_id)
and not user_obj["superuser"]
):
self.access_denied("unknown")
return
elif not self.permissions[
"Commands" "Commands"
] in self.controller.server_perms.get_api_key_permissions_list( ] in self.controller.server_perms.get_api_key_permissions_list(
self.controller.users.get_api_key_by_token(self.api_token), server_id self.controller.users.get_api_key_by_token(self.api_token), server_id
): ):
self.access_denied(user) self.access_denied("unknown")
return
server = self.controller.get_server_obj(server_id) server = self.controller.get_server_obj(server_id)
@ -216,16 +248,27 @@ class StopServer(ApiHandler):
user = self.authenticate_user() user = self.authenticate_user()
remote_ip = self.get_remote_ip() remote_ip = self.get_remote_ip()
user_obj = self.controller.users.get_user_by_api_token(self.api_token)
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
server_id = self.get_argument("id") server_id = self.get_argument("id")
if (
not user_obj["user_id"]
in self.controller.server_perms.get_server_user_list(server_id)
and not user_obj["superuser"]
):
self.access_denied("unknown")
if not self.permissions[ if not self.permissions[
"Commands" "Commands"
] in self.controller.server_perms.get_api_key_permissions_list( ] in self.controller.server_perms.get_api_key_permissions_list(
self.controller.users.get_api_key_by_token(self.api_token), server_id self.controller.users.get_api_key_by_token(self.api_token), server_id
): ):
self.access_denied(user) self.access_denied(user)
return
server = self.controller.get_server_obj(server_id) server = self.controller.get_server_obj(server_id)
@ -243,10 +286,17 @@ class RestartServer(ApiHandler):
def post(self): def post(self):
user = self.authenticate_user() user = self.authenticate_user()
remote_ip = self.get_remote_ip() remote_ip = self.get_remote_ip()
server_id = self.get_argument("id") user_obj = self.controller.users.get_user_by_api_token(self.api_token)
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
server_id = self.get_argument("id")
if not user_obj["user_id"] in self.controller.server_perms.get_server_user_list(
server_id
):
self.access_denied("unknown")
if not self.permissions[ if not self.permissions[
"Commands" "Commands"
@ -264,9 +314,21 @@ class RestartServer(ApiHandler):
class CreateUser(ApiHandler): class CreateUser(ApiHandler):
def post(self): def post(self):
user = self.authenticate_user() user = self.authenticate_user()
user_obj = self.controller.users.get_user_by_api_token(self.api_token)
user_perms = self.controller.crafty_perms.get_crafty_permissions_list(
user_obj["user_id"]
)
if (
not self.permissions["User_Config"] in user_perms
and not user_obj["superuser"]
):
self.access_denied("unknown")
return
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
if not self.permissions[ if not self.permissions[
"User_Config" "User_Config"
@ -274,6 +336,7 @@ class CreateUser(ApiHandler):
self.controller.users.get_api_key_by_token(self.api_token) self.controller.users.get_api_key_by_token(self.api_token)
): ):
self.access_denied(user) self.access_denied(user)
return
new_username = self.get_argument("username") new_username = self.get_argument("username")
new_pass = self.get_argument("password") new_pass = self.get_argument("password")
@ -305,8 +368,22 @@ class DeleteUser(ApiHandler):
def post(self): def post(self):
user = self.authenticate_user() user = self.authenticate_user()
user_obj = self.controller.users.get_user_by_api_token(self.api_token)
user_perms = self.controller.crafty_perms.get_crafty_permissions_list(
user_obj["user_id"]
)
if (
not self.permissions["User_Config"] in user_perms
and not user_obj["superuser"]
):
self.access_denied("unknown")
return
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
if not self.permissions[ if not self.permissions[
"User_Config" "User_Config"
@ -314,6 +391,7 @@ class DeleteUser(ApiHandler):
self.controller.users.get_api_key_by_token(self.api_token) self.controller.users.get_api_key_by_token(self.api_token)
): ):
self.access_denied(user) self.access_denied(user)
return
user_id = self.get_argument("user_id", None, True) user_id = self.get_argument("user_id", None, True)
user_to_del = self.controller.users.get_user_by_id(user_id) user_to_del = self.controller.users.get_user_by_id(user_id)
@ -336,15 +414,19 @@ class ListServers(ApiHandler):
if user is None: if user is None:
self.access_denied("unknown") self.access_denied("unknown")
return
if self.api_token is None: if self.api_token is None:
self.access_denied("unknown") self.access_denied("unknown")
return
if user_obj["superuser"]: if user_obj["superuser"]:
servers = self.controller.servers.get_all_defined_servers() servers = self.controller.servers.get_all_defined_servers()
servers = [str(i) for i in servers] servers = [str(i) for i in servers]
else: else:
servers = self.controller.servers.get_all_defined_servers() servers = self.controller.servers.get_authorized_servers(
user_obj["user_id"]
)
servers = [str(i) for i in servers] servers = [str(i) for i in servers]
self.return_response( self.return_response(

View File

@ -1,17 +1,9 @@
import logging import logging
from typing import Union, List, Optional, Tuple, Dict, Any from typing import Union, List, Optional, Tuple, Dict, Any
import bleach
import tornado.web
from app.classes.models.users import ApiKeys from app.classes.models.users import ApiKeys
from app.classes.shared.authentication import authentication
from app.classes.shared.main_controller import Controller
from app.classes.shared.helpers import helper
try:
import tornado.web
import bleach
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -23,8 +15,9 @@ class BaseHandler(tornado.web.RequestHandler):
# noinspection PyAttributeOutsideInit # noinspection PyAttributeOutsideInit
def initialize( def initialize(
self, controller: Controller = None, tasks_manager=None, translator=None self, helper=None, controller=None, tasks_manager=None, translator=None
): ):
self.helper = helper
self.controller = controller self.controller = controller
self.tasks_manager = tasks_manager self.tasks_manager = tasks_manager
self.translator = translator self.translator = translator
@ -42,7 +35,7 @@ class BaseHandler(tornado.web.RequestHandler):
def get_current_user( def get_current_user(
self, self,
) -> Optional[Tuple[Optional[ApiKeys], Dict[str, Any], Dict[str, Any]]]: ) -> Optional[Tuple[Optional[ApiKeys], Dict[str, Any], Dict[str, Any]]]:
return authentication.check(self.get_cookie("token")) return self.controller.authentication.check(self.get_cookie("token"))
def autobleach(self, name, text): def autobleach(self, name, text):
for r in self.redactables: for r in self.redactables:

View File

@ -1,20 +1,15 @@
import os import os
import logging import logging
import bleach
import tornado.web
import tornado.escape
from app.classes.models.server_permissions import Enum_Permissions_Server from app.classes.models.server_permissions import Enum_Permissions_Server
from app.classes.shared.console import console from app.classes.shared.console import Console
from app.classes.shared.helpers import helper from app.classes.shared.helpers import Helpers
from app.classes.shared.file_helpers import file_helper from app.classes.shared.file_helpers import FileHelpers
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
try:
import bleach
import tornado.web
import tornado.escape
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -54,7 +49,7 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
file_path = helper.get_os_understandable_path( file_path = Helpers.get_os_understandable_path(
self.get_argument("file_path", None) self.get_argument("file_path", None)
) )
@ -63,16 +58,16 @@ class FileHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
file_path, file_path,
) or not helper.check_file_exists(os.path.abspath(file_path)): ) or not Helpers.check_file_exists(os.path.abspath(file_path)):
logger.warning( logger.warning(
f"Invalid path in get_file file file ajax call ({file_path})" f"Invalid path in get_file file file ajax call ({file_path})"
) )
console.warning( Console.warning(
f"Invalid path in get_file file file ajax call ({file_path})" f"Invalid path in get_file file file ajax call ({file_path})"
) )
return return
@ -101,13 +96,13 @@ class FileHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if helper.validate_traversal( if Helpers.validate_traversal(
self.controller.servers.get_server_data_by_id(server_id)["path"], path self.controller.servers.get_server_data_by_id(server_id)["path"], path
): ):
self.write( self.write(
helper.get_os_understandable_path(path) Helpers.get_os_understandable_path(path)
+ "\n" + "\n"
+ helper.generate_tree(path) + Helpers.generate_tree(path)
) )
self.finish() self.finish()
@ -123,13 +118,13 @@ class FileHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if helper.validate_traversal( if Helpers.validate_traversal(
self.controller.servers.get_server_data_by_id(server_id)["path"], path self.controller.servers.get_server_data_by_id(server_id)["path"], path
): ):
self.write( self.write(
helper.get_os_understandable_path(path) Helpers.get_os_understandable_path(path)
+ "\n" + "\n"
+ helper.generate_dir(path) + Helpers.generate_dir(path)
) )
self.finish() self.finish()
@ -161,7 +156,7 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
file_parent = helper.get_os_understandable_path( file_parent = Helpers.get_os_understandable_path(
self.get_body_argument("file_parent", default=None, strip=True) self.get_body_argument("file_parent", default=None, strip=True)
) )
file_name = self.get_body_argument("file_name", default=None, strip=True) file_name = self.get_body_argument("file_name", default=None, strip=True)
@ -172,16 +167,16 @@ class FileHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
file_path, file_path,
) or helper.check_file_exists(os.path.abspath(file_path)): ) or Helpers.check_file_exists(os.path.abspath(file_path)):
logger.warning( logger.warning(
f"Invalid path in create_file file ajax call ({file_path})" f"Invalid path in create_file file ajax call ({file_path})"
) )
console.warning( Console.warning(
f"Invalid path in create_file file ajax call ({file_path})" f"Invalid path in create_file file ajax call ({file_path})"
) )
return return
@ -195,7 +190,7 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
dir_parent = helper.get_os_understandable_path( dir_parent = Helpers.get_os_understandable_path(
self.get_body_argument("dir_parent", default=None, strip=True) self.get_body_argument("dir_parent", default=None, strip=True)
) )
dir_name = self.get_body_argument("dir_name", default=None, strip=True) dir_name = self.get_body_argument("dir_name", default=None, strip=True)
@ -206,16 +201,16 @@ class FileHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
dir_path, dir_path,
) or helper.check_path_exists(os.path.abspath(dir_path)): ) or Helpers.check_path_exists(os.path.abspath(dir_path)):
logger.warning( logger.warning(
f"Invalid path in create_dir file ajax call ({dir_path})" f"Invalid path in create_dir file ajax call ({dir_path})"
) )
console.warning( Console.warning(
f"Invalid path in create_dir file ajax call ({dir_path})" f"Invalid path in create_dir file ajax call ({dir_path})"
) )
return return
@ -227,8 +222,8 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
path = helper.get_os_understandable_path(self.get_argument("path", None)) path = Helpers.get_os_understandable_path(self.get_argument("path", None))
helper.unzipFile(path) Helpers.unzipFile(path)
self.redirect(f"/panel/server_detail?id={server_id}&subpage=files") self.redirect(f"/panel/server_detail?id={server_id}&subpage=files")
return return
@ -259,11 +254,11 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
file_path = helper.get_os_understandable_path( file_path = Helpers.get_os_understandable_path(
self.get_body_argument("file_path", default=None, strip=True) self.get_body_argument("file_path", default=None, strip=True)
) )
console.warning(f"Delete {file_path} for server {server_id}") Console.warning(f"Delete {file_path} for server {server_id}")
if not self.check_server_id(server_id, "del_file"): if not self.check_server_id(server_id, "del_file"):
return return
@ -272,33 +267,33 @@ class FileHandler(BaseHandler):
server_info = self.controller.servers.get_server_data_by_id(server_id) server_info = self.controller.servers.get_server_data_by_id(server_id)
if not ( if not (
helper.in_path( Helpers.in_path(
helper.get_os_understandable_path(server_info["path"]), file_path Helpers.get_os_understandable_path(server_info["path"]), file_path
) )
or helper.in_path( or Helpers.in_path(
helper.get_os_understandable_path(server_info["backup_path"]), Helpers.get_os_understandable_path(server_info["backup_path"]),
file_path, file_path,
) )
) or not helper.check_file_exists(os.path.abspath(file_path)): ) or not Helpers.check_file_exists(os.path.abspath(file_path)):
logger.warning(f"Invalid path in del_file file ajax call ({file_path})") logger.warning(f"Invalid path in del_file file ajax call ({file_path})")
console.warning( Console.warning(
f"Invalid path in del_file file ajax call ({file_path})" f"Invalid path in del_file file ajax call ({file_path})"
) )
return return
# Delete the file # Delete the file
file_helper.del_file(file_path) FileHelpers.del_file(file_path)
elif page == "del_dir": elif page == "del_dir":
if not permissions["Files"] in user_perms: if not permissions["Files"] in user_perms:
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
dir_path = helper.get_os_understandable_path( dir_path = Helpers.get_os_understandable_path(
self.get_body_argument("dir_path", default=None, strip=True) self.get_body_argument("dir_path", default=None, strip=True)
) )
console.warning(f"Delete {dir_path} for server {server_id}") Console.warning(f"Delete {dir_path} for server {server_id}")
if not self.check_server_id(server_id, "del_dir"): if not self.check_server_id(server_id, "del_dir"):
return return
@ -306,20 +301,20 @@ class FileHandler(BaseHandler):
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
server_info = self.controller.servers.get_server_data_by_id(server_id) server_info = self.controller.servers.get_server_data_by_id(server_id)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path(server_info["path"]), dir_path Helpers.get_os_understandable_path(server_info["path"]), dir_path
) or not helper.check_path_exists(os.path.abspath(dir_path)): ) or not Helpers.check_path_exists(os.path.abspath(dir_path)):
logger.warning(f"Invalid path in del_file file ajax call ({dir_path})") logger.warning(f"Invalid path in del_file file ajax call ({dir_path})")
console.warning(f"Invalid path in del_file file ajax call ({dir_path})") Console.warning(f"Invalid path in del_file file ajax call ({dir_path})")
return return
# Delete the directory # Delete the directory
# os.rmdir(dir_path) # Would only remove empty directories # os.rmdir(dir_path) # Would only remove empty directories
if helper.validate_traversal( if Helpers.validate_traversal(
helper.get_os_understandable_path(server_info["path"]), dir_path Helpers.get_os_understandable_path(server_info["path"]), dir_path
): ):
# Removes also when there are contents # Removes also when there are contents
file_helper.del_dirs(dir_path) FileHelpers.del_dirs(dir_path)
@tornado.web.authenticated @tornado.web.authenticated
def put(self, page): def put(self, page):
@ -350,7 +345,7 @@ class FileHandler(BaseHandler):
file_contents = self.get_body_argument( file_contents = self.get_body_argument(
"file_contents", default=None, strip=True "file_contents", default=None, strip=True
) )
file_path = helper.get_os_understandable_path( file_path = Helpers.get_os_understandable_path(
self.get_body_argument("file_path", default=None, strip=True) self.get_body_argument("file_path", default=None, strip=True)
) )
@ -359,16 +354,16 @@ class FileHandler(BaseHandler):
else: else:
server_id = bleach.clean(server_id) server_id = bleach.clean(server_id)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
file_path, file_path,
) or not helper.check_file_exists(os.path.abspath(file_path)): ) or not Helpers.check_file_exists(os.path.abspath(file_path)):
logger.warning( logger.warning(
f"Invalid path in save_file file ajax call ({file_path})" f"Invalid path in save_file file ajax call ({file_path})"
) )
console.warning( Console.warning(
f"Invalid path in save_file file ajax call ({file_path})" f"Invalid path in save_file file ajax call ({file_path})"
) )
return return
@ -382,7 +377,7 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
item_path = helper.get_os_understandable_path( item_path = Helpers.get_os_understandable_path(
self.get_body_argument("item_path", default=None, strip=True) self.get_body_argument("item_path", default=None, strip=True)
) )
new_item_name = self.get_body_argument( new_item_name = self.get_body_argument(
@ -396,35 +391,35 @@ class FileHandler(BaseHandler):
if item_path is None or new_item_name is None: if item_path is None or new_item_name is None:
logger.warning("Invalid path(s) in rename_file file ajax call") logger.warning("Invalid path(s) in rename_file file ajax call")
console.warning("Invalid path(s) in rename_file file ajax call") Console.warning("Invalid path(s) in rename_file file ajax call")
return return
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
item_path, item_path,
) or not helper.check_path_exists(os.path.abspath(item_path)): ) or not Helpers.check_path_exists(os.path.abspath(item_path)):
logger.warning( logger.warning(
f"Invalid old name path in rename_file file ajax call ({server_id})" f"Invalid old name path in rename_file file ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Invalid old name path in rename_file file ajax call ({server_id})" f"Invalid old name path in rename_file file ajax call ({server_id})"
) )
return return
new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name) new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
new_item_path, new_item_path,
) or helper.check_path_exists(os.path.abspath(new_item_path)): ) or Helpers.check_path_exists(os.path.abspath(new_item_path)):
logger.warning( logger.warning(
f"Invalid new name path in rename_file file ajax call ({server_id})" f"Invalid new name path in rename_file file ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Invalid new name path in rename_file file ajax call ({server_id})" f"Invalid new name path in rename_file file ajax call ({server_id})"
) )
return return
@ -458,7 +453,7 @@ class FileHandler(BaseHandler):
if not superuser: if not superuser:
self.redirect("/panel/error?error=Unauthorized access to Files") self.redirect("/panel/error?error=Unauthorized access to Files")
return return
item_path = helper.get_os_understandable_path( item_path = Helpers.get_os_understandable_path(
self.get_body_argument("item_path", default=None, strip=True) self.get_body_argument("item_path", default=None, strip=True)
) )
new_item_name = self.get_body_argument( new_item_name = self.get_body_argument(
@ -472,35 +467,35 @@ class FileHandler(BaseHandler):
if item_path is None or new_item_name is None: if item_path is None or new_item_name is None:
logger.warning("Invalid path(s) in rename_file file ajax call") logger.warning("Invalid path(s) in rename_file file ajax call")
console.warning("Invalid path(s) in rename_file file ajax call") Console.warning("Invalid path(s) in rename_file file ajax call")
return return
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
item_path, item_path,
) or not helper.check_path_exists(os.path.abspath(item_path)): ) or not Helpers.check_path_exists(os.path.abspath(item_path)):
logger.warning( logger.warning(
f"Invalid old name path in rename_file file ajax call ({server_id})" f"Invalid old name path in rename_file file ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Invalid old name path in rename_file file ajax call ({server_id})" f"Invalid old name path in rename_file file ajax call ({server_id})"
) )
return return
new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name) new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
new_item_path, new_item_path,
) or helper.check_path_exists(os.path.abspath(new_item_path)): ) or Helpers.check_path_exists(os.path.abspath(new_item_path)):
logger.warning( logger.warning(
f"Invalid new name path in rename_file file ajax call ({server_id})" f"Invalid new name path in rename_file file ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Invalid new name path in rename_file file ajax call ({server_id})" f"Invalid new name path in rename_file file ajax call ({server_id})"
) )
return return
@ -513,7 +508,7 @@ class FileHandler(BaseHandler):
logger.warning( logger.warning(
f"Server ID not defined in {page_name} file ajax call ({server_id})" f"Server ID not defined in {page_name} file ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Server ID not defined in {page_name} file ajax call ({server_id})" f"Server ID not defined in {page_name} file ajax call ({server_id})"
) )
return return
@ -525,7 +520,7 @@ class FileHandler(BaseHandler):
logger.warning( logger.warning(
f"Server ID not found in {page_name} file ajax call ({server_id})" f"Server ID not found in {page_name} file ajax call ({server_id})"
) )
console.warning( Console.warning(
f"Server ID not found in {page_name} file ajax call ({server_id})" f"Server ID not found in {page_name} file ajax call ({server_id})"
) )
return return

View File

@ -1,14 +1,8 @@
import logging import logging
import requests
from app.classes.shared.helpers import helper
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
try:
import requests
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -21,7 +15,7 @@ class HTTPHandler(BaseHandler):
url = "https://" + url_list[0] url = "https://" + url_list[0]
else: else:
url = "https://" + url url = "https://" + url
db_port = helper.get_setting("https_port") db_port = self.helper.get_setting("https_port")
try: try:
resp = requests.get(url + ":" + str(port)) resp = requests.get(url + ":" + str(port))
resp.raise_for_status() resp.raise_for_status()
@ -39,7 +33,7 @@ class HTTPHandlerPage(BaseHandler):
url = "https://" + url_list[0] url = "https://" + url_list[0]
else: else:
url = "https://" + url url = "https://" + url
db_port = helper.get_setting("https_port") db_port = self.helper.get_setting("https_port")
try: try:
resp = requests.get(url + ":" + str(port)) resp = requests.get(url + ":" + str(port))
resp.raise_for_status() resp.raise_for_status()

View File

@ -1,7 +1,5 @@
import logging import logging
import requests import requests
from app.classes.shared.helpers import helper
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -16,13 +14,15 @@ class HTTPHandlerPage(BaseHandler):
url_list = url.split("/") url_list = url.split("/")
if url_list[0] != "": if url_list[0] != "":
primary_url = url_list[0] + ":" + str(port) + "/" primary_url = url_list[0] + ":" + str(port) + "/"
backup_url = url_list[0] + ":" + str(helper.get_setting("https_port")) + "/" backup_url = (
url_list[0] + ":" + str(self.helper.get_setting("https_port")) + "/"
)
for i in range(len(url_list) - 1): for i in range(len(url_list) - 1):
primary_url += url_list[i + 1] primary_url += url_list[i + 1]
backup_url += url_list[i + 1] backup_url += url_list[i + 1]
else: else:
primary_url = url + str(port) primary_url = url + str(port)
backup_url = url + str(helper.get_setting("https_port")) backup_url = url + str(self.helper.get_setting("https_port"))
try: try:
resp = requests.get(primary_url) resp = requests.get(primary_url)

View File

@ -6,29 +6,23 @@ from typing import Dict, Any, Tuple
import json import json
import logging import logging
import threading import threading
import bleach
import libgravatar
import requests
import tornado.web
import tornado.escape
from tornado import iostream
# TZLocal is set as a hidden import on win pipeline
from tzlocal import get_localzone
from cron_validator import CronValidator
from app.classes.models.server_permissions import Enum_Permissions_Server from app.classes.models.server_permissions import Enum_Permissions_Server
from app.classes.models.crafty_permissions import Enum_Permissions_Crafty from app.classes.models.crafty_permissions import Enum_Permissions_Crafty
from app.classes.models.management import management_helper from app.classes.models.management import helpers_management
from app.classes.shared.authentication import authentication from app.classes.shared.helpers import Helpers
from app.classes.shared.helpers import helper
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
try:
import bleach
import libgravatar
import requests
import tornado.web
import tornado.escape
from tornado import iostream
# TZLocal is set as a hidden import on win pipeline
from tzlocal import get_localzone
from cron_validator import CronValidator
except ModuleNotFoundError as ex:
helper.auto_installer_fix(ex)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -268,7 +262,7 @@ class PanelHandler(BaseHandler):
# todo: make this actually pull and compare version data # todo: make this actually pull and compare version data
"update_available": False, "update_available": False,
"serverTZ": get_localzone(), "serverTZ": get_localzone(),
"version_data": helper.get_version_string(), "version_data": self.helper.get_version_string(),
"user_data": exec_user, "user_data": exec_user,
"user_role": exec_user_role, "user_role": exec_user_role,
"user_crafty_permissions": exec_user_crafty_permissions, "user_crafty_permissions": exec_user_crafty_permissions,
@ -287,11 +281,11 @@ class PanelHandler(BaseHandler):
}, },
"menu_servers": defined_servers, "menu_servers": defined_servers,
"hosts_data": self.controller.management.get_latest_hosts_stats(), "hosts_data": self.controller.management.get_latest_hosts_stats(),
"show_contribute": helper.get_setting("show_contribute_link", True), "show_contribute": self.helper.get_setting("show_contribute_link", True),
"error": error, "error": error,
"time": formatted_time, "time": formatted_time,
"lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]), "lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]),
"lang_page": helper.getLangPage( "lang_page": Helpers.getLangPage(
self.controller.users.get_user_lang_by_id(exec_user["user_id"]) self.controller.users.get_user_lang_by_id(exec_user["user_id"])
), ),
"super_user": superuser, "super_user": superuser,
@ -306,7 +300,7 @@ class PanelHandler(BaseHandler):
else None, else None,
"superuser": superuser, "superuser": superuser,
} }
if helper.get_setting("allow_nsfw_profile_pictures"): if self.helper.get_setting("allow_nsfw_profile_pictures"):
rating = "x" rating = "x"
else: else:
rating = "g" rating = "g"
@ -341,7 +335,9 @@ class PanelHandler(BaseHandler):
template = "public/error.html" template = "public/error.html"
elif page == "credits": elif page == "credits":
with open(helper.credits_cache, encoding="utf-8") as credits_default_local: with open(
self.helper.credits_cache, encoding="utf-8"
) as credits_default_local:
try: try:
remote = requests.get( remote = requests.get(
"https://craftycontrol.com/credits", allow_redirects=True "https://craftycontrol.com/credits", allow_redirects=True
@ -585,7 +581,7 @@ class PanelHandler(BaseHandler):
"/panel/error?error=Unauthorized access To Schedules" "/panel/error?error=Unauthorized access To Schedules"
) )
return return
page_data["schedules"] = management_helper.get_schedules_by_server( page_data["schedules"] = helpers_management.get_schedules_by_server(
server_id server_id
) )
@ -635,7 +631,7 @@ class PanelHandler(BaseHandler):
).send_backup_status() ).send_backup_status()
# makes it so relative path is the only thing shown # makes it so relative path is the only thing shown
for file in page_data["exclusions"]: for file in page_data["exclusions"]:
if helper.is_os_windows(): if Helpers.is_os_windows():
exclusions.append(file.replace(server_info["path"] + "\\", "")) exclusions.append(file.replace(server_info["path"] + "\\", ""))
else: else:
exclusions.append(file.replace(server_info["path"] + "/", "")) exclusions.append(file.replace(server_info["path"] + "/", ""))
@ -645,7 +641,7 @@ class PanelHandler(BaseHandler):
page_data["backup_list"] = server.list_backups() page_data["backup_list"] = server.list_backups()
except: except:
page_data["backup_list"] = [] page_data["backup_list"] = []
page_data["backup_path"] = helper.wtol_path(server_info["backup_path"]) page_data["backup_path"] = Helpers.wtol_path(server_info["backup_path"])
def get_banned_players_html(): def get_banned_players_html():
banned_players = self.controller.servers.get_banned_players(server_id) banned_players = self.controller.servers.get_banned_players(server_id)
@ -688,11 +684,11 @@ class PanelHandler(BaseHandler):
server_info = self.controller.servers.get_server_data_by_id(server_id) server_info = self.controller.servers.get_server_data_by_id(server_id)
backup_file = os.path.abspath( backup_file = os.path.abspath(
os.path.join( os.path.join(
helper.get_os_understandable_path(server_info["backup_path"]), file Helpers.get_os_understandable_path(server_info["backup_path"]), file
) )
) )
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path(server_info["backup_path"]), Helpers.get_os_understandable_path(server_info["backup_path"]),
backup_file, backup_file,
) or not os.path.isfile(backup_file): ) or not os.path.isfile(backup_file):
self.redirect("/panel/error?error=Invalid path detected") self.redirect("/panel/error?error=Invalid path detected")
@ -799,10 +795,10 @@ class PanelHandler(BaseHandler):
else: else:
page_data["super-disabled"] = "disabled" page_data["super-disabled"] = "disabled"
for file in sorted( for file in sorted(
os.listdir(os.path.join(helper.root_dir, "app", "translations")) os.listdir(os.path.join(self.helper.root_dir, "app", "translations"))
): ):
if file.endswith(".json"): if file.endswith(".json"):
if file not in helper.get_setting("disabled_language_files"): if file not in self.helper.get_setting("disabled_language_files"):
if file != str(page_data["languages"][0] + ".json"): if file != str(page_data["languages"][0] + ".json"):
page_data["languages"].append(file.split(".")[0]) page_data["languages"].append(file.split(".")[0])
@ -810,7 +806,7 @@ class PanelHandler(BaseHandler):
elif page == "add_schedule": elif page == "add_schedule":
server_id = self.get_argument("id", None) server_id = self.get_argument("id", None)
page_data["schedules"] = management_helper.get_schedules_by_server( page_data["schedules"] = helpers_management.get_schedules_by_server(
server_id server_id
) )
page_data["get_players"] = lambda: self.controller.stats.get_server_players( page_data["get_players"] = lambda: self.controller.stats.get_server_players(
@ -867,7 +863,7 @@ class PanelHandler(BaseHandler):
elif page == "edit_schedule": elif page == "edit_schedule":
server_id = self.get_argument("id", None) server_id = self.get_argument("id", None)
page_data["schedules"] = management_helper.get_schedules_by_server( page_data["schedules"] = helpers_management.get_schedules_by_server(
server_id server_id
) )
sch_id = self.get_argument("sch_id", None) sch_id = self.get_argument("sch_id", None)
@ -979,10 +975,10 @@ class PanelHandler(BaseHandler):
page_data["super-disabled"] = "disabled" page_data["super-disabled"] = "disabled"
for file in sorted( for file in sorted(
os.listdir(os.path.join(helper.root_dir, "app", "translations")) os.listdir(os.path.join(self.helper.root_dir, "app", "translations"))
): ):
if file.endswith(".json"): if file.endswith(".json"):
if file not in helper.get_setting("disabled_language_files"): if file not in self.helper.get_setting("disabled_language_files"):
if file != str(page_data["languages"][0] + ".json"): if file != str(page_data["languages"][0] + ".json"):
page_data["languages"].append(file.split(".")[0]) page_data["languages"].append(file.split(".")[0])
@ -1150,7 +1146,7 @@ class PanelHandler(BaseHandler):
template = "panel/activity_logs.html" template = "panel/activity_logs.html"
elif page == "download_file": elif page == "download_file":
file = helper.get_os_understandable_path(self.get_argument("path", "")) file = Helpers.get_os_understandable_path(self.get_argument("path", ""))
name = self.get_argument("name", "") name = self.get_argument("name", "")
server_id = self.check_server_id() server_id = self.check_server_id()
@ -1159,8 +1155,8 @@ class PanelHandler(BaseHandler):
server_info = self.controller.servers.get_server_data_by_id(server_id) server_info = self.controller.servers.get_server_data_by_id(server_id)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path(server_info["path"]), file Helpers.get_os_understandable_path(server_info["path"]), file
) or not os.path.isfile(file): ) or not os.path.isfile(file):
self.redirect("/panel/error?error=Invalid path detected") self.redirect("/panel/error?error=Invalid path detected")
return return
@ -1275,13 +1271,13 @@ class PanelHandler(BaseHandler):
server_obj = self.controller.servers.get_server_obj(server_id) server_obj = self.controller.servers.get_server_obj(server_id)
if superuser: if superuser:
server_path = self.get_argument("server_path", None) server_path = self.get_argument("server_path", None)
if helper.is_os_windows(): if Helpers.is_os_windows():
server_path.replace(" ", "^ ") server_path.replace(" ", "^ ")
server_path = helper.wtol_path(server_path) server_path = Helpers.wtol_path(server_path)
log_path = self.get_argument("log_path", None) log_path = self.get_argument("log_path", None)
if helper.is_os_windows(): if Helpers.is_os_windows():
log_path.replace(" ", "^ ") log_path.replace(" ", "^ ")
log_path = helper.wtol_path(log_path) log_path = Helpers.wtol_path(log_path)
executable = self.get_argument("executable", None) executable = self.get_argument("executable", None)
execution_command = self.get_argument("execution_command", None) execution_command = self.get_argument("execution_command", None)
server_ip = self.get_argument("server_ip", None) server_ip = self.get_argument("server_ip", None)
@ -1312,12 +1308,14 @@ class PanelHandler(BaseHandler):
server_obj.server_name = server_name server_obj.server_name = server_name
if superuser: if superuser:
if helper.validate_traversal( if Helpers.validate_traversal(
helper.get_servers_root_dir(), server_path self.helper.get_servers_root_dir(), server_path
): ):
server_obj.path = server_path server_obj.path = server_path
server_obj.log_path = log_path server_obj.log_path = log_path
if helper.validate_traversal(helper.get_servers_root_dir(), executable): if Helpers.validate_traversal(
self.helper.get_servers_root_dir(), executable
):
server_obj.executable = executable server_obj.executable = executable
server_obj.execution_command = execution_command server_obj.execution_command = execution_command
server_obj.server_ip = server_ip server_obj.server_ip = server_ip
@ -1362,9 +1360,9 @@ class PanelHandler(BaseHandler):
checked = self.controller.management.get_excluded_backup_dirs(server_id) checked = self.controller.management.get_excluded_backup_dirs(server_id)
if superuser: if superuser:
backup_path = bleach.clean(self.get_argument("backup_path", None)) backup_path = bleach.clean(self.get_argument("backup_path", None))
if helper.is_os_windows(): if Helpers.is_os_windows():
backup_path.replace(" ", "^ ") backup_path.replace(" ", "^ ")
backup_path = helper.wtol_path(backup_path) backup_path = Helpers.wtol_path(backup_path)
else: else:
backup_path = server_obj.backup_path backup_path = server_obj.backup_path
max_backups = bleach.clean(self.get_argument("max_backups", None)) max_backups = bleach.clean(self.get_argument("max_backups", None))
@ -1477,7 +1475,7 @@ class PanelHandler(BaseHandler):
one_time = False one_time = False
if not superuser and not permissions[ if not superuser and not permissions[
"Backup" "Schedule"
] in self.controller.server_perms.get_user_id_permissions_list( ] in self.controller.server_perms.get_user_id_permissions_list(
exec_user["user_id"], server_id exec_user["user_id"], server_id
): ):
@ -1635,7 +1633,7 @@ class PanelHandler(BaseHandler):
one_time = False one_time = False
if not superuser and not permissions[ if not superuser and not permissions[
"Backup" "Schedule"
] in self.controller.server_perms.get_user_id_permissions_list( ] in self.controller.server_perms.get_user_id_permissions_list(
exec_user["user_id"], server_id exec_user["user_id"], server_id
): ):
@ -1741,7 +1739,7 @@ class PanelHandler(BaseHandler):
except: except:
hints = False hints = False
lang = bleach.clean( lang = bleach.clean(
self.get_argument("language"), helper.get_setting("language") self.get_argument("language"), self.helper.get_setting("language")
) )
if superuser: if superuser:
@ -1895,7 +1893,9 @@ class PanelHandler(BaseHandler):
) )
self.write( self.write(
authentication.generate(key.user_id.user_id, {"token_id": key.token_id}) self.controller.authentication.generate(
key.user_id.user_id, {"token_id": key.token_id}
)
) )
self.finish() self.finish()
@ -1914,7 +1914,7 @@ class PanelHandler(BaseHandler):
enabled = int(float(self.get_argument("enabled", "0"))) enabled = int(float(self.get_argument("enabled", "0")))
hints = True hints = True
lang = bleach.clean( lang = bleach.clean(
self.get_argument("lang", helper.get_setting("language")) self.get_argument("lang", self.helper.get_setting("language"))
) )
# We don't want a non-super user to be able to create a super user. # We don't want a non-super user to be able to create a super user.
if superuser: if superuser:
@ -2056,8 +2056,8 @@ class PanelHandler(BaseHandler):
else: else:
self.set_status(404) self.set_status(404)
page_data = { page_data = {
"lang": helper.get_setting("language"), "lang": self.helper.get_setting("language"),
"lang_page": helper.getLangPage(helper.get_setting("language")), "lang_page": Helpers.getLangPage(self.helper.get_setting("language")),
} }
self.render( self.render(
"public/404.html", translate=self.translator.translate, data=page_data "public/404.html", translate=self.translator.translate, data=page_data
@ -2073,12 +2073,12 @@ class PanelHandler(BaseHandler):
page_data = { page_data = {
# todo: make this actually pull and compare version data # todo: make this actually pull and compare version data
"update_available": False, "update_available": False,
"version_data": helper.get_version_string(), "version_data": self.helper.get_version_string(),
"user_data": exec_user, "user_data": exec_user,
"hosts_data": self.controller.management.get_latest_hosts_stats(), "hosts_data": self.controller.management.get_latest_hosts_stats(),
"show_contribute": helper.get_setting("show_contribute_link", True), "show_contribute": self.helper.get_setting("show_contribute_link", True),
"lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]), "lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]),
"lang_page": helper.getLangPage( "lang_page": Helpers.getLangPage(
self.controller.users.get_user_lang_by_id(exec_user["user_id"]) self.controller.users.get_user_lang_by_id(exec_user["user_id"])
), ),
} }

View File

@ -1,24 +1,17 @@
import logging import logging
import bleach
from app.classes.models.users import Users from app.classes.shared.helpers import Helpers
from app.classes.shared.authentication import authentication from app.classes.models.users import helper_users
from app.classes.shared.helpers import helper
from app.classes.shared.main_models import fn
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
try:
import bleach
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class PublicHandler(BaseHandler): class PublicHandler(BaseHandler):
def set_current_user(self, user_id: str = None): def set_current_user(self, user_id: str = None):
expire_days = helper.get_setting("cookie_expire") expire_days = self.helper.get_setting("cookie_expire")
# if helper comes back with false # if helper comes back with false
if not expire_days: if not expire_days:
@ -26,7 +19,9 @@ class PublicHandler(BaseHandler):
if user_id is not None: if user_id is not None:
self.set_cookie( self.set_cookie(
"token", authentication.generate(user_id), expires_days=int(expire_days) "token",
self.controller.authentication.generate(user_id),
expires_days=int(expire_days),
) )
else: else:
self.clear_cookie("token") self.clear_cookie("token")
@ -39,10 +34,10 @@ class PublicHandler(BaseHandler):
error_msg = bleach.clean(self.get_argument("error_msg", "")) error_msg = bleach.clean(self.get_argument("error_msg", ""))
page_data = { page_data = {
"version": helper.get_version_string(), "version": self.helper.get_version_string(),
"error": error, "error": error,
"lang": helper.get_setting("language"), "lang": self.helper.get_setting("language"),
"lang_page": helper.getLangPage(helper.get_setting("language")), "lang_page": self.helper.getLangPage(self.helper.get_setting("language")),
"query": "", "query": "",
} }
if self.request.query: if self.request.query:
@ -88,10 +83,10 @@ class PublicHandler(BaseHandler):
error_msg = bleach.clean(self.get_argument("error_msg", "")) error_msg = bleach.clean(self.get_argument("error_msg", ""))
page_data = { page_data = {
"version": helper.get_version_string(), "version": self.helper.get_version_string(),
"error": error, "error": error,
"lang": helper.get_setting("language"), "lang": self.helper.get_setting("language"),
"lang_page": helper.getLangPage(helper.get_setting("language")), "lang_page": self.helper.getLangPage(self.helper.get_setting("language")),
"query": "", "query": "",
} }
if self.request.query: if self.request.query:
@ -107,9 +102,21 @@ class PublicHandler(BaseHandler):
entered_password = bleach.clean(self.get_argument("password")) entered_password = bleach.clean(self.get_argument("password"))
# pylint: disable=no-member # pylint: disable=no-member
user_data = Users.get_or_none( try:
fn.Lower(Users.username) == entered_username.lower() user_id = helper_users.get_user_id_by_name(entered_username.lower())
user_data = helper_users.get_user_model(user_id)
except:
error_msg = "Incorrect username or password. Please try again."
# self.clear_cookie("user")
# self.clear_cookie("user_data")
self.clear_cookie("token")
if self.request.query:
self.redirect(
f"/public/login?error_msg={error_msg}&{self.request.query}"
) )
else:
self.redirect(f"/public/login?error_msg={error_msg}")
return
# if we don't have a user # if we don't have a user
if not user_data: if not user_data:
@ -142,7 +149,7 @@ class PublicHandler(BaseHandler):
self.redirect(f"/public/login?error_msg={error_msg}") self.redirect(f"/public/login?error_msg={error_msg}")
return return
login_result = helper.verify_pass(entered_password, user_data.password) login_result = self.helper.verify_pass(entered_password, user_data.password)
# Valid Login # Valid Login
if login_result: if login_result:
@ -152,14 +159,9 @@ class PublicHandler(BaseHandler):
) )
# record this login # record this login
q = ( user_data.last_ip = self.get_remote_ip()
Users.select() user_data.last_login = Helpers.get_time_as_string()
.where(Users.username == entered_username.lower()) user_data.save()
.get()
)
q.last_ip = self.get_remote_ip()
q.last_login = helper.get_time_as_string()
q.save()
# log this login # log this login
self.controller.management.add_to_audit_log( self.controller.management.add_to_audit_log(

View File

@ -1,23 +1,17 @@
import json import json
import logging import logging
import os import os
import tornado.web
import tornado.escape
import bleach
import libgravatar
import requests
from app.classes.minecraft.serverjars import server_jar_obj
from app.classes.models.crafty_permissions import Enum_Permissions_Crafty from app.classes.models.crafty_permissions import Enum_Permissions_Crafty
from app.classes.shared.helpers import helper from app.classes.shared.helpers import Helpers
from app.classes.shared.file_helpers import file_helper from app.classes.shared.file_helpers import FileHelpers
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
try:
import tornado.web
import tornado.escape
import bleach
import libgravatar
import requests
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -58,7 +52,7 @@ class ServerHandler(BaseHandler):
template = "public/404.html" template = "public/404.html"
page_data = { page_data = {
"version_data": helper.get_version_string(), "version_data": self.helper.get_version_string(),
"user_data": exec_user, "user_data": exec_user,
"user_role": exec_user_role, "user_role": exec_user_role,
"roles": list_roles, "roles": list_roles,
@ -78,9 +72,9 @@ class ServerHandler(BaseHandler):
}, },
"hosts_data": self.controller.management.get_latest_hosts_stats(), "hosts_data": self.controller.management.get_latest_hosts_stats(),
"menu_servers": defined_servers, "menu_servers": defined_servers,
"show_contribute": helper.get_setting("show_contribute_link", True), "show_contribute": self.helper.get_setting("show_contribute_link", True),
"lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]), "lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]),
"lang_page": helper.getLangPage( "lang_page": Helpers.getLangPage(
self.controller.users.get_user_lang_by_id(exec_user["user_id"]) self.controller.users.get_user_lang_by_id(exec_user["user_id"])
), ),
"api_key": { "api_key": {
@ -95,7 +89,7 @@ class ServerHandler(BaseHandler):
"superuser": superuser, "superuser": superuser,
} }
if helper.get_setting("allow_nsfw_profile_pictures"): if self.helper.get_setting("allow_nsfw_profile_pictures"):
rating = "x" rating = "x"
else: else:
rating = "g" rating = "g"
@ -134,10 +128,10 @@ class ServerHandler(BaseHandler):
) )
return return
page_data["online"] = helper.check_internet() page_data["online"] = Helpers.check_internet()
page_data["server_types"] = server_jar_obj.get_serverjar_data() page_data["server_types"] = self.controller.server_jars.get_serverjar_data()
page_data["js_server_types"] = json.dumps( page_data["js_server_types"] = json.dumps(
server_jar_obj.get_serverjar_data() self.controller.server_jars.get_serverjar_data()
) )
template = "server/wizard.html" template = "server/wizard.html"
@ -171,9 +165,9 @@ class ServerHandler(BaseHandler):
page_data = { page_data = {
"version_data": "version_data_here", # TODO "version_data": "version_data_here", # TODO
"user_data": exec_user, "user_data": exec_user,
"show_contribute": helper.get_setting("show_contribute_link", True), "show_contribute": self.helper.get_setting("show_contribute_link", True),
"lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]), "lang": self.controller.users.get_user_lang_by_id(exec_user["user_id"]),
"lang_page": helper.getLangPage( "lang_page": Helpers.getLangPage(
self.controller.users.get_user_lang_by_id(exec_user["user_id"]) self.controller.users.get_user_lang_by_id(exec_user["user_id"])
), ),
} }
@ -204,15 +198,17 @@ class ServerHandler(BaseHandler):
server_data.get("server_name") + f" (Copy {name_counter})" server_data.get("server_name") + f" (Copy {name_counter})"
) )
new_server_uuid = helper.create_uuid() new_server_uuid = Helpers.create_uuid()
while os.path.exists( while os.path.exists(
os.path.join(helper.servers_dir, new_server_uuid) os.path.join(self.helper.servers_dir, new_server_uuid)
): ):
new_server_uuid = helper.create_uuid() new_server_uuid = Helpers.create_uuid()
new_server_path = os.path.join(helper.servers_dir, new_server_uuid) new_server_path = os.path.join(
self.helper.servers_dir, new_server_uuid
)
# copy the old server # copy the old server
file_helper.copy_dir(server_data.get("path"), new_server_path) FileHelpers.copy_dir(server_data.get("path"), new_server_path)
# TODO get old server DB data to individual variables # TODO get old server DB data to individual variables
stop_command = server_data.get("stop_command") stop_command = server_data.get("stop_command")
@ -221,8 +217,9 @@ class ServerHandler(BaseHandler):
).replace(server_uuid, new_server_uuid) ).replace(server_uuid, new_server_uuid)
new_executable = server_data.get("executable") new_executable = server_data.get("executable")
new_server_log_file = str( new_server_log_file = str(
helper.get_os_understandable_path(server_data.get("log_path")) Helpers.get_os_understandable_path(server_data.get("log_path"))
).replace(server_uuid, new_server_uuid) ).replace(server_uuid, new_server_uuid)
backup_path = os.path.join(self.helper.backup_path, new_server_uuid)
server_port = server_data.get("server_port") server_port = server_data.get("server_port")
server_type = server_data.get("type") server_type = server_data.get("type")
@ -230,7 +227,7 @@ class ServerHandler(BaseHandler):
new_server_name, new_server_name,
new_server_uuid, new_server_uuid,
new_server_path, new_server_path,
"", backup_path,
new_server_command, new_server_command,
new_executable, new_executable,
new_server_log_file, new_server_log_file,
@ -299,7 +296,7 @@ class ServerHandler(BaseHandler):
elif import_type == "import_zip": elif import_type == "import_zip":
# here import_server_path means the zip path # here import_server_path means the zip path
zip_path = bleach.clean(self.get_argument("root_path")) zip_path = bleach.clean(self.get_argument("root_path"))
good_path = helper.check_path_exists(zip_path) good_path = Helpers.check_path_exists(zip_path)
if not good_path: if not good_path:
self.redirect("/panel/error?error=Temp path not found!") self.redirect("/panel/error?error=Temp path not found!")
return return
@ -322,7 +319,7 @@ class ServerHandler(BaseHandler):
self.get_remote_ip(), self.get_remote_ip(),
) )
# deletes temp dir # deletes temp dir
file_helper.del_dirs(zip_path) FileHelpers.del_dirs(zip_path)
else: else:
if len(server_parts) != 2: if len(server_parts) != 2:
self.redirect("/panel/error?error=Invalid server data") self.redirect("/panel/error?error=Invalid server data")
@ -417,7 +414,7 @@ class ServerHandler(BaseHandler):
elif import_type == "import_zip": elif import_type == "import_zip":
# here import_server_path means the zip path # here import_server_path means the zip path
zip_path = bleach.clean(self.get_argument("root_path")) zip_path = bleach.clean(self.get_argument("root_path"))
good_path = helper.check_path_exists(zip_path) good_path = Helpers.check_path_exists(zip_path)
if not good_path: if not good_path:
self.redirect("/panel/error?error=Temp path not found!") self.redirect("/panel/error?error=Temp path not found!")
return return
@ -440,7 +437,7 @@ class ServerHandler(BaseHandler):
self.get_remote_ip(), self.get_remote_ip(),
) )
# deletes temp dir # deletes temp dir
file_helper.del_dirs(zip_path) FileHelpers.del_dirs(zip_path)
else: else:
if len(server_parts) != 2: if len(server_parts) != 2:
self.redirect("/panel/error?error=Invalid server data") self.redirect("/panel/error?error=Invalid server data")

View File

@ -1,6 +1,5 @@
import logging import logging
from app.classes.shared.helpers import helper
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -9,8 +8,10 @@ logger = logging.getLogger(__name__)
class StatusHandler(BaseHandler): class StatusHandler(BaseHandler):
def get(self): def get(self):
page_data = {} page_data = {}
page_data["lang"] = helper.get_setting("language") page_data["lang"] = self.helper.get_setting("language")
page_data["lang_page"] = helper.getLangPage(helper.get_setting("language")) page_data["lang_page"] = self.helper.getLangPage(
self.helper.get_setting("language")
)
page_data["servers"] = self.controller.servers.get_all_servers_stats() page_data["servers"] = self.controller.servers.get_all_servers_stats()
running = 0 running = 0
for srv in page_data["servers"]: for srv in page_data["servers"]:

View File

@ -3,10 +3,16 @@ import sys
import json import json
import asyncio import asyncio
import logging import logging
import tornado.web
import tornado.ioloop
import tornado.log
import tornado.template
import tornado.escape
import tornado.locale
import tornado.httpserver
from app.classes.shared.translation import translation from app.classes.shared.console import Console
from app.classes.shared.console import console from app.classes.shared.helpers import Helpers
from app.classes.shared.helpers import helper
from app.classes.web.file_handler import FileHandler from app.classes.web.file_handler import FileHandler
from app.classes.web.public_handler import PublicHandler from app.classes.web.public_handler import PublicHandler
from app.classes.web.panel_handler import PanelHandler from app.classes.web.panel_handler import PanelHandler
@ -31,26 +37,16 @@ from app.classes.web.upload_handler import UploadHandler
from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage
from app.classes.web.status_handler import StatusHandler from app.classes.web.status_handler import StatusHandler
try:
import tornado.web
import tornado.ioloop
import tornado.log
import tornado.template
import tornado.escape
import tornado.locale
import tornado.httpserver
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Webserver: class Webserver:
def __init__(self, controller, tasks_manager): def __init__(self, helper, controller, tasks_manager):
self.ioloop = None self.ioloop = None
self.HTTP_Server = None self.HTTP_Server = None
self.HTTPS_Server = None self.HTTPS_Server = None
self.helper = helper
self.controller = controller self.controller = controller
self.tasks_manager = tasks_manager self.tasks_manager = tasks_manager
self._asyncio_patch() self._asyncio_patch()
@ -103,16 +99,16 @@ class Webserver:
def run_tornado(self): def run_tornado(self):
# let's verify we have an SSL cert # let's verify we have an SSL cert
helper.create_self_signed_cert() self.helper.create_self_signed_cert()
http_port = helper.get_setting("http_port") http_port = self.helper.get_setting("http_port")
https_port = helper.get_setting("https_port") https_port = self.helper.get_setting("https_port")
debug_errors = helper.get_setting("show_errors") debug_errors = self.helper.get_setting("show_errors")
cookie_secret = helper.get_setting("cookie_secret") cookie_secret = self.helper.get_setting("cookie_secret")
if cookie_secret is False: if cookie_secret is False:
cookie_secret = helper.random_string_generator(32) cookie_secret = self.helper.random_string_generator(32)
if not http_port: if not http_port:
http_port = 8000 http_port = 8000
@ -122,10 +118,10 @@ class Webserver:
cert_objects = { cert_objects = {
"certfile": os.path.join( "certfile": os.path.join(
helper.config_dir, "web", "certs", "commander.cert.pem" self.helper.config_dir, "web", "certs", "commander.cert.pem"
), ),
"keyfile": os.path.join( "keyfile": os.path.join(
helper.config_dir, "web", "certs", "commander.key.pem" self.helper.config_dir, "web", "certs", "commander.key.pem"
), ),
} }
@ -139,9 +135,10 @@ class Webserver:
tornado.locale.set_default_locale("en_EN") tornado.locale.set_default_locale("en_EN")
handler_args = { handler_args = {
"helper": self.helper,
"controller": self.controller, "controller": self.controller,
"tasks_manager": self.tasks_manager, "tasks_manager": self.tasks_manager,
"translator": translation, "translator": self.helper.translation,
} }
handlers = [ handlers = [
(r"/", DefaultHandler, handler_args), (r"/", DefaultHandler, handler_args),
@ -168,8 +165,8 @@ class Webserver:
app = tornado.web.Application( app = tornado.web.Application(
handlers, handlers,
template_path=os.path.join(helper.webroot, "templates"), template_path=os.path.join(self.helper.webroot, "templates"),
static_path=os.path.join(helper.webroot, "static"), static_path=os.path.join(self.helper.webroot, "static"),
debug=debug_errors, debug=debug_errors,
cookie_secret=cookie_secret, cookie_secret=cookie_secret,
xsrf_cookies=True, xsrf_cookies=True,
@ -193,8 +190,8 @@ class Webserver:
] ]
HTTPapp = tornado.web.Application( HTTPapp = tornado.web.Application(
HTTPhanders, HTTPhanders,
template_path=os.path.join(helper.webroot, "templates"), template_path=os.path.join(self.helper.webroot, "templates"),
static_path=os.path.join(helper.webroot, "static"), static_path=os.path.join(self.helper.webroot, "static"),
debug=debug_errors, debug=debug_errors,
cookie_secret=cookie_secret, cookie_secret=cookie_secret,
xsrf_cookies=True, xsrf_cookies=True,
@ -212,24 +209,24 @@ class Webserver:
self.HTTPS_Server.listen(https_port) self.HTTPS_Server.listen(https_port)
logger.info( logger.info(
f"https://{helper.get_local_ip()}:{https_port} " f"https://{Helpers.get_local_ip()}:{https_port} "
f"is up and ready for connections." f"is up and ready for connections."
) )
console.info( Console.info(
f"https://{helper.get_local_ip()}:{https_port} " f"https://{Helpers.get_local_ip()}:{https_port} "
f"is up and ready for connections." f"is up and ready for connections."
) )
console.info("Server Init Complete: Listening For Connections:") Console.info("Server Init Complete: Listening For Connections:")
self.ioloop = tornado.ioloop.IOLoop.current() self.ioloop = tornado.ioloop.IOLoop.current()
self.ioloop.start() self.ioloop.start()
def stop_web_server(self): def stop_web_server(self):
logger.info("Shutting Down Web Server") logger.info("Shutting Down Web Server")
console.info("Shutting Down Web Server") Console.info("Shutting Down Web Server")
self.ioloop.stop() self.ioloop.stop()
self.HTTP_Server.stop() self.HTTP_Server.stop()
self.HTTPS_Server.stop() self.HTTPS_Server.stop()
logger.info("Web Server Stopped") logger.info("Web Server Stopped")
console.info("Web Server Stopped") Console.info("Web Server Stopped")

View File

@ -1,22 +1,15 @@
import logging import logging
import os import os
import time import time
import tornado.web
import tornado.options
import tornado.httpserver
from app.classes.models.server_permissions import Enum_Permissions_Server from app.classes.models.server_permissions import Enum_Permissions_Server
from app.classes.shared.helpers import helper from app.classes.shared.console import Console
from app.classes.shared.console import console from app.classes.shared.helpers import Helpers
from app.classes.shared.main_controller import Controller from app.classes.shared.main_controller import Controller
from app.classes.web.websocket_helper import websocket_helper
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
from app.classes.shared.translation import translation
try:
import tornado.web
import tornado.options
import tornado.httpserver
except ModuleNotFoundError as ex:
helper.auto_installer_fix(ex)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -26,8 +19,13 @@ class UploadHandler(BaseHandler):
# noinspection PyAttributeOutsideInit # noinspection PyAttributeOutsideInit
def initialize( def initialize(
self, controller: Controller = None, tasks_manager=None, translator=None self,
helper: Helpers = None,
controller: Controller = None,
tasks_manager=None,
translator=None,
): ):
self.helper = helper
self.controller = controller self.controller = controller
self.tasks_manager = tasks_manager self.tasks_manager = tasks_manager
self.translator = translator self.translator = translator
@ -40,7 +38,7 @@ class UploadHandler(BaseHandler):
if api_key is not None: if api_key is not None:
superuser = superuser and api_key.superuser superuser = superuser and api_key.superuser
user_id = exec_user["user_id"] user_id = exec_user["user_id"]
stream_size_value = helper.get_setting("stream_size_GB") stream_size_value = self.helper.get_setting("stream_size_GB")
MAX_STREAMED_SIZE = (1024 * 1024 * 1024) * stream_size_value MAX_STREAMED_SIZE = (1024 * 1024 * 1024) * stream_size_value
@ -50,11 +48,11 @@ class UploadHandler(BaseHandler):
f"User with ID {user_id} attempted to upload a file that" f"User with ID {user_id} attempted to upload a file that"
f" exceeded the max body size." f" exceeded the max body size."
) )
websocket_helper.broadcast_user( self.helper.websocket_helper.broadcast_user(
user_id, user_id,
"send_start_error", "send_start_error",
{ {
"error": translation.translate( "error": self.helper.translation.translate(
"error", "error",
"fileTooLarge", "fileTooLarge",
self.controller.users.get_user_lang_by_id(user_id), self.controller.users.get_user_lang_by_id(user_id),
@ -85,12 +83,12 @@ class UploadHandler(BaseHandler):
if user_id is None: if user_id is None:
logger.warning("User ID not found in upload handler call") logger.warning("User ID not found in upload handler call")
console.warning("User ID not found in upload handler call") Console.warning("User ID not found in upload handler call")
self.do_upload = False self.do_upload = False
if server_id is None: if server_id is None:
logger.warning("Server ID not found in upload handler call") logger.warning("Server ID not found in upload handler call")
console.warning("Server ID not found in upload handler call") Console.warning("Server ID not found in upload handler call")
self.do_upload = False self.do_upload = False
if Enum_Permissions_Server.Files not in exec_user_server_permissions: if Enum_Permissions_Server.Files not in exec_user_server_permissions:
@ -98,7 +96,7 @@ class UploadHandler(BaseHandler):
f"User {user_id} tried to upload a file to " f"User {user_id} tried to upload a file to "
f"{server_id} without permissions!" f"{server_id} without permissions!"
) )
console.warning( Console.warning(
f"User {user_id} tried to upload a file to " f"User {user_id} tried to upload a file to "
f"{server_id} without permissions!" f"{server_id} without permissions!"
) )
@ -108,8 +106,8 @@ class UploadHandler(BaseHandler):
filename = self.request.headers.get("X-FileName", None) filename = self.request.headers.get("X-FileName", None)
full_path = os.path.join(path, filename) full_path = os.path.join(path, filename)
if not helper.in_path( if not Helpers.in_path(
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
full_path, full_path,
@ -117,7 +115,7 @@ class UploadHandler(BaseHandler):
print( print(
user_id, user_id,
server_id, server_id,
helper.get_os_understandable_path( Helpers.get_os_understandable_path(
self.controller.servers.get_server_data_by_id(server_id)["path"] self.controller.servers.get_server_data_by_id(server_id)["path"]
), ),
full_path, full_path,
@ -126,7 +124,7 @@ class UploadHandler(BaseHandler):
f"User {user_id} tried to upload a file to {server_id} " f"User {user_id} tried to upload a file to {server_id} "
f"but the path is not inside of the server!" f"but the path is not inside of the server!"
) )
console.warning( Console.warning(
f"User {user_id} tried to upload a file to {server_id} " f"User {user_id} tried to upload a file to {server_id} "
f"but the path is not inside of the server!" f"but the path is not inside of the server!"
) )
@ -148,13 +146,13 @@ class UploadHandler(BaseHandler):
if self.do_upload: if self.do_upload:
time.sleep(5) time.sleep(5)
if files_left == 0: if files_left == 0:
websocket_helper.broadcast("close_upload_box", "success") self.helper.websocket_helper.broadcast("close_upload_box", "success")
self.finish("success") # Nope, I'm sending "success" self.finish("success") # Nope, I'm sending "success"
self.f.close() self.f.close()
else: else:
time.sleep(5) time.sleep(5)
if files_left == 0: if files_left == 0:
websocket_helper.broadcast("close_upload_box", "error") self.helper.websocket_helper.broadcast("close_upload_box", "error")
self.finish("error") self.finish("error")
def data_received(self, chunk): def data_received(self, chunk):

View File

@ -2,16 +2,9 @@ import json
import logging import logging
import asyncio import asyncio
from urllib.parse import parse_qsl from urllib.parse import parse_qsl
import tornado.websocket
from app.classes.shared.authentication import authentication from app.classes.shared.helpers import Helpers
from app.classes.shared.helpers import helper
from app.classes.web.websocket_helper import websocket_helper
try:
import tornado.websocket
except ModuleNotFoundError as e:
helper.auto_installer_fix(e)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -24,7 +17,10 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
translator = None translator = None
io_loop = None io_loop = None
def initialize(self, controller=None, tasks_manager=None, translator=None): def initialize(
self, helper=None, controller=None, tasks_manager=None, translator=None
):
self.helper = helper
self.controller = controller self.controller = controller
self.tasks_manager = tasks_manager self.tasks_manager = tasks_manager
self.translator = translator self.translator = translator
@ -39,11 +35,11 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
return remote_ip return remote_ip
def get_user_id(self): def get_user_id(self):
_, _, user = authentication.check(self.get_cookie("token")) _, _, user = self.controller.authentication.check(self.get_cookie("token"))
return user["user_id"] return user["user_id"]
def check_auth(self): def check_auth(self):
return authentication.check_bool(self.get_cookie("token")) return self.controller.authentication.check_bool(self.get_cookie("token"))
# pylint: disable=arguments-differ # pylint: disable=arguments-differ
def open(self): def open(self):
@ -51,7 +47,7 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
if self.check_auth(): if self.check_auth():
self.handle() self.handle()
else: else:
websocket_helper.send_message( self.helper.websocket_helper.send_message(
self, "notification", "Not authenticated for WebSocket connection" self, "notification", "Not authenticated for WebSocket connection"
) )
self.close() self.close()
@ -62,7 +58,7 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
"Someone tried to connect via WebSocket without proper authentication", "Someone tried to connect via WebSocket without proper authentication",
self.get_remote_ip(), self.get_remote_ip(),
) )
websocket_helper.broadcast( self.helper.websocket_helper.broadcast(
"notification", "notification",
"Someone tried to connect via WebSocket without proper authentication", "Someone tried to connect via WebSocket without proper authentication",
) )
@ -74,10 +70,10 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
self.page = self.get_query_argument("page") self.page = self.get_query_argument("page")
self.page_query_params = dict( self.page_query_params = dict(
parse_qsl( parse_qsl(
helper.remove_prefix(self.get_query_argument("page_query_params"), "?") Helpers.remove_prefix(self.get_query_argument("page_query_params"), "?")
) )
) )
websocket_helper.add_client(self) self.helper.websocket_helper.add_client(self)
logger.debug("Opened WebSocket connection") logger.debug("Opened WebSocket connection")
# pylint: disable=arguments-renamed # pylint: disable=arguments-renamed
@ -89,7 +85,7 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
logger.debug(f"Event Type: {message['event']}, Data: {message['data']}") logger.debug(f"Event Type: {message['event']}, Data: {message['data']}")
def on_close(self): def on_close(self):
websocket_helper.remove_client(self) self.helper.websocket_helper.remove_client(self)
logger.debug("Closed WebSocket connection") logger.debug("Closed WebSocket connection")
async def write_message_int(self, message): async def write_message_int(self, message):

View File

@ -1,13 +1,14 @@
import json import json
import logging import logging
from app.classes.shared.console import console from app.classes.shared.console import Console
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class WebSocketHelper: class WebSocketHelper:
def __init__(self): def __init__(self, helper):
self.helper = helper
self.clients = set() self.clients = set()
def add_client(self, client): def add_client(self, client):
@ -101,10 +102,7 @@ class WebSocketHelper:
) )
def disconnect_all(self): def disconnect_all(self):
console.info("Disconnecting WebSocket clients") Console.info("Disconnecting WebSocket clients")
for client in self.clients: for client in self.clients:
client.close() client.close()
console.info("Disconnected WebSocket clients") Console.info("Disconnected WebSocket clients")
websocket_helper = WebSocketHelper()

View File

@ -588,11 +588,15 @@
$(".clone_button").click(function () { $(".clone_button").click(function () {
server_id = $(this).attr("data-id"); server_id = $(this).attr("data-id");
send_command(server_id, 'clone_server'); send_command(server_id, 'clone_server');
bootbox.alert({ bootbox.dialog({
backdrop: true, backdrop: true,
title: '{% raw translate("dashboard", "sendingCommand", data["lang"]) %}', title: '{% raw translate("dashboard", "sendingCommand", data["lang"]) %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("dashboard", "bePatientClone", data["lang"]) %} </div>' message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("dashboard", "bePatientClone", data["lang"]) %} </div>',
closeButton: false,
}); });
setTimeout(function () {
location.reload();
}, 5000)
}); });
}); });

View File

@ -14,7 +14,8 @@
<div class="col-12"> <div class="col-12">
<div class="page-header"> <div class="page-header">
<h4 class="page-title"> <h4 class="page-title">
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{ data['server_stats']['server_id']['server_name'] }} {{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{
data['server_stats']['server_id']['server_name'] }}
<br /> <br />
<small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small> <small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small>
</h4> </h4>
@ -45,7 +46,10 @@
{% if data['backing_up'] %} {% if data['backing_up'] %}
<div class="progress" style="height: 15px;"> <div class="progress" style="height: 15px;">
<div class="progress-bar progress-bar-striped progress-bar-animated" id="backup_progress_bar" role="progressbar" style="width:{{data['backup_stats']['percent']}}%;" aria-valuenow="{{data['backup_stats']['percent']}}" aria-valuemin="0" aria-valuemax="100">{{ data['backup_stats']['percent'] }}%</div> <div class="progress-bar progress-bar-striped progress-bar-animated" id="backup_progress_bar"
role="progressbar" style="width:{{data['backup_stats']['percent']}}%;"
aria-valuenow="{{data['backup_stats']['percent']}}" aria-valuemin="0" aria-valuemax="100">{{
data['backup_stats']['percent'] }}%</div>
</div> </div>
<p>Backing up <span id="total_files">{{data['backup_stats']['total_files']}}</span> Files</p> <p>Backing up <span id="total_files">{{data['backup_stats']['total_files']}}</span> Files</p>
{% end %} {% end %}
@ -53,47 +57,63 @@
<br> <br>
{% if not data['backing_up'] %} {% if not data['backing_up'] %}
<div id="backup_button" class="form-group"> <div id="backup_button" class="form-group">
<button class="btn btn-primary" id="backup_now_button">{{ translate('serverBackups', 'backupNow', data['lang']) }}</button> <button class="btn btn-primary" id="backup_now_button">{{ translate('serverBackups', 'backupNow',
data['lang']) }}</button>
</div> </div>
{% end %} {% end %}
<div class="form-group"> <div class="form-group">
{% if data['super_user'] %} {% if data['super_user'] %}
<label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang']) }}</small> </label> <label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small
<input type="text" class="form-control" name="backup_path" id="backup_path" value="{{ data['server_stats']['server_id']['backup_path'] }}" placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}" > class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="backup_path" id="backup_path"
value="{{ data['server_stats']['server_id']['backup_path'] }}"
placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}">
{% end %} {% end %}
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang']) }}</small> </label> <label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small
<input type="text" class="form-control" name="max_backups" id="max_backups" value="{{ data['backup_config']['max_backups'] }}" placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}" > class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="max_backups" id="max_backups"
value="{{ data['backup_config']['max_backups'] }}"
placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="compress" class="form-check-label ml-4 mb-4"></label> <label for="compress" class="form-check-label ml-4 mb-4"></label>
{% if data['backup_config']['compress'] %} {% if data['backup_config']['compress'] %}
<input type="checkbox" class="form-check-input" id="compress" name="compress" <input type="checkbox" class="form-check-input" id="compress" name="compress" checked=""
checked="" value="True">{{ translate('serverBackups', 'compress', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="compress" name="compress"
value="True">{{ translate('serverBackups', 'compress', data['lang']) }} value="True">{{ translate('serverBackups', 'compress', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="compress" name="compress" value="True">{{
translate('serverBackups', 'compress', data['lang']) }}
{% end %} {% end %}
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{ translate('serverBackups', 'excludedChoose', data['lang']) }}</small></label> <label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{
translate('serverBackups', 'excludedChoose', data['lang']) }}</small></label>
<br> <br>
<button class="btn btn-primary mr-2" id="root_files_button" data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{ translate('serverBackups', 'clickExclude', data['lang']) }}</button> <button class="btn btn-primary mr-2" id="root_files_button"
data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{
translate('serverBackups', 'clickExclude', data['lang']) }}</button>
</div> </div>
<input type="number" class="form-control" name="changed" id="changed" value="0" style="visibility: hidden;"></input> <input type="number" class="form-control" name="changed" id="changed" value="0"
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select" aria-hidden="true"> style="visibility: hidden;"></input>
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select"
aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">{{ translate('serverBackups', 'excludedChoose', data['lang']) }}</h5> <h5 class="modal-title" id="exampleModalLongTitle">{{ translate('serverBackups',
'excludedChoose', data['lang']) }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="tree-ctx-item" id="main-tree-div" data-path="" style="overflow: scroll; max-height:75%;"> <div class="tree-ctx-item" id="main-tree-div" data-path=""
style="overflow: scroll; max-height:75%;">
<input type="checkbox" id="main-tree-input" name="root_path" value="" disabled> <input type="checkbox" id="main-tree-input" name="root_path" value="" disabled>
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path=""> <span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
<i class="far fa-folder"></i> <i class="far fa-folder"></i>
@ -104,15 +124,19 @@
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" id="modal-cancel" class="btn btn-secondary" data-dismiss="modal">{{ translate('serverBackups', 'cancel', data['lang']) }}</button> <button type="button" id="modal-cancel" class="btn btn-secondary" data-dismiss="modal">{{
<button type="button" id="modal-okay" data-dismiss="modal" class="btn btn-primary">{{ translate('serverWizard', 'save', data['lang']) }}</button> translate('serverBackups', 'cancel', data['lang']) }}</button>
<button type="button" id="modal-okay" data-dismiss="modal" class="btn btn-primary">{{
translate('serverWizard', 'save', data['lang']) }}</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<button type="submit" class="btn btn-success mr-2">{{ translate('serverBackups', 'save', data['lang']) }}</button> <button type="submit" class="btn btn-success mr-2">{{ translate('serverBackups', 'save', data['lang'])
<button type="reset" class="btn btn-light">{{ translate('serverBackups', 'cancel', data['lang']) }}</button> }}</button>
<button type="reset" class="btn btn-light">{{ translate('serverBackups', 'cancel', data['lang'])
}}</button>
</form> </form>
</div> </div>
@ -132,13 +156,15 @@
{% for backup in data['backup_list'] %} {% for backup in data['backup_list'] %}
<tr> <tr>
<td> <td>
<a href="/panel/download_backup?file={{ backup['path'] }}&id={{ data['server_stats']['server_id']['server_id'] }}" class="btn btn-primary"> <a href="/panel/download_backup?file={{ backup['path'] }}&id={{ data['server_stats']['server_id']['server_id'] }}"
class="btn btn-primary">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
{{ translate('serverBackups', 'download', data['lang']) }} {{ translate('serverBackups', 'download', data['lang']) }}
</a> </a>
<br> <br>
<br> <br>
<button data-file="{{ backup['path'] }}" data-backup_path="{{ data['backup_path'] }}" class="btn btn-danger del_button"> <button data-file="{{ backup['path'] }}" data-backup_path="{{ data['backup_path'] }}"
class="btn btn-danger del_button">
<i class="fas fa-trash" aria-hidden="true"></i> <i class="fas fa-trash" aria-hidden="true"></i>
{{ translate('serverBackups', 'delete', data['lang']) }} {{ translate('serverBackups', 'delete', data['lang']) }}
</button> </button>
@ -162,7 +188,8 @@
<br> <br>
<br> <br>
<div class="card-header header-sm d-flex justify-content-between align-items-center"> <div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-server"></i> {{ translate('serverBackups', 'excludedBackups', data['lang']) }} <small class="text-muted ml-1"></small> </h4> <h4 class="card-title"><i class="fas fa-server"></i> {{ translate('serverBackups', 'excludedBackups',
data['lang']) }} <small class="text-muted ml-1"></small> </h4>
</div> </div>
<br> <br>
<ul> <ul>
@ -195,13 +222,15 @@
.tree-item, .tree-item,
.files-tree-title { .files-tree-title {
cursor: pointer; cursor: pointer;
user-select: none; /* Prevent text selection */ user-select: none;
/* Prevent text selection */
} }
/* Create the caret/arrow with a unicode, and style it */ /* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder { .tree-caret .fa-folder {
display: inline-block; display: inline-block;
} }
.tree-caret .fa-folder-open { .tree-caret .fa-folder-open {
display: none; display: none;
} }
@ -210,6 +239,7 @@
.tree-caret-down .fa-folder { .tree-caret-down .fa-folder {
display: none; display: none;
} }
.tree-caret-down .fa-folder-open { .tree-caret-down .fa-folder-open {
display: inline-block; display: inline-block;
} }
@ -226,7 +256,7 @@
{% block js %} {% block js %}
<script> <script>
const server_id = new URLSearchParams(document.location.search).get('id') const server_id = new URLSearchParams(document.location.search).get('id')
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security //used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
@ -244,34 +274,34 @@ const server_id = new URLSearchParams(document.location.search).get('id')
}); });
$.ajax({ $.ajax({
type: "POST", type: "POST",
headers: {'X-XSRFToken': token}, headers: { 'X-XSRFToken': token },
url: '/ajax/backup_now?id='+server_id, url: '/ajax/backup_now?id=' + server_id,
success: function(data) { success: function (data) {
}, },
}); });
} }
function del_backup(filename, id){ function del_backup(filename, id) {
var token = getCookie("_xsrf") var token = getCookie("_xsrf")
data_to_send = { file_name :filename} data_to_send = { file_name: filename }
console.log('Sending Command to delete backup: ' + filename) console.log('Sending Command to delete backup: ' + filename)
$.ajax({ $.ajax({
type: "DELETE", type: "DELETE",
headers: {'X-XSRFToken': token}, headers: { 'X-XSRFToken': token },
url: '/ajax/del_backup?server_id='+id, url: '/ajax/del_backup?server_id=' + id,
data: { data: {
file_path: filename, file_path: filename,
id: id id: id
}, },
success: function(data) { success: function (data) {
location.reload(); location.reload();
}, },
}); });
} }
function restore_backup(filename, id){ function restore_backup(filename, id) {
var token = getCookie("_xsrf") var token = getCookie("_xsrf")
var dialog = bootbox.dialog({ var dialog = bootbox.dialog({
message: '<i class="fa fa-spin fa-spinner"></i> {{ translate('serverBackups', 'restoring', data['lang']) }}', message: '<i class="fa fa-spin fa-spinner"></i> {{ translate('serverBackups', 'restoring', data['lang']) }}',
@ -281,23 +311,41 @@ const server_id = new URLSearchParams(document.location.search).get('id')
console.log('Sending Command to restore backup: ' + filename) console.log('Sending Command to restore backup: ' + filename)
$.ajax({ $.ajax({
type: "POST", type: "POST",
headers: {'X-XSRFToken': token}, headers: { 'X-XSRFToken': token },
url: '/ajax/restore_backup?server_id='+id, url: '/ajax/restore_backup?server_id=' + id,
data: { data: {
zip_file: filename, zip_file: filename,
id: id id: id
}, },
success: function(data) { success: function (data) {
setTimeout(function(){ setTimeout(function () {
location.href=('/panel/dashboard'); location.href = ('/panel/dashboard');
}, 15000); }, 15000);
}, },
}); });
} }
$( document ).ready(function() { $(document).ready(function () {
console.log( "ready!" ); try {
if ($('#backup_path').val() == '') {
console.log('true')
try {
document.getElementById('backup_now_button').disabled = true;
} catch {
}
} else {
document.getElementById('backup_now_button').disabled = false;
}
} catch {
try {
document.getElementById('backup_now_button').disabled = false;
} catch {
}
}
console.log("ready!");
$("#backup_config_box").hide(); $("#backup_config_box").hide();
$("#backup_save_note").hide(); $("#backup_save_note").hide();
@ -309,8 +357,8 @@ const server_id = new URLSearchParams(document.location.search).get('id')
}); });
$('#backup_table').DataTable({ $('#backup_table').DataTable({
"order": [[ 1, "desc" ]], "order": [[1, "desc"]],
"paging":true, "paging": true,
"lengthChange": false, "lengthChange": false,
"searching": true, "searching": true,
"ordering": true, "ordering": true,
@ -319,7 +367,7 @@ const server_id = new URLSearchParams(document.location.search).get('id')
"responsive": true, "responsive": true,
}); });
$( ".del_button" ).click(function() { $(".del_button").click(function () {
var file_to_del = $(this).data("file"); var file_to_del = $(this).data("file");
var backup_path = $(this).data('backup_path'); var backup_path = $(this).data('backup_path');
@ -346,12 +394,12 @@ const server_id = new URLSearchParams(document.location.search).get('id')
}); });
}); });
$( ".restore_button" ).click(function() { $(".restore_button").click(function () {
var file_to_restore = $(this).data("file"); var file_to_restore = $(this).data("file");
bootbox.confirm({ bootbox.confirm({
title: "{{ translate('serverBackups', 'restore', data['lang']) }} "+file_to_restore, title: "{{ translate('serverBackups', 'restore', data['lang']) }} " + file_to_restore,
message: "{{ translate('serverBackups', 'confirmRestore', data['lang']) }}", message: "{{ translate('serverBackups', 'confirmRestore', data['lang']) }}",
buttons: { buttons: {
cancel: { cancel: {
@ -370,23 +418,23 @@ const server_id = new URLSearchParams(document.location.search).get('id')
} }
}); });
}); });
$( "#backup_now_button" ).click(function() { $("#backup_now_button").click(function () {
backup_started(); backup_started();
}); });
}); });
document.getElementById("modal-cancel").addEventListener("click", function(){ document.getElementById("modal-cancel").addEventListener("click", function () {
document.getElementById("root_files_button").classList.remove('clicked'); document.getElementById("root_files_button").classList.remove('clicked');
document.getElementById("main-tree-div").innerHTML = '<input type="checkbox" id="main-tree-input" name="root_path" value="" disabled><span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path=""><i class="far fa-folder"></i><i class="far fa-folder-open"></i>{{ translate("serverFiles", "files", data["lang"]) }}</span></input>' document.getElementById("main-tree-div").innerHTML = '<input type="checkbox" id="main-tree-input" name="root_path" value="" disabled><span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path=""><i class="far fa-folder"></i><i class="far fa-folder-open"></i>{{ translate("serverFiles", "files", data["lang"]) }}</span></input>'
}) })
document.getElementById("root_files_button").addEventListener("click", function(){ document.getElementById("root_files_button").addEventListener("click", function () {
if($("#root_files_button").data('server_path') != ""){ if ($("#root_files_button").data('server_path') != "") {
if(document.getElementById('root_files_button').classList.contains('clicked')){ if (document.getElementById('root_files_button').classList.contains('clicked')) {
show_file_tree(); show_file_tree();
return; return;
}else{ } else {
document.getElementById('root_files_button').classList.add('clicked'); document.getElementById('root_files_button').classList.add('clicked');
document.getElementById("changed").value = 1; document.getElementById("changed").value = 1;
} }
@ -400,16 +448,16 @@ document.getElementById("modal-cancel").addEventListener("click", function(){
$.ajax({ $.ajax({
type: "POST", type: "POST",
headers: {'X-XSRFToken': token}, headers: { 'X-XSRFToken': token },
url: '/ajax/backup_select?id='+server_id+'&path='+path, url: '/ajax/backup_select?id=' + server_id + '&path=' + path,
}); });
}else{ } else {
bootbox.alert("You must input a path before selecting this button"); bootbox.alert("You must input a path before selecting this button");
} }
}); });
if (webSocket) { if (webSocket) {
webSocket.on('send_temp_path', function (data) { webSocket.on('send_temp_path', function (data) {
setTimeout(function(){ setTimeout(function () {
var x = document.querySelector('.bootbox'); var x = document.querySelector('.bootbox');
if (x) { if (x) {
x.remove() x.remove()
@ -427,14 +475,14 @@ document.getElementById("modal-cancel").addEventListener("click", function(){
} }
if (webSocket) { if (webSocket) {
webSocket.on('backup_status', function (backup) { webSocket.on('backup_status', function (backup) {
if(backup.percent >= 100){ if (backup.percent >= 100) {
document.getElementById('backup_progress_bar').innerHTML = '100%'; document.getElementById('backup_progress_bar').innerHTML = '100%';
document.getElementById('backup_progress_bar').style.width = '100%'; document.getElementById('backup_progress_bar').style.width = '100%';
setTimeout(function(){ setTimeout(function () {
window.location.reload(1); window.location.reload(1);
}, 5000); }, 5000);
}else{ } else {
document.getElementById('backup_progress_bar').innerHTML = backup.percent +'%'; document.getElementById('backup_progress_bar').innerHTML = backup.percent + '%';
document.getElementById('backup_progress_bar').style.width = backup.percent + '%'; document.getElementById('backup_progress_bar').style.width = backup.percent + '%';
document.getElementById('total_files').innerHTML = backup.total_files; document.getElementById('total_files').innerHTML = backup.total_files;
} }
@ -451,9 +499,9 @@ document.getElementById("modal-cancel").addEventListener("click", function(){
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: '/ajax/get_backup_tree?id='+server_id+'&path='+path, url: '/ajax/get_backup_tree?id=' + server_id + '&path=' + path,
dataType: 'text', dataType: 'text',
success: function(data){ success: function (data) {
console.log("got response:"); console.log("got response:");
console.log(data); console.log(data);
@ -461,10 +509,10 @@ document.getElementById("modal-cancel").addEventListener("click", function(){
serverDir = dataArr.shift(); // Remove & return first element (server directory) serverDir = dataArr.shift(); // Remove & return first element (server directory)
text = dataArr.join('\n'); text = dataArr.join('\n');
try{ try {
document.getElementById('main-tree-div').innerHTML += text; document.getElementById('main-tree-div').innerHTML += text;
document.getElementById('main-tree').parentElement.classList.add("clicked"); document.getElementById('main-tree').parentElement.classList.add("clicked");
}catch{ } catch {
document.getElementById('files-tree').innerHTML = text; document.getElementById('files-tree').innerHTML = text;
} }
@ -478,56 +526,56 @@ document.getElementById("modal-cancel").addEventListener("click", function(){
function getToggleMain(event) { function getToggleMain(event) {
path = event.target.parentElement.getAttribute('data-path'); path = event.target.parentElement.getAttribute('data-path');
document.getElementById("files-tree").classList.toggle("d-block"); document.getElementById("files-tree").classList.toggle("d-block");
document.getElementById(path+"span").classList.toggle("tree-caret-down"); document.getElementById(path + "span").classList.toggle("tree-caret-down");
document.getElementById(path+"span").classList.toggle("tree-caret"); document.getElementById(path + "span").classList.toggle("tree-caret");
} }
function getDirView(event) { function getDirView(event) {
path = event.target.parentElement.getAttribute('data-path'); path = event.target.parentElement.getAttribute('data-path');
if (document.getElementById(path).classList.contains('clicked')){ if (document.getElementById(path).classList.contains('clicked')) {
var toggler = document.getElementById(path+"span"); var toggler = document.getElementById(path + "span");
if (toggler.classList.contains('files-tree-title')){ if (toggler.classList.contains('files-tree-title')) {
document.getElementById(path+"ul").classList.toggle("d-block"); document.getElementById(path + "ul").classList.toggle("d-block");
document.getElementById(path+"span").classList.toggle("tree-caret-down"); document.getElementById(path + "span").classList.toggle("tree-caret-down");
} }
return; return;
}else{ } else {
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: '/ajax/get_backup_dir?id='+server_id+'&path='+path, url: '/ajax/get_backup_dir?id=' + server_id + '&path=' + path,
dataType: 'text', dataType: 'text',
success: function(data){ success: function (data) {
console.log("got response:"); console.log("got response:");
dataArr = data.split('\n'); dataArr = data.split('\n');
serverDir = dataArr.shift(); // Remove & return first element (server directory) serverDir = dataArr.shift(); // Remove & return first element (server directory)
text = dataArr.join('\n'); text = dataArr.join('\n');
try{ try {
document.getElementById(path+"span").classList.add('tree-caret-down'); document.getElementById(path + "span").classList.add('tree-caret-down');
document.getElementById(path).innerHTML += text; document.getElementById(path).innerHTML += text;
document.getElementById(path).classList.add("clicked"); document.getElementById(path).classList.add("clicked");
}catch{ } catch {
console.log("Bad") console.log("Bad")
} }
var toggler = document.getElementById(path); var toggler = document.getElementById(path);
if (toggler.classList.contains('files-tree-title')){ if (toggler.classList.contains('files-tree-title')) {
document.getElementById(path+"span").addEventListener("click", function caretListener() { document.getElementById(path + "span").addEventListener("click", function caretListener() {
document.getElementById(path+"ul").classList.toggle("d-block"); document.getElementById(path + "ul").classList.toggle("d-block");
document.getElementById(path+"span").classList.toggle("tree-caret-down"); document.getElementById(path + "span").classList.toggle("tree-caret-down");
}); });
} }
}, },
}); });
} }
} }
function show_file_tree(){ function show_file_tree() {
$("#dir_select").modal(); $("#dir_select").modal();
} }

69
main.py
View File

@ -5,24 +5,31 @@ import time
import argparse import argparse
import logging.config import logging.config
import signal import signal
from app.classes.shared.console import console import peewee
from app.classes.shared.helpers import helper from app.classes.models.users import helper_users
from app.classes.shared.console import Console
from app.classes.shared.helpers import Helpers
console = Console()
helper = Helpers()
if helper.checkRoot(): if helper.checkRoot():
console.critical( Console.critical(
"Root detected. Root/Admin access denied. " "Root detected. Root/Admin access denied. "
"Run Crafty again with non-elevated permissions." "Run Crafty again with non-elevated permissions."
) )
time.sleep(5) time.sleep(5)
console.critical("Crafty shutting down. Root/Admin access denied.") Console.critical("Crafty shutting down. Root/Admin access denied.")
sys.exit(0) sys.exit(0)
# pylint: disable=wrong-import-position # pylint: disable=wrong-import-position
from app.classes.shared.main_models import installer, database try:
from app.classes.shared.tasks import TasksManager from app.classes.models.base_model import database_proxy
from app.classes.shared.main_controller import Controller from app.classes.shared.main_models import db_builder
from app.classes.shared.migration import MigrationManager from app.classes.shared.tasks import TasksManager
from app.classes.shared.main_controller import Controller
from app.classes.shared.command import MainPrompt from app.classes.shared.migration import MigrationManager
from app.classes.shared.command import MainPrompt
except ModuleNotFoundError as err:
helper.auto_installer_fix(err)
def do_intro(): def do_intro():
@ -39,7 +46,7 @@ def do_intro():
{'/' * 75} {'/' * 75}
""" """
console.magenta(intro) Console.magenta(intro)
def setup_logging(debug=True): def setup_logging(debug=True):
@ -57,7 +64,7 @@ def setup_logging(debug=True):
else: else:
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logging.warning(f"Unable to read logging config from {logging_config_file}") logging.warning(f"Unable to read logging config from {logging_config_file}")
console.critical(f"Unable to read logging config from {logging_config_file}") Console.critical(f"Unable to read logging config from {logging_config_file}")
# Our Main Starter # Our Main Starter
@ -87,7 +94,9 @@ if __name__ == "__main__":
# setting up the logger object # setting up the logger object
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
console.cyan(f"Logging set to: {logger.level}") Console.cyan(f"Logging set to: {logger.level}")
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
# print our pretty start message # print our pretty start message
do_intro() do_intro()
@ -95,15 +104,23 @@ if __name__ == "__main__":
# our session file, helps prevent multiple controller agents on the same machine. # our session file, helps prevent multiple controller agents on the same machine.
helper.create_session_file(ignore=args.ignore) helper.create_session_file(ignore=args.ignore)
migration_manager = MigrationManager(database) # start the database
database = peewee.SqliteDatabase(
helper.db_path, pragmas={"journal_mode": "wal", "cache_size": -1024 * 10}
)
database_proxy.initialize(database)
migration_manager = MigrationManager(database, helper)
migration_manager.up() # Automatically runs migrations migration_manager.up() # Automatically runs migrations
# do our installer stuff # do our installer stuff
user_helper = helper_users(database, helper)
installer = db_builder(database, helper, user_helper)
fresh_install = installer.is_fresh_install() fresh_install = installer.is_fresh_install()
if fresh_install: if fresh_install:
console.debug("Fresh install detected") Console.debug("Fresh install detected")
console.warning( Console.warning(
f"We have detected a fresh install. Please be sure to forward " f"We have detected a fresh install. Please be sure to forward "
f"Crafty's port, {helper.get_setting('https_port')}, " f"Crafty's port, {helper.get_setting('https_port')}, "
f"through your router/firewall if you would like to be able " f"through your router/firewall if you would like to be able "
@ -111,11 +128,11 @@ if __name__ == "__main__":
) )
installer.default_settings() installer.default_settings()
else: else:
console.debug("Existing install detected") Console.debug("Existing install detected")
# now the tables are created, we can load the tasks_manger and server controller # now the tables are created, we can load the tasks_manger and server controller
controller = Controller() controller = Controller(database, helper)
tasks_manager = TasksManager(controller) tasks_manager = TasksManager(helper, controller)
tasks_manager.start_webserver() tasks_manager.start_webserver()
# slowing down reporting just for a 1/2 second so messages look cleaner # slowing down reporting just for a 1/2 second so messages look cleaner
@ -123,7 +140,7 @@ if __name__ == "__main__":
# init servers # init servers
logger.info("Initializing all servers defined") logger.info("Initializing all servers defined")
console.info("Initializing all servers defined") Console.info("Initializing all servers defined")
controller.init_all_servers() controller.init_all_servers()
servers = controller.list_defined_servers() servers = controller.list_defined_servers()
@ -139,10 +156,10 @@ if __name__ == "__main__":
tasks_manager.serverjar_cache_refresher() tasks_manager.serverjar_cache_refresher()
logger.info("Checking Internet. This may take a minute.") logger.info("Checking Internet. This may take a minute.")
console.info("Checking Internet. This may take a minute.") Console.info("Checking Internet. This may take a minute.")
if not helper.check_internet(): if not helper.check_internet():
console.warning( Console.warning(
"We have detected the machine running Crafty has no " "We have detected the machine running Crafty has no "
"connection to the internet. Client connections to " "connection to the internet. Client connections to "
"the server may be limited." "the server may be limited."
@ -151,7 +168,7 @@ if __name__ == "__main__":
if not controller.check_system_user(): if not controller.check_system_user():
controller.add_system_user() controller.add_system_user()
Crafty = MainPrompt(tasks_manager, migration_manager) Crafty = MainPrompt(helper, tasks_manager, migration_manager)
project_root = os.path.dirname(__file__) project_root = os.path.dirname(__file__)
controller.set_project_root(project_root) controller.set_project_root(project_root)
@ -163,7 +180,7 @@ if __name__ == "__main__":
logger.info( logger.info(
f"Recieved {signal.Signals(sig[0]).name} [{sig[0]}], stopping Crafty..." f"Recieved {signal.Signals(sig[0]).name} [{sig[0]}], stopping Crafty..."
) )
console.info( Console.info(
f"Recieved {signal.Signals(sig[0]).name} [{sig[0]}], stopping Crafty..." f"Recieved {signal.Signals(sig[0]).name} [{sig[0]}], stopping Crafty..."
) )
tasks_manager._main_graceful_exit() tasks_manager._main_graceful_exit()
@ -177,7 +194,7 @@ if __name__ == "__main__":
except KeyboardInterrupt: except KeyboardInterrupt:
print() # for newline print() # for newline
logger.info("Recieved SIGINT, stopping Crafty...") logger.info("Recieved SIGINT, stopping Crafty...")
console.info("Recieved SIGINT, stopping Crafty...") Console.info("Recieved SIGINT, stopping Crafty...")
tasks_manager._main_graceful_exit() tasks_manager._main_graceful_exit()
Crafty.universal_exit() Crafty.universal_exit()
else: else:
@ -189,7 +206,7 @@ if __name__ == "__main__":
time.sleep(1) time.sleep(1)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("Recieved SIGINT, stopping Crafty...") logger.info("Recieved SIGINT, stopping Crafty...")
console.info("Recieved SIGINT, stopping Crafty...") Console.info("Recieved SIGINT, stopping Crafty...")
break break
tasks_manager._main_graceful_exit() tasks_manager._main_graceful_exit()
Crafty.universal_exit() Crafty.universal_exit()

View File

@ -5,7 +5,7 @@ bleach==4.1
cached_property==1.5.2 cached_property==1.5.2
colorama==0.4 colorama==0.4
cron-validator==1.0.3 cron-validator==1.0.3
cryptography==3.4 cryptography==3.4.8
libgravatar==1.0.0 libgravatar==1.0.0
peewee==3.13 peewee==3.13
pexpect==4.8 pexpect==4.8