Merge branch 'dev' into tweak/themes

This commit is contained in:
Zedifus 2022-10-08 18:12:37 +01:00
commit fbb6dad524
16 changed files with 254 additions and 203 deletions

View File

@ -4,8 +4,11 @@
TBD
### Bug fixes
- Fix conditional issue with zip imports/uploads ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/476))
- Fix API Schedule updates ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/478))
- Add port constraint for all server creation & api ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/479))
- Clean up backup configs when deleting servers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/480))
### Tweaks
- Fix sidebar to not move when scrolling ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/475))
- Fix sidebar to not move when scrolling ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/481))
### Lang
TBD
<br><br>

View File

@ -134,8 +134,13 @@ class ServersController(metaclass=Singleton):
role_id = role.role_id
role_data = RolesController.get_role_with_servers(role_id)
role_data["servers"] = {server_id}
# Remove server id permissions from role
PermissionsServers.delete_roles_permissions(role_id, role_data["servers"])
# Remove roles from server
PermissionsServers.remove_roles_of_server(server_id)
# Remove backup configs tied to server
self.management_helper.remove_backup_config(server_id)
# Finally remove server
self.servers_helper.remove_server(server_id)
@staticmethod

View File

@ -139,7 +139,7 @@ def ping(ip, port):
try:
sock.connect((ip, port))
except socket.error:
except:
return False
try:

View File

@ -367,6 +367,10 @@ class HelpersManagement:
}
return conf
@staticmethod
def remove_backup_config(server_id):
Backups.delete().where(Backups.server_id == server_id).execute()
def set_backup_config(
self,
server_id: int,

View File

@ -420,6 +420,7 @@ class Controller:
and root_create_data["create_type"] == "download_jar"
):
self.server_jars.download_jar(
create_data["category"],
create_data["type"],
create_data["version"],
full_jar_path,

View File

@ -436,7 +436,15 @@ class TasksManager:
and "cron_string" in job_data
and "interval_type" in job_data
):
return
if not "enabled" in job_data:
return
if job_data["enabled"] is True:
job_data = HelpersManagement.get_scheduled_task(sch_id)
job_data["server_id"] = job_data["server_id"]["server_id"]
else:
self.scheduler.remove_job(str(sch_id))
return
try:
if job_data["interval"] != "reaction":

View File

@ -1501,6 +1501,12 @@ class PanelHandler(BaseHandler):
execution_command = self.get_argument("execution_command", None)
server_ip = self.get_argument("server_ip", None)
server_port = self.get_argument("server_port", None)
if int(server_port) < 1 or int(server_port) > 65535:
self.redirect(
"/panel/error?error=Constraint Error: "
"Port must be greater than 0 and less than 65535"
)
return
executable_update_url = self.get_argument("executable_update_url", "")
show_status = int(float(self.get_argument("show_status", "0")))
else:

View File

@ -648,7 +648,7 @@ class ApiServersIndexHandler(BaseApiHandler):
try:
data = orjson.loads(self.request.body)
except orjson.decoder.JSONDecodeError as e:
except orjson.JSONDecodeError as e:
return self.finish_json(
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
)
@ -664,7 +664,22 @@ class ApiServersIndexHandler(BaseApiHandler):
"error_data": str(e),
},
)
# Check to make sure port is allowable
if data["monitoring_type"] == "minecraft_java":
try:
port = data["minecraft_java_monitoring_data"]["port"]
except:
port = 25565
else:
try:
port = data["minecraft_bedrock_monitoring_data"]["port"]
except:
port = 19132
if port > 65535 or port < 1:
self.finish_json(
405, {"status": "error", "error": "DATA CONSTRAINT FAILED"}
)
return
new_server_id, new_server_uuid = self.controller.create_api_server(
data, user["user_id"]
)

View File

