403 und 404 hübsch gemacht
This commit is contained in:
parent
6789ac73c8
commit
882eb1af66
@ -336,7 +336,7 @@ def allgemein():
|
|||||||
@app.route("/login", methods=["GET", "POST"])
|
@app.route("/login", methods=["GET", "POST"])
|
||||||
def login():
|
def login():
|
||||||
error_message = ""
|
error_message = ""
|
||||||
next_url = request.args.get("next") or request.form.get("next") or url_for("preise")
|
next_url = request.args.get("next") or request.form.get("next") or url_for("course_list")
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
email = request.form.get("email", "").strip().lower()
|
email = request.form.get("email", "").strip().lower()
|
||||||
@ -2463,3 +2463,19 @@ def download_certificate_admin(guid):
|
|||||||
filename = f"{guid}.pdf"
|
filename = f"{guid}.pdf"
|
||||||
|
|
||||||
return send_from_directory(certificate_dir, filename, as_attachment=True)
|
return send_from_directory(certificate_dir, filename, as_attachment=True)
|
||||||
|
|
||||||
|
@app.errorhandler(403)
|
||||||
|
def forbidden(e):
|
||||||
|
return render_template(
|
||||||
|
"403.html",
|
||||||
|
page_title="Zugriff verweigert",
|
||||||
|
**get_current_user()
|
||||||
|
), 403
|
||||||
|
|
||||||
|
@app.errorhandler(404)
|
||||||
|
def not_found(e):
|
||||||
|
return render_template(
|
||||||
|
"404.html",
|
||||||
|
page_title="Seite nicht gefunden",
|
||||||
|
**get_current_user()
|
||||||
|
), 404
|
||||||
@ -1,18 +1,31 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html lang="de">
|
|
||||||
<head>
|
{% block content %}
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<div class="error-page">
|
||||||
<title>{{ page_title }}</title>
|
|
||||||
<link rel="stylesheet" href="/styles/site.css">
|
<div class="error-card">
|
||||||
</head>
|
|
||||||
<body>
|
<div class="error-icon">🚫</div>
|
||||||
<main class="content-area">
|
|
||||||
<section class="content-box">
|
<h1>Zugriff verweigert</h1>
|
||||||
<h1>Kein Zugriff</h1>
|
|
||||||
<p>Sie haben keine Berechtigung für diese Seite.</p>
|
<p>
|
||||||
<p><a href="/home">Zurück zur Startseite</a></p>
|
Sie haben keine Berechtigung, diese Seite aufzurufen.
|
||||||
</section>
|
</p>
|
||||||
</main>
|
|
||||||
</body>
|
<div class="error-actions">
|
||||||
</html>
|
|
||||||
|
|
||||||
|
{% if is_logged_in %}
|
||||||
|
<a href="/courses" class="btn-secondary">Zu den Kursen</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="/login" class="btn-secondary">Login</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
29
app/flask-postgres/app/templates/404.html
Normal file
29
app/flask-postgres/app/templates/404.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="error-page">
|
||||||
|
|
||||||
|
<div class="error-card">
|
||||||
|
|
||||||
|
<div class="error-icon">🔍</div>
|
||||||
|
|
||||||
|
<h1>Seite nicht gefunden</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Die angeforderte Seite existiert nicht oder wurde verschoben.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="error-actions">
|
||||||
|
{% if is_logged_in %}
|
||||||
|
<a href="/courses" class="btn-secondary">Zu den Kursen</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="/preise" class="btn-secondary">Preise ansehen</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -30,25 +30,57 @@
|
|||||||
|
|
||||||
{% if is_logged_in %}
|
{% if is_logged_in %}
|
||||||
<div class="user-menu">
|
<div class="user-menu">
|
||||||
<button class="user-menu-toggle" type="button">{{ user_name }} ▾</button>
|
<button class="user-menu-btn">
|
||||||
<div class="user-menu-dropdown">
|
{{ user_name }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="user-dropdown">
|
||||||
|
|
||||||
|
<!-- USER -->
|
||||||
|
<div class="menu-group">
|
||||||
|
<div class="menu-group-title">User</div>
|
||||||
|
|
||||||
<a href="/profil">Profil</a>
|
<a href="/profil">Profil</a>
|
||||||
|
<a href="/logout">Logout</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if is_admin %}
|
{% if is_admin %}
|
||||||
|
<div class="menu-separator"></div>
|
||||||
|
|
||||||
|
<!-- ADMIN -->
|
||||||
|
<div class="menu-group">
|
||||||
|
<div class="menu-group-title">Admin</div>
|
||||||
|
|
||||||
<a href="/admin/mandanten">Mandanten</a>
|
<a href="/admin/mandanten">Mandanten</a>
|
||||||
<a href="/admin/checklist">Checklist</a>
|
|
||||||
<a href="/admin/courses">Kurse</a>
|
<a href="/admin/courses">Kurse</a>
|
||||||
<a href="/admin/questions">Assessment</a>
|
<a href="/admin/questions">Fragen</a>
|
||||||
{% endif %}
|
</div>
|
||||||
{% if is_user_admin %}
|
{% endif %}
|
||||||
<a href="/useradmin/mandant">Useradministration</a>
|
|
||||||
<a href="/reporting/assessments">Reporting</a>
|
{% if is_user_admin %}
|
||||||
<a href="/certificates">Zertifikate</a>
|
<div class="menu-separator"></div>
|
||||||
{% endif %}
|
|
||||||
{% if is_contentmanager %}
|
<!-- USERADMIN -->
|
||||||
<a href="/dokumente">Dokumente</a>
|
<div class="menu-group">
|
||||||
|
<div class="menu-group-title">Useradmin</div>
|
||||||
|
|
||||||
|
<a href="/useradmin/mandant">Userverwaltung</a>
|
||||||
|
<a href="/certificates">Zertifikate</a>
|
||||||
|
<a href="/reporting">Reporting</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if is_contentmanager %}
|
||||||
|
<div class="menu-separator"></div>
|
||||||
|
|
||||||
|
<!-- CONTENTMANAGER -->
|
||||||
|
<div class="menu-group">
|
||||||
|
<div class="menu-group-title">Contentmanager</div>
|
||||||
|
|
||||||
|
<a href="/dokumente">Dokumente</a>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<a href="/logout">Logout</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@ -1444,3 +1444,210 @@ button {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background: linear-gradient(90deg, #22c55e, #15803d);
|
background: linear-gradient(90deg, #22c55e, #15803d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===============================
|
||||||
|
User Dropdown Menü (neu)
|
||||||
|
=============================== */
|
||||||
|
|
||||||
|
.user-menu {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-btn {
|
||||||
|
background: #eef3f9;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 14px;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1f2f46;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 42px;
|
||||||
|
min-width: 240px;
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
|
||||||
|
padding: 10px 0;
|
||||||
|
display: none;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover öffnen */
|
||||||
|
.user-menu:hover .user-dropdown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gruppen */
|
||||||
|
.menu-group {
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Titel */
|
||||||
|
.menu-group-title {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #64748b;
|
||||||
|
padding: 6px 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
.user-dropdown a {
|
||||||
|
display: block;
|
||||||
|
padding: 10px 16px;
|
||||||
|
color: #1f2937;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover Effekt */
|
||||||
|
.user-dropdown a:hover {
|
||||||
|
background: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Separator */
|
||||||
|
.menu-separator {
|
||||||
|
height: 1px;
|
||||||
|
background: #e2e8f0;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pastell-Hintergründe pro Gruppe */
|
||||||
|
|
||||||
|
.menu-group:nth-child(1) {
|
||||||
|
background: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-group:nth-child(3) {
|
||||||
|
background: #f0fdf4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-group:nth-child(5) {
|
||||||
|
background: #fefce8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-group:nth-child(7) {
|
||||||
|
background: #fdf2f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************/
|
||||||
|
/*. User Menü */
|
||||||
|
/*********************/
|
||||||
|
.top-nav a,
|
||||||
|
.user-menu-btn,
|
||||||
|
.lang-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
height: 44px;
|
||||||
|
min-width: 140px; /* 👈 gleich breit */
|
||||||
|
padding: 0 18px;
|
||||||
|
|
||||||
|
border-radius: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 15px;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav a,
|
||||||
|
.lang-btn {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🔥 WICHTIG: kein Abstand mehr */
|
||||||
|
.user-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 100%; /* direkt anschließen */
|
||||||
|
margin-top: 4px; /* kleiner Abstand erlaubt */
|
||||||
|
|
||||||
|
min-width: 240px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(6px);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🔥 Hover stabil */
|
||||||
|
.user-menu:hover .user-dropdown {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
height: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===============================
|
||||||
|
Error Pages
|
||||||
|
=============================== */
|
||||||
|
|
||||||
|
.error-page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 60px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card {
|
||||||
|
max-width: 480px;
|
||||||
|
width: 100%;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 18px;
|
||||||
|
padding: 40px 30px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 12px 40px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card h1 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #0d2f57;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card p {
|
||||||
|
color: #475569;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #e2e8f0;
|
||||||
|
color: #1f2937;
|
||||||
|
padding: 10px 16px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user