Compare commits
No commits in common. "bfd1c081e9924f3414d59d5bd88f34918b3c75a5" and "8f0edf86d160224005fcf7234905efadde68909a" have entirely different histories.
bfd1c081e9
...
8f0edf86d1
6 changed files with 77 additions and 52 deletions
16
TODO
Normal file
16
TODO
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
✅Risiken
|
||||||
|
✅Eintrittswahrscheinlichkeiten
|
||||||
|
✅Schadenshöhen
|
||||||
|
✅Maßnahmen
|
||||||
|
✅Maßnahmenstatus
|
||||||
|
✅Restrisiko
|
||||||
|
✅Schutzziele (CIA)
|
||||||
|
✅Benutzer
|
||||||
|
✅Audit
|
||||||
|
✅Vorfälle
|
||||||
|
|
||||||
|
Benachrichtigungen
|
||||||
|
|
||||||
|
Workflow
|
||||||
|
|
||||||
|
Riskomatrix
|
|
@ -45,15 +45,15 @@ INSTALLED_APPS = [
|
||||||
# Middleware
|
# Middleware
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware", # CSRF protection
|
"django.middleware.security.SecurityMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware", # session management
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
"django.middleware.locale.LocaleMiddleware", # language settings
|
"django.middleware.locale.LocaleMiddleware",
|
||||||
"django.middleware.common.CommonMiddleware", # common middleware
|
"django.middleware.common.CommonMiddleware",
|
||||||
"django.middleware.csrf.CsrfViewMiddleware", # CSRF protection
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
"django.contrib.auth.middleware.AuthenticationMiddleware", # authentication
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||||
"risks.middleware.AuditUserMiddleware", # audit user
|
"risks.middleware.AuditUserMiddleware",
|
||||||
"django.contrib.messages.middleware.MessageMiddleware", # messages
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware", # clickjacking protection
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
@ -72,11 +72,11 @@ TEMPLATES = [
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"context_processors": [
|
"context_processors": [
|
||||||
"django.template.context_processors.debug", # debug info
|
"django.template.context_processors.debug",
|
||||||
"django.template.context_processors.request", # request info
|
"django.template.context_processors.request",
|
||||||
"django.contrib.auth.context_processors.auth", # auth info
|
"django.contrib.auth.context_processors.auth",
|
||||||
"django.contrib.messages.context_processors.messages", # messages
|
"django.contrib.messages.context_processors.messages",
|
||||||
"risks.context_processors.unread_notifications_count", # unread notifications
|
"risks.context_processors.unread_notifications_count",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -118,7 +118,7 @@ else: # default: SQLite
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
"default": {
|
"default": {
|
||||||
"ENGINE": "django.db.backends.sqlite3",
|
"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
|
"django.contrib.auth.backends.ModelBackend", # local auth
|
||||||
]
|
]
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}, # check for username similarity
|
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
|
||||||
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, # min length
|
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
|
||||||
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, # check for common passwords
|
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
|
||||||
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, # check for numeric passwords
|
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
|
||||||
]
|
]
|
||||||
|
|
||||||
# Login-Flow
|
# Login-Flow
|
||||||
|
|
|
@ -14,18 +14,13 @@ router.register(r"users", UserViewSet)
|
||||||
router.register(r"logs", AuditViewSet)
|
router.register(r"logs", AuditViewSet)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Risk Management
|
|
||||||
path("", include("risks.urls", namespace="risks")),
|
|
||||||
# Admin
|
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
# Login/Logout
|
path("i18n/", include("django.conf.urls.i18n")), # Language Switch
|
||||||
path("accounts/", include("django.contrib.auth.urls")),
|
path("api/ping/", ping), # Public healthcheck endpoint
|
||||||
# Language Switch
|
path("api/secure-ping/", secure_ping), # Protected API endpoint
|
||||||
path("i18n/", include("django.conf.urls.i18n")),
|
|
||||||
# API
|
|
||||||
path("api/", include(router.urls)),
|
path("api/", include(router.urls)),
|
||||||
path("api/ping/", ping),
|
path("accounts/", include("django.contrib.auth.urls")),
|
||||||
path("api/secure-ping/", secure_ping),
|
path("", include("risks.urls", namespace="risks")),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add OIDC routes only if Single Sign-On is enabled
|
# Add OIDC routes only if Single Sign-On is enabled
|
||||||
|
|
|
@ -410,7 +410,8 @@ msgstr "Sende an alle App-Mitarbeiter"
|
||||||
|
|
||||||
#: risks/models.py:438
|
#: risks/models.py:438
|
||||||
msgid "Extra recipients (emails, comma or newline separated)"
|
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
|
#: risks/signals.py:71
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
@ -458,7 +459,8 @@ msgstr "Maßnahme gelöscht: {t}"
|
||||||
#: risks/signals.py:218
|
#: risks/signals.py:218
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Residual review required for risk '{t}' due to control change"
|
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
|
#: risks/signals.py:245
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
|
@ -506,7 +508,9 @@ msgstr "Das Risiko wurde geprüft und als geschlossen markiert"
|
||||||
|
|
||||||
#: risks/views.py:220
|
#: risks/views.py:220
|
||||||
msgid "Not all controls are completed. Risk cannot be closed yet."
|
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
|
#: risks/views.py:409
|
||||||
msgid "Risk status updated."
|
msgid "Risk status updated."
|
||||||
|
|
|
@ -462,7 +462,6 @@ def update_residual_review(request, risk_id):
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Risk Matrix
|
# Risk Matrix
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@login_required
|
|
||||||
def risk_matrix(request):
|
def risk_matrix(request):
|
||||||
"""Show gross/net risk matrix."""
|
"""Show gross/net risk matrix."""
|
||||||
risks = Risk.objects.select_related("owner", "residual_risk").all()
|
risks = Risk.objects.select_related("owner", "residual_risk").all()
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
{% extends "base.html" %}
|
{% load static %}
|
||||||
{% load i18n %}
|
<!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 #}
|
<section class="hero is-fullheight">
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<section class="hero is-fullheight has-background-light">
|
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
|
@ -14,7 +19,7 @@
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<header class="card-header">
|
<header class="card-header">
|
||||||
<p class="card-header-title">{% trans "Bitte anmelden" %}</p>
|
<p class="card-header-title">Bitte anmelden</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
|
@ -31,7 +36,7 @@
|
||||||
|
|
||||||
<!-- Benutzername -->
|
<!-- Benutzername -->
|
||||||
<div class="field">
|
<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">
|
<div class="control has-icons-left">
|
||||||
<input
|
<input
|
||||||
class="input{% if form.username.errors %} is-danger{% endif %}"
|
class="input{% if form.username.errors %} is-danger{% endif %}"
|
||||||
|
@ -44,14 +49,16 @@
|
||||||
required>
|
required>
|
||||||
<span class="icon is-left">👤</span>
|
<span class="icon is-left">👤</span>
|
||||||
</div>
|
</div>
|
||||||
|
{% if form.username.errors %}
|
||||||
{% for error in form.username.errors %}
|
{% for error in form.username.errors %}
|
||||||
<p class="help is-danger">{{ error }}</p>
|
<p class="help is-danger">{{ error }}</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Passwort -->
|
<!-- Passwort -->
|
||||||
<div class="field">
|
<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">
|
<div class="control has-icons-left">
|
||||||
<input
|
<input
|
||||||
class="input{% if form.password.errors %} is-danger{% endif %}"
|
class="input{% if form.password.errors %} is-danger{% endif %}"
|
||||||
|
@ -63,9 +70,11 @@
|
||||||
required>
|
required>
|
||||||
<span class="icon is-left">🔒</span>
|
<span class="icon is-left">🔒</span>
|
||||||
</div>
|
</div>
|
||||||
|
{% if form.password.errors %}
|
||||||
{% for error in form.password.errors %}
|
{% for error in form.password.errors %}
|
||||||
<p class="help is-danger">{{ error }}</p>
|
<p class="help is-danger">{{ error }}</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="next" value="{{ next }}">
|
<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="field is-grouped is-justify-content-space-between is-align-items-center">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button type="submit" class="button is-primary">
|
<button type="submit" class="button is-primary">
|
||||||
{% trans "Anmelden" %}
|
Anmelden
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -95,4 +104,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Add table
Reference in a new issue