Compare commits

...

4 commits

Author SHA1 Message Date
Kevin Heyer
bfd1c081e9 add login_required to Risk Matrix 2025-09-22 07:43:34 +02:00
Kevin Heyer
f8d3062da6 change Login Style 2025-09-22 07:42:26 +02:00
Kevin Heyer
566d6aa096 cleanup 2025-09-22 07:42:17 +02:00
Kevin Heyer
d35ed7b292 cleanup 2025-09-22 07:34:49 +02:00
6 changed files with 53 additions and 78 deletions

16
TODO
View file

@ -1,16 +0,0 @@
✅Risiken
✅Eintrittswahrscheinlichkeiten
✅Schadenshöhen
✅Maßnahmen
✅Maßnahmenstatus
✅Restrisiko
✅Schutzziele (CIA)
✅Benutzer
✅Audit
✅Vorfälle
Benachrichtigungen
Workflow
Riskomatrix

View file

@ -45,15 +45,15 @@ INSTALLED_APPS = [
# Middleware
# ---------------------------------------------------------------------------
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"risks.middleware.AuditUserMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django.middleware.security.SecurityMiddleware", # CSRF protection
"django.contrib.sessions.middleware.SessionMiddleware", # session management
"django.middleware.locale.LocaleMiddleware", # language settings
"django.middleware.common.CommonMiddleware", # common middleware
"django.middleware.csrf.CsrfViewMiddleware", # CSRF protection
"django.contrib.auth.middleware.AuthenticationMiddleware", # authentication
"risks.middleware.AuditUserMiddleware", # audit user
"django.contrib.messages.middleware.MessageMiddleware", # messages
"django.middleware.clickjacking.XFrameOptionsMiddleware", # clickjacking protection
]
# ---------------------------------------------------------------------------
@ -72,11 +72,11 @@ TEMPLATES = [
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"risks.context_processors.unread_notifications_count",
"django.template.context_processors.debug", # debug info
"django.template.context_processors.request", # request info
"django.contrib.auth.context_processors.auth", # auth info
"django.contrib.messages.context_processors.messages", # messages
"risks.context_processors.unread_notifications_count", # unread notifications
],
},
},
@ -118,7 +118,7 @@ else: # default: SQLite
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3", # fixed filename for simplicity
"NAME": BASE_DIR / "db.sqlite3",
}
}
@ -130,10 +130,10 @@ AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend", # local auth
]
AUTH_PASSWORD_VALIDATORS = [
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}, # check for username similarity
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, # min length
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, # check for common passwords
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, # check for numeric passwords
]
# Login-Flow

View file

@ -14,13 +14,18 @@ router.register(r"users", UserViewSet)
router.register(r"logs", AuditViewSet)
urlpatterns = [
path("admin/", admin.site.urls),
path("i18n/", include("django.conf.urls.i18n")), # Language Switch
path("api/ping/", ping), # Public healthcheck endpoint
path("api/secure-ping/", secure_ping), # Protected API endpoint
path("api/", include(router.urls)),
path("accounts/", include("django.contrib.auth.urls")),
# Risk Management
path("", include("risks.urls", namespace="risks")),
# Admin
path("admin/", admin.site.urls),
# Login/Logout
path("accounts/", include("django.contrib.auth.urls")),
# Language Switch
path("i18n/", include("django.conf.urls.i18n")),
# API
path("api/", include(router.urls)),
path("api/ping/", ping),
path("api/secure-ping/", secure_ping),
]
# Add OIDC routes only if Single Sign-On is enabled

View file

