Userverwaltung
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -34,6 +34,9 @@ __pycache__/
|
|||||||
!/srv/poe_manager/static/
|
!/srv/poe_manager/static/
|
||||||
!/srv/poe_manager/static/css/
|
!/srv/poe_manager/static/css/
|
||||||
!/srv/poe_manager/static/css/*
|
!/srv/poe_manager/static/css/*
|
||||||
|
!/srv/poe_manager/static/js/
|
||||||
|
!/srv/poe_manager/static/js/*
|
||||||
|
|
||||||
|
|
||||||
# Optional: SQLite DB ignorieren (falls du nicht willst, dass Passwörter im Repo landen)
|
# Optional: SQLite DB ignorieren (falls du nicht willst, dass Passwörter im Repo landen)
|
||||||
# /srv/poe_manager/sqlite.db
|
# /srv/poe_manager/sqlite.db
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
from flask import Flask, render_template, request, redirect, url_for, flash
|
from flask import Flask, render_template, request, redirect, url_for, flash
|
||||||
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin, current_user
|
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin, current_user
|
||||||
from flask_bcrypt import Bcrypt
|
from flask_bcrypt import Bcrypt
|
||||||
|
from werkzeug.security import generate_password_hash
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import glob, os, re
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = "309cc4d5ce1fe7486ae25cbd232bbdfe6a72539c03f0127d372186dbdc0fc928"
|
app.secret_key = "309cc4d5ce1fe7486ae25cbd232bbdfe6a72539c03f0127d372186dbdc0fc928"
|
||||||
@@ -235,10 +237,22 @@ def switches():
|
|||||||
|
|
||||||
switches = conn.execute("SELECT hostname, ip, username FROM switches").fetchall()
|
switches = conn.execute("SELECT hostname, ip, username FROM switches").fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('switches.html', switches=switches)
|
return render_template('switche.html', switches=switches)
|
||||||
|
|
||||||
import glob
|
@app.route("/get_log")
|
||||||
import os
|
@login_required
|
||||||
|
def get_log():
|
||||||
|
log_files = glob.glob("/var/log/rpi-*.log")
|
||||||
|
if not log_files:
|
||||||
|
return "Keine Logfiles gefunden."
|
||||||
|
|
||||||
|
latest_log = max(log_files, key=os.path.getctime)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(latest_log, "r") as f:
|
||||||
|
return f.read()
|
||||||
|
except Exception as e:
|
||||||
|
return f"Fehler beim Lesen des Logs: {e}"
|
||||||
|
|
||||||
@app.route('/logs')
|
@app.route('/logs')
|
||||||
@login_required
|
@login_required
|
||||||
@@ -259,8 +273,6 @@ def logs():
|
|||||||
|
|
||||||
return render_template('logs.html', log_content=log_content, log_name=os.path.basename(latest_log))
|
return render_template('logs.html', log_content=log_content, log_name=os.path.basename(latest_log))
|
||||||
|
|
||||||
import glob, os, re
|
|
||||||
|
|
||||||
def load_device_status():
|
def load_device_status():
|
||||||
"""
|
"""
|
||||||
Liest das aktuellste rpi-Logfile und extrahiert den letzten Status jedes Devices.
|
Liest das aktuellste rpi-Logfile und extrahiert den letzten Status jedes Devices.
|
||||||
@@ -292,5 +304,52 @@ def load_device_status():
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
@app.route("/users", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
|
def users():
|
||||||
|
if not current_user.is_admin:
|
||||||
|
flash("Nur Admins dürfen Benutzer verwalten!")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
conn = sqlite3.connect("sqlite.db")
|
||||||
|
conn.row_factory = sqlite3.Row # wichtig für Template
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
# Neues Benutzer hinzufügen
|
||||||
|
if request.method == "POST":
|
||||||
|
if "add_user" in request.form:
|
||||||
|
username = request.form["username"]
|
||||||
|
password = generate_password_hash(request.form["password"])
|
||||||
|
is_admin = 1 if "is_admin" in request.form else 0
|
||||||
|
try:
|
||||||
|
c.execute("INSERT INTO users (username, password, is_admin) VALUES (?, ?, ?)",
|
||||||
|
(username, password, is_admin))
|
||||||
|
conn.commit()
|
||||||
|
flash(f"Benutzer {username} hinzugefügt!")
|
||||||
|
except sqlite3.IntegrityError:
|
||||||
|
flash("Benutzername existiert bereits!")
|
||||||
|
|
||||||
|
if "delete_user" in request.form:
|
||||||
|
user_id = request.form["delete_user"]
|
||||||
|
c.execute("DELETE FROM users WHERE id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
flash("Benutzer gelöscht!")
|
||||||
|
|
||||||
|
if "edit_user" in request.form:
|
||||||
|
user_id = request.form["user_id"]
|
||||||
|
username = request.form["username"]
|
||||||
|
is_admin = 1 if "is_admin" in request.form else 0
|
||||||
|
c.execute("UPDATE users SET username=?, is_admin=? WHERE id=?",
|
||||||
|
(username, is_admin, user_id))
|
||||||
|
conn.commit()
|
||||||
|
flash("Benutzer geändert!")
|
||||||
|
|
||||||
|
# Alle Benutzer laden
|
||||||
|
c.execute("SELECT id, username, is_admin FROM users")
|
||||||
|
users_list = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return render_template("users.html", users=users_list)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
app.run(host='0.0.0.0', port=5000, debug=True)
|
||||||
|
|||||||
6
srv/poe_manager/static/css/bootstrap.min.css
vendored
Normal file
6
srv/poe_manager/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -22,3 +22,27 @@ pre {
|
|||||||
.mb-3 a.btn {
|
.mb-3 a.btn {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.device-card {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-name {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-online {
|
||||||
|
color: green;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-offline {
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|||||||
7
srv/poe_manager/static/js/bootstrap.bundle.min.js
vendored
Normal file
7
srv/poe_manager/static/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
32
srv/poe_manager/templates/base.html
Normal file
32
srv/poe_manager/templates/base.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ title or "PoE Manager" }}</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||||
|
</head>
|
||||||
|
<body class="p-4">
|
||||||
|
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="mb-4">
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<a href="{{ url_for('index') }}" class="btn btn-secondary">Dashboard</a>
|
||||||
|
<a href="{{ url_for('devices') }}" class="btn btn-secondary">Devices</a>
|
||||||
|
{% if current_user.is_admin %}
|
||||||
|
<a href="{{ url_for('switches') }}" class="btn btn-secondary">Switches</a>
|
||||||
|
<a href="{{ url_for('users') }}" class="btn btn-secondary">Users</a>
|
||||||
|
<a href="{{ url_for('logs') }}" class="btn btn-secondary">Live-Log</a>
|
||||||
|
<a href="{{ url_for('settings') }}" class="btn btn-secondary">Settings</a>
|
||||||
|
{% endif %}
|
||||||
|
<a href="{{ url_for('logout') }}" class="btn btn-danger">Logout</a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<div class="container-fluid">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% block content %}
|
||||||
<head>
|
|
||||||
<title>Devices</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body class="p-5">
|
|
||||||
|
|
||||||
<h2>Devices</h2>
|
<h2>Devices</h2>
|
||||||
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
|
|
||||||
|
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@@ -20,14 +14,13 @@
|
|||||||
<p>Prüfintervall: <strong>{{ interval }} Minuten</strong></p>
|
<p>Prüfintervall: <strong>{{ interval }} Minuten</strong></p>
|
||||||
|
|
||||||
{% if current_user.is_admin %}
|
{% if current_user.is_admin %}
|
||||||
<!-- Inline-Add Form -->
|
|
||||||
<h4>Neues Gerät hinzufügen</h4>
|
<h4>Neues Gerät hinzufügen</h4>
|
||||||
<form method="post" class="row g-2 mb-4">
|
<form method="post" class="row g-2 mb-4">
|
||||||
<input type="hidden" name="add_device" value="1">
|
<input type="hidden" name="add_device" value="1">
|
||||||
<div class="col"><input type="text" name="mac" placeholder="MAC" class="form-control" required></div>
|
<div class="col"><input type="text" name="name" placeholder="Hostname" class="form-control" required></div>
|
||||||
<div class="col"><input type="text" name="rpi_ip" placeholder="RPI IP" class="form-control" required></div>
|
<div class="col"><input type="text" name="rpi_ip" placeholder="IP-Adresse" class="form-control" required></div>
|
||||||
|
<div class="col"><input type="text" name="mac" placeholder="MAC-Adresse" class="form-control" required></div>
|
||||||
<div class="col"><input type="text" name="port" placeholder="Port" class="form-control" required></div>
|
<div class="col"><input type="text" name="port" placeholder="Port" class="form-control" required></div>
|
||||||
<div class="col"><input type="text" name="name" placeholder="Name" class="form-control" required></div>
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<select name="switch_hostname" class="form-control" required>
|
<select name="switch_hostname" class="form-control" required>
|
||||||
<option value="">Switch wählen</option>
|
<option value="">Switch wählen</option>
|
||||||
@@ -40,15 +33,14 @@
|
|||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Devices Table -->
|
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>MAC</th>
|
<th>Hostname</th>
|
||||||
<th>RPI IP</th>
|
<th>IP-Adresse</th>
|
||||||
<th>Port</th>
|
<th>MAC-Adresse</th>
|
||||||
<th>Name</th>
|
|
||||||
<th>Switch</th>
|
<th>Switch</th>
|
||||||
|
<th>Port</th>
|
||||||
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
|
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -56,14 +48,12 @@
|
|||||||
{% for d in devices %}
|
{% for d in devices %}
|
||||||
<tr>
|
<tr>
|
||||||
{% if current_user.is_admin %}
|
{% if current_user.is_admin %}
|
||||||
<!-- Inline-Edit Form -->
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="hidden" name="edit_device" value="1">
|
<input type="hidden" name="edit_device" value="1">
|
||||||
<input type="hidden" name="old_mac" value="{{ d['mac'] }}">
|
<input type="hidden" name="old_mac" value="{{ d['mac'] }}">
|
||||||
<td><input name="mac" value="{{ d['mac'] }}" class="form-control" required></td>
|
|
||||||
<td><input name="rpi_ip" value="{{ d['rpi_ip'] }}" class="form-control" required></td>
|
|
||||||
<td><input name="port" value="{{ d['port'] }}" class="form-control" required></td>
|
|
||||||
<td><input name="name" value="{{ d['name'] }}" class="form-control" required></td>
|
<td><input name="name" value="{{ d['name'] }}" class="form-control" required></td>
|
||||||
|
<td><input name="rpi_ip" value="{{ d['rpi_ip'] }}" class="form-control" required></td>
|
||||||
|
<td><input name="mac" value="{{ d['mac'] }}" class="form-control" required></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="switch_hostname" class="form-control" required>
|
<select name="switch_hostname" class="form-control" required>
|
||||||
{% for sw in switches %}
|
{% for sw in switches %}
|
||||||
@@ -73,21 +63,23 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
<td><input name="port" value="{{ d['port'] }}" class="form-control" required></td>
|
||||||
<td class="d-flex gap-1">
|
<td class="d-flex gap-1">
|
||||||
<button class="btn btn-primary btn-sm">Speichern</button>
|
<button class="btn btn-primary btn-sm">Speichern</button>
|
||||||
<button name="delete_device" value="{{ d['mac'] }}" class="btn btn-danger btn-sm" onclick="return confirm('Willst du das Gerät wirklich löschen?');"> Löschen </button>
|
<button name="delete_device" value="{{ d['mac'] }}" class="btn btn-danger btn-sm"
|
||||||
|
onclick="return confirm('Willst du das Gerät wirklich löschen?');">Löschen</button>
|
||||||
</td>
|
</td>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td>{{ d['mac'] }}</td>
|
|
||||||
<td>{{ d['rpi_ip'] }}</td>
|
|
||||||
<td>{{ d['port'] }}</td>
|
|
||||||
<td>{{ d['name'] }}</td>
|
<td>{{ d['name'] }}</td>
|
||||||
|
<td>{{ d['rpi_ip'] }}</td>
|
||||||
|
<td>{{ d['mac'] }}</td>
|
||||||
<td>{{ d['switch_hostname'] }}</td>
|
<td>{{ d['switch_hostname'] }}</td>
|
||||||
|
<td>{{ d['port'] }}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
|
||||||
</html>
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,44 +1,22 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% block content %}
|
||||||
<head>
|
|
||||||
<title>Device Dashboard</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body class="p-3">
|
|
||||||
|
|
||||||
<h2>Device Dashboard</h2>
|
<h2>Dashboard</h2>
|
||||||
|
<div class="row">
|
||||||
<div class="mb-3">
|
{% for d in devices %}
|
||||||
<a href="{{ url_for('logs') }}" class="btn btn-primary">Live Log</a>
|
<div class="col-md-2 col-sm-4 col-6 mb-3">
|
||||||
<a href="{{ url_for('devices') }}" class="btn btn-secondary">Devices verwalten</a>
|
<div class="card text-center shadow-sm">
|
||||||
<a href="{{ url_for('switches') }}" class="btn btn-secondary">Switches verwalten</a>
|
<div class="card-body">
|
||||||
<a href="{{ url_for('settings') }}" class="btn btn-warning">Einstellungen</a>
|
<h6 class="card-title">{{ d['name'] }}</h6>
|
||||||
|
{% if d['status'] == 'online' %}
|
||||||
|
<p class="text-success">Online</p>
|
||||||
|
{% else %}
|
||||||
|
<p class="text-danger">Offline</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Prüfintervall: <strong>{{ interval }} Minuten</strong></p>
|
{% endblock %}
|
||||||
|
|
||||||
<table class="table table-bordered table-striped">
|
|
||||||
<thead class="table-dark">
|
|
||||||
<tr>
|
|
||||||
<th>Device-Name</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for d in devices %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ d['name'] }}</td>
|
|
||||||
<td>
|
|
||||||
{% if status[d['name']] == 'online' %}
|
|
||||||
<span class="badge bg-success">Online</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="badge bg-danger">Offline</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -2,19 +2,32 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Login</title>
|
<title>Login</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="p-5">
|
<body class="p-5">
|
||||||
<h2>Login</h2>
|
|
||||||
<form method="post">
|
<h2>Login</h2>
|
||||||
<input class="form-control mb-2" name="username" placeholder="Benutzername" required>
|
|
||||||
<input type="password" class="form-control mb-2" name="password" placeholder="Passwort" required>
|
{% with messages = get_flashed_messages() %}
|
||||||
<button class="btn btn-primary">Login</button>
|
{% if messages %}
|
||||||
</form>
|
<div class="mt-2 alert alert-danger">
|
||||||
{% with messages = get_flashed_messages() %}
|
{% for message in messages %}{{ message }}<br>{% endfor %}
|
||||||
{% if messages %}
|
</div>
|
||||||
<div class="mt-2 alert alert-danger">{{ messages[0] }}</div>
|
{% endif %}
|
||||||
{% endif %}
|
{% endwith %}
|
||||||
{% endwith %}
|
|
||||||
|
<form method="post" class="w-25">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Username</label>
|
||||||
|
<input type="text" name="username" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Password</label>
|
||||||
|
<input type="password" name="password" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary">Login</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,37 +1,22 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% block content %}
|
||||||
<head>
|
|
||||||
<title>Live Log</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
<meta http-equiv="refresh" content="5"> <!-- automatische Aktualisierung alle 5 Sekunden -->
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>Live Log</h2>
|
<h2>Live Log</h2>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div id="log-box" class="border p-3 bg-light" style="height:500px; overflow:auto; white-space: pre-wrap; font-family: monospace;"></div>
|
||||||
<a href="{{ url_for('index') }}" class="btn btn-secondary">Dashboard</a>
|
|
||||||
<a href="{{ url_for('devices') }}" class="btn btn-secondary">Devices verwalten</a>
|
|
||||||
<a href="{{ url_for('switches') }}" class="btn btn-secondary">Switches verwalten</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-bordered table-striped">
|
<script>
|
||||||
<thead class="table-dark">
|
function fetchLog() {
|
||||||
<tr>
|
fetch("{{ url_for('get_log') }}")
|
||||||
<th>Timestamp</th>
|
.then(response => response.text())
|
||||||
<th>Log</th>
|
.then(data => {
|
||||||
</tr>
|
document.getElementById("log-box").innerText = data;
|
||||||
</thead>
|
let box = document.getElementById("log-box");
|
||||||
<tbody>
|
box.scrollTop = box.scrollHeight;
|
||||||
{% for line in log_lines %}
|
});
|
||||||
<tr>
|
}
|
||||||
{% set parts = line.split(' ', 1) %}
|
setInterval(fetchLog, 3000);
|
||||||
<td>{{ parts[0] if parts|length > 0 else '' }}</td>
|
fetchLog();
|
||||||
<td>{{ parts[1] if parts|length > 1 else line }}</td>
|
</script>
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</body>
|
{% endblock %}
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% block content %}
|
||||||
<head>
|
|
||||||
<title>Einstellungen</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body class="p-5">
|
|
||||||
|
|
||||||
<h2>PoE-Check Intervall</h2>
|
<h2>Settings</h2>
|
||||||
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
|
|
||||||
|
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@@ -17,15 +11,14 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<form method="post" class="row g-2">
|
<form method="post" class="row g-3">
|
||||||
<div class="col-auto">
|
<div class="col-md-4">
|
||||||
<label for="interval" class="form-label">Intervall (Minuten)</label>
|
<label for="interval" class="form-label">Prüfintervall (Minuten)</label>
|
||||||
<input type="number" name="interval" id="interval" class="form-control" value="{{ interval }}" min="1" required>
|
<input type="number" class="form-control" id="interval" name="interval" value="{{ interval }}" min="1" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto align-self-end">
|
<div class="col-12">
|
||||||
<button class="btn btn-primary">Speichern</button>
|
<button class="btn btn-primary">Speichern</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</body>
|
{% endblock %}
|
||||||
</html>
|
|
||||||
|
|||||||
53
srv/poe_manager/templates/switche.html
Normal file
53
srv/poe_manager/templates/switche.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>Switche</h2>
|
||||||
|
|
||||||
|
{% if current_user.is_admin %}
|
||||||
|
<h4>Neuen Switch hinzufügen</h4>
|
||||||
|
<form method="post" class="row g-2 mb-4">
|
||||||
|
<input type="hidden" name="add_switch" value="1">
|
||||||
|
<div class="col"><input type="text" name="hostname" placeholder="Hostname" class="form-control" required></div>
|
||||||
|
<div class="col"><input type="text" name="ip" placeholder="IP-Adresse" class="form-control" required></div>
|
||||||
|
<div class="col"><input type="text" name="username" placeholder="Username" class="form-control" required></div>
|
||||||
|
<div class="col"><input type="password" name="password" placeholder="Password" class="form-control" required></div>
|
||||||
|
<div class="col"><button class="btn btn-success w-100">Hinzufügen</button></div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Hostname</th>
|
||||||
|
<th>IP-Adresse</th>
|
||||||
|
<th>Username</th>
|
||||||
|
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for s in switches %}
|
||||||
|
<tr>
|
||||||
|
{% if current_user.is_admin %}
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="edit_switch" value="1">
|
||||||
|
<input type="hidden" name="old_hostname" value="{{ s['hostname'] }}">
|
||||||
|
<td><input name="hostname" value="{{ s['hostname'] }}" class="form-control" required></td>
|
||||||
|
<td><input name="ip" value="{{ s['ip'] }}" class="form-control" required></td>
|
||||||
|
<td><input name="username" value="{{ s['username'] }}" class="form-control" required></td>
|
||||||
|
<td class="d-flex gap-1">
|
||||||
|
<button class="btn btn-primary btn-sm">Speichern</button>
|
||||||
|
<button name="delete_switch" value="{{ s['hostname'] }}" class="btn btn-danger btn-sm"
|
||||||
|
onclick="return confirm('Willst du den Switch wirklich löschen?');">Löschen</button>
|
||||||
|
</td>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<td>{{ s['hostname'] }}</td>
|
||||||
|
<td>{{ s['ip'] }}</td>
|
||||||
|
<td>{{ s['username'] }}</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Switches</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body class="p-5">
|
|
||||||
|
|
||||||
<h2>Switches</h2>
|
|
||||||
<a href="{{ url_for('index') }}" class="btn btn-secondary mb-3">Zurück zum Dashboard</a>
|
|
||||||
|
|
||||||
{% with messages = get_flashed_messages() %}
|
|
||||||
{% if messages %}
|
|
||||||
<div class="mt-2 alert alert-info">
|
|
||||||
{% for message in messages %}{{ message }}<br>{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
{% if current_user.is_admin %}
|
|
||||||
<!-- Inline-Add Form -->
|
|
||||||
<h4>Neuen Switch hinzufügen</h4>
|
|
||||||
<form method="post" class="row g-2 mb-4">
|
|
||||||
<input type="hidden" name="add_switch" value="1">
|
|
||||||
<div class="col"><input type="text" name="hostname" placeholder="Hostname" class="form-control" required></div>
|
|
||||||
<div class="col"><input type="text" name="ip" placeholder="IP" class="form-control" required></div>
|
|
||||||
<div class="col"><input type="text" name="username" placeholder="Username" class="form-control" required></div>
|
|
||||||
<div class="col"><input type="password" name="password" placeholder="Passwort" class="form-control" required></div>
|
|
||||||
<div class="col"><button class="btn btn-success w-100">Hinzufügen</button></div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Switches Table -->
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Hostname</th>
|
|
||||||
<th>IP</th>
|
|
||||||
<th>Username</th>
|
|
||||||
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for sw in switches %}
|
|
||||||
<tr>
|
|
||||||
{% if current_user.is_admin %}
|
|
||||||
<!-- Inline-Edit Form -->
|
|
||||||
<form method="post">
|
|
||||||
<input type="hidden" name="edit_switch" value="1">
|
|
||||||
<input type="hidden" name="old_hostname" value="{{ sw['hostname'] }}">
|
|
||||||
<td><input name="hostname" value="{{ sw['hostname'] }}" class="form-control" required></td>
|
|
||||||
<td><input name="ip" value="{{ sw['ip'] }}" class="form-control" required></td>
|
|
||||||
<td><input name="username" value="{{ sw['username'] }}" class="form-control" required></td>
|
|
||||||
<td class="d-flex gap-1">
|
|
||||||
<button class="btn btn-primary btn-sm">Speichern</button>
|
|
||||||
<button name="delete_switch" value="{{ sw['hostname'] }}" class="btn btn-danger btn-sm" onclick="return confirm('Willst du den Switch wirklich löschen?');"> Löschen </button>
|
|
||||||
</td>
|
|
||||||
</form>
|
|
||||||
{% else %}
|
|
||||||
<td>{{ sw['hostname'] }}</td>
|
|
||||||
<td>{{ sw['ip'] }}</td>
|
|
||||||
<td>{{ sw['username'] }}</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
87
srv/poe_manager/templates/users.html
Normal file
87
srv/poe_manager/templates/users.html
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>Users</h2>
|
||||||
|
|
||||||
|
{% if current_user.is_admin %}
|
||||||
|
<!-- Button Neues User-Popup -->
|
||||||
|
<button class="btn btn-success mb-3" data-bs-toggle="modal" data-bs-target="#userModal" onclick="openUserModal()">Neuer Benutzer</button>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Username</th>
|
||||||
|
<th>Funktion</th>
|
||||||
|
{% if current_user.is_admin %}<th>Aktionen</th>{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for u in users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ u['username'] }}</td>
|
||||||
|
<td>{% if u['is_admin'] %}Admin{% else %}User{% endif %}</td>
|
||||||
|
{% if current_user.is_admin %}
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#userModal"
|
||||||
|
onclick="openUserModal({{ u['id'] }}, '{{ u['username'] }}', {{ u['is_admin'] }})">Bearbeiten</button>
|
||||||
|
<form method="post" style="display:inline;">
|
||||||
|
<button name="delete_user" value="{{ u['id'] }}" class="btn btn-danger btn-sm"
|
||||||
|
onclick="return confirm('Willst du den Benutzer wirklich löschen?');">Löschen</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="userModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form method="post" id="userForm">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="userModalTitle">Benutzer</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<input type="hidden" name="user_id" id="user_id">
|
||||||
|
<input type="hidden" name="edit_user" id="edit_user">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Username</label>
|
||||||
|
<input type="text" name="username" id="modal_username" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Passwort</label>
|
||||||
|
<input type="password" name="password" id="modal_password" class="form-control" placeholder="Nur eintragen, wenn Passwort geändert werden soll">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Rolle</label>
|
||||||
|
<select name="is_admin" id="modal_is_admin" class="form-control">
|
||||||
|
<option value="0">User</option>
|
||||||
|
<option value="1">Admin</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary">Speichern</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function openUserModal(id=null, username='', is_admin=0) {
|
||||||
|
document.getElementById('user_id').value = id || '';
|
||||||
|
document.getElementById('modal_username').value = username || '';
|
||||||
|
document.getElementById('modal_password').value = '';
|
||||||
|
document.getElementById('modal_is_admin').value = is_admin;
|
||||||
|
document.getElementById('edit_user').value = id ? 1 : '';
|
||||||
|
document.getElementById('userModalTitle').innerText = id ? 'Benutzer bearbeiten' : 'Neuen Benutzer anlegen';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user