many new things,

regexit sub function created
virtual console now has colors
fixed error with login function auditing None instead of 0
other things I can't remember atm
This commit is contained in:
Phillip Tarrant 2020-09-01 21:30:39 -04:00
parent ab1772397d
commit adf8d3f51a
8 changed files with 306 additions and 22 deletions

View File

@ -1,4 +1,5 @@
import os import os
import re
import sys import sys
import json import json
import time import time
@ -8,7 +9,7 @@ import base64
import socket import socket
import random import random
import logging import logging
import configparser
from datetime import datetime from datetime import datetime
from socket import gethostname from socket import gethostname
@ -125,6 +126,64 @@ class Helpers:
pass pass
return False return False
def log_colors(self, line):
# our regex replacements
# note these are in a tuple
user_keywords = self.get_setting('keywords')
replacements = [
(r'(\[.+?/INFO\])', r'<span class="mc-log-info">\1</span>'),
(r'(\[.+?/WARN\])', r'<span class="mc-log-warn">\1</span>'),
(r'(\[.+?/ERROR\])', r'<span class="mc-log-error">\1</span>'),
(r'(\w+?\[/\d+?\.\d+?\.\d+?\.\d+?\:\d+?\])', r'<span class="mc-log-keyword">\1</span>'),
(r'\[(\d\d:\d\d:\d\d)\]', r'<span class="mc-log-time">[\1]</span>'),
]
# highlight users keywords
for keyword in user_keywords:
search_replace = (r'({})'.format(keyword), r'<span class="mc-log-keyword">\1</span>')
replacements.append(search_replace)
for old, new in replacements:
line = re.sub(old, new, line, flags=re.IGNORECASE)
return line
def tail_file(self, file_name, number_lines=20):
if not self.check_file_exists(file_name):
logger.warning("Unable to find file to tail: {}".format(file_name))
return ["Unable to find file to tail: {}".format(file_name)]
# length of lines is X char here
avg_line_length = 255
# create our buffer number - number of lines * avg_line_length
line_buffer = number_lines * avg_line_length
# open our file
with open(file_name, 'r') as f:
# seek
f.seek(0, 2)
# get file size
fsize = f.tell()
# set pos @ last n chars (buffer from above = number of lines * avg_line_length)
f.seek(max(fsize-line_buffer, 0), 0)
# read file til the end
try:
lines = f.readlines()
except Exception as e:
logger.warning('Unable to read a line in the file:{} - due to error: {}'.format(file_name, e))
pass
# now we are done getting the lines, let's return it
return lines
@staticmethod @staticmethod
def check_writeable(path: str): def check_writeable(path: str):
filename = os.path.join(path, "tempfile.txt") filename = os.path.join(path, "tempfile.txt")
@ -334,7 +393,7 @@ class Helpers:
cert.get_subject().CN = gethostname() cert.get_subject().CN = gethostname()
cert.set_serial_number(1000) cert.set_serial_number(1000)
cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) cert.gmtime_adj_notAfter(365 * 24 * 60 * 60)
cert.set_issuer(cert.get_subject()) cert.set_issuer(cert.get_subject())
cert.set_pubkey(k) cert.set_pubkey(k)
cert.sign(k, 'sha256') cert.sign(k, 'sha256')

View File

@ -0,0 +1,72 @@
import json
import logging
import tornado.web
import tornado.escape
import bleach
from app.classes.shared.console import console
from app.classes.shared.models import Users, installer
from app.classes.web.base_handler import BaseHandler
from app.classes.shared.controller import controller
from app.classes.shared.models import db_helper
from app.classes.shared.helpers import helper
logger = logging.getLogger(__name__)
class AjaxHandler(BaseHandler):
def render_page(self, template, page_data):
self.render(
template,
data=page_data
)
@tornado.web.authenticated
def get(self, page):
user_data = json.loads(self.get_secure_cookie("user_data"))
error = bleach.clean(self.get_argument('error', "WTF Error!"))
template = "panel/denied.html"
page_data = {
'user_data': user_data,
'error': error
}
if page == "error":
template = "public/error.html"
self.render_page(template, page_data)
elif page == 'server_log':
server_id = self.get_argument('id', None)
if server_id is None:
logger.warning("Server ID not found in server_log ajax call")
self.redirect("/panel/error?error=Server ID Not Found")
return False
server_id = bleach.clean(server_id)
server_data = db_helper.get_server_data_by_id(server_id)
if not server_data:
logger.warning("Server Data not found in server_log ajax call")
self.redirect("/panel/error?error=Server ID Not Found")
if server_data['log_path']:
logger.warning("Server ID not found in server_log ajax call")
log_lines = helper.get_setting('virtual_terminal_lines')
data = helper.tail_file(server_data['log_path'], log_lines)
for d in data:
try:
line = helper.log_colors(d)
self.write('{}<br />'.format(line))
# self.write(d.encode("utf-8"))
except Exception as e:
logger.warning("Skipping Log Line due to error: {}".format(e))
pass

View File

@ -101,7 +101,7 @@ class PublicHandler(BaseHandler):
}).where(Users.username == entered_username).execute() }).where(Users.username == entered_username).execute()
# log this login # log this login
db_helper.add_to_audit_log(user_data.user_id, "Logged in", None, self.get_remote_ip()) db_helper.add_to_audit_log(user_data.user_id, "Logged in", 0, self.get_remote_ip())
cookie_data = { cookie_data = {
"username": user_data.username, "username": user_data.username,

View File

@ -22,6 +22,7 @@ try:
from app.classes.web.panel_handler import PanelHandler from app.classes.web.panel_handler import PanelHandler
from app.classes.web.default_handler import DefaultHandler from app.classes.web.default_handler import DefaultHandler
from app.classes.web.server_handler import ServerHandler from app.classes.web.server_handler import ServerHandler
from app.classes.web.ajax_handler import AjaxHandler
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))
@ -120,6 +121,7 @@ class webserver:
(r'/public/(.*)', PublicHandler), (r'/public/(.*)', PublicHandler),
(r'/panel/(.*)', PanelHandler), (r'/panel/(.*)', PanelHandler),
(r'/server/(.*)', ServerHandler), (r'/server/(.*)', ServerHandler),
(r'/ajax/(.*)', AjaxHandler),
] ]
app = tornado.web.Application( app = tornado.web.Application(

View File

@ -35,4 +35,28 @@
.sidebar > .nav .nav-item .nav-link, .collapsed{ .sidebar > .nav .nav-item .nav-link, .collapsed{
padding: 15px 30px; padding: 15px 30px;
}
.mc-log-time{
color:#19d895;
}
.mc-log-info{
color:#8862e0;
}
.mc-log-warn{
color:#ffaf00;
}
.mc-log-error{
color:#ff6258;
}
.mc-log-keyword{
color:#2196f3;
}
.scrollable-element {
scrollbar-color: red yellow;
} }

View File

@ -132,6 +132,7 @@
{% else %} {% else %}
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"></i></a> &nbsp; <a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"></i></a> &nbsp;
{% end %} {% end %}
</td> </td>
<td> <td>

View File

@ -24,14 +24,58 @@
</div> </div>
<!-- Page Title Header Ends--> <!-- Page Title Header Ends-->
<div class="row">
<div class="col-sm-12 grid-margin">
<div class="card">
<div class="card-body pt-3 pb-3">
<div class="row">
<div class="col-sm-3 mr-2">
<b>Server Status:</b>
{% if data['server_stats'][0]['running'] %}
<span class="text-success">Online</span><br />
<b>Server Started:</b> {{ data['server_stats'][0]['started'] }}
{% else %}
<span class="text-danger">Offline</span><br />
<b>Server Started:</b> Not Started
{% end %}
</div>
<div class="col-sm-3 mr-2">
<b>CPU:</b> {{ data['server_stats'][0]['cpu'] }}% <br />
<b>Mem:</b> {{ data['server_stats'][0]['mem'] }} <br />
{% if data['server_stats'][0]['int_ping_results'] %}
<b>Players:</b> {{ data['server_stats'][0]['online'] }} / {{ data['server_stats'][0]['max'] }}<br />
{% else %}
<b>Players:</b> 0/0<br />
{% end %}
</div>
<div class="col-sm-3 mr-2">
{% if data['server_stats'][0]['version'] != 'False' %}
<b>Server:</b> {{ data['server_stats'][0]['version'] }} <br />
<b>Desc:</b> {{ data['server_stats'][0]['desc'] }} <br />
{% else %}
<b>Server:</b> Unable To Connect <br />
<b>Desc:</b> Unable To Connect <br />
{% end %}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-sm-12 grid-margin"> <div class="col-sm-12 grid-margin">
<div class="card"> <div class="card">
<div class="card-body pt-0"> <div class="card-body pt-0">
<div class="row "> <ul class="nav nav-tabs col-md-12 tab-simple-styled " role="tablist">
<ul class="nav nav-tabs col-md-12 tab-simple-styled " role="tablist">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=term" role="tab" aria-selected="true"> <a class="nav-link active" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=term" role="tab" aria-selected="true">
<i class="fas fa-terminal"></i>Terminal</a> <i class="fas fa-terminal"></i>Terminal</a>
@ -56,22 +100,28 @@
<a class="nav-link" href="#analytics-2-6" role="tab" aria-selected="false"> <a class="nav-link" href="#analytics-2-6" role="tab" aria-selected="false">
<i class="fas fa-cogs"></i>Config</a> <i class="fas fa-cogs"></i>Config</a>
</li> </li>
<li>
<label class="p-0 m-0">
<input type="checkbox" name="stop_scroll" id="stop_scroll" />
{{ _('Stop Refresh') }}
</label>
</li>
</ul> </ul>
<div class="col-md-11">
<div class="input-group">
<textarea id="virt_console" rows="20" readonly class="form-control" style="background-color:#2a2c44;"></textarea>
</div>
<br />
<div class="input-group">
<input type="text" class="form-control" id="server_command" name="server_command" placeholder="Enter your server command" autofocus="">
<span class="input-group-btn ml-5">
<button id="submit" class="btn btn-sm btn-info" type="button">Send Command</button>
</span>
</div>
</div>
</div>
<div class="col-md-12">
<div class="input-group">
<div id="virt_console" class="" style="font-size: .8em; padding: 5px 10px; border: 1px solid #383e5d; background-color:#2a2c44;height:500px; overflow: scroll;"></div>
</div>
<br />
<div class="input-group">
<input type="text" class="form-control" id="server_command" name="server_command" placeholder="Enter your server command" autofocus="">
<span class="input-group-btn ml-5">
<button id="submit" class="btn btn-sm btn-info" type="button">Send Command</button>
</span>
</div>
</div>
</div> </div>
</div> </div>
@ -89,11 +139,85 @@
{% block js %} {% block js %}
<script> <script>
function get_server_log(){
if( !$("#stop_scroll").is(':checked')){
$.ajax({
type: 'GET',
url: '/ajax/server_log?id={{ data['server_stats'][0]['server_id']['server_id'] }}',
dataType: 'text',
success: function (data) {
console.log('Got Log From Server')
$('#virt_console').html(data);
scroll();
},
});
}
}
$( document ).ready(function() { //used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
console.log('ready for JS!') 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()
setInterval(function(){
get_server_log() // this will run after every 5 seconds
}, 1500);
});
$('#server_command').on('keydown', function (e) {
if (e.which == 13){
$(this).attr("disabled", "disabled"); //Disable textbox to prevent multiple submit
send_command_to_server()
$(this).removeAttr("disabled"); //Enable the textbox again if needed.
$(this).focus();
}
else if (e.which == 38){
last_command = $('#last_command').val()
$("#server_command").val(last_command)
}
});
$("#submit").click(function(e) {
e.preventDefault();
send_command_to_server();
});
function scroll(){
var logview = $('#virt_console');
if(logview.length)
logview.scrollTop(logview[0].scrollHeight - logview.height());
}
function send_command_to_server(){
var server_command = $("#server_command").val()
console.log(server_command)
$("#last_command").val(server_command)
var token = getCookie("_xsrf")
data_to_send = { command :server_command, }
console.log('sending command: ' + server_command)
$.ajax({
type: "POST",
headers: {'X-XSRFToken': token},
url: '/ajax/send_command?id={{ data['server_stats'][0]['server_id']['server_id'] }}',
data: data_to_send,
success: function(data){
console.log("got response:");
console.log(data);
$("#server_command").val('')
},
});
}
</script> </script>
{% end %} {% end %}

View File

@ -10,5 +10,7 @@
"stats_update_frequency": 60, "stats_update_frequency": 60,
"max_stats_count": 1000, "max_stats_count": 1000,
"delete_default_json": false, "delete_default_json": false,
"show_contribute_link": true "show_contribute_link": true,
"virtual_terminal_lines": 100,
"keywords": ["help", "chunk"]
} }