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
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
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

View file

@ -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

View file

@ -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."

View file

@ -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()

View file

@ -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>