diff --git a/README.md b/README.md new file mode 100644 index 0000000..fb87e72 --- /dev/null +++ b/README.md @@ -0,0 +1,154 @@ +# Modul-Integration in das *risks* Projekt + +Dieses Dokument beschreibt, wie weitere Apps (z. B. **ToDo**) in dein ISO-27001 Risk-Management Projekt (App heißt `risks`) integriert werden. +Alle Apps im Bestand sind/werden nach demselben Muster aufgebaut und registrieren sich selbst in der Navigation, wenn sie installiert sind und vorhandene Permissions passen. + +--- + +## Schritte zur Einbindung einer neuen App + +### 1. Submodul hinzufügen + +Füge das gewünschte App-Repo als Git-Submodul hinzu: + +```bash +git submodule add +``` + +Beispiel für ToDo-App: + +```bash +git submodule add https://skulldev.de/Skull-IT/todo-app.git todo +``` + +> Wichtig: Der Zielpfad sollte dem App-Namen entsprechen (`todo` etc). + +--- + +### 2. App in `INSTALLED_APPS` aktivieren + +In deinem Projekt unter `config/settings.py` oder dem entsprechenden Settings-Modul: + +```python +INSTALLED_APPS = [ + # bestehende Apps + "risks", + "todo", # neu hinzugefügte App + # … weitere +] +``` + +Damit registriert Django Models, Migrations, Templates & static files der App. + +--- + +### 3. URLs einbinden + +In deiner zentralen `urls.py` (unter `config/` oder wo dein Root URLs definiert sind) muss die neue App eingebunden werden: + +```python +from django.urls import include, path + +urlpatterns = [ + # … + path("todo/", include("todo.urls", namespace="todo")), +] +``` + +Damit werden die Views der App über `/todo/` erreichbar. + +--- + +### 4. Navigation (automatisch) + +#### Registry-Ansatz + +* In `risks` existiert eine Navigation-Registry. +* Jede App registriert sich selbst in dieser Registry mit Label, URL-Name, und erforderlicher Permission. +* `risks` rendert automatisch alle registrierten Navigationseinträge im Menü, sofern installiert + Benutzer berechtigt. + +#### Beispiel: Registrierung in der neuen App (`apps.py`) + +```python +from django.apps import AppConfig + +class TodoConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "todo" + + def ready(self): + try: + from risks.navigation_registry import register + register( + label="ToDo", + url_name="todo:list", # Name, wie in todo.urls + permission="todo.view_task", # Permission nötig + ) + except ImportError: + # risks App ist nicht installiert → nichts machen + pass +``` + +#### Verhalten + +* Ist die App **nicht installiert** → kein Menüpunkt +* Ist sie **installiert, aber User hat keine entsprechende Permission** → kein Menüpunkt +* Ist sie **installiert und hat User die Permission** → Menüpunkt erscheint automatisch + +--- + +### 5. Base-Template-Vererbung + +* Läuft die neue App **allein** (Standalone/Demo) → sie liefert ein eigenes `base.html`. +* Wenn sie im `risks` Projekt eingebunden ist → sie erbt das `base.html` aus `risks`. + +Dies funktioniert über die Reihenfolge in `INSTALLED_APPS` oder über ein optionales Setting wie z. B. `TODO_BASE_TEMPLATE`, welches gesetzt werden kann, wenn `risks` das Base vorgibt. + +--- + +### 6. Migration & Datenbankstruktur + +Nach Einbindung: + +```bash +python manage.py migrate +``` + +Stelle sicher, dass Migrationen der neuen App mitlaufen und keine Konflikte bestehen. + +--- + +### 7. Permissions setzen + +Die neue App definiert eigene Permissions via `Meta` in `models` oder explizit via Migration. + +Beispiele: + +* `todo.view_task` → um den Menüpunkt und Zugriffe zu erlauben +* Weitere wie `todo.add_task`, `todo.change_task`, `todo.delete_task` + +Rechte können über Django Admin oder Migration vergeben werden. + +--- + +### 8. Tests ausführen + +Sicherheitshalber: + +```bash +python manage.py test todo +``` + +So siehst du, ob die App sauber arbeitet und integriert ist. + +--- + +### 9. Checkliste + +* [ ] Submodul hinzugefügt +* [ ] App in `INSTALLED_APPS` eingetragen +* [ ] URL-Einbindung in Root URLs umgesetzt +* [ ] Neue App registriert sich in der Navigation via Registry +* [ ] Migrationen ausgeführt +* [ ] Permissions gesetzt +* [ ] Navigation erscheint/dem User sichtbar, wo nötig \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 index a6e5de5..7d06d7d 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/risks/navigation_registry.py b/risks/navigation_registry.py new file mode 100644 index 0000000..bbf6b18 --- /dev/null +++ b/risks/navigation_registry.py @@ -0,0 +1,8 @@ +registry = [] + +def register(label, url_name, permission=None): + registry.append({ + "label": label, + "url_name": url_name, + "permission": permission, + }) \ No newline at end of file diff --git a/risks/templatetags/navigation.py b/risks/templatetags/navigation.py new file mode 100644 index 0000000..d52a3b7 --- /dev/null +++ b/risks/templatetags/navigation.py @@ -0,0 +1,34 @@ +from django import template +from django.urls import reverse, NoReverseMatch +from django.apps import apps +from risks.navigation_registry import registry + +register = template.Library() + +@register.inclusion_tag("risks/_extra_nav.html", takes_context=True) +def render_extra_nav(context): + user = context["request"].user + extra_items = [] + + for item in registry: + # Check: ist die App überhaupt installiert? + app_label = item["permission"].split(".")[0] if item["permission"] else None + if app_label and not apps.is_installed(app_label): + continue + + # Check: hat der User die Berechtigung? + if item["permission"] and not user.has_perm(item["permission"]): + continue + + # URL auflösen + try: + url = reverse(item["url_name"]) + except NoReverseMatch: + continue + + extra_items.append({ + "label": item["label"], + "url": url, + }) + + return {"extra_items": extra_items} diff --git a/templates/base.html b/templates/base.html index 3d3a7e9..d78ba96 100644 --- a/templates/base.html +++ b/templates/base.html @@ -56,6 +56,8 @@ + {% load navigation %} + {% render_extra_nav %} diff --git a/templates/risks/_extra_nav.html b/templates/risks/_extra_nav.html new file mode 100644 index 0000000..f0fa1ae --- /dev/null +++ b/templates/risks/_extra_nav.html @@ -0,0 +1,8 @@ +{% for item in extra_items %} + +{% endfor %} \ No newline at end of file