@ -410,8 +410,7 @@ msgstr "Sende an alle App-Mitarbeiter"
#: risks/models.py:438
msgid "Extra recipients (emails, comma or newline separated)"
msgstr ""
"Zusätzliche Empfänger (E-Mails, durch Komma oder Zeilenumbruch getrennt)"
msgstr "Zusätzliche Empfänger (E-Mails, durch Komma oder Zeilenumbruch getrennt)"
#: risks/signals.py:71
#, python-brace-format
@ -459,8 +458,7 @@ msgstr "Maßnahme gelöscht: {t}"
#: risks/signals.py:218
#, python-brace-format
msgid "Residual review required for risk '{t}' due to control change"
msgstr ""
"Restrisikoprüfung nötig für das Risiko: '{t}', da Maßnahmen geändert wurden"
msgstr "Restrisikoprüfung nötig für das Risiko: '{t}', da Maßnahmen geändert wurden"
#: risks/signals.py:245
#, python-brace-format
@ -508,9 +506,7 @@ msgstr "Das Risiko wurde geprüft und als geschlossen markiert"
#: risks/views.py:220
msgid "Not all controls are completed. Risk cannot be closed yet."
msgstr ""
"Nicht alle Maßnhamen sind abgeschlossen, das Risiko kann nicht geschlossen "
"werden."
msgstr "Nicht alle Maßnhamen sind abgeschlossen, das Risiko kann nicht geschlossen werden."
#: risks/views.py:409
msgid "Risk status updated."

View file

@ -462,6 +462,7 @@ def update_residual_review(request, risk_id):
# ---------------------------------------------------------------------------
# Risk Matrix
# ---------------------------------------------------------------------------
@login_required
def risk_matrix(request):
"""Show gross/net risk matrix."""
risks = Risk.objects.select_related("owner", "residual_risk").all()

View file

@ -1,17 +1,12 @@
{% load static %}
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
{% extends "base.html" %}
{% load i18n %}
<!-- Wenn Bulma bereits global geladen wird, diesen Link entfernen -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.2/css/bulma.min.css">
</head>
<body class="has-background-light">
{% block title %}{% trans "Login" %}{% endblock %}
<section class="hero is-fullheight">
{% block breadcrumbs %}{% endblock %} {# Breadcrumbs bei Login-Seite ausblenden #}
{% block content %}
<section class="hero is-fullheight has-background-light">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
@ -19,7 +14,7 @@
<div class="card">
<header class="card-header">
<p class="card-header-title">Bitte anmelden</p>
<p class="card-header-title">{% trans "Bitte anmelden" %}</p>
</header>
<div class="card-content">
@ -36,7 +31,7 @@
<!-- Benutzername -->
<div class="field">
<label class="label" for="{{ form.username.id_for_label }}">Benutzername</label>
<label class="label" for="{{ form.username.id_for_label }}">{% trans "Benutzername" %}</label>
<div class="control has-icons-left">
<input
class="input{% if form.username.errors %} is-danger{% endif %}"
@ -49,16 +44,14 @@
required>
<span class="icon is-left">👤</span>
</div>
{% if form.username.errors %}
{% for error in form.username.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
{% endif %}
{% for error in form.username.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
</div>
<!-- Passwort -->
<div class="field">
<label class="label" for="{{ form.password.id_for_label }}">Passwort</label>
<label class="label" for="{{ form.password.id_for_label }}">{% trans "Passwort" %}</label>
<div class="control has-icons-left">
<input
class="input{% if form.password.errors %} is-danger{% endif %}"
@ -70,11 +63,9 @@
required>
<span class="icon is-left">🔒</span>
</div>
{% if form.password.errors %}
{% for error in form.password.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
{% endif %}
{% for error in form.password.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
</div>
<input type="hidden" name="next" value="{{ next }}">
@ -82,11 +73,11 @@
<div class="field is-grouped is-justify-content-space-between is-align-items-center">
<div class="control">
<button type="submit" class="button is-primary">
Anmelden
{% trans "Anmelden" %}
</button>
</div>
<div class="control">
<a class="button is-text" href="{% url 'password_reset' %}">Passwort vergessen?</a>
<a class="button is-text" href="{% url 'password_reset' %}">{% trans "Passwort vergessen?" %}</a>
</div>
</div>
</form>
@ -104,6 +95,4 @@
</div>
</div>
</section>
</body>
</html>
{% endblock %}