Rework server start to look for user_id and not user_lang. Gives acces to more user info.

Fixes websocket broadcast to only send broadcast to user who sent original request.
This commit is contained in:
Andrew 2021-11-27 17:10:43 -05:00
parent db4812c8ea
commit 1bf47b5c54
5 changed files with 77 additions and 40 deletions

View File

@ -20,6 +20,7 @@ from app.classes.models.servers import Servers, servers_helper
from app.classes.models.management import management_helper
from app.classes.web.websocket_helper import websocket_helper
from app.classes.shared.translation import translation
from app.classes.models.users import users_helper
logger = logging.getLogger(__name__)
@ -145,14 +146,14 @@ class Server:
def run_scheduled_server(self):
console.info("Starting server ID: {} - {}".format(self.server_id, self.name))
logger.info("Starting server {}".format(self.server_id, self.name))
self.run_threaded_server(helper.get_setting('language'))
self.run_threaded_server(None)
# remove the scheduled job since it's ran
return schedule.CancelJob
def run_threaded_server(self, lang):
def run_threaded_server(self, user_id):
# start the server
self.server_thread = threading.Thread(target=self.start_server, daemon=True, args=(lang,), name='{}_server_thread'.format(self.server_id))
self.server_thread = threading.Thread(target=self.start_server, daemon=True, args=(user_id,), name='{}_server_thread'.format(self.server_id))
self.server_thread.start()
def setup_server_run_command(self):
@ -177,7 +178,11 @@ class Server:
console.warning("Unable to write/access {}".format(self.server_path))
helper.do_exit()
def start_server(self, user_lang):
def start_server(self, user_id):
if not user_id:
user_lang = helper.get_setting('language')
else:
user_lang = users_helper.get_user_lang_by_id(user_id)
logger.info("Start command detected. Reloading settings from DB for server {}".format(self.name))
self.setup_server_run_command()
@ -214,7 +219,7 @@ class Server:
e_flag = False
if e_flag == False:
websocket_helper.broadcast('send_eula_bootbox', {
websocket_helper.broadcast_user(user_id, 'send_eula_bootbox', {
'id': self.server_id
})
return False
@ -235,23 +240,25 @@ class Server:
except Exception as ex:
msg = "Server {} failed to start with error code: {}".format(self.name, ex)
logger.error(msg)
websocket_helper.broadcast('send_start_error', {
'error': translation.translate('error', 'start-error', user_lang).format(self.name, ex)
})
if user_id:
websocket_helper.broadcast_user(user_id, 'send_start_error',{
'error': translation.translate('error', 'start-error', user_lang).format(self.name, ex)
})
return False
if helper.check_internet():
loc_server_port = servers_helper.get_server_stats_by_id(self.server_id)['server_port']
if helper.check_port(loc_server_port):
websocket_helper.broadcast('send_start_reload', {
if user_id:
if helper.check_internet():
loc_server_port = servers_helper.get_server_stats_by_id(self.server_id)['server_port']
if helper.check_port(loc_server_port):
websocket_helper.broadcast_user(user_id, 'send_start_reload', {
})
else:
websocket_helper.broadcast_user(user_id, 'send_start_error', {
'error': translation.translate('error', 'closedPort', user_lang).format(loc_server_port)
})
else:
websocket_helper.broadcast('send_start_error', {
'error': translation.translate('error', 'closedPort', user_lang).format(loc_server_port)
})
else:
websocket_helper.broadcast('send_start_error', {
'error': translation.translate('error', 'internet', user_lang)
})
websocket_helper.broadcast_user(user_id, 'send_start_error', {
'error': translation.translate('error', 'internet', user_lang)
})
servers_helper.set_waiting_start(self.server_id, False)
out_buf = ServerOutBuf(self.process, self.server_id)
@ -322,15 +329,14 @@ class Server:
self.stats.record_stats()
def restart_threaded_server(self, lang):
def restart_threaded_server(self, user_id):
# if not already running, let's just start
if not self.check_running():
self.run_threaded_server(lang)
self.run_threaded_server(user_id)
else:
self.stop_threaded_server()
time.sleep(2)
self.run_threaded_server(lang)
self.run_threaded_server(user_id)
def cleanup_server_object(self):
self.start_time = None
@ -373,7 +379,7 @@ class Server:
if self.settings['crash_detection']:
logger.warning("The server {} has crashed and will be restarted. Restarting server".format(name))
console.warning("The server {} has crashed and will be restarted. Restarting server".format(name))
self.run_threaded_server(helper.get_setting('language'))
self.run_threaded_server(None)
return True
else:
logger.critical(
@ -447,12 +453,12 @@ class Server:
console.info("Removing old crash detection watcher thread")
schedule.clear(self.name)
def agree_eula(self, user_lang):
def agree_eula(self, user_id):
file = os.path.join(self.server_path, 'eula.txt')
f = open(file, 'w')
f.write('eula=true')
f.close
self.run_threaded_server(user_lang)
self.run_threaded_server(user_id)
def is_backup_running(self):
if self.is_backingup:

View File

@ -98,20 +98,17 @@ class TasksManager:
for c in commands:
svr = self.controller.get_server_obj(c['server_id']['server_id'])
user_lang = c.get('user')['lang']
user_id = c.get('user')['user_id']
command = c.get('command', None)
if command == 'start_server':
if user_lang is None:
logger.warning('Could not capture user language from request. Falling back to default language from config file.')
user_lang = helper.get_setting('language')
svr.run_threaded_server(user_lang)
svr.run_threaded_server(user_id)
elif command == 'stop_server':
svr.stop_threaded_server()
elif command == "restart_server":
svr.restart_threaded_server(user_lang)
svr.restart_threaded_server(user_id)
elif command == "backup_server":
svr.backup_server()

View File

@ -210,7 +210,7 @@ class AjaxHandler(BaseHandler):
elif page == "eula":
server_id = self.get_argument('id', None)
svr = self.controller.get_server_obj(server_id)
svr.agree_eula(self.controller.users.get_user_lang_by_id(user_data['user_id']))
svr.agree_eula(user_data['user_id'])
@tornado.web.authenticated
def delete(self, page):

View File

@ -1,11 +1,13 @@
import json
import logging
import asyncio
import sys
from urllib.parse import parse_qsl
from app.classes.models.users import Users
from app.classes.shared.helpers import helper
from app.classes.web.websocket_helper import websocket_helper
from app.classes.shared.console import console
logger = logging.getLogger(__name__)
@ -31,6 +33,14 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
self.request.remote_ip
return remote_ip
def get_user_id(self):
user_data_cookie_raw = self.get_secure_cookie('user_data')
if user_data_cookie_raw and user_data_cookie_raw.decode('utf-8'):
user_data_cookie = user_data_cookie_raw.decode('utf-8')
user_id = json.loads(user_data_cookie)['user_id']
return user_id
def check_auth(self):
user_data_cookie_raw = self.get_secure_cookie('user_data')

View File

@ -42,15 +42,36 @@ class WebSocketHelper:
def filter_fn(client):
return client.page == page
clients = list(filter(filter_fn, self.clients))
self.broadcast_with_fn(filter_fn, event_type, data)
logger.debug('Sending to {} out of {} clients: {}'.format(len(clients), len(self.clients), json.dumps({'event': event_type, 'data': data})))
def broadcast_user(self, user_id: str, event_type: str, data):
def filter_fn(client):
return client.get_user_id() == user_id
for client in clients:
try:
self.send_message(client, event_type, data)
except Exception as e:
logger.exception('Error catched while sending WebSocket message to {}'.format(client.get_remote_ip()))
self.broadcast_with_fn(filter_fn, event_type, data)
def broadcast_user_page(self, page: str, user_id: str, event_type: str, data):
def filter_fn(client):
if client.get_user_id() != user_id:
return False
if client.page != page:
return False
return True
self.broadcast_with_fn(filter_fn, event_type, data)
def broadcast_user_page_params(self, page: str, params: dict, user_id: str, event_type: str, data):
def filter_fn(client):
if client.get_user_id() != user_id:
return False
if client.page != page:
return False
for key, param in params.items():
if param != client.page_query_params.get(key, None):
return False
return True
self.broadcast_with_fn(filter_fn, event_type, data)
def broadcast_page_params(self, page: str, params: dict, event_type: str, data):
def filter_fn(client):
@ -61,6 +82,9 @@ class WebSocketHelper:
return False
return True
self.broadcast_with_fn(filter_fn, event_type, data)
def broadcast_with_fn(self, filter_fn, event_type: str, data):
clients = list(filter(filter_fn, self.clients))
logger.debug('Sending to {} out of {} clients: {}'.format(len(clients), len(self.clients), json.dumps({'event': event_type, 'data': data})))