commit 5126decf364589a4fd841878ea73a0a4abff7e80 Author: Bjoern Runden Date: Thu Jun 18 08:38:37 2026 +0200 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..fdb3fe6 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# kbcrm + +[Kurzbeschreibung folgt – Zweck und Ziel der Applikation] + +**Authentifizierung** vollständig an Zitadel delegiert. Lokale Datenhaltung, +Benutzer- und Rollenverwaltung über SQLite. + +--- + +## Technologie-Stack + +| Komponente | Technologie | +|---|---| +| Backend | Python Flask 2.x | +| OIDC-Client | Authlib | +| Datenbank | SQLite via SQLAlchemy | +| IdP | Zitadel | +| Produktion | Docker / gunicorn | + +--- + +## Lokale Entwicklung + +```bash +python3 -m venv venv +source venv/bin/activate +pip install -r requirements.txt +cp .env.example .env # Zitadel-Credentials eintragen +flask db-init # Schema initialisieren +flask seed-db # Testdaten einspielen +flask run # App startet auf http://localhost:5000 diff --git a/ai-context/AI-auth-vorgaben.md b/ai-context/AI-auth-vorgaben.md new file mode 100644 index 0000000..73b267d --- /dev/null +++ b/ai-context/AI-auth-vorgaben.md @@ -0,0 +1,138 @@ +# Zitadel-Einrichtung – Schritt-für-Schritt + +Zitadel-Instanz: **https://id.vmlx.de** + +Ziel dieser Anleitung: Das OIDC-Projekt **kbcrm** anlegen, drei Testrollen definieren, +drei Testnutzer erstellen, ihnen Rollen zuweisen und die Zitadel-User-IDs +(`sub`-Werte) für das DB-Seeding ermitteln. + +--- + +## Schritt 1 – Zitadel-Projekt anlegen + +1. Login unter https://id.vmlx.de +2. Linke Navigation → **Projekte** → **Neu anlegen** +3. Name: `kbcrm` → Speichern +4. Im Projekt-Detail unter **Einstellungen** folgende Optionen aktivieren: + - ☑ **Assert Roles on Authentication** (Rollen werden in Token geschrieben) + - ☑ **Check Authorization on Authentication** (Zugriff nur für zugewiesene Nutzer) + +--- + +## Schritt 2 – Rollen anlegen + +Im Projekt → Tab **Rollen** → drei Rollen anlegen: + +| Anzeigename | Schlüssel (Key) | +|---|---| +| Admin | `Admin` | +| Mitarbeiter | `Mitarbeiter` | +| Kunde | `Kunde` | + +> Der Schlüssel (Key) muss **exakt** so geschrieben sein – er erscheint so im Token-Claim. + +--- + +## Schritt 3 – OIDC-Anwendung anlegen + +Im Projekt → Tab **Anwendungen** → **Neu anlegen** + +| Feld | Wert | +|---|---| +| Name | `kbcrm-web` | +| Typ | **Web** | +| Auth-Methode | **Code** (Authorization Code mit Client Secret) | + +Nach dem Erstellen: +- **Client-ID** und **Client-Secret** notieren → kommen in die `.env` +- Unter **Redirect-URIs** eintragen: + - `http://localhost:5000/auth/callback` (Lokal) + - `https:///auth/callback` (Prod, falls zutreffend) +- Unter **Post-Logout-Redirect-URIs** eintragen: + - `http://localhost:5000/` + +--- + +## Schritt 4 – Testnutzer anlegen + +Navigation: **Nutzer** (oberste Ebene, nicht innerhalb eines Projekts) → **Neu anlegen** + +Drei Nutzer erstellen: + +| Name | E-Mail | Passwort | Zitadel-Rolle | +|---|---|---|---| +| Admin Test | admin@test.local | (eigenes PW) | Admin | +| Mitarbeiter Test | ma@test.local | (eigenes PW) | Mitarbeiter | +| Kunde Test | kunde@test.local | (eigenes PW) | Kunde | + +> Bei der Erstellung: **Passwort beim ersten Login ändern** deaktivieren empfohlen, damit Tests flüssig laufen. + +--- + +## Schritt 5 – Rollen an Nutzer vergeben + +Für jeden Nutzer: + +1. **Nutzer** → Nutzer auswählen → Tab **Autorisierungen** +2. → **Neu** → Projekt `kbcrm` wählen → entsprechende Rolle wählen → Speichern + +--- + +## Schritt 6 – User-IDs (sub) ermitteln + +Die User-ID (Zitadel-`sub`) ist die interne Zitadel-Nutzer-ID, **nicht** die E-Mail. + +**Methode A – Zitadel-Konsole:** +Nutzer auswählen → oben in der Detailansicht steht die **User-ID** (z. B. `236968807784841234`) + +**Methode B – Aus dem App-Log (nach Schritt 7):** +Nach dem ersten Login loggt die App in stdout: +``` +OIDC Login – sub: 236968807784841234 | email: admin@test.local | roles: ['Admin'] +``` + +Alle drei Sub-Werte notieren für den nächsten Schritt. + +--- + +## Schritt 7 – .env befüllen und DB seeden + +`.env` aus `.env.example` kopieren und befüllen: + +```bash +cp .env.example .env +``` + +```env +ZITADEL_CLIENT_ID= +ZITADEL_CLIENT_SECRET= +ZITADEL_DISCOVERY_URL=https://id.vmlx.de/.well-known/openid-configuration +SECRET_KEY= +``` + +Dann in `app/__init__.py` die Platzhalter in `seed_db()` mit den echten Sub-Werten ersetzen: + +```python +ADMIN_ID = "236968807784841234" # <-- echte Zitadel-User-ID +MITARBEITER_ID = "..." +KUNDE_ID = "..." +``` + +Anschließend seeden: + +```bash +source venv/bin/activate +flask seed-db +``` + +--- + +## Discovery-URL verifizieren + +```bash +curl https://id.vmlx.de/.well-known/openid-configuration | python3 -m json.tool +``` + +Wenn die Antwort ein JSON mit `issuer`, `authorization_endpoint` usw. ist, ist die URL korrekt. +Sollte die URL nicht funktionieren, alternative probieren: +`https://id.vmlx.de/oauth/v2/.well-known/openid-configuration` diff --git a/ai-context/AI-operative_Vorgaben.md b/ai-context/AI-operative_Vorgaben.md new file mode 100644 index 0000000..4b1bb47 --- /dev/null +++ b/ai-context/AI-operative_Vorgaben.md @@ -0,0 +1,41 @@ +# AI.md — Strukturvorgaben für neue Applikation + +**Autoren:** Björn Runden, Gerd Goldberg +**Zweck dieses Dokuments:** Verbindliche strukturelle, betriebliche und infrastrukturelle Vorgaben für eine neue Python-Applikation. Applikationslogik, Routing und Frontend sind bewusst nicht Teil dieses Dokuments. + +--- + +## 1. Technologie-Stack + +| Schicht | Technologie | +|---|---| +| Backend-Framework | Python Flask 2.x | +| OIDC-Authentifizierung | Authlib (gegen Zitadel als externen IdP) | +| Datenbank / ORM | SQLite + SQLAlchemy | +| Konfiguration | 12-Factor-App via `.env`-Datei | +| Produktions-Server | Gunicorn | +| Container | Docker (`python:3.11-slim`), orchestriert via `docker-compose.yml` | + +--- + +## 2. Verzeichnisstruktur + +```text +. +├── .gitignore +├── .env +├── .env.example +├── requirements.txt +├── docker-compose.yml +├── Dockerfile +├── wsgi.py +├── data/ ← Datenbankverzeichnis (persistente SQLite-Datei, nicht im Image) +└── app/ + ├── __init__.py + ├── config.py + ├── database.py + ├── models.py + ├── auth.py + ├── routes.py + ├── templates/ + └── static/ diff --git a/ai-context/strukturelle-vorgaben.md b/ai-context/strukturelle-vorgaben.md new file mode 100644 index 0000000..2fc1c0b --- /dev/null +++ b/ai-context/strukturelle-vorgaben.md @@ -0,0 +1,131 @@ +# Strukturelle Vorgaben – Quellcode-Konventionen + +Dieses Dokument legt verbindliche Konventionen für alle Quelldateien im Projekt fest. + +--- + +## 1. Datei-Header + +Jede Quelldatei beginnt mit einem standardisierten Header. Der Header dient gleichzeitig als Modul-Docstring und wird von **Sphinx** zur automatischen Dokumentationserzeugung ausgewertet (Python-Äquivalent zu JavaDoc). + +### Python (`.py`) + +Der Header ist ein Modul-Docstring (triple-quoted) direkt am Dateianfang. Sphinx liest ihn automatisch aus: + +```python +""" + + + + +:author: Vorname Nachname +:date: YYYY-MM-DD +:version: 1.0 +""" +``` + +Pflichtfelder: `:author:`, `:date:` +Optionale Felder: `:version:`, `:see:`, `:note:` + +### Jinja2 / HTML (`.html`) + +Jinja2-Kommentare (`{# ... #}`) werden vom Browser nicht gerendert und sind deshalb die richtige Wahl für Template-Header: + +```html +{# + Datei: templates/beispiel.html + Autor: Vorname Nachname + Datum: YYYY-MM-DD + Zweck: Kurze Beschreibung, welche Seite/Komponente dieses Template rendert + und welche Jinja2-Variablen es erwartet. +#} +``` + +Pflichtfelder: `Datei:`, `Autor:`, `Datum:`, `Zweck:` + +--- + +## 2. Dokumentationserzeugung mit Sphinx + +Python bietet mit **Sphinx** ein mächtiges Werkzeug analog zu JavaDoc. Es liest Modul-Docstrings (inkl. `:author:`/`:date:`-Felder) und erzeugt daraus eine vollständige HTML-Dokumentation. + +### Einrichtung (einmalig) + +```bash +pip install sphinx +cd docs/ +sphinx-quickstart # Interaktiver Setup-Assistent +``` + +Im Setup-Assistenten: +- `autodoc` aktivieren (liest Docstrings automatisch) +- Projektname, Autor und Version eingeben + +Anschließend in `docs/conf.py` sicherstellen: + +```python +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.viewcode", # Links zum Quellcode +] +``` + +### Dokumentation aus dem `app/`-Verzeichnis einlesen + +```bash +sphinx-apidoc -o docs/source/ app/ +``` + +Dieser Befehl scannt alle `.py`-Dateien unter `app/` und erzeugt `.rst`-Stub-Dateien, die den Modul-Docstring und alle Klassen/Funktionen einbinden. + +### Dokumentation bauen + +```bash +cd docs/ +make html +# Ergebnis liegt unter: docs/_build/html/index.html +``` + +### Ablauf + +``` +Modul-Docstrings → sphinx-apidoc → .rst-Dateien → make html → HTML-Doku +``` + +> **Hinweis:** Für HTML-Templates gibt es kein Python-natives Doku-Tool. Die Header-Kommentare dienen dort als Inline-Dokumentation für Entwickler. + +--- + +## 3. Template-Dateien + +Im Verzeichnis [`_templates/`](_templates/) liegen Vorlagen, von denen sich der Entwickler **jederzeit eine frische Kopie ziehen** kann: + +| Template | Verwendung | +|---|---| +| [`_templates/_template.py`](_templates/_template.py) | Neue Python-Quelldatei | +| [`_templates/_template.html`](_templates/_template.html) | Neues Jinja2/HTML-Template | + +### Workflow: neue Datei aus Template erzeugen + +```bash +# Python-Datei +cp _templates/_template.py app/mein_modul.py + +# HTML-Template +cp _templates/_template.html app/templates/meine_seite.html +``` + +Anschließend im kopierten File die Platzhalter (`<...>`) ersetzen. + +--- + +## 4. Kurzreferenz – Pflichtfelder auf einen Blick + +| Feldname | Python (Docstring) | HTML (Kommentar) | Pflicht | +|---|---|---|---| +| Autor | `:author:` | `Autor:` | Ja | +| Datum | `:date:` | `Datum:` | Ja | +| Zweck/Titel | Erste Docstring-Zeile | `Zweck:` | Ja | +| Version | `:version:` | – | Nein | +| Dateiname | – | `Datei:` | Ja |