Zabezpieczenie API
This commit is contained in:
parent
dfb6f5f370
commit
3b689196a0
4 changed files with 155 additions and 51 deletions
46
app/api.py
46
app/api.py
|
@ -17,6 +17,7 @@ client = docker.from_env()
|
||||||
|
|
||||||
# Server Deployment
|
# Server Deployment
|
||||||
@api.route('/setup', methods=['POST'])
|
@api.route('/setup', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def setup_server():
|
def setup_server():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
username = oidc.user_getfield('preferred_username')
|
username = oidc.user_getfield('preferred_username')
|
||||||
|
@ -31,9 +32,9 @@ def setup_server():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/delete', methods=['POST'])
|
@api.route('/delete', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def delete():
|
def delete():
|
||||||
data = request.get_json()
|
username = oidc.user_getfield('preferred_username')
|
||||||
username = data.get("username")
|
|
||||||
|
|
||||||
if not username:
|
if not username:
|
||||||
return jsonify({"error": "Brak nazwy użytkownika"}), 400
|
return jsonify({"error": "Brak nazwy użytkownika"}), 400
|
||||||
|
@ -44,8 +45,9 @@ def delete():
|
||||||
|
|
||||||
# Server Controls
|
# Server Controls
|
||||||
@api.route('/start', methods=['POST'])
|
@api.route('/start', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def start():
|
def start():
|
||||||
username = request.json['username']
|
username = oidc.user_getfield('preferred_username')
|
||||||
setup_file_path = f"./servers/mc-{username}/server_info.json"
|
setup_file_path = f"./servers/mc-{username}/server_info.json"
|
||||||
|
|
||||||
if not os.path.exists(setup_file_path):
|
if not os.path.exists(setup_file_path):
|
||||||
|
@ -66,22 +68,25 @@ def start():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/stop', methods=['POST'])
|
@api.route('/stop', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def stop():
|
def stop():
|
||||||
username = request.json['username']
|
username = oidc.user_getfield('preferred_username')
|
||||||
stop_server(username)
|
stop_server(username)
|
||||||
return jsonify({"status": "stopped"})
|
return jsonify({"status": "stopped"})
|
||||||
|
|
||||||
|
|
||||||
@api.route('/restart', methods=['POST'])
|
@api.route('/restart', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def restart():
|
def restart():
|
||||||
username = request.json['username']
|
username = oidc.user_getfield('preferred_username')
|
||||||
restart_server(username)
|
restart_server(username)
|
||||||
return jsonify({"status": "restarted"})
|
return jsonify({"status": "restarted"})
|
||||||
|
|
||||||
|
|
||||||
@api.route('/logs', methods=['GET'])
|
@api.route('/logs', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
def logs():
|
def logs():
|
||||||
username = request.args.get('username')
|
username = oidc.user_getfield('preferred_username')
|
||||||
return jsonify({"logs": get_logs(username)})
|
return jsonify({"logs": get_logs(username)})
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +97,9 @@ def send_command():
|
||||||
username = data['username']
|
username = data['username']
|
||||||
command = data['command']
|
command = data['command']
|
||||||
|
|
||||||
|
if username != oidc.user_getfield('preferred_username'):
|
||||||
|
return jsonify({"error": "Unauthorized request."}), 403
|
||||||
|
|
||||||
container_name = f"mc-{username}"
|
container_name = f"mc-{username}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -107,8 +115,9 @@ def send_command():
|
||||||
|
|
||||||
# Files APIs (Upload, download, delete)
|
# Files APIs (Upload, download, delete)
|
||||||
@api.route('/files', methods=['GET'])
|
@api.route('/files', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
def list_files():
|
def list_files():
|
||||||
username = request.args.get('username')
|
username = oidc.user_getfield('preferred_username')
|
||||||
path = request.args.get('path', '')
|
path = request.args.get('path', '')
|
||||||
|
|
||||||
base_path = os.path.abspath(f'./servers/mc-{username}')
|
base_path = os.path.abspath(f'./servers/mc-{username}')
|
||||||
|
@ -134,8 +143,9 @@ def list_files():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/files/download', methods=['GET'])
|
@api.route('/files/download', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
def download_file():
|
def download_file():
|
||||||
username = request.args.get('username')
|
username = oidc.user_getfield('preferred_username')
|
||||||
path = request.args.get('path')
|
path = request.args.get('path')
|
||||||
|
|
||||||
base_path = os.path.abspath(f'./servers/mc-{username}')
|
base_path = os.path.abspath(f'./servers/mc-{username}')
|
||||||
|
@ -150,8 +160,9 @@ def download_file():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/files/upload', methods=['POST'])
|
@api.route('/files/upload', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def upload_file():
|
def upload_file():
|
||||||
username = request.form.get('username')
|
username = oidc.user_getfield('preferred_username')
|
||||||
path = request.form.get('path', '')
|
path = request.form.get('path', '')
|
||||||
file = request.files['files']
|
file = request.files['files']
|
||||||
base_path = os.path.abspath(f'./servers/mc-{username}')
|
base_path = os.path.abspath(f'./servers/mc-{username}')
|
||||||
|
@ -167,12 +178,17 @@ def upload_file():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/files/delete', methods=['POST'])
|
@api.route('/files/delete', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def delete_file_or_folder():
|
def delete_file_or_folder():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
username = data.get('username')
|
username = data.get('username')
|
||||||
|
if username != oidc.user_getfield('preferred_username'):
|
||||||
|
return jsonify({"error": "Unauthorized request."}), 403
|
||||||
|
|
||||||
path = data.get('path')
|
path = data.get('path')
|
||||||
base_path = os.path.abspath(f'./servers/mc-{username}')
|
base_path = os.path.abspath(f'./servers/mc-{username}')
|
||||||
target_path = os.path.abspath(os.path.join(base_path, path))
|
target_path = os.path.abspath(os.path.join(base_path, path))
|
||||||
|
|
||||||
if not target_path.startswith(base_path):
|
if not target_path.startswith(base_path):
|
||||||
return abort(403)
|
return abort(403)
|
||||||
if not os.path.exists(target_path):
|
if not os.path.exists(target_path):
|
||||||
|
@ -189,8 +205,9 @@ def delete_file_or_folder():
|
||||||
|
|
||||||
# Server config
|
# Server config
|
||||||
@api.route('/config')
|
@api.route('/config')
|
||||||
|
@oidc.require_login
|
||||||
def get_config():
|
def get_config():
|
||||||
username = request.args.get('username')
|
username = oidc.user_getfield('preferred_username')
|
||||||
server_info_path = f'./servers/mc-{username}/server_info.json'
|
server_info_path = f'./servers/mc-{username}/server_info.json'
|
||||||
if not os.path.exists(server_info_path):
|
if not os.path.exists(server_info_path):
|
||||||
return jsonify({"success": False, "message": "Server config not found"})
|
return jsonify({"success": False, "message": "Server config not found"})
|
||||||
|
@ -201,9 +218,13 @@ def get_config():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/config', methods=['POST'])
|
@api.route('/config', methods=['POST'])
|
||||||
|
@oidc.require_login
|
||||||
def update_config():
|
def update_config():
|
||||||
data = request.json
|
data = request.json
|
||||||
username = data.get('username')
|
username = data.get('username')
|
||||||
|
if username != oidc.user_getfield('preferred_username'):
|
||||||
|
return jsonify({"error": "Unauthorized request."}), 403
|
||||||
|
|
||||||
incoming_config = data.get('config', {})
|
incoming_config = data.get('config', {})
|
||||||
server_info_path = f'./servers/mc-{username}/server_info.json'
|
server_info_path = f'./servers/mc-{username}/server_info.json'
|
||||||
if os.path.exists(server_info_path):
|
if os.path.exists(server_info_path):
|
||||||
|
@ -211,9 +232,11 @@ def update_config():
|
||||||
server_info = json.load(f)
|
server_info = json.load(f)
|
||||||
else:
|
else:
|
||||||
server_info = DEFAULT_CONFIG.copy()
|
server_info = DEFAULT_CONFIG.copy()
|
||||||
|
|
||||||
for key in ["type", "version"]:
|
for key in ["type", "version"]:
|
||||||
if key in incoming_config:
|
if key in incoming_config:
|
||||||
server_info[key] = incoming_config.pop(key)
|
server_info[key] = incoming_config.pop(key)
|
||||||
|
|
||||||
formatted_config = {key.replace('_', '-'): value for key, value in incoming_config.items()}
|
formatted_config = {key.replace('_', '-'): value for key, value in incoming_config.items()}
|
||||||
server_info["config"] = formatted_config
|
server_info["config"] = formatted_config
|
||||||
with open(server_info_path, 'w') as f:
|
with open(server_info_path, 'w') as f:
|
||||||
|
@ -235,8 +258,9 @@ def status():
|
||||||
|
|
||||||
|
|
||||||
@api.route('/stats', methods=['GET'])
|
@api.route('/stats', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
def stats():
|
def stats():
|
||||||
username = request.args.get("username")
|
username = oidc.user_getfield("preferred_username")
|
||||||
container_name = f"mc-{username}"
|
container_name = f"mc-{username}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -528,26 +528,6 @@ a.non-link:hover {
|
||||||
justify-content: center;
|
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 */
|
/* 404 Error */
|
||||||
.error-container {
|
.error-container {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
|
@ -580,25 +560,6 @@ a.non-link:hover {
|
||||||
margin-bottom: 2rem;
|
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 {
|
.back-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.75rem 1.5rem;
|
padding: 0.75rem 1.5rem;
|
||||||
|
@ -614,4 +575,119 @@ a.non-link:hover {
|
||||||
.back-button:hover {
|
.back-button:hover {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #000;
|
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;
|
||||||
}
|
}
|
|
@ -9,6 +9,10 @@
|
||||||
<button class="tab-button" onclick="showTab('files')">Pliki 📁</button>
|
<button class="tab-button" onclick="showTab('files')">Pliki 📁</button>
|
||||||
<button class="tab-button" onclick="showTab('config')">Konfiguracja 🛠️</button>
|
<button class="tab-button" onclick="showTab('config')">Konfiguracja 🛠️</button>
|
||||||
<button class="tab-button" onclick="showTab('statistics')">Statystyki 📈</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>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
|
@ -12,6 +12,6 @@
|
||||||
<li><b>Motywacja</b> do dalszego rozwijania panelu</li>
|
<li><b>Motywacja</b> do dalszego rozwijania panelu</li>
|
||||||
<li><b>Wsparcie</b> w opłacaniu serwera na backupy</li>
|
<li><b>Wsparcie</b> w opłacaniu serwera na backupy</li>
|
||||||
</ul>
|
</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>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Add table
Reference in a new issue