@ -4,7 +4,6 @@ import json
import logging
from jsonschema import ValidationError, validate
from app.classes.models.management import HelpersManagement
from app.classes.models.server_permissions import EnumPermissionsServer
from app.classes.web.base_api_handler import BaseApiHandler
@ -97,7 +96,7 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler):
if str(data.get("parent")) == str(task_id) and data.get("parent") is not None:
data["parent"] = None
HelpersManagement.update_scheduled_task(task_id, data)
self.tasks_manager.update_job(task_id, data)
self.controller.management.add_to_audit_log(
auth_data[4]["user_id"],

View File

@ -311,6 +311,12 @@ class ServerHandler(BaseHandler):
min_mem = bleach.clean(self.get_argument("min_memory", ""))
max_mem = bleach.clean(self.get_argument("max_memory", ""))
port = bleach.clean(self.get_argument("port", ""))
if int(port) < 1 or int(port) > 65535:
self.redirect(
"/panel/error?error=Constraint Error: "
"Port must be greater than 0 and less than 65535"
)
return
import_type = bleach.clean(self.get_argument("create_type", ""))
import_server_path = bleach.clean(self.get_argument("server_path", ""))
import_server_jar = bleach.clean(self.get_argument("server_jar", ""))
@ -451,6 +457,12 @@ class ServerHandler(BaseHandler):
server = bleach.clean(self.get_argument("server", ""))
server_name = bleach.clean(self.get_argument("server_name", ""))
port = bleach.clean(self.get_argument("port", ""))
if int(port) < 1 or int(port) > 65535:
self.redirect(
"/panel/error?error=Constraint Error: "
"Port must be greater than 0 and less than 65535"
)
return
import_type = bleach.clean(self.get_argument("create_type", ""))
import_server_path = bleach.clean(self.get_argument("server_path", ""))
import_server_exe = bleach.clean(self.get_argument("server_jar", ""))

View File

@ -8,6 +8,26 @@
color: var(--base-text)
}
nav.sidebar {
position: fixed;
}
@media (min-width: 992px) {
nav.sidebar {
position: fixed;
max-height: auto;
}
.main-panel {
margin-left: 270px;
}
.sidebar-icon-only .main-panel {
margin-left: 70px;
}
}
.sidebar>.nav>.nav-item:not(.nav-profile)>.nav-link:before {
content: none;
@ -21,30 +41,6 @@
display: block;
}
.sticky-sidebar {
position: fixed;
max-height: fit-content;
width: (100% - 270px);
z-index: 100;
}
.main-panel {
margin-left: 70px;
margin-top: 63px;
}
@media (min-width: 1200px) {
.main-panel {
margin-left: 270px;
}
}
@media (max-width: 991px) {
.main-panel {
margin-left: 0px;
}
}
.toggle-handle {
background-color: white !important;
}

View File

@ -197,6 +197,12 @@ if ($("canvas").length) {
!body.hasClass("sidebar-icon-only")
);
}
if (vw >= 992 && vw < 1200) {
localStorage.setItem(
"crafty-sidebar-expanded",
!body.hasClass("sidebar-icon-only")
);
}
}
});

View File

@ -55,43 +55,42 @@
</head>
<body>
<!-- partial:partials/_navbar.html -->
<nav class="navbar default-layout col-lg-12 col-12 p-0 fixed-top d-flex flex-row">
<div class="text-center navbar-brand-wrapper d-flex align-items-top justify-content-center">
<a class="navbar-brand brand-logo" href="/panel/dashboard">
<img src="/static/assets/images/logo_long.svg" alt="logo" /> </a>
<a class="navbar-brand brand-logo-mini" href="/panel/dashboard">
<img src="/static/assets/images/logo_small.svg" alt="logo" /> </a>
</div>
<div class="navbar-menu-wrapper d-flex align-items-center">
<style>
body:not(.sidebar-icon-only) .navbar-toggler .mdi-chevron-double-right {
display: none;
}
body.sidebar-icon-only .navbar-toggler .mdi-chevron-double-left {
display: none;
}
</style>
<button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize">
<span class="mdi mdi-chevron-double-left"></span>
<span class="mdi mdi-chevron-double-right"></span>
</button>
{% include notify.html %}
<button class="navbar-toggler navbar-toggler-right d-lg-none align-self-center" type="button"
data-toggle="offcanvas">
<span class="mdi mdi-menu"></span>
</button>
</div>
</nav>
<div class="container-scroller">
<div class="flex-column">
<div class="sticky-sidebar">
{% include main_menu.html %}
<!-- partial:partials/_navbar.html -->
<nav class="navbar default-layout col-lg-12 col-12 p-0 fixed-top d-flex flex-row">
<div class="text-center navbar-brand-wrapper d-flex align-items-top justify-content-center">
<a class="navbar-brand brand-logo" href="/panel/dashboard">
<img src="/static/assets/images/logo_long.svg" alt="logo" /> </a>
<a class="navbar-brand brand-logo-mini" href="/panel/dashboard">
<img src="/static/assets/images/logo_small.svg" alt="logo" /> </a>
</div>
<div class="navbar-menu-wrapper d-flex align-items-center">
<style>
body:not(.sidebar-icon-only) .navbar-toggler .mdi-chevron-double-right {
display: none;
}
body.sidebar-icon-only .navbar-toggler .mdi-chevron-double-left {
display: none;
}
</style>
<button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize">
<span class="mdi mdi-chevron-double-left"></span>
<span class="mdi mdi-chevron-double-right"></span>
</button>
{% include notify.html %}
<button class="navbar-toggler navbar-toggler-right d-lg-none align-self-center" type="button"
data-toggle="offcanvas">
<span class="mdi mdi-menu"></span>
</button>
</div>
</nav>
<div class="container-fluid page-body-wrapper">
{% include main_menu.html %}
<div class="main-panel">
<div class="warnings">
@ -107,6 +106,7 @@
</div>
<!-- main-panel ends -->
</div>
<!-- page-body-wrapper ends -->
</div>

View File

@ -1,145 +1,141 @@
<!-- partial -->
<div class="container-fluid page-body-wrapper vh-100">
<!-- partial:partials/_sidebar.html -->
<style>
@media screen and (max-width: 991px) {
.sidebar-offcanvas {
-webkit-transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
box-shadow: 0px 8px 17px 2px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12), 0px 5px 5px -3px rgba(0, 0, 0, 0.2);
}
<!-- partial:partials/_sidebar.html -->
<style>
@media screen and (max-width: 991px) {
.sidebar-offcanvas {
-webkit-transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
box-shadow: 0px 8px 17px 2px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12), 0px 5px 5px -3px rgba(0, 0, 0, 0.2);
}
</style>
<script>
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
}
</style>
<script>
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
function isExtraLargeBreakpoint() {
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
return vw >= 1200;
};
function isExtraLargeBreakpoint() {
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
return vw >= 1200;
}
function isLargeBreakpoint() {
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
return vw >= 992;
}
$(document).ready(function () {
sidebarResizeHandler(null);
$(window).on(
'resize',
debounce(sidebarResizeHandler, 25, true)
);
});
function sidebarResizeHandler(e) {
/*
Viewport sizes: Extra large (vw >= 1200px), large (vw >= 992px), medium (vw >= 768px)
- A localstorage item is set to remember a user's preference between collapsed or expanded.
- For extra large viewports, the sidebar is the user's preference (by default expanded). When
expanded or collapsed manually, it doesn't overlap the page content and the preference
gets saved to a localstorage item.
- For large viewports, the sidebar is collapsed. When expanded manually, it doesn't overlap
the page content. The user's localstorage preference is not overridden during this state.
- For medium and below viewports, the sidebar is hidden behing a hamburger icon. When expanded, the sidebar
overlaps the page content. The user's localstorage preference is not overridden during this state.
More code in `app/frontend/static/assets/js/shared/misc.js` and `app/frontend/templates/base.html`
*/
if (isLargeBreakpoint()) {
let value = localStorage.getItem('crafty-sidebar-expanded') !== 'false';
$('body').toggleClass('sidebar-icon-only', !value);
localStorage.setItem('crafty-sidebar-expanded', value);
}
function isLargeBreakpoint() {
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
return vw >= 992;
}
$(document).ready(function () {
sidebarResizeHandler(null);
$(window).on(
'resize',
debounce(sidebarResizeHandler, 25, true)
);
});
function sidebarResizeHandler(e) {
/*
Viewport sizes: Extra large (vw >= 1200px), large (vw >= 992px), medium (vw >= 768px)
- A localstorage item is set to remember a user's preference between collapsed or expanded.
- For extra large viewports, the sidebar is the user's preference (by default expanded). When
expanded or collapsed manually, it doesn't overlap the page content and the preference
gets saved to a localstorage item.
- For large viewports, the sidebar is collapsed. When expanded manually, it doesn't overlap
the page content. The user's localstorage preference is not overridden during this state.
- For medium and below viewports, the sidebar is hidden behing a hamburger icon. When expanded, the sidebar
overlaps the page content. The user's localstorage preference is not overridden during this state.
}
</script>
<nav class="sidebar sidebar-offcanvas" id="sidebar">
<ul class="nav">
More code in `app/frontend/static/assets/js/shared/misc.js` and `app/frontend/templates/base.html`
*/
if (isExtraLargeBreakpoint()) {
let value = localStorage.getItem('crafty-sidebar-expanded') !== 'false';
$('body').toggleClass('sidebar-icon-only', !value);
localStorage.setItem('crafty-sidebar-expanded', value);
} else if (isLargeBreakpoint()) {
$('body').toggleClass('sidebar-icon-only', true);
}
}
</script>
<nav class="sidebar sidebar-offcanvas" id="sidebar">
<ul class="nav">
<li class="nav-item nav-category" style="margin-top:10px;">{{ translate('sidebar', 'navigation', data['lang']) }}
</li>
<li class="nav-item nav-category" style="margin-top:10px;">{{ translate('sidebar', 'navigation', data['lang']) }}
</li>
<li class="nav-item">
<a class="nav-link" href="/panel/dashboard">
<i class="fas fa-chart-network"></i>&nbsp;
<span class="menu-title">{{ translate('sidebar', 'dashboard', data['lang']) }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/panel/dashboard">
<i class="fas fa-chart-network"></i>&nbsp;
<span class="menu-title">{{ translate('sidebar', 'dashboard', data['lang']) }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="collapse" href="#page-layouts" aria-expanded="false"
aria-controls="page-layouts">
<i class="fas fa-server"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'servers', data['lang']) }}</span>
<i class="menu-arrow"></i>
</a>
<div class="collapse" id="page-layouts">
<ul class="nav flex-column sub-menu">
{% if data['crafty_permissions']['Server_Creation'] in data['user_crafty_permissions'] %}
<li class="nav-item">
<a class="nav-link" href="/server/step1"><i class="fas fa-plus-circle"></i> &nbsp; {{ translate('sidebar',
'newServer', data['lang']) }}</a>
</li>
{% end %}
{% for s in data['menu_servers'] %}
<li class="nav-item">
<a class="nav-link" href="/panel/server_detail?id={{s['server_id']}}"><i class="fas fa-server"></i> &nbsp;
{{s['server_name']}}</a>
</li>
{% end %}
<li class="nav-item">
<a class="nav-link" data-toggle="collapse" href="#page-layouts" aria-expanded="false"
aria-controls="page-layouts">
<i class="fas fa-server"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'servers', data['lang']) }}</span>
<i class="menu-arrow"></i>
</a>
<div class="collapse" id="page-layouts">
<ul class="nav flex-column sub-menu">
{% if data['crafty_permissions']['Server_Creation'] in data['user_crafty_permissions'] %}
<li class="nav-item">
<a class="nav-link" href="/server/step1"><i class="fas fa-plus-circle"></i> &nbsp; {{ translate('sidebar',
'newServer', data['lang']) }}</a>
</li>
{% end %}
{% for s in data['menu_servers'] %}
<li class="nav-item">
<a class="nav-link" href="/panel/server_detail?id={{s['server_id']}}"><i class="fas fa-server"></i> &nbsp;
{{s['server_name']}}</a>
</li>
{% end %}
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="https://wiki.craftycontrol.com" target="_blank">
<i class="fas fa-book"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'documentation', data['lang']) }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://wiki.craftycontrol.com" target="_blank">
<i class="fas fa-book"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'documentation', data['lang']) }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/panel/wiki">
<i class="fa fa-info-circle"></i> &nbsp;
<span class="menu-title">Wiki</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/panel/wiki">
<i class="fa fa-info-circle"></i> &nbsp;
<span class="menu-title">Wiki</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://discord.gg/9VJPhCE" target="_blank">
<i class="fab fa-discord"></i> &nbsp;
<span class="menu-title">Discord</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://discord.gg/9VJPhCE" target="_blank">
<i class="fab fa-discord"></i> &nbsp;
<span class="menu-title">Discord</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/panel/credits">
<i class="fas fa-heart"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'credits', data['lang']) }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/panel/credits">
<i class="fas fa-heart"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'credits', data['lang']) }}</span>
</a>
</li>
{% if data['show_contribute'] %}
<li class="nav-item">
<a class="nav-link" href="/panel/contribute">
<i class="fas fa-donate"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'contribute', data['lang']) }}</span>
</a>
</li>
{% end %}
{% if data['show_contribute'] %}
<li class="nav-item">
<a class="nav-link" href="/panel/contribute">
<i class="fas fa-donate"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'contribute', data['lang']) }}</span>
</a>
</li>
{% end %}
</ul>
</nav>
<!-- partial -->
</div>
</ul>
</nav>
<!-- partial -->

View File

@ -131,7 +131,7 @@
<label for="port2">{{ translate('serverWizard', 'serverPort', data['lang']) }}
<small></small></label>
<input type="number" class="form-control" id="port2" name="port" value="19132" step="1" min="1"
required>
max="65535" required>
</div>
</div>
<div class="col-sm-12">
@ -241,7 +241,7 @@
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }}
<small></small></label>
<input type="number" class="form-control" id="port3" name="port" value="19132" step="1" min="1"
required>
max="65535" required>
</div>
</div>
@ -387,7 +387,7 @@
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port4" name="port" value="19132" step="1" min="1"
required>
max="65535" required>
</div>
</div>

View File

@ -109,7 +109,7 @@
<label for="port1">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port1" name="port" value="25565" step="1" min="1"
required>
max="65535 " required>
</div>
</div>
<div class="col-sm-12">
@ -224,7 +224,7 @@
<label for="port2">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port2" name="port" value="25565" step="1" min="1"
required>
max="65535" required>
</div>
</div>
<div class="col-sm-12">
@ -351,7 +351,7 @@
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port3" name="port" value="25565" step="1" min="1"
required>
max="65535" required>
</div>
</div>
@ -515,7 +515,7 @@
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port3" name="port" value="25565" step="1" min="1"
required>
max="65535" required>
</div>
</div>