--- type: konzept-modul projekt: 3d.lehrstun.de stand: 2026-05-24 tags: [konzept, routen, api] --- # Routen > Vollständige Routen-Liste. Live im Code: `app.py` + `routes/*.py` (V8: Blueprint-Struktur, siehe [[../decisions#E-020]]). > Welche Etappe was baut: [[etappen]]. Selbstlern-Loop-Details: [[selbstlern-loop]]. Lehrer-Dashboard: [[lehrer-dashboard]]. ## Blueprint-Aufteilung (V8) | Blueprint-Datei | URL-Präfix | Inhalt | |---|---|---| | `routes/oeffentlich.py` | `/` (kein Präfix) | Startseite, Lektionen, Software, Projekt-Katalog, Drucker, Troubleshooting | | `routes/profil.py` | `/cockpit`, `/login` | Login, Cockpit, Projekt-Workflow, Slots, Druckaufträge | | `routes/admin.py` | `/admin` | Dashboard, Profile, Lektionen, Projekt-Freigabe, Inline-Edit | | `routes/api.py` | `/api` | JSON-Endpunkte für Frontend-Polling | | `services/bambu.py` | (kein HTTP) | Bambu-Cloud-API-Wrapper, isoliert für späteren Austausch | | `services/datei.py` | (kein HTTP) | File-BLOB-Handling, abstrahiert für spätere Object-Storage-Migration | ## Öffentlich (`routes/oeffentlich.py`) | Methode | Pfad | Zweck | Etappe | |---|---|---|---| | GET | `/` | Startseite | ✓ skelett | | GET | `/lektionen` | Onboarding-Pfad + freie Module | 3 | | GET | `/lektion/` | Einzelne Lektion | 3 | | GET | `/software` | Software-Tools | 3 | | GET | `/software/` | Software-Detail | 3 | | GET | `/projekte` | **Projekt-Katalog** (mit Filter: tag, level, erfolg, macher) | 6 | | GET | `/projekte/` | Projekt-Detail (Cover, Beschreibung, Files, Bewertung, Macher) | 6 | | GET | `/projekte/datei/` | Datei-Download (mit Auth-Check, sichtbar_in_ag prüfen) | 6 | | GET | `/troubleshooting` | Entscheidungsbaum + Suchliste | 3 | | GET | `/drucker` | 4 Drucker live | 5 | ## Profil (`routes/profil.py` — eingeloggt) | Methode | Pfad | Zweck | Etappe | |---|---|---|---| | GET | `/login` | Profil-Kacheln (Vorname + Tier) | 1 | | POST | `/login/` | PIN-Eingabe (Rate-Limit + persistenter Lockout) | 1 | | GET | `/logout` | Abmelden | 1 | | GET | `/cockpit` | **Progressiv** (V1): zeigt nur was zum Status passt | 2 | | POST | `/cockpit/check-in` | Stunden-Beginn-Abfrage (V3: 1 Radio, 1 optionaler Freitext, "weiter wie bisher" als Default) | 2 | | POST | `/cockpit/lektion//status` | Onboarding-Lektion als fertig/läuft markieren (V2-relevant) | 3 | | GET | `/cockpit/projekt/neu` | Projekt anlegen (mit Vorlage-Auswahl aus Katalog) | 6 | | POST | `/cockpit/projekt/neu` | Speichern | 6 | | POST | `/cockpit/projekt//edit` | Projekt-Details anpassen (während `in_arbeit`) | 6 | | GET | `/cockpit/projekt//abschluss` | **Abschluss-Checkliste** (V4: 3 Pflicht-Felder) | 6 | | POST | `/cockpit/projekt//abschluss` | Abschluss absenden → Status `wartet_auf_freigabe` | 6 | | POST | `/cockpit/projekt//datei` | Datei hochladen (30 MB Limit) | 6 | | POST | `/cockpit/projekt//datei//loeschen` | Eigene Datei entfernen | 6 | | POST | `/cockpit/projekt//rueckfrage//erledigt` | Rückfrage als erledigt markieren (V6) | 6 | | GET | `/cockpit/druckauftraege` | Eigene Auftragsliste | 7 | | POST | `/cockpit/druckauftrag/neu` | Auftrag eintragen | 7 | | GET | `/cockpit/slots` | Slot-Kalender (eigene + freie) — **gesperrt bis L1 fertig** (V2) | 6 | | POST | `/cockpit/slot/reservieren` | Neuen Slot buchen — gesperrt bis L1 fertig | 6 | | POST | `/cockpit/slot//stornieren` | Slot zurückgeben | 6 | | POST | `/cockpit/paarung/anfragen/` | Paar-Anfrage | 2 | | POST | `/cockpit/paarung/aufloesen` | Paar trennen | 2 | ## Admin (`routes/admin.py` — Herb + Markus) | Methode | Pfad | Zweck | Etappe | |---|---|---|---| | GET | `/admin/login` | Passwort-Eingabe | 1 | | GET | `/admin/dashboard` | **Drill-Down** (V5): „Wer ist heute hier / Wartet auf Review / Wer hängt fest" | 2 | | GET | `/admin/profile` | Liste + Edit | 1 | | POST | `/admin/profil/neu` | Neues SuS-Profil + PIN-Generation | 1 | | GET | `/admin/profile/karten` | Druckbogen PIN-Karten (CSS-Print) | 1 | | GET | `/admin/projekt-freigabe` | **Review-Queue** mit Badge im Dashboard | 6 | | GET | `/admin/projekt-freigabe/` | Detail-Review mit Three.js-Vorschau + Edit-Möglichkeit | 6 | | POST | `/admin/projekt//freigeben` | Projekt freigeben (mit optionaler Eigenbearbeitung) | 6 | | POST | `/admin/projekt//rueckfrage` | Rückfrage stellen → Status `rueckfrage` + Notiz im Cockpit | 6 | | POST | `/admin/projekt//loeschen` | **Hartes Löschen** mit Bestätigung (Audit-Log behält Datum + Lehrer + SuS-Name) | 6 | | POST | `/admin/projekt//datei-aus-3d` | Three.js-Screenshot als Cover speichern (von Detail-Review aus) | 6 | | GET | `/admin/druckauftraege` | Queue + Freigabe-UI | 7 | | POST | `/admin/druckauftrag//freigeben` | Lange Drucke explizit freigeben | 7 | | POST | `/admin/slot//prioritaet` | Slot-Priorität setzen | 6 | | POST | `/admin/slot//verschieben` | Slot bei Drucker-Ausfall auf anderen Drucker | 6 | | GET | `/admin/drucker` | Drucker-Stammdaten + manueller Status | 5 | | POST | `/admin/drucker//manueller_status` | Override bei API-Ausfall | 5 | | GET/POST | `/admin/lektionen` | Lektionen-CRUD | 3 | | GET | `/admin/einstellungen` | Konfig-Werte (auch Tag-Vorschläge) | 1 | | POST | `/admin/inline-edit` | Universal-Endpoint für Inline-Edit (Whitelist!) | 1 | ## API (`routes/api.py` — JSON für Frontend-Polling) | Methode | Pfad | Liefert | Frequenz | |---|---|---|---| | GET | `/api/drucker/status` | JSON aller 4 Drucker mit Status/Restzeit | alle 30 s im Frontend | | GET | `/api/slots/heute` | JSON aller aktiven/anstehenden Slots heute | alle 60 s | | GET | `/api/projekte/suche?q=...&tag=...&erfolg=...` | Projekt-Filter-Ergebnis als JSON (für Live-Suche im Katalog) | on-demand | | GET | `/api/admin/dashboard-zahlen` | Badge-Zahlen für Admin-Dashboard | beim Page-Load | ## Inline-Edit-Whitelist (`ERLAUBTE_INLINE_TABELLEN`) Pattern aus Arduino-Kurs (`app.py:~1530-1550`). Pro Tabelle und Feld definiert, was editiert werden darf. ```python ERLAUBTE_INLINE_TABELLEN = { "lektion": {"titel", "aufgabe_md", "tipp_md", "extern_link"}, "projekt": {"titel", "beschreibung_md", "tags"}, # bei Lehrer-Review zusätzlich "einstellung": {"wert"}, "software_seite": {"titel", "inhalt_md", "url", "quickstart_md"}, "drucker": {"name", "notiz"}, } # Zeitliche Begrenzung beim Projekt: Lehrer darf alle Felder editieren, # aber nur wenn projekt.freigabe_status IN ('wartet_auf_freigabe', 'rueckfrage') ``` Jede Änderung loggt in `aenderung_log` (Tabelle, Datensatz-ID, Feld, alter Wert, neuer Wert, Lehrer-Profil-ID). ## Sicherheit - Admin-Routen via `@admin_required`-Decorator (Passwort aus `.env`). - Profil-Routen via `@login_required` (Session-basiert). - Slot-Buchung zusätzlich via `@onboarding_l1_fertig` (V2). - Inline-Edit-POST mit CSRF-Token. - Login: persistenter Lockout über `login_lockout`-Tabelle (V7). Fenster: 5 Versuche / 5 Min, danach 15 Min Sperre. - Datei-Download nur wenn `sichtbar_in_ag=1` und SuS eingeloggt; Lehrer sieht immer alles. - Hartes Löschen (V3-Aktion) mit Audit-Log (Datum, Lehrer, SuS, Grund optional) — Dateien sind danach weg.