mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'lukas-noinjection' into 'dev'
Reduced the amount of injection in JavaScript. See merge request crafty-controller/crafty-commander!170
This commit is contained in:
commit
67c76f1d1c
@ -1,5 +1,4 @@
|
||||
import os
|
||||
import shutil
|
||||
import html
|
||||
import re
|
||||
import logging
|
||||
@ -85,53 +84,8 @@ class AjaxHandler(BaseHandler):
|
||||
page_data['notify_data'] = data
|
||||
self.render_page('ajax/notify.html', page_data)
|
||||
|
||||
elif page == "get_file":
|
||||
file_path = helper.get_os_understandable_path(self.get_argument('file_path', None))
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'get_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), file_path)\
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in get_file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in get_file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
|
||||
error = None
|
||||
|
||||
try:
|
||||
with open(file_path, encoding='utf-8') as file:
|
||||
file_contents = file.read()
|
||||
except UnicodeDecodeError:
|
||||
file_contents = ''
|
||||
error = 'UnicodeDecodeError'
|
||||
|
||||
self.write({
|
||||
'content': file_contents,
|
||||
'error': error
|
||||
})
|
||||
self.finish()
|
||||
|
||||
elif page == "get_tree":
|
||||
server_id = self.get_argument('id', None)
|
||||
path = self.get_argument('path', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'get_tree'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if helper.validate_traversal(self.controller.servers.get_server_data_by_id(server_id)['path'], path):
|
||||
self.write(helper.get_os_understandable_path(path) + '\n' +
|
||||
helper.generate_tree(path))
|
||||
self.finish()
|
||||
|
||||
elif page == "get_zip_tree":
|
||||
server_id = self.get_argument('id', None)
|
||||
path = self.get_argument('path', None)
|
||||
|
||||
self.write(helper.get_os_understandable_path(path) + '\n' +
|
||||
@ -139,26 +93,12 @@ class AjaxHandler(BaseHandler):
|
||||
self.finish()
|
||||
|
||||
elif page == "get_zip_dir":
|
||||
server_id = self.get_argument('id', None)
|
||||
path = self.get_argument('path', None)
|
||||
|
||||
self.write(helper.get_os_understandable_path(path) + '\n' +
|
||||
helper.generate_zip_dir(path))
|
||||
self.finish()
|
||||
|
||||
elif page == "get_dir":
|
||||
server_id = self.get_argument('id', None)
|
||||
path = self.get_argument('path', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'get_tree'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if helper.validate_traversal(self.controller.servers.get_server_data_by_id(server_id)['path'], path):
|
||||
self.write(helper.get_os_understandable_path(path) + '\n' +
|
||||
helper.generate_dir(path))
|
||||
self.finish()
|
||||
|
||||
@tornado.web.authenticated
|
||||
def post(self, page):
|
||||
@ -210,69 +150,10 @@ class AjaxHandler(BaseHandler):
|
||||
server_id,
|
||||
self.get_remote_ip())
|
||||
|
||||
elif page == "create_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_parent = helper.get_os_understandable_path(self.get_body_argument('file_parent', default=None, strip=True))
|
||||
file_name = self.get_body_argument('file_name', default=None, strip=True)
|
||||
file_path = os.path.join(file_parent, file_name)
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'create_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), file_path) \
|
||||
or helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in create_file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in create_file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
# Create the file by opening it
|
||||
with open(file_path, 'w', encoding='utf-8') as file_object:
|
||||
file_object.close()
|
||||
|
||||
elif page == "create_dir":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
dir_parent = helper.get_os_understandable_path(self.get_body_argument('dir_parent', default=None, strip=True))
|
||||
dir_name = self.get_body_argument('dir_name', default=None, strip=True)
|
||||
dir_path = os.path.join(dir_parent, dir_name)
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'create_dir'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), dir_path) \
|
||||
or helper.check_path_exists(os.path.abspath(dir_path)):
|
||||
logger.warning(f"Invalid path in create_dir ajax call ({dir_path})")
|
||||
console.warning(f"Invalid path in create_dir ajax call ({dir_path})")
|
||||
return
|
||||
# Create the directory
|
||||
os.mkdir(dir_path)
|
||||
|
||||
elif page == "send_order":
|
||||
self.controller.users.update_server_order(exec_user['user_id'], bleach.clean(self.get_argument('order')))
|
||||
return
|
||||
|
||||
elif page == "unzip_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
server_id = self.get_argument('id', None)
|
||||
path = helper.get_os_understandable_path(self.get_argument('path', None))
|
||||
helper.unzipFile(path)
|
||||
self.redirect(f"/panel/server_detail?id={server_id}&subpage=files")
|
||||
return
|
||||
|
||||
elif page == "kill":
|
||||
if not permissions['Commands'] in user_perms:
|
||||
if not superuser:
|
||||
@ -341,31 +222,6 @@ class AjaxHandler(BaseHandler):
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
if page == "del_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
console.warning(f"Delete {file_path} for server {server_id}")
|
||||
|
||||
if not self.check_server_id(server_id, 'del_file'):
|
||||
return
|
||||
else: server_id = bleach.clean(server_id)
|
||||
|
||||
server_info = self.controller.servers.get_server_data_by_id(server_id)
|
||||
if not (helper.in_path(helper.get_os_understandable_path(server_info['path']), file_path) \
|
||||
or helper.in_path(helper.get_os_understandable_path(server_info['backup_path']), file_path)) \
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in del_file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in del_file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
# Delete the file
|
||||
os.remove(file_path)
|
||||
|
||||
if page == "del_task":
|
||||
if not permissions['Schedule'] in user_perms:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Tasks")
|
||||
@ -383,7 +239,7 @@ class AjaxHandler(BaseHandler):
|
||||
|
||||
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_backup'):
|
||||
return
|
||||
else: server_id = bleach.clean(server_id)
|
||||
|
||||
@ -391,41 +247,14 @@ class AjaxHandler(BaseHandler):
|
||||
if not (helper.in_path(helper.get_os_understandable_path(server_info['path']), file_path) \
|
||||
or helper.in_path(helper.get_os_understandable_path(server_info['backup_path']), file_path)) \
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in del_file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in del_file 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})")
|
||||
return
|
||||
|
||||
# Delete the file
|
||||
if helper.validate_traversal(helper.get_os_understandable_path(server_info['backup_path']), file_path):
|
||||
os.remove(file_path)
|
||||
|
||||
elif page == "del_dir":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
dir_path = helper.get_os_understandable_path(self.get_body_argument('dir_path', default=None, strip=True))
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
console.warning(f"Delete {dir_path} for server {server_id}")
|
||||
|
||||
if not self.check_server_id(server_id, 'del_dir'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
server_info = self.controller.servers.get_server_data_by_id(server_id)
|
||||
if not helper.in_path(helper.get_os_understandable_path(server_info['path']), dir_path) \
|
||||
or not helper.check_path_exists(os.path.abspath(dir_path)):
|
||||
logger.warning(f"Invalid path in del_file ajax call ({dir_path})")
|
||||
console.warning(f"Invalid path in del_file ajax call ({dir_path})")
|
||||
return
|
||||
|
||||
# Delete the directory
|
||||
# os.rmdir(dir_path) # Would only remove empty directories
|
||||
if helper.validate_traversal(helper.get_os_understandable_path(server_info['path']), dir_path):
|
||||
shutil.rmtree(dir_path) # Removes also when there are contents
|
||||
|
||||
elif page == "delete_server":
|
||||
if not permissions['Config'] in user_perms:
|
||||
if not superuser:
|
||||
@ -464,86 +293,6 @@ class AjaxHandler(BaseHandler):
|
||||
self.tasks_manager.remove_all_server_tasks(server_id)
|
||||
self.controller.remove_server(server_id, True)
|
||||
|
||||
@tornado.web.authenticated
|
||||
def put(self, page):
|
||||
api_key, _, exec_user = self.current_user
|
||||
superuser = exec_user['superuser']
|
||||
if api_key is not None:
|
||||
superuser = superuser and api_key.superuser
|
||||
|
||||
server_id = self.get_argument('id', None)
|
||||
permissions = {
|
||||
'Commands': Enum_Permissions_Server.Commands,
|
||||
'Terminal': Enum_Permissions_Server.Terminal,
|
||||
'Logs': Enum_Permissions_Server.Logs,
|
||||
'Schedule': Enum_Permissions_Server.Schedule,
|
||||
'Backup': Enum_Permissions_Server.Backup,
|
||||
'Files': Enum_Permissions_Server.Files,
|
||||
'Config': Enum_Permissions_Server.Config,
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
if page == "save_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_contents = self.get_body_argument('file_contents', default=None, strip=True)
|
||||
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'save_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), file_path)\
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in save_file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in save_file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
# Open the file in write mode and store the content in file_object
|
||||
with open(file_path, 'w', encoding='utf-8') as file_object:
|
||||
file_object.write(file_contents)
|
||||
|
||||
elif page == "rename_item":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
item_path = helper.get_os_understandable_path(self.get_body_argument('item_path', default=None, strip=True))
|
||||
new_item_name = self.get_body_argument('new_item_name', default=None, strip=True)
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'rename_item'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if item_path is None or new_item_name is None:
|
||||
logger.warning("Invalid path(s) in rename_item ajax call")
|
||||
console.warning("Invalid path(s) in rename_item ajax call")
|
||||
return
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), item_path) \
|
||||
or not helper.check_path_exists(os.path.abspath(item_path)):
|
||||
logger.warning(f"Invalid old name path in rename_item ajax call ({server_id})")
|
||||
console.warning(f"Invalid old name path in rename_item ajax call ({server_id})")
|
||||
return
|
||||
|
||||
new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']),
|
||||
new_item_path) \
|
||||
or helper.check_path_exists(os.path.abspath(new_item_path)):
|
||||
logger.warning(f"Invalid new name path in rename_item ajax call ({server_id})")
|
||||
console.warning(f"Invalid new name path in rename_item ajax call ({server_id})")
|
||||
return
|
||||
|
||||
# RENAME
|
||||
os.rename(item_path, new_item_path)
|
||||
|
||||
def check_server_id(self, server_id, page_name):
|
||||
if server_id is None:
|
||||
logger.warning(f"Server ID not defined in {page_name} ajax call ({server_id})")
|
||||
|
410
app/classes/web/file_handler.py
Normal file
410
app/classes/web/file_handler.py
Normal file
@ -0,0 +1,410 @@
|
||||
import os
|
||||
import shutil
|
||||
import logging
|
||||
import tornado.web
|
||||
import tornado.escape
|
||||
import bleach
|
||||
|
||||
from app.classes.shared.console import console
|
||||
from app.classes.shared.helpers import helper
|
||||
|
||||
from app.classes.web.base_handler import BaseHandler
|
||||
from app.classes.models.server_permissions import Enum_Permissions_Server
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FileHandler(BaseHandler):
|
||||
|
||||
def render_page(self, template, page_data):
|
||||
self.render(
|
||||
template,
|
||||
data=page_data,
|
||||
translate=self.translator.translate,
|
||||
)
|
||||
|
||||
@tornado.web.authenticated
|
||||
def get(self, page):
|
||||
api_key, _, exec_user = self.current_user
|
||||
superuser = exec_user['superuser']
|
||||
if api_key is not None:
|
||||
superuser = superuser and api_key.superuser
|
||||
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
permissions = {
|
||||
'Commands': Enum_Permissions_Server.Commands,
|
||||
'Terminal': Enum_Permissions_Server.Terminal,
|
||||
'Logs': Enum_Permissions_Server.Logs,
|
||||
'Schedule': Enum_Permissions_Server.Schedule,
|
||||
'Backup': Enum_Permissions_Server.Backup,
|
||||
'Files': Enum_Permissions_Server.Files,
|
||||
'Config': Enum_Permissions_Server.Config,
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
|
||||
if page == "get_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_path = helper.get_os_understandable_path(self.get_argument('file_path', None))
|
||||
|
||||
if not self.check_server_id(server_id, 'get_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), file_path)\
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in get_file file file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in get_file file file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
|
||||
error = None
|
||||
|
||||
try:
|
||||
with open(file_path, encoding='utf-8') as file:
|
||||
file_contents = file.read()
|
||||
except UnicodeDecodeError:
|
||||
file_contents = ''
|
||||
error = 'UnicodeDecodeError'
|
||||
|
||||
self.write({
|
||||
'content': file_contents,
|
||||
'error': error
|
||||
})
|
||||
self.finish()
|
||||
|
||||
elif page == "get_tree":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
path = self.get_argument('path', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'get_tree'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if helper.validate_traversal(self.controller.servers.get_server_data_by_id(server_id)['path'], path):
|
||||
self.write(helper.get_os_understandable_path(path) + '\n' +
|
||||
helper.generate_tree(path))
|
||||
self.finish()
|
||||
|
||||
elif page == "get_dir":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
path = self.get_argument('path', None)
|
||||
|
||||
if not self.check_server_id(server_id, 'get_tree'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if helper.validate_traversal(self.controller.servers.get_server_data_by_id(server_id)['path'], path):
|
||||
self.write(helper.get_os_understandable_path(path) + '\n' +
|
||||
helper.generate_dir(path))
|
||||
self.finish()
|
||||
|
||||
@tornado.web.authenticated
|
||||
def post(self, page):
|
||||
api_key, _, exec_user = self.current_user
|
||||
superuser = exec_user['superuser']
|
||||
if api_key is not None:
|
||||
superuser = superuser and api_key.superuser
|
||||
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
permissions = {
|
||||
'Commands': Enum_Permissions_Server.Commands,
|
||||
'Terminal': Enum_Permissions_Server.Terminal,
|
||||
'Logs': Enum_Permissions_Server.Logs,
|
||||
'Schedule': Enum_Permissions_Server.Schedule,
|
||||
'Backup': Enum_Permissions_Server.Backup,
|
||||
'Files': Enum_Permissions_Server.Files,
|
||||
'Config': Enum_Permissions_Server.Config,
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
|
||||
if page == "create_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_parent = helper.get_os_understandable_path(self.get_body_argument('file_parent', default=None, strip=True))
|
||||
file_name = self.get_body_argument('file_name', default=None, strip=True)
|
||||
file_path = os.path.join(file_parent, file_name)
|
||||
|
||||
if not self.check_server_id(server_id, 'create_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), file_path) \
|
||||
or helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in create_file file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in create_file file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
# Create the file by opening it
|
||||
with open(file_path, 'w', encoding='utf-8') as file_object:
|
||||
file_object.close()
|
||||
|
||||
elif page == "create_dir":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
dir_parent = helper.get_os_understandable_path(self.get_body_argument('dir_parent', default=None, strip=True))
|
||||
dir_name = self.get_body_argument('dir_name', default=None, strip=True)
|
||||
dir_path = os.path.join(dir_parent, dir_name)
|
||||
|
||||
if not self.check_server_id(server_id, 'create_dir'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), dir_path) \
|
||||
or helper.check_path_exists(os.path.abspath(dir_path)):
|
||||
logger.warning(f"Invalid path in create_dir file ajax call ({dir_path})")
|
||||
console.warning(f"Invalid path in create_dir file ajax call ({dir_path})")
|
||||
return
|
||||
# Create the directory
|
||||
os.mkdir(dir_path)
|
||||
|
||||
elif page == "unzip_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
path = helper.get_os_understandable_path(self.get_argument('path', None))
|
||||
helper.unzipFile(path)
|
||||
self.redirect(f"/panel/server_detail?id={server_id}&subpage=files")
|
||||
return
|
||||
|
||||
|
||||
@tornado.web.authenticated
|
||||
def delete(self, page):
|
||||
api_key, _, exec_user = self.current_user
|
||||
superuser = exec_user['superuser']
|
||||
if api_key is not None:
|
||||
superuser = superuser and api_key.superuser
|
||||
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
permissions = {
|
||||
'Commands': Enum_Permissions_Server.Commands,
|
||||
'Terminal': Enum_Permissions_Server.Terminal,
|
||||
'Logs': Enum_Permissions_Server.Logs,
|
||||
'Schedule': Enum_Permissions_Server.Schedule,
|
||||
'Backup': Enum_Permissions_Server.Backup,
|
||||
'Files': Enum_Permissions_Server.Files,
|
||||
'Config': Enum_Permissions_Server.Config,
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
if page == "del_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
|
||||
|
||||
console.warning(f"Delete {file_path} for server {server_id}")
|
||||
|
||||
if not self.check_server_id(server_id, 'del_file'):
|
||||
return
|
||||
else: server_id = bleach.clean(server_id)
|
||||
|
||||
server_info = self.controller.servers.get_server_data_by_id(server_id)
|
||||
if not (helper.in_path(helper.get_os_understandable_path(server_info['path']), file_path) \
|
||||
or helper.in_path(helper.get_os_understandable_path(server_info['backup_path']), file_path)) \
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in del_file file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in del_file file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
# Delete the file
|
||||
os.remove(file_path)
|
||||
|
||||
elif page == "del_dir":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
dir_path = helper.get_os_understandable_path(self.get_body_argument('dir_path', default=None, strip=True))
|
||||
|
||||
console.warning(f"Delete {dir_path} for server {server_id}")
|
||||
|
||||
if not self.check_server_id(server_id, 'del_dir'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
server_info = self.controller.servers.get_server_data_by_id(server_id)
|
||||
if not helper.in_path(helper.get_os_understandable_path(server_info['path']), dir_path) \
|
||||
or not helper.check_path_exists(os.path.abspath(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})")
|
||||
return
|
||||
|
||||
# Delete the directory
|
||||
# os.rmdir(dir_path) # Would only remove empty directories
|
||||
if helper.validate_traversal(helper.get_os_understandable_path(server_info['path']), dir_path):
|
||||
shutil.rmtree(dir_path) # Removes also when there are contents
|
||||
|
||||
@tornado.web.authenticated
|
||||
def put(self, page):
|
||||
api_key, _, exec_user = self.current_user
|
||||
superuser = exec_user['superuser']
|
||||
if api_key is not None:
|
||||
superuser = superuser and api_key.superuser
|
||||
|
||||
server_id = self.get_argument('id', None)
|
||||
permissions = {
|
||||
'Commands': Enum_Permissions_Server.Commands,
|
||||
'Terminal': Enum_Permissions_Server.Terminal,
|
||||
'Logs': Enum_Permissions_Server.Logs,
|
||||
'Schedule': Enum_Permissions_Server.Schedule,
|
||||
'Backup': Enum_Permissions_Server.Backup,
|
||||
'Files': Enum_Permissions_Server.Files,
|
||||
'Config': Enum_Permissions_Server.Config,
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
if page == "save_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
file_contents = self.get_body_argument('file_contents', default=None, strip=True)
|
||||
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
|
||||
|
||||
if not self.check_server_id(server_id, 'save_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), file_path)\
|
||||
or not helper.check_file_exists(os.path.abspath(file_path)):
|
||||
logger.warning(f"Invalid path in save_file file ajax call ({file_path})")
|
||||
console.warning(f"Invalid path in save_file file ajax call ({file_path})")
|
||||
return
|
||||
|
||||
# Open the file in write mode and store the content in file_object
|
||||
with open(file_path, 'w', encoding='utf-8') as file_object:
|
||||
file_object.write(file_contents)
|
||||
|
||||
elif page == "rename_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
item_path = helper.get_os_understandable_path(self.get_body_argument('item_path', default=None, strip=True))
|
||||
new_item_name = self.get_body_argument('new_item_name', default=None, strip=True)
|
||||
|
||||
if not self.check_server_id(server_id, 'rename_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if item_path is None or new_item_name is None:
|
||||
logger.warning("Invalid path(s) in rename_file file ajax call")
|
||||
console.warning("Invalid path(s) in rename_file file ajax call")
|
||||
return
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), item_path) \
|
||||
or not helper.check_path_exists(os.path.abspath(item_path)):
|
||||
logger.warning(f"Invalid old name path in rename_file file ajax call ({server_id})")
|
||||
console.warning(f"Invalid old name path in rename_file file ajax call ({server_id})")
|
||||
return
|
||||
|
||||
new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']),
|
||||
new_item_path) \
|
||||
or helper.check_path_exists(os.path.abspath(new_item_path)):
|
||||
logger.warning(f"Invalid new name path in rename_file file ajax call ({server_id})")
|
||||
console.warning(f"Invalid new name path in rename_file file ajax call ({server_id})")
|
||||
return
|
||||
|
||||
# RENAME
|
||||
os.rename(item_path, new_item_path)
|
||||
|
||||
|
||||
@tornado.web.authenticated
|
||||
def patch(self, page):
|
||||
api_key, _, exec_user = self.current_user
|
||||
superuser = exec_user['superuser']
|
||||
if api_key is not None:
|
||||
superuser = superuser and api_key.superuser
|
||||
|
||||
server_id = self.get_argument('id', None)
|
||||
permissions = {
|
||||
'Commands': Enum_Permissions_Server.Commands,
|
||||
'Terminal': Enum_Permissions_Server.Terminal,
|
||||
'Logs': Enum_Permissions_Server.Logs,
|
||||
'Schedule': Enum_Permissions_Server.Schedule,
|
||||
'Backup': Enum_Permissions_Server.Backup,
|
||||
'Files': Enum_Permissions_Server.Files,
|
||||
'Config': Enum_Permissions_Server.Config,
|
||||
'Players': Enum_Permissions_Server.Players,
|
||||
}
|
||||
user_perms = self.controller.server_perms.get_user_id_permissions_list(exec_user['user_id'], server_id)
|
||||
if page == "rename_file":
|
||||
if not permissions['Files'] in user_perms:
|
||||
if not superuser:
|
||||
self.redirect("/panel/error?error=Unauthorized access to Files")
|
||||
return
|
||||
item_path = helper.get_os_understandable_path(self.get_body_argument('item_path', default=None, strip=True))
|
||||
new_item_name = self.get_body_argument('new_item_name', default=None, strip=True)
|
||||
|
||||
if not self.check_server_id(server_id, 'rename_file'):
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
if item_path is None or new_item_name is None:
|
||||
logger.warning("Invalid path(s) in rename_file file ajax call")
|
||||
console.warning("Invalid path(s) in rename_file file ajax call")
|
||||
return
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']), item_path) \
|
||||
or not helper.check_path_exists(os.path.abspath(item_path)):
|
||||
logger.warning(f"Invalid old name path in rename_file file ajax call ({server_id})")
|
||||
console.warning(f"Invalid old name path in rename_file file ajax call ({server_id})")
|
||||
return
|
||||
|
||||
new_item_path = os.path.join(os.path.split(item_path)[0], new_item_name)
|
||||
|
||||
if not helper.in_path(helper.get_os_understandable_path(self.controller.servers.get_server_data_by_id(server_id)['path']),
|
||||
new_item_path) \
|
||||
or helper.check_path_exists(os.path.abspath(new_item_path)):
|
||||
logger.warning(f"Invalid new name path in rename_file file ajax call ({server_id})")
|
||||
console.warning(f"Invalid new name path in rename_file file ajax call ({server_id})")
|
||||
return
|
||||
|
||||
# RENAME
|
||||
os.rename(item_path, new_item_path)
|
||||
|
||||
def check_server_id(self, server_id, page_name):
|
||||
if server_id is None:
|
||||
logger.warning(f"Server ID not defined in {page_name} file ajax call ({server_id})")
|
||||
console.warning(f"Server ID not defined in {page_name} file ajax call ({server_id})")
|
||||
return
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
# does this server id exist?
|
||||
if not self.controller.servers.server_id_exists(server_id):
|
||||
logger.warning(f"Server ID not found in {page_name} file ajax call ({server_id})")
|
||||
console.warning(f"Server ID not found in {page_name} file ajax call ({server_id})")
|
||||
return
|
||||
return True
|
@ -14,6 +14,7 @@ try:
|
||||
import tornado.escape
|
||||
import tornado.locale
|
||||
import tornado.httpserver
|
||||
from app.classes.web.file_handler import FileHandler
|
||||
from app.classes.web.public_handler import PublicHandler
|
||||
from app.classes.web.panel_handler import PanelHandler
|
||||
from app.classes.web.default_handler import DefaultHandler
|
||||
@ -122,6 +123,7 @@ class Webserver:
|
||||
(r'/panel/(.*)', PanelHandler, handler_args),
|
||||
(r'/server/(.*)', ServerHandler, handler_args),
|
||||
(r'/ajax/(.*)', AjaxHandler, handler_args),
|
||||
(r'/files/(.*)', FileHandler, handler_args),
|
||||
(r'/api/stats/servers', ServersStats, handler_args),
|
||||
(r'/api/stats/node', NodeStats, handler_args),
|
||||
(r'/ws', SocketHandler, handler_args),
|
||||
|
@ -34,6 +34,10 @@
|
||||
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
|
||||
<link rel="stylesheet" href="/static/assets/css/crafty.css">
|
||||
|
||||
<!-- Alpine.js - The modern jQuery alternative -->
|
||||
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<!-- End Alpine.js -->
|
||||
|
||||
</head>
|
||||
|
||||
<body class="dark-theme">
|
||||
@ -375,7 +379,7 @@
|
||||
}
|
||||
|
||||
function notify(message) {
|
||||
console.log(`notify(${message}})`);
|
||||
console.log(`notify(${message})`);
|
||||
var paragraphEl = document.createElement('p');
|
||||
var closeEl = document.createElement('span');
|
||||
|
||||
@ -410,7 +414,15 @@
|
||||
}
|
||||
webSocket.on('notification', notify);
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
console.log('%c[Crafty Controller] %cAlpine.js pre-initialization!', 'font-weight: 900; color: #800080;', 'color: #eee;');
|
||||
})
|
||||
document.addEventListener('alpine:initialized', () => {
|
||||
console.log('%c[Crafty Controller] %cAlpine.js initialized!', 'font-weight: 900; color: #800080;', 'color: #eee;');
|
||||
})
|
||||
|
||||
$(document).ready(function () {
|
||||
console.log('%c[Crafty Controller] %cReady for JS!', 'font-weight: 900; color: #800080;', 'font-weight: 900; color: #eee;');
|
||||
$('#support_logs').click(function () {
|
||||
var dialog = bootbox.dialog({
|
||||
message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i>{{ translate('notify', 'preparingLogs', data['lang']) }}</p>',
|
||||
|
@ -2,11 +2,11 @@
|
||||
<footer class="footer">
|
||||
<div class="container-fluid ">
|
||||
|
||||
<span class="text-muted d-block text-center text-sm-left d-sm-inline-block">{{ translate('footer', 'copyright', data['lang']) }} © 2021 - 2022 <a href="https://craftycontrol.com/" target="_blank">Crafty Controller</a>. {{ translate('footer', 'allRightsReserved', data['lang']) }}.</span>
|
||||
<span class="text-muted d-block text-center text-sm-left d-sm-inline-block">{{ translate('footer', 'copyright', data['lang']) }} © 2021 - <span x-data x-text="new Date().getFullYear()"></span> <a href="https://craftycontrol.com/" target="_blank">Crafty Controller</a>. {{ translate('footer', 'allRightsReserved', data['lang']) }}.</span>
|
||||
|
||||
<span class="float-none float-sm-right d-block mt-1 mt-sm-0 text-center">{{ translate('footer', 'version', data['lang']) }}: {{ data['version_data'] }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</footer>
|
||||
<!-- partial -->
|
||||
<!-- partial -->
|
||||
|
@ -134,29 +134,43 @@
|
||||
<td id="controls{{server['server_data']['server_id']}}" class="actions_serverlist">
|
||||
{% if server['user_command_permission'] %}
|
||||
{% if server['stats']['running'] %}
|
||||
<a class="stop_button" data-id="{{server['server_data']['server_id']}}" data-toggle="tooltip"
|
||||
title={{ translate('dashboard', 'stop' , data['lang']) }}> <i class="fas fa-stop"></i></a>
|
||||
<a class="restart_button" data-id="{{server['server_data']['server_id']}}" data-toggle="tooltip"
|
||||
title={{ translate('dashboard', 'restart' , data['lang']) }}> <i class="fas fa-sync"></i></a>
|
||||
|
||||
<a class="kill_button" data-id="{{server['server_data']['server_id']}}" class="kill_button"
|
||||
data-toggle="tooltip" title={{ translate('dashboard', 'kill' , data['lang']) }}> <i
|
||||
class="fas fa-skull"></i></a>
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="stop_button"
|
||||
data-toggle="tooltip" title="{{ translate('dashboard', 'stop' , data['lang']) }}">
|
||||
<i class="fas fa-stop"></i>
|
||||
</a>
|
||||
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="restart_button"
|
||||
data-toggle="tooltip" title="{{ translate('dashboard', 'restart' , data['lang']) }}">
|
||||
<i class="fas fa-sync"></i>
|
||||
</a>
|
||||
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="kill_button"
|
||||
data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
|
||||
<i class="fas fa-skull"></i>
|
||||
</a>
|
||||
|
||||
{% elif server['stats']['updating']%}
|
||||
<!-- WHAT HAPPENED HERE -->
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="">{{ translate('serverTerm', 'updating',
|
||||
data['lang']) }}</i></a>
|
||||
{% elif server['stats']['waiting_start']%}
|
||||
<!-- WHAT HAPPENED HERE -->
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="" title={{
|
||||
translate('dashboard', 'delay-explained' , data['lang'])}}>{{ translate('dashboard', 'starting',
|
||||
data['lang']) }}</i></a>
|
||||
{% else %}
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"
|
||||
data-toggle="tooltip" title={{ translate('dashboard', 'start' , data['lang']) }}></i></a>
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="clone_button"> <i class="fas fa-clone"
|
||||
data-toggle="tooltip" title={{ translate('dashboard', 'clone' , data['lang']) }}></i></a>
|
||||
<a class="kill_button" data-id="{{server['server_data']['server_id']}}" class="kill_button"
|
||||
data-toggle="tooltip" title={{ translate('dashboard', 'kill' , data['lang']) }}> <i
|
||||
class="fas fa-skull"></i></a>
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="play_button"
|
||||
data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
|
||||
<i class="fas fa-play"></i>
|
||||
</a>
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="clone_button"
|
||||
data-toggle="tooltip" title="{{ translate('dashboard', 'clone' , data['lang']) }}">
|
||||
<i class="fas fa-clone"></i>
|
||||
</a>
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="kill_button"
|
||||
data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
|
||||
<i class="fas fa-skull"></i>
|
||||
</a>
|
||||
{% end %}
|
||||
{% end %}
|
||||
</td>
|
||||
@ -439,9 +453,9 @@
|
||||
send_command(server_id, 'start_server');
|
||||
bootbox.alert({
|
||||
backdrop: true,
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data['lang']) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientStart", data['lang']) %} </div>'
|
||||
});
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data["lang"]) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientStart", data["lang"]) %} </div>'
|
||||
});
|
||||
});
|
||||
|
||||
$(".stop_button").click(function () {
|
||||
@ -450,9 +464,9 @@
|
||||
send_command(server_id, 'stop_server');
|
||||
bootbox.alert({
|
||||
backdrop: true,
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data['lang']) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientStop", data['lang']) %} </div>'
|
||||
});
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data["lang"]) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientStop", data["lang"]) %} </div>'
|
||||
});
|
||||
});
|
||||
|
||||
$(".restart_button").click(function () {
|
||||
@ -460,9 +474,9 @@
|
||||
send_command(server_id, 'restart_server');
|
||||
bootbox.alert({
|
||||
backdrop: true,
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data['lang']) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientRestart", data['lang']) %} </div>'
|
||||
});
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data["lang"]) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientRestart", data["lang"]) %} </div>'
|
||||
});
|
||||
});
|
||||
$(".kill_button").click(function () {
|
||||
server_id = $(this).attr("data-id");
|
||||
@ -470,11 +484,11 @@
|
||||
message: "This will kill the server process and all it's subprocesses. Killing a process can potentially corrupt files. Only do this in extreme circumstances. Are you sure you would like to continue?",
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: '{% raw translate("dashboard", "kill", data['lang']) %}',
|
||||
label: '{% raw translate("dashboard", "kill", data["lang"]) %}',
|
||||
className: 'btn-danger'
|
||||
},
|
||||
cancel: {
|
||||
label: '{% raw translate("panelConfig", "cancel", data['lang']) %}',
|
||||
label: '{% raw translate("panelConfig", "cancel", data["lang"]) %}',
|
||||
className: 'btn-secondary'
|
||||
}
|
||||
},
|
||||
@ -482,7 +496,7 @@
|
||||
if (result) {
|
||||
send_kill(server_id);
|
||||
var dialog = bootbox.dialog({
|
||||
title: '{% raw translate("dashboard", "killing", data['lang']) %}',
|
||||
title: '{% raw translate("dashboard", "killing", data["lang"]) %}',
|
||||
message: '<p><i class="fa fa-spin fa-spinner"></i> Loading...</p>'
|
||||
});
|
||||
|
||||
@ -524,13 +538,13 @@
|
||||
|
||||
if (webSocket) {
|
||||
webSocket.on('update_button_status', function (updateButton) {
|
||||
var id = 'controls';
|
||||
var dataId = updateButton.server_id;
|
||||
var string = updateButton.string
|
||||
var id = id.concat(updateButton.server_id);
|
||||
if (updateButton.isUpdating) {
|
||||
console.log(updateButton.isUpdating)
|
||||
document.getElementById(id).innerHTML = string;
|
||||
let serverId = updateButton.server_id;
|
||||
let message = updateButton.string;
|
||||
let updating = updateButton.isUpdating;
|
||||
let id = 'controls' + serverId;
|
||||
if (updating) {
|
||||
console.log(updating)
|
||||
document.getElementById(id).innerHTML = message;
|
||||
}
|
||||
else {
|
||||
window.location.reload()
|
||||
@ -547,9 +561,9 @@
|
||||
send_command(server_id, 'clone_server');
|
||||
bootbox.alert({
|
||||
backdrop: true,
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data['lang']) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientClone", data['lang']) %} </div>'
|
||||
});
|
||||
title: '{% raw translate("dashboard", "sendingCommand", data["lang"]) %}',
|
||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientClone", data["lang"]) %} </div>'
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@ -605,4 +619,4 @@
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -91,7 +91,7 @@
|
||||
document.body.onload = (() => {
|
||||
console.log('calculateTime');
|
||||
|
||||
startedUTC = '{{ data['server_stats']['started'] }}';
|
||||
startedUTC = "{{ data['server_stats']['started'] }}";
|
||||
if (startedUTC != 'False') {
|
||||
console.log('started utc:', startedUTC);
|
||||
startedUTC = moment.utc(startedUTC, 'YYYY-MM-DD HH:mm:ss');
|
||||
@ -220,4 +220,4 @@
|
||||
webSocket.on('update_server_details', update_server_details);
|
||||
//}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
@ -123,136 +123,138 @@
|
||||
{% block js %}
|
||||
<script>
|
||||
|
||||
const serverId = 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
|
||||
function getCookie(name) {
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
|
||||
function backup_started(time='5-10') {
|
||||
bootbox.alert({
|
||||
message: "{{ translate('serverBackups', 'backupTask', data['lang']) }}",
|
||||
backdrop: true
|
||||
});
|
||||
}
|
||||
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
||||
function getCookie(name) {
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
|
||||
function del_backup(filename, id){
|
||||
var token = getCookie("_xsrf")
|
||||
function backup_started(time='5-10') {
|
||||
bootbox.alert({
|
||||
message: "{{ translate('serverBackups', 'backupTask', data['lang']) }}",
|
||||
backdrop: true
|
||||
});
|
||||
}
|
||||
|
||||
data_to_send = { file_name :filename}
|
||||
function del_backup(filename, id){
|
||||
var token = getCookie("_xsrf")
|
||||
|
||||
console.log('Sending Command to delete backup: ' + filename)
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
headers: {'X-XSRFToken': token},
|
||||
url: '/ajax/del_backup?server_id='+id,
|
||||
data: {
|
||||
file_path: filename,
|
||||
id: id
|
||||
},
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
},
|
||||
});
|
||||
}
|
||||
data_to_send = { file_name :filename}
|
||||
|
||||
function restore_backup(filename, id){
|
||||
var token = getCookie("_xsrf")
|
||||
console.log('Sending Command to delete backup: ' + filename)
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
headers: {'X-XSRFToken': token},
|
||||
url: '/ajax/del_backup?server_id='+id,
|
||||
data: {
|
||||
file_path: filename,
|
||||
id: id
|
||||
},
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Sending Command to restore backup: ' + filename)
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: {'X-XSRFToken': token},
|
||||
url: '/ajax/restore_backup?server_id='+id,
|
||||
data: {
|
||||
zip_file: filename,
|
||||
id: id
|
||||
},
|
||||
success: function(data) {
|
||||
var dialog = bootbox.dialog({
|
||||
message: '<i class="fa fa-spin fa-spinner"></i> {{ translate('serverBackups', 'restoring', data['lang']) }}',
|
||||
closeButton: false
|
||||
});
|
||||
setTimeout(function(){
|
||||
location.href=('/panel/dashboard');
|
||||
}, 15000);
|
||||
},
|
||||
function restore_backup(filename, id){
|
||||
var token = getCookie("_xsrf")
|
||||
|
||||
console.log('Sending Command to restore backup: ' + filename)
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: {'X-XSRFToken': token},
|
||||
url: '/ajax/restore_backup?server_id='+id,
|
||||
data: {
|
||||
zip_file: filename,
|
||||
id: id
|
||||
},
|
||||
success: function(data) {
|
||||
var dialog = bootbox.dialog({
|
||||
message: '<i class="fa fa-spin fa-spinner"></i> {{ translate('serverBackups', 'restoring', data['lang']) }}',
|
||||
closeButton: false
|
||||
});
|
||||
setTimeout(function(){
|
||||
location.href=('/panel/dashboard');
|
||||
}, 15000);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$( document ).ready(function() {
|
||||
console.log( "ready!" );
|
||||
$("#backup_config_box").hide();
|
||||
$("#backup_save_note").hide();
|
||||
$( document ).ready(function() {
|
||||
console.log( "ready!" );
|
||||
$("#backup_config_box").hide();
|
||||
$("#backup_save_note").hide();
|
||||
|
||||
$("#show_config").click(function () {
|
||||
$("#backup_config_box").toggle();
|
||||
$('#backup_button').hide();
|
||||
$('#backup_save_note').show();
|
||||
$('#backup_data').hide();
|
||||
});
|
||||
$("#show_config").click(function () {
|
||||
$("#backup_config_box").toggle();
|
||||
$('#backup_button').hide();
|
||||
$('#backup_save_note').show();
|
||||
$('#backup_data').hide();
|
||||
});
|
||||
|
||||
$('#backup_table').DataTable({
|
||||
"order": [[ 1, "desc" ]],
|
||||
"paging":true,
|
||||
"lengthChange": false,
|
||||
"searching": true,
|
||||
"ordering": true,
|
||||
"info": true,
|
||||
"autoWidth": false,
|
||||
"responsive": true,
|
||||
});
|
||||
$('#backup_table').DataTable({
|
||||
"order": [[ 1, "desc" ]],
|
||||
"paging":true,
|
||||
"lengthChange": false,
|
||||
"searching": true,
|
||||
"ordering": true,
|
||||
"info": true,
|
||||
"autoWidth": false,
|
||||
"responsive": true,
|
||||
});
|
||||
|
||||
$( ".del_button" ).click(function() {
|
||||
var file_to_del = $(this).data("file");
|
||||
$( ".del_button" ).click(function() {
|
||||
var file_to_del = $(this).data("file");
|
||||
|
||||
console.log("file to delete is" + file_to_del);
|
||||
console.log("file to delete is" + file_to_del);
|
||||
|
||||
bootbox.confirm({
|
||||
title: "{% raw translate('serverBackups', 'destroyBackup', data['lang']) %}",
|
||||
message: "{{ translate('serverBackups', 'confirmDelete', data['lang']) }}",
|
||||
buttons: {
|
||||
cancel: {
|
||||
label: '<i class="fas fa-times"></i> {{ translate("serverBackups", "cancel", data['lang']) }}'
|
||||
},
|
||||
confirm: {
|
||||
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "confirm", data['lang']) }}'
|
||||
}
|
||||
},
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
if (result == true) {
|
||||
var full_path = '{{ data['backup_path'] }}' + '/' + file_to_del;
|
||||
del_backup(full_path, {{ data['server_stats']['server_id']['server_id'] }} );
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
bootbox.confirm({
|
||||
title: "{% raw translate('serverBackups', 'destroyBackup', data['lang']) %}",
|
||||
message: "{{ translate('serverBackups', 'confirmDelete', data['lang']) }}",
|
||||
buttons: {
|
||||
cancel: {
|
||||
label: '<i class="fas fa-times"></i> {{ translate("serverBackups", "cancel", data['lang']) }}'
|
||||
},
|
||||
confirm: {
|
||||
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "confirm", data['lang']) }}'
|
||||
}
|
||||
},
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
if (result == true) {
|
||||
var full_path = '{{ data['backup_path'] }}' + '/' + file_to_del;
|
||||
del_backup(full_path, serverId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$( ".restore_button" ).click(function() {
|
||||
var file_to_restore = $(this).data("file");
|
||||
$( ".restore_button" ).click(function() {
|
||||
var file_to_restore = $(this).data("file");
|
||||
|
||||
|
||||
bootbox.confirm({
|
||||
title: "{{ translate('serverBackups', 'restore', data['lang']) }} "+file_to_restore,
|
||||
message: "{{ translate('serverBackups', 'confirmRestore', data['lang']) }}",
|
||||
buttons: {
|
||||
cancel: {
|
||||
label: '<i class="fas fa-times"></i> {{ translate("serverBackups", "cancel", data['lang']) }}'
|
||||
},
|
||||
confirm: {
|
||||
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "restore", data['lang']) }}'
|
||||
}
|
||||
},
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
if (result == true) {
|
||||
restore_backup(file_to_restore, {{ data['server_stats']['server_id']['server_id'] }} );
|
||||
}
|
||||
}
|
||||
});
|
||||
bootbox.confirm({
|
||||
title: "{{ translate('serverBackups', 'restore', data['lang']) }} "+file_to_restore,
|
||||
message: "{{ translate('serverBackups', 'confirmRestore', data['lang']) }}",
|
||||
buttons: {
|
||||
cancel: {
|
||||
label: '<i class="fas fa-times"></i> {{ translate("serverBackups", "cancel", data['lang']) }}'
|
||||
},
|
||||
confirm: {
|
||||
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "restore", data['lang']) }}'
|
||||
}
|
||||
},
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
if (result == true) {
|
||||
restore_backup(file_to_restore, serverId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@ -260,4 +262,4 @@
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -32,7 +32,7 @@
|
||||
<div class="col-sm-12 grid-margin">
|
||||
<div class="card">
|
||||
<div class="card-body pt-0">
|
||||
{% include "parts/server_controls_list.html %}
|
||||
{% include "parts/server_controls_list.html" %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-sm-12">
|
||||
@ -188,14 +188,14 @@
|
||||
</div>
|
||||
<div class="text-center">
|
||||
{% if data['server_stats']['running'] %}
|
||||
<button onclick="send_command(server_id, 'update_executable');" id="update_executable"
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverConfig',
|
||||
'update', data['lang']) }}</button>
|
||||
<a class="btn btn-sm btn-danger disabled">{{ translate('serverConfig', 'deleteServer', data['lang'])
|
||||
}}</a><br />
|
||||
<small>{{ translate('serverConfig', 'stopBeforeDeleting', data['lang']) }}</small>
|
||||
{% else %}
|
||||
<button onclick="send_command(server_id, 'update_executable');" id="update_executable"
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig',
|
||||
'update', data['lang']) }}</button>
|
||||
<button onclick="deleteConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig',
|
||||
@ -221,6 +221,8 @@
|
||||
{% block js %}
|
||||
<script>
|
||||
|
||||
const serverId = 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
|
||||
function getCookie(name) {
|
||||
@ -238,7 +240,7 @@
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/delete_server?id={{ data['server_stats']['server_id']['server_id'] }}',
|
||||
url: '/ajax/delete_server?id=' + serverId,
|
||||
data: {
|
||||
},
|
||||
success: function (data) {
|
||||
@ -252,7 +254,7 @@
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/delete_server_files?id={{ data['server_stats']['server_id']['server_id'] }}',
|
||||
url: '/ajax/delete_server_files?id=' + serverId,
|
||||
data: {
|
||||
},
|
||||
success: function (data) {
|
||||
@ -262,16 +264,14 @@
|
||||
});
|
||||
}
|
||||
|
||||
let server_id = '{{ data['server_stats']['server_id']['server_id'] }}';
|
||||
|
||||
function send_command(server_id, command) {
|
||||
function send_command(serverId, command) {
|
||||
//<!-- this getCookie function is in base.html-->
|
||||
var token = getCookie("_xsrf");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/server/command?command=' + command + '&id=' + server_id,
|
||||
url: '/server/command?command=' + command + '&id=' + serverId,
|
||||
success: function (data) {
|
||||
console.log("got response:");
|
||||
console.log(data);
|
||||
@ -373,4 +373,4 @@
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,14 +24,14 @@
|
||||
</div>
|
||||
<!-- Page Title Header Ends-->
|
||||
|
||||
{% include "parts/details_stats.html %}
|
||||
{% include "parts/details_stats.html" %}
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-12 grid-margin">
|
||||
<div class="card">
|
||||
<div class="card-body pt-0">
|
||||
{% include "parts/server_controls_list.html %}
|
||||
{% include "parts/server_controls_list.html" %}
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="input-group">
|
||||
@ -55,42 +55,44 @@
|
||||
|
||||
{% block js %}
|
||||
<script>
|
||||
function get_server_log(){
|
||||
if( !$("#stop_scroll").is(':checked')){
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '/ajax/server_log?id={{ data['server_stats']['server_id']['server_id'] }}&full=1',
|
||||
dataType: 'text',
|
||||
success: function (data) {
|
||||
console.log('Got Log From Server')
|
||||
$('#virt_console').html(data);
|
||||
scroll();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const serverId = new URLSearchParams(document.location.search).get('id')
|
||||
function get_server_log(){
|
||||
if( !$("#stop_scroll").is(':checked')){
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '/ajax/server_log?id=' + serverId + '&full=1',
|
||||
dataType: 'text',
|
||||
success: function (data) {
|
||||
console.log('Got Log From Server')
|
||||
$('#virt_console').html(data);
|
||||
scroll();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
||||
function getCookie(name) {
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
||||
function getCookie(name) {
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
console.log( "ready!" );
|
||||
get_server_log()
|
||||
$( document ).ready(function() {
|
||||
console.log( "ready!" );
|
||||
get_server_log()
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function scroll(){
|
||||
var logview = $('#virt_console');
|
||||
if(logview.length)
|
||||
logview.scrollTop(logview[0].scrollHeight - logview.height());
|
||||
}
|
||||
function scroll(){
|
||||
var logview = $('#virt_console');
|
||||
if(logview.length)
|
||||
logview.scrollTop(logview[0].scrollHeight - logview.height());
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -31,7 +31,7 @@
|
||||
<div class="col-sm-12 grid-margin">
|
||||
<div class="card">
|
||||
<div class="card-body pt-0">
|
||||
{% include "parts/server_controls_list.html %}
|
||||
{% include "parts/server_controls_list.html" %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-8">
|
||||
@ -264,4 +264,4 @@ try{
|
||||
window.onload(startup())
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -233,6 +233,9 @@ td {
|
||||
|
||||
{% block js %}
|
||||
<script>
|
||||
|
||||
const serverId = new URLSearchParams(document.location.search).get('id')
|
||||
|
||||
$( document ).ready(function() {
|
||||
console.log('ready for JS!')
|
||||
$('#schedule_table').DataTable({
|
||||
@ -325,7 +328,6 @@ function ifDays(that) {
|
||||
|
||||
$( ".del_button" ).click(function() {
|
||||
var sch_id = $(this).data('sch');
|
||||
var server_id = {{ data['server_stats']['server_id']['server_id'] }};
|
||||
|
||||
console.log(sch_id)
|
||||
|
||||
@ -344,7 +346,7 @@ $( ".del_button" ).click(function() {
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
if (result == true) {
|
||||
del_task(sch_id, server_id);
|
||||
del_task(sch_id, serverId);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -369,4 +371,4 @@ function del_task(sch_id, id){
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -61,9 +61,9 @@
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
||||
<button onclick="send_command(server_id, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
|
||||
<button onclick="send_command(server_id, 'restart_server');" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
|
||||
<button onclick="send_command(server_id, 'stop_server');" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
|
||||
<button onclick="send_command(serverId, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
|
||||
<button onclick="send_command(serverId, 'restart_server');" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
|
||||
<button onclick="send_command(serverId, 'stop_server');" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
|
||||
</div>
|
||||
{% end %}
|
||||
{% end %}
|
||||
@ -93,7 +93,9 @@
|
||||
{% block js %}
|
||||
<script>
|
||||
|
||||
function send_command(server_id, command) {
|
||||
const serverId = new URLSearchParams(document.location.search).get('id')
|
||||
|
||||
function send_command(serverId, command) {
|
||||
if (command == 'start_server') {
|
||||
startBtn.setAttribute('disabled', 'disabled');
|
||||
restartBtn.removeAttribute('disabled');
|
||||
@ -110,7 +112,7 @@
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/server/command?command=' + command + '&id=' + server_id,
|
||||
url: '/server/command?command=' + command + '&id=' + serverId,
|
||||
success: function (data) {
|
||||
console.log("got response:");
|
||||
console.log(data);
|
||||
@ -120,28 +122,28 @@
|
||||
if (webSocket) {
|
||||
webSocket.on('update_button_status', function (updateButton) {
|
||||
if (updateButton.isUpdating) {
|
||||
if (updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') {
|
||||
if (updateButton.server_id == serverId) {
|
||||
console.log(updateButton.isUpdating)
|
||||
document.getElementById('control_buttons').innerHTML = '<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "updating", data['lang']) }}</button><button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data['lang']) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data['lang']) }}</button>';
|
||||
document.getElementById('control_buttons').innerHTML = '<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "updating", data["lang"]) }}</button><button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data["lang"]) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data["lang"]) }}</button>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') {
|
||||
if (updateButton.server_id == serverId) {
|
||||
window.location.reload()
|
||||
document.getElementById('update_control_buttons').innerHTML = '<button onclick="send_command(server_id, "start_server");" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "start", data['lang']) }}</button><button onclick="send_command(server_id, "restart_server");" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data['lang']) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data['lang']) }}</button>';
|
||||
document.getElementById('update_control_buttons').innerHTML = '<button onclick="send_command(serverId, "start_server");" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "start", data["lang"]) }}</button><button onclick="send_command(serverId, "restart_server");" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data["lang"]) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data["lang"]) }}</button>';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Convert running to lower case (example: 'True' converts to 'true') and
|
||||
// then to boolean via JSON.parse()
|
||||
let online = JSON.parse('{{ data['server_stats']['running'] }}'.toLowerCase());
|
||||
let online = JSON.parse("{{ data['server_stats']['running'] }}".toLowerCase());
|
||||
|
||||
let startBtn = document.querySelector('#start-btn');
|
||||
let restartBtn = document.querySelector('#restart-btn');
|
||||
let stopBtn = document.querySelector('#stop-btn');
|
||||
|
||||
{% if data['permissions']['Commands'] in data['user_permissions'] %}
|
||||
//{% if data['permissions']['Commands'] in data['user_permissions'] %}
|
||||
if (online) {
|
||||
startBtn.setAttribute('disabled', 'disabled');
|
||||
restartBtn.removeAttribute('disabled');
|
||||
@ -151,14 +153,12 @@
|
||||
restartBtn.setAttribute('disabled', 'disabled');
|
||||
stopBtn.setAttribute('disabled', 'disabled');
|
||||
}
|
||||
{% end %}
|
||||
|
||||
let server_id = '{{ data['server_stats']['server_id']['server_id'] }}';
|
||||
//{% end %}
|
||||
|
||||
function get_server_log() {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '/ajax/server_log?id={{ data['server_stats']['server_id']['server_id'] }}',
|
||||
url: '/ajax/server_log?id=' + serverId,
|
||||
dataType: 'text',
|
||||
success: function (data) {
|
||||
console.log('Got Log From Server')
|
||||
@ -195,7 +195,7 @@
|
||||
$('#server_command').on('keydown', function (e) {
|
||||
if (e.which == 13) {
|
||||
$(this).attr("disabled", "disabled"); //Disable textbox to prevent multiple submit
|
||||
send_command_to_server()
|
||||
sendConsoleCommand()
|
||||
$(this).removeAttr("disabled"); //Enable the textbox again if needed.
|
||||
$(this).focus();
|
||||
}
|
||||
@ -211,7 +211,7 @@
|
||||
|
||||
$("#submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
send_command_to_server();
|
||||
sendConsoleCommand();
|
||||
|
||||
});
|
||||
|
||||
@ -222,28 +222,31 @@
|
||||
}
|
||||
|
||||
|
||||
function send_command_to_server() {
|
||||
var server_command = $("#server_command").val()
|
||||
console.log(server_command)
|
||||
async function sendConsoleCommand() {
|
||||
let serverCommand = $("#server_command").val()
|
||||
console.log(serverCommand)
|
||||
|
||||
cmdHistory.push(server_command);
|
||||
cmdHistory.push(serverCommand);
|
||||
|
||||
var token = getCookie("_xsrf")
|
||||
let token = getCookie("_xsrf")
|
||||
|
||||
data_to_send = { command: server_command, }
|
||||
let formdata = new FormData();
|
||||
|
||||
console.log('sending command: ' + server_command)
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/send_command?id={{ data['server_stats']['server_id']['server_id'] }}',
|
||||
data: data_to_send,
|
||||
success: function (data) {
|
||||
console.log("got response:");
|
||||
console.log(data);
|
||||
$("#server_command").val('')
|
||||
formdata.append('command', serverCommand)
|
||||
|
||||
console.log('sending command: ' + serverCommand)
|
||||
let res = await fetch("/ajax/send_command?id=" + serverId, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-XSRFToken': token
|
||||
},
|
||||
body: formdata,
|
||||
});
|
||||
|
||||
let responseData = await res.text();
|
||||
console.log("got response:");
|
||||
console.log(responseData);
|
||||
$("#server_command").val('')
|
||||
}
|
||||
|
||||
|
||||
@ -272,4 +275,4 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -426,7 +426,7 @@
|
||||
document.getElementById("root_files_button").addEventListener("click", function(){
|
||||
if(document.forms["zip"]["server_path"].value != ""){
|
||||
if(document.getElementById('root_files_button').classList.contains('clicked')){
|
||||
document.getElementById('main-tree-div').innerHTML = '<input type="radio" id="main-tree-input" name="root_path" value="" checked><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="radio" id="main-tree-input" name="root_path" value="" checked><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>'
|
||||
}else{
|
||||
document.getElementById('root_files_button').classList.add('clicked')
|
||||
}
|
||||
@ -482,8 +482,8 @@ function hide(event) {
|
||||
|
||||
function wait_msg(importing){
|
||||
bootbox.alert({
|
||||
title: importing ? '{% raw translate("serverWizard", "importing", data['lang']) %}' : '{% raw translate("serverWizard", "downloading", data['lang']) %}',
|
||||
message: '<i class="fas fa-cloud-download"></i> {% raw translate("serverWizard", "bePatient", data['lang']) %}',
|
||||
title: importing ? '{% raw translate("serverWizard", "importing", data["lang"]) %}' : '{% raw translate("serverWizard", "downloading", data["lang"]) %}',
|
||||
message: '<i class="fas fa-cloud-download"></i> {% raw translate("serverWizard", "bePatient", data["lang"]) %}',
|
||||
});
|
||||
}
|
||||
|
||||
@ -647,4 +647,4 @@ function hide(event) {
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -76,10 +76,67 @@
|
||||
"clickRoot": "Napsauta tästä valitaksesi juurihakemiston",
|
||||
"explainRoot": "Napsauta alla olevaa painiketta valitaksesi palvelimesi juurihakemiston arkistosta"
|
||||
},
|
||||
"usersConfig":{
|
||||
"userConfig":{
|
||||
"pageTitle": "Muokkaa käyttäjää",
|
||||
"pageTitleNew": "Luo käyttäjä",
|
||||
"config": "Asetukset",
|
||||
"apiKey": "API-avaimet",
|
||||
"userSettings": "Käyttäjäasetukset",
|
||||
"userName": "Käyttäjätunnus",
|
||||
"userNameDesc": "Millä nimellä haluat kutsua tätä käyttäjää?",
|
||||
"password": "Salasana",
|
||||
"repeat": "Toista salasana",
|
||||
"leaveBlank": "Jos haluat muokata käyttäjää vaihtamatta salasanaa, jätä se tyhjäksi.",
|
||||
"craftyPermDesc": "Craftyn oikeuksia, joita tällä käyttäjällä on",
|
||||
"gravEmail": "Gravatar™ Sähköposti",
|
||||
"gravDesc": "Tämä shäköposti on vain Gravatar™-palvelun käyttöön. Crafty ei missään olosuhteissa käytä tätä sähköpostia muuhun kuin Gravatar™-tietojesi etsimiseen",
|
||||
"userLang": "Käyttäjän kieli",
|
||||
"userRoles": "Käyttäjän roolit",
|
||||
"userRolesDesc": "Roolit, joissa tämä käyttäjä on",
|
||||
"roleName": "Roolin nimi",
|
||||
"member": "Jäsen?",
|
||||
"craftyPerms": "Craftyn oikeudet: ",
|
||||
"permName":"Oikeuden nimi",
|
||||
"auth": "Valtuutettu? ",
|
||||
"uses": "Sallittujen käyttäkertojen määtä (-1 == Ei rajaa)",
|
||||
"super": "Järjestelmänvalvoja",
|
||||
"enabled": "Päällä",
|
||||
"configArea": "Käyttäjän Asetukset",
|
||||
"configAreaDesc": "Tässä voi muokata kaikkia käyttäjän asetuksia",
|
||||
"created": "Luotu: ",
|
||||
"lastLogin": "Viimeinen Sisäänkirjautuminen: ",
|
||||
"lastUpdate": "Viimeinen Muokkaus: ",
|
||||
"lastIP": "Viimeinen IP: ",
|
||||
"deleteUserB": "Poista käyttäjä",
|
||||
"notExist": "Et voi poistaa mitään, joka ei ole olemassa!",
|
||||
"delSuper": "Et voi poistaa järjestelmänvalvojaa!",
|
||||
"deleteUser": "Poista käyttäjä: ",
|
||||
"confirmDelete": "Oletko varma, että haluat poistaa tämän käyttäjän? Tätä ei voi peruuttaa."
|
||||
},
|
||||
"rolesConfig": {
|
||||
"pageTitle": "Muokkaa roolia",
|
||||
"pageTitleNew": "Luo rooli",
|
||||
"config": "Asetukset",
|
||||
"roleTitle": "Roolin asetukset",
|
||||
"roleName": "Roolin nimi: ",
|
||||
"roleDesc": "Millä nimellä haluaisit kutsua tätä roolia?",
|
||||
"roleServers": "Sallitut palvelimet",
|
||||
"serversDesc": "Palvelimet, joihin tällä roolilla on pääsy",
|
||||
"serverName": "Server Name",
|
||||
"serverAccess": "Pääsy?",
|
||||
"rolePerms": "Roolin käyttöoikeudet",
|
||||
"permsServer": "Tämän roolin käyttöoikeudet näille määritetyille palvelimille",
|
||||
"permName": "Oikeuden nimi",
|
||||
"permAccess": "Pääsy?",
|
||||
"roleUsers": "Roolin käyttäjät: ",
|
||||
"roleUserName": "Käyttäjätunnus",
|
||||
"roleConfigArea": "Roolin asetukset",
|
||||
"configDesc": "Täällä voit muuttaa roolin asetuksia",
|
||||
"created": "Luotu: ",
|
||||
"configUpdate": "Viimeinen muokkaus: ",
|
||||
"delRole": "Poista rooli",
|
||||
"doesNotExist": "Et voi poistaa mitään, joka ei ole olemassa!"
|
||||
},
|
||||
"dashboard": {
|
||||
"dashboard": "Kojelauta",
|
||||
"memUsage": "Muistin käyttö",
|
||||
@ -113,16 +170,17 @@
|
||||
"cpuCurFreq": "Nykyinen kellotaajuus",
|
||||
"cpuMaxFreq": "Maksimi kellotaajuus",
|
||||
"cpuCores": "Suorittimen ytimet",
|
||||
"start": "Alkaa",
|
||||
"stop": "Lopettaa",
|
||||
"clone": "Klooni",
|
||||
"start": "Käynnistä",
|
||||
"stop": "Pysäytä",
|
||||
"clone": "Kloonaa",
|
||||
"kill": "Tapa prosessi",
|
||||
"restart": "Uudelleenkäynnistää",
|
||||
"killing": "Tappamisprosessi ...",
|
||||
"starting": "Myöhästynyt lähtö",
|
||||
"delay-explained": "Palvelu/agentti on äskettäin aloittanut ja viivästyttää minecraft -palvelimen ilmentymän alkua",
|
||||
"killing": "Tapetaan prosessia...",
|
||||
"starting": "Myöhästynyt käynnistys",
|
||||
"delay-explained": "Palvelu/agentti on äskettäin aloittanut ja viivästyttää palvelimen käynnistämistä",
|
||||
"no-servers": "Palvelimia ei tällä hetkellä ole. Aloita napsauttamalla",
|
||||
"welcome": "Tervetuloa Crafty Controller"
|
||||
"welcome": "Tervetuloa Crafty Controlleriin",
|
||||
"crashed": "Kaatui"
|
||||
},
|
||||
"accessDenied": {
|
||||
"accessDenied": "Käyttö estetty",
|
||||
@ -133,7 +191,7 @@
|
||||
"serverStats": {
|
||||
"online": "Päällä",
|
||||
"offline": "Pois päältä",
|
||||
"starting": "Myöhästynyt lähtö",
|
||||
"starting": "Myöhästynyt aloitus",
|
||||
"serverStatus": "Palvelimen tila",
|
||||
"serverStarted": "Palvelin käynnistyi",
|
||||
"serverUptime": "Palvelimen käyttöaika",
|
||||
@ -165,7 +223,7 @@
|
||||
"restart": "Uudelleen­käynnistä",
|
||||
"stop": "Sammuta",
|
||||
"updating": "Updating",
|
||||
"starting": "Myöhästynyt lähtö",
|
||||
"starting": "Myöhästynyt aloitus",
|
||||
"delay-explained": "Palvelu/agentti on äskettäin aloittanut ja viivästyttää minecraft -palvelimen ilmentymän alkua"
|
||||
},
|
||||
"serverPlayerManagement": {
|
||||
@ -277,7 +335,9 @@
|
||||
"noDeleteFiles": "Ei, poista vain paneelista",
|
||||
"sendingDelete": "Poistetaan palvelinta",
|
||||
"bePatientDelete": "Ole kärsivällinen, kun poistamme palvelimesi Crafty-paneelista. Tämä näyttö sulkeutuu hetken kuluttua.",
|
||||
"bePatientDeleteFiles" : "Ole kärsivällinen, kun poistamme palvelimesi Crafty-paneelista ja poistamme kaikki tiedostot. Tämä näyttö sulkeutuu hetken kuluttua."
|
||||
"bePatientDeleteFiles" : "Ole kärsivällinen, kun poistamme palvelimesi Crafty-paneelista ja poistamme kaikki tiedostot. Tämä näyttö sulkeutuu hetken kuluttua.",
|
||||
"crashTime": "Kaatumisen aikakatkaisu",
|
||||
"crashTimeDesc": "Kuinka kauan meidän pitäisi odottaa, ennen kuin harkitsemme palvelimesi kaatuneen?"
|
||||
},
|
||||
"serverConfigHelp": {
|
||||
"title": "Palvelimen asetukset",
|
||||
@ -297,6 +357,18 @@
|
||||
]
|
||||
},
|
||||
"panelConfig": {
|
||||
"pageTitle": "Paneelin asetukset",
|
||||
"users": "Käyttäjät",
|
||||
"roles": "Roolit",
|
||||
"newUser": "Luo uusi käyttäjä",
|
||||
"newRole": "Luo uusi rooli",
|
||||
"user": "Käyttäjä",
|
||||
"enabled": "Käytössä",
|
||||
"allowedServers": "Sallitut palvelimet",
|
||||
"assignedRoles": "Määrätyt roolit",
|
||||
"edit": "Muokkaa",
|
||||
"role": "Rooli",
|
||||
"roleUsers": "Roolin käyttäjät",
|
||||
"save": "Tallenna",
|
||||
"cancel": "Peruuta",
|
||||
"delete": "Poista",
|
||||
@ -395,6 +467,23 @@
|
||||
"doesNotWorkWithoutJavascript": "<strong>Varoitus: </strong>Crafty ei toimi kunnolla ilman JavaScriptiä!"
|
||||
},
|
||||
"apiKeys": {
|
||||
"pageTitle": "Muokkaa käyttäjän API-avaimia",
|
||||
"config": "Asetukset",
|
||||
"apiKeys": "API-avaimet",
|
||||
"name": "Nimi",
|
||||
"created": "Luotu",
|
||||
"perms": "Käyttöoikeudet",
|
||||
"buttons": "Painikkeet",
|
||||
"yes": "Kyllä",
|
||||
"no": "Ei",
|
||||
"server": "Palvelin: ",
|
||||
"crafty": "Crafty: ",
|
||||
"getToken": "Hanki API-avain",
|
||||
"createNew": "Luo uusi API-avain",
|
||||
"nameDesc": "Millä nimellä haluat kutsua tätä API-avainta? ",
|
||||
"permName": "Oikeuden nimi",
|
||||
"auth":"Valtuutettu? ",
|
||||
"superUser": "Järjestelmänvalvoja",
|
||||
"deleteKeyConfirmation": "Haluatko varmasti poistaa tämän API-avaimen? Tämä on peruuttamaton toimenpide!",
|
||||
"deleteKeyConfirmationTitle": "Poistetaanko API-avain ${keyId}?"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user