mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add authentication to WS, notify user when an activity log gets logged, and more
This commit is contained in:
parent
a965af5491
commit
9c62099f32
@ -6,6 +6,7 @@ import datetime
|
|||||||
from app.classes.shared.helpers import helper
|
from app.classes.shared.helpers import helper
|
||||||
from app.classes.shared.console import console
|
from app.classes.shared.console import console
|
||||||
from app.classes.minecraft.server_props import ServerProps
|
from app.classes.minecraft.server_props import ServerProps
|
||||||
|
from app.classes.web.websocket_helper import websocket_helper
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -254,14 +255,14 @@ class db_shortcuts:
|
|||||||
|
|
||||||
def get_server_friendly_name(self, server_id):
|
def get_server_friendly_name(self, server_id):
|
||||||
server_data = self.get_server_data_by_id(server_id)
|
server_data = self.get_server_data_by_id(server_id)
|
||||||
friendly_name = "{}-{}".format(server_data.get('server_id', 0), server_data.get('server_name', None))
|
friendly_name = "{} with ID: {}".format(server_data.get('server_name', None), server_data.get('server_id', 0))
|
||||||
return friendly_name
|
return friendly_name
|
||||||
|
|
||||||
def send_command(self, user_id, server_id, remote_ip, command):
|
def send_command(self, user_id, server_id, remote_ip, command):
|
||||||
|
|
||||||
server_name = self.get_server_friendly_name(server_id)
|
server_name = self.get_server_friendly_name(server_id)
|
||||||
|
|
||||||
self.add_to_audit_log(user_id, "Issued Command {} for Server: {}".format(command, server_name),
|
self.add_to_audit_log(user_id, "issued command {} for server {}".format(command, server_name),
|
||||||
server_id, remote_ip)
|
server_id, remote_ip)
|
||||||
|
|
||||||
Commands.insert({
|
Commands.insert({
|
||||||
@ -294,6 +295,8 @@ class db_shortcuts:
|
|||||||
|
|
||||||
audit_msg = "{} {}".format(str(user_data.username).capitalize(), log_msg)
|
audit_msg = "{} {}".format(str(user_data.username).capitalize(), log_msg)
|
||||||
|
|
||||||
|
websocket_helper.broadcast('notification', audit_msg)
|
||||||
|
|
||||||
Audit_Log.insert({
|
Audit_Log.insert({
|
||||||
Audit_Log.user_name: user_data.username,
|
Audit_Log.user_name: user_data.username,
|
||||||
Audit_Log.user_id: user_id,
|
Audit_Log.user_id: user_id,
|
||||||
@ -302,6 +305,16 @@ class db_shortcuts:
|
|||||||
Audit_Log.source_ip: source_ip
|
Audit_Log.source_ip: source_ip
|
||||||
}).execute()
|
}).execute()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_to_audit_log_raw(user_name, user_id, server_id, log_msg, source_ip):
|
||||||
|
Audit_Log.insert({
|
||||||
|
Audit_Log.user_name: user_name,
|
||||||
|
Audit_Log.user_id: user_id,
|
||||||
|
Audit_Log.server_id: server_id,
|
||||||
|
Audit_Log.log_msg: log_msg,
|
||||||
|
Audit_Log.source_ip: source_ip
|
||||||
|
}).execute()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,7 +142,6 @@ class TasksManager:
|
|||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
|
|
||||||
console.debug('realtime start')
|
|
||||||
host_stats = db_helper.get_latest_hosts_stats()
|
host_stats = db_helper.get_latest_hosts_stats()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -153,11 +152,9 @@ class TasksManager:
|
|||||||
db_helper.get_latest_hosts_stats().get('mem_percent'):
|
db_helper.get_latest_hosts_stats().get('mem_percent'):
|
||||||
# Stats are different
|
# Stats are different
|
||||||
|
|
||||||
console.debug('realtime 1')
|
|
||||||
host_stats = db_helper.get_latest_hosts_stats()
|
host_stats = db_helper.get_latest_hosts_stats()
|
||||||
if len(websocket_helper.clients) > 0:
|
if len(websocket_helper.clients) > 0:
|
||||||
# There are clients
|
# There are clients
|
||||||
console.debug('realtime 11')
|
|
||||||
websocket_helper.broadcast('update_host_stats', {
|
websocket_helper.broadcast('update_host_stats', {
|
||||||
'cpu_usage': host_stats.get('cpu_usage'),
|
'cpu_usage': host_stats.get('cpu_usage'),
|
||||||
'cpu_cores': host_stats.get('cpu_cores'),
|
'cpu_cores': host_stats.get('cpu_cores'),
|
||||||
@ -169,7 +166,6 @@ class TasksManager:
|
|||||||
time.sleep(4)
|
time.sleep(4)
|
||||||
else:
|
else:
|
||||||
# Stats are same
|
# Stats are same
|
||||||
console.debug('realtime 0')
|
|
||||||
time.sleep(8)
|
time.sleep(8)
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ class ServerHandler(BaseHandler):
|
|||||||
|
|
||||||
if new_server_id:
|
if new_server_id:
|
||||||
db_helper.add_to_audit_log(user_data['user_id'],
|
db_helper.add_to_audit_log(user_data['user_id'],
|
||||||
"Created server {} named {}".format(server, server_name),
|
"created a {} {} server named \"{}\"".format(server_parts[1], str(server_parts[0]).capitalize(), server_name), # Example: Admin created a 1.16.5 Bukkit server named "survival"
|
||||||
new_server_id,
|
new_server_id,
|
||||||
self.get_remote_ip())
|
self.get_remote_ip())
|
||||||
else:
|
else:
|
||||||
|
@ -24,7 +24,7 @@ try:
|
|||||||
from app.classes.web.server_handler import ServerHandler
|
from app.classes.web.server_handler import ServerHandler
|
||||||
from app.classes.web.ajax_handler import AjaxHandler
|
from app.classes.web.ajax_handler import AjaxHandler
|
||||||
from app.classes.web.api_handler import ServersStats, NodeStats
|
from app.classes.web.api_handler import ServersStats, NodeStats
|
||||||
from app.classes.web.websocket_handler import WebSocketHandler
|
from app.classes.web.websocket_handler import SocketHandler
|
||||||
|
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
|
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
|
||||||
@ -126,7 +126,7 @@ class webserver:
|
|||||||
(r'/ajax/(.*)', AjaxHandler),
|
(r'/ajax/(.*)', AjaxHandler),
|
||||||
(r'/api/stats/servers', ServersStats),
|
(r'/api/stats/servers', ServersStats),
|
||||||
(r'/api/stats/node', NodeStats),
|
(r'/api/stats/node', NodeStats),
|
||||||
(r'/ws', WebSocketHandler),
|
(r'/ws', SocketHandler),
|
||||||
]
|
]
|
||||||
|
|
||||||
app = tornado.web.Application(
|
app = tornado.web.Application(
|
||||||
|
@ -2,15 +2,44 @@ import json
|
|||||||
|
|
||||||
import tornado.websocket
|
import tornado.websocket
|
||||||
from app.classes.shared.console import console
|
from app.classes.shared.console import console
|
||||||
|
from app.classes.shared.models import Users, db_helper
|
||||||
from app.classes.web.websocket_helper import websocket_helper
|
from app.classes.web.websocket_helper import websocket_helper
|
||||||
|
|
||||||
|
|
||||||
class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
class SocketHandler(tornado.websocket.WebSocketHandler):
|
||||||
|
|
||||||
|
def get_remote_ip(self):
|
||||||
|
remote_ip = self.request.headers.get("X-Real-IP") or \
|
||||||
|
self.request.headers.get("X-Forwarded-For") or \
|
||||||
|
self.request.remote_ip
|
||||||
|
return remote_ip
|
||||||
|
|
||||||
|
def check_auth(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']
|
||||||
|
query = Users.select().where(Users.user_id == user_id)
|
||||||
|
if query.exists():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
|
if self.check_auth():
|
||||||
|
self.handle()
|
||||||
|
else:
|
||||||
|
websocket_helper.send_message(self, 'notification', 'Not authenticated for WebSocket connection')
|
||||||
|
self.close()
|
||||||
|
db_helper.add_to_audit_log_raw('unknown', 0, 0, 'Someone tried to connect via WebSocket without proper authentication', self.get_remote_ip())
|
||||||
|
websocket_helper.broadcast('notification', 'Someone tried to connect via WebSocket without proper authentication')
|
||||||
|
|
||||||
|
def handle(self):
|
||||||
|
|
||||||
websocket_helper.addClient(self)
|
websocket_helper.addClient(self)
|
||||||
console.debug('Opened WebSocket connection')
|
console.debug('Opened WebSocket connection')
|
||||||
websocket_helper.broadcast('notification', 'New client connected')
|
# websocket_helper.broadcast('notification', 'New client connected')
|
||||||
|
|
||||||
def on_message(self, rawMessage):
|
def on_message(self, rawMessage):
|
||||||
|
|
||||||
@ -21,5 +50,5 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
|||||||
def on_close(self):
|
def on_close(self):
|
||||||
websocket_helper.removeClient(self)
|
websocket_helper.removeClient(self)
|
||||||
console.debug('Closed WebSocket connection')
|
console.debug('Closed WebSocket connection')
|
||||||
websocket_helper.broadcast('notification', 'Client disconnected')
|
# websocket_helper.broadcast('notification', 'Client disconnected')
|
||||||
|
|
||||||
|
@ -11,12 +11,15 @@ class WebSocketHelper:
|
|||||||
def removeClient(self, client):
|
def removeClient(self, client):
|
||||||
self.clients.add(client)
|
self.clients.add(client)
|
||||||
|
|
||||||
def broadcast(self, message_type: str, data):
|
def send_message(self, client, event_type, data):
|
||||||
console.debug('Sending: ' + str(json.dumps({'type': message_type, 'data': data})))
|
message = str(json.dumps({'event': event_type, 'data': data}))
|
||||||
message = str(json.dumps({'event': message_type, 'data': data}))
|
client.write_message(message)
|
||||||
|
|
||||||
|
def broadcast(self, event_type, data):
|
||||||
|
console.debug('Sending: ' + str(json.dumps({'event': event_type, 'data': data})))
|
||||||
for client in self.clients:
|
for client in self.clients:
|
||||||
try:
|
try:
|
||||||
client.write_message(message)
|
self.send_message(client, event_type, data)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -184,7 +184,13 @@
|
|||||||
listenEvents
|
listenEvents
|
||||||
.filter(listenedEvent => listenedEvent.event == message.event)
|
.filter(listenedEvent => listenedEvent.event == message.event)
|
||||||
.forEach(listenedEvent => listenedEvent.callback(message.data))
|
.forEach(listenedEvent => listenedEvent.callback(message.data))
|
||||||
}
|
};
|
||||||
|
wsInternal.onerror = function (errorEvent) {
|
||||||
|
console.error('WebSocket Error', errorEvent);
|
||||||
|
};
|
||||||
|
wsInternal.onclose = function (closeEvent) {
|
||||||
|
console.log('Closed WebSocket', closeEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
webSocket = {
|
webSocket = {
|
||||||
|
Loading…
Reference in New Issue
Block a user