Zabezpieczenie API

This commit is contained in:
Andus 2025-04-13 17:11:29 +02:00
parent dfb6f5f370
commit 3b689196a0
4 changed files with 155 additions and 51 deletions

View file

@ -17,6 +17,7 @@ client = docker.from_env()
# Server Deployment
@api.route('/setup', methods=['POST'])
@oidc.require_login
def setup_server():
data = request.get_json()
username = oidc.user_getfield('preferred_username')
@ -31,9 +32,9 @@ def setup_server():
@api.route('/delete', methods=['POST'])
@oidc.require_login
def delete():
data = request.get_json()
username = data.get("username")
username = oidc.user_getfield('preferred_username')
if not username:
return jsonify({"error": "Brak nazwy użytkownika"}), 400
@ -44,8 +45,9 @@ def delete():
# Server Controls
@api.route('/start', methods=['POST'])
@oidc.require_login
def start():
username = request.json['username']
username = oidc.user_getfield('preferred_username')
setup_file_path = f"./servers/mc-{username}/server_info.json"
if not os.path.exists(setup_file_path):
@ -66,22 +68,25 @@ def start():
@api.route('/stop', methods=['POST'])
@oidc.require_login
def stop():
username = request.json['username']
username = oidc.user_getfield('preferred_username')
stop_server(username)
return jsonify({"status": "stopped"})
@api.route('/restart', methods=['POST'])
@oidc.require_login
def restart():
username = request.json['username']
username = oidc.user_getfield('preferred_username')
restart_server(username)
return jsonify({"status": "restarted"})
@api.route('/logs', methods=['GET'])
@oidc.require_login
def logs():
username = request.args.get('username')
username = oidc.user_getfield('preferred_username')
return jsonify({"logs": get_logs(username)})
@ -92,6 +97,9 @@ def send_command():
username = data['username']
command = data['command']
if username != oidc.user_getfield('preferred_username'):
return jsonify({"error": "Unauthorized request."}), 403
container_name = f"mc-{username}"
try:
@ -107,8 +115,9 @@ def send_command():
# Files APIs (Upload, download, delete)
@api.route('/files', methods=['GET'])
@oidc.require_login
def list_files():
username = request.args.get('username')
username = oidc.user_getfield('preferred_username')
path = request.args.get('path', '')
base_path = os.path.abspath(f'./servers/mc-{username}')
@ -134,8 +143,9 @@ def list_files():
@api.route('/files/download', methods=['GET'])
@oidc.require_login
def download_file():
username = request.args.get('username')
username = oidc.user_getfield('preferred_username')
path = request.args.get('path')
base_path = os.path.abspath(f'./servers/mc-{username}')
@ -150,8 +160,9 @@ def download_file():
@api.route('/files/upload', methods=['POST'])
@oidc.require_login
def upload_file():
username = request.form.get('username')
username = oidc.user_getfield('preferred_username')
path = request.form.get('path', '')
file = request.files['files']
base_path = os.path.abspath(f'./servers/mc-{username}')
@ -167,12 +178,17 @@ def upload_file():
@api.route('/files/delete', methods=['POST'])
@oidc.require_login
def delete_file_or_folder():
data = request.get_json()
username = data.get('username')
if username != oidc.user_getfield('preferred_username'):
return jsonify({"error": "Unauthorized request."}), 403
path = data.get('path')
base_path = os.path.abspath(f'./servers/mc-{username}')
target_path = os.path.abspath(os.path.join(base_path, path))
if not target_path.startswith(base_path):
return abort(403)
if not os.path.exists(target_path):
@ -189,8 +205,9 @@ def delete_file_or_folder():
# Server config
@api.route('/config')
@oidc.require_login
def get_config():
username = request.args.get('username')
username = oidc.user_getfield('preferred_username')
server_info_path = f'./servers/mc-{username}/server_info.json'
if not os.path.exists(server_info_path):
return jsonify({"success": False, "message": "Server config not found"})
@ -201,9 +218,13 @@ def get_config():
@api.route('/config', methods=['POST'])
@oidc.require_login
def update_config():
data = request.json
username = data.get('username')
if username != oidc.user_getfield('preferred_username'):
return jsonify({"error": "Unauthorized request."}), 403
incoming_config = data.get('config', {})
server_info_path = f'./servers/mc-{username}/server_info.json'
if os.path.exists(server_info_path):
@ -211,9 +232,11 @@ def update_config():
server_info = json.load(f)
else:
server_info = DEFAULT_CONFIG.copy()
for key in ["type", "version"]:
if key in incoming_config:
server_info[key] = incoming_config.pop(key)
formatted_config = {key.replace('_', '-'): value for key, value in incoming_config.items()}
server_info["config"] = formatted_config
with open(server_info_path, 'w') as f:
@ -235,8 +258,9 @@ def status():
@api.route('/stats', methods=['GET'])
@oidc.require_login
def stats():
username = request.args.get("username")
username = oidc.user_getfield("preferred_username")
container_name = f"mc-{username}"
try:

