Compare commits

..

No commits in common. "bfd1c081e9924f3414d59d5bd88f34918b3c75a5" and "8f0edf86d160224005fcf7234905efadde68909a" have entirely different histories.

6 changed files with 77 additions and 52 deletions

16
TODO Normal file
View file

@ -0,0 +1,16 @@
✅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", # 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
"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",
]
# ---------------------------------------------------------------------------
@ -72,11 +72,11 @@ TEMPLATES = [
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"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
"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",
],
},
},
@ -118,7 +118,7 @@ else: # default: SQLite
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"NAME": BASE_DIR / "db.sqlite3", # fixed filename for simplicity
}
}
@ -130,10 +130,10 @@ AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend", # local auth
]
AUTH_PASSWORD_VALIDATORS = [
{"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
{"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"},
]
# Login-Flow

View file

@ -14,18 +14,13 @@ router.register(r"users", UserViewSet)
router.register(r"logs", AuditViewSet)
urlpatterns = [
# 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("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("api/ping/", ping),
path("api/secure-ping/", secure_ping),
path("accounts/", include("django.contrib.auth.urls")),
path("", include("risks.urls", namespace="risks")),
]
# Add OIDC routes only if Single Sign-On is enabled

View file

@ -410,7 +410,8 @@ 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
@ -458,7 +459,8 @@ 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
@ -506,7 +508,9 @@ 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,7 +462,6 @@ 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,12 +1,17 @@
{% extends "base.html" %}
{% load i18n %}
{% 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">
{% block title %}{% trans "Login" %}{% endblock %}
<!-- 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 breadcrumbs %}{% endblock %} {# Breadcrumbs bei Login-Seite ausblenden #}
{% block content %}
<section class="hero is-fullheight has-background-light">
<section class="hero is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
@ -14,7 +19,7 @@
<div class="card">
<header class="card-header">
<p class="card-header-title">{% trans "Bitte anmelden" %}</p>
<p class="card-header-title">Bitte anmelden</p>
</header>
<div class="card-content">
@ -31,7 +36,7 @@
<!-- Benutzername -->
<div class="field">
<label class="label" for="{{ form.username.id_for_label }}">{% trans "Benutzername" %}</label>
<label class="label" for="{{ form.username.id_for_label }}">Benutzername</label>
<div class="control has-icons-left">
<input
class="input{% if form.username.errors %} is-danger{% endif %}"
@ -44,14 +49,16 @@
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 %}
</div>
<!-- Passwort -->
<div class="field">
<label class="label" for="{{ form.password.id_for_label }}">{% trans "Passwort" %}</label>
<label class="label" for="{{ form.password.id_for_label }}">Passwort</label>
<div class="control has-icons-left">
<input
class="input{% if form.password.errors %} is-danger{% endif %}"
@ -63,9 +70,11 @@
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 %}
</div>
<input type="hidden" name="next" value="{{ next }}">
@ -73,11 +82,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">
{% trans "Anmelden" %}
Anmelden
</button>
</div>
<div class="control">
<a class="button is-text" href="{% url 'password_reset' %}">{% trans "Passwort vergessen?" %}</a>
<a class="button is-text" href="{% url 'password_reset' %}">Passwort vergessen?</a>
</div>
</div>
</form>
@ -95,4 +104,6 @@
</div>
</div>
</section>
{% endblock %}
</body>
</html>