mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
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:
parent
ab1772397d
commit
adf8d3f51a
@ -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')
|
||||||
|
72
app/classes/web/ajax_handler.py
Normal file
72
app/classes/web/ajax_handler.py
Normal 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
|
||||||
|
|
||||||
|
|
@ -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,
|
||||||
|
@ -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(
|
||||||
|
@ -36,3 +36,27 @@
|
|||||||
.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;
|
||||||
|
}
|
@ -132,6 +132,7 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"></i></a>
|
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"></i></a>
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
@ -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 %}
|
@ -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"]
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user