View file

@ -528,26 +528,6 @@ a.non-link:hover {
justify-content: center;
}
/* Mobile Tweaks */
@media (max-width: 600px) {
body {
padding: 24px 12px;
}
.dashboard-card {
padding: 20px;
}
.btn {
width: 100%;
margin: 8px 0;
}
.console-output {
height: 180px;
}
}
/* 404 Error */
.error-container {
max-width: 800px;
@ -580,25 +560,6 @@ a.non-link:hover {
margin-bottom: 2rem;
}
.references-list {
list-style: none;
padding: 0;
margin: 0 auto 3rem;
max-width: 600px;
text-align: left;
}
.references-list li {
margin: 1rem 0;
font-size: 1.1rem;
line-height: 1.5;
transition: transform 0.2s;
}
.references-list li:hover {
transform: translateX(10px);
}
.back-button {
display: inline-block;
padding: 0.75rem 1.5rem;
@ -614,4 +575,119 @@ a.non-link:hover {
.back-button:hover {
background-color: #fff;
color: #000;
}
/* Mobile Tweaks */
@media (max-width: 480px) {
html {
font-size: clamp(14px, 2.5vw, 16px);
}
/* Heading adjustment */
h2 {
font-size: 1.5rem;
}
/* Dashboard Card */
.dashboard-card {
padding: 16px;
max-width: 100%;
}
/* Tab buttons */
.tab-button {
padding: 10px;
font-size: 0.85rem;
}
/* Square button adjustments */
.square-button {
width: 100%;
aspect-ratio: unset;
flex-direction: row;
justify-content: flex-start;
gap: 12px;
padding: 10px;
font-size: 0.9rem;
}
.square-button img {
width: 32px;
margin: 0;
}
/* Navigation Bar */
.top-nav {
padding: 12px;
font-size: 0.9rem;
flex-direction: column;
align-items: flex-start;
}
.nav-links a {
margin-left: 10px;
font-size: 0.9rem;
}
/* Console Output */
.console-output {
font-size: 0.8rem;
height: 160px;
}
/* Chart container */
.chart-container {
width: 100%;
height: auto;
padding: 12px;
}
/* Buttons */
.btn {
font-size: 0.9rem;
padding: 12px;
width: 100%;
}
/* Form layout */
form {
padding: 0 8px;
}
/* Tab content spacing */
.tab-content {
margin-top: 8px;
}
/* Particle background on small screens */
#particle-background {
display: none; /* Improves performance */
}
/* Charts Row - Allow horizontal scroll */
.charts-row {
overflow-x: auto;
padding-bottom: 10px;
}
/* Input Fields */
input[type="text"], input[type="number"], select {
width: 100%;
}
/* Adjust drop zone */
#drop-zone {
padding: 20px;
}
/* Adjust text area height */
.console-output {
height: 160px;
}
}
/* Additional general fixes for small screens */
* {
max-width: 100%;
word-wrap: break-word;
}

View file

@ -9,6 +9,10 @@
<button class="tab-button" onclick="showTab('files')">Pliki 📁</button>
<button class="tab-button" onclick="showTab('config')">Konfiguracja 🛠️</button>
<button class="tab-button" onclick="showTab('statistics')">Statystyki 📈</button>
</div>
<div class="tabs">
<button class="tab-button" onclick="showTab('mods')">Mody/Pluginy 🧩</button>
</div>
<div class="tab-content">

View file

@ -12,6 +12,6 @@
<li><b>Motywacja</b> do dalszego rozwijania panelu</li>
<li><b>Wsparcie</b> w opłacaniu serwera na backupy</li>
</ul>
Donate możesz wysłać <a href="https://ko-fi.com/andusdev">tutaj</a>
<p>Donate możesz wysłać <a href="https://ko-fi.com/andusdev">tutaj</a></p>
</div>
{% endblock %}