Entry Points

Diese Seite dokumentiert alle Einstiegspunkte (Entry Points) des Vogelschlagmelders. Sie richtet sich an Entwickler*innen und Integrator*innen, die das System erweitern, anbinden oder debuggen möchten.

Die Anwendung ist ein FastAPI-basierter Webservice, der über Docker bereitgestellt wird. Die Entry Points gliedern sich in zwei Hauptkategorien:

  • Öffentliche Entry Points – ohne Authentifizierung erreichbar, für Endnutzer*innen und externe Systeme

  • Interne Entry Points – erfordern Authentifizierung, für Administration und Meldezentrale


Anwendungsstart

Der zentrale Einstiegspunkt der Anwendung ist app/main.py. Die Anwendung wird mit Uvicorn gestartet:

uvicorn main:app --host 0.0.0.0 --port 8000

Beim Start werden folgende Schritte ausgeführt:

  1. FastAPI-App initialisieren (Titel: „Vogelschlagmelder“)

  2. Statische Dateien und Jinja2-Templates registrieren

  3. Alle Routen-Module einbinden

  4. CSRF-Schutz- und Security-Header-Middleware aktivieren

  5. Zugangsdaten validieren (ADMIN_PASSWORD, MELDEZENTRALE_PASSWORD, CSRF_SECRET)

  6. Datenbank initialisieren und Standardeinstellungen anlegen

  7. Vogelarten und Abdruckgrößen aus Seed-Daten befüllen

Docker

Die produktive Bereitstellung erfolgt über Docker Compose (docker-compose.yaml):

Eigenschaft

Wert

Basis-Image

python:3.11-slim

Port

8000

Benutzer

appuser (nicht-root)

Healthcheck

GET /healthz (alle 30 s)

Persistenz

Volume ./data:/app/data (Datenbank + Uploads)

Umgebungsvariablen

Variable

Pflicht

Standard

Beschreibung

ADMIN_USER

ja

admin

Benutzername des System-Administrators

ADMIN_PASSWORD

ja

Passwort (mind. 8 Zeichen, nicht auf Schwachstellenliste)

MELDEZENTRALE_USER

ja

meldezentrale

Benutzername der Meldezentrale

MELDEZENTRALE_PASSWORD

ja

Passwort (mind. 8 Zeichen)

CSRF_SECRET

ja

Zufälliger Schlüssel für CSRF-Tokens

PRODUCTION_MODE

nein

false

Aktiviert HTTPS-only-Cookies

SMTP_HOST

nein

SMTP-Server für E-Mail-Benachrichtigungen

SMTP_PORT

nein

587

SMTP-Port

SMTP_USER

nein

SMTP-Benutzername

SMTP_PASSWORD

nein

SMTP-Passwort

SMTP_FROM

nein

Absender-Adresse

SMTP_STARTTLS

nein

true

TLS-Verschlüsselung verwenden

FROM_EMAIL

nein

Von-Adresse in E-Mails

FROM_NAME

nein

Von-Name in E-Mails

Tipp

CSRF-Secret generieren: python3 -c "import secrets; print(secrets.token_hex(32))"


Öffentliche Entry Points

Alle hier aufgeführten Routen sind ohne Anmeldung erreichbar und bilden die Schnittstelle für Endnutzer*innen sowie externe Systeme.

Öffentliche Webseiten

Diese Routen liefern HTML-Seiten für die Bürger*innen-Interaktion aus.

Modul: app/src/routes_public.py

Route

Methode

Beschreibung

/

GET

Meldeformular mit Karte, Vogelartenliste und aktueller Uhrzeit

/meldung

POST

Neue Vogelschlagmeldung absenden (inkl. Bildupload, Validierung, Benachrichtigungen)

/info

GET

Optionale Infoseite (Weiterleitung auf / wenn deaktiviert)

/gefahrenkarte

GET

Öffentliche Heatmap aller Vogelschläge (wenn aktiviert)

/dynamic-styles.css

GET

Dynamisch generiertes CSS mit konfigurierten Theme-Farben

Meldeformular-Felder (/meldung): Koordinaten, Zeitstempel, Fensterabdruck (ja/nein/unbekannt), Vogelzustand (keiner/verletzt/tot), Fassadenrichtung, Adresse, Ortshinweise, Kontaktdaten, Vogelart, Abdruckgröße und bis zu 5 Fotos (max. 10 MB, HEIC/HEIF wird automatisch zu JPEG konvertiert).

Öffentliche REST-API

Die öffentliche API liefert Daten im JSON-Format und benötigt keine Authentifizierung.

Modul: app/src/routes_api.py

Route

Methode

Beschreibung

Rückgabe

/api/heatmap-data

GET

Heatmap-Rasterdaten für die Gefahrenkarte (inkl. historischer Daten)

grid_data, thresholds, grid_size_meters

/api/map-settings

GET

Karten-Konfiguration

center_lat, center_lng, default_zoom, max_radius_km

Authentifizierte REST-API (API-Key)

Diese Endpunkte erfordern einen gültigen API-Schlüssel im Header X-Api-Key. API-Schlüssel werden in der Adminoberfläche verwaltet und in der Datenbank gespeichert.

Modul: app/src/routes_api.py

Route

Methode

Beschreibung

Rückgabe

/api/v1/meldungen/heute

GET

Alle Meldungen des heutigen Tages

count + reports-Array

/api/v1/meldungen/letzte

GET

Die zuletzt eingegangene Meldung

Einzelnes Report-Objekt oder null

/api/v1/statistik

GET

Umfassende Statistik (nach Jahr, Status, Fassadenrichtung, Monat)

summary, yearly, by_status, by_orientation, by_month

Report-JSON-Struktur:

{
  "id": 42,
  "lat": 50.927,
  "lng": 11.586,
  "timestamp": "2026-03-15T08:30:00",
  "bird_status": "Vogel gefunden (tot)",
  "has_window_imprint": true,
  "bird_found": "dead",
  "facade_orientation": "Süd",
  "location_hint": "3. OG, Fenster zur Straße",
  "email": "melder@example.org",
  "phone": "+49 123 456789",
  "image_paths": ["uploads/img_001.jpg"],
  "duplicate": false,
  "duplicate_reference_id": null,
  "is_verified": true,
  "bird_species": "Amsel",
  "imprint_size": "Mittel (15–25 cm)"
}

Statische Dateien und Uploads

Route

Methode

Beschreibung

/uploads/{filename}

GET

Liefert hochgeladene Dateien aus; Logo und Favicon sind öffentlich, alle anderen erfordern Authentifizierung

/uploads/cms/{filename}

GET

Öffentlich erreichbare CMS-Uploads (Bilder/Videos der Infoseite)

/healthz

GET

Healthcheck-Endpunkt für Docker (gibt 200 OK zurück)


Interne Entry Points

Alle folgenden Routen erfordern eine gültige Sitzung (Cookie-basiert). Es gibt zwei Berechtigungsstufen:

  • Admin – Vollzugriff auf alle Einstellungen und die Meldezentrale

  • Meldezentrale – Zugriff auf Meldungsverwaltung und Datenexport

Authentifizierung

Modul: app/src/routes_auth.py

Route

Methode

Beschreibung

/anmelden

GET

Login-Seite mit CSRF-Token

/anmelden

POST

Login-Verarbeitung; setzt admin_token- bzw. meldezentrale_token-Cookie

/admin/login

GET/POST

Weiterleitung auf /anmelden

/admin/logout

GET

Admin-Abmeldung (Sitzung und Cookies löschen)

/meldezentrale/login

GET/POST

Weiterleitung auf /anmelden

/meldezentrale/logout

GET

Meldezentrale-Abmeldung

Authentifizierungsarten:

  1. Systemkonten – über Umgebungsvariablen konfiguriert (ADMIN_USER/ADMIN_PASSWORD, MELDEZENTRALE_USER/MELDEZENTRALE_PASSWORD)

  2. Datenbankkonten – in der Adminoberfläche erstellt und verwaltet, Passwörter mit PBKDF2-SHA256 (120.000 Iterationen) gehasht

Sicherheitsmaßnahmen:

  • CSRF-Schutz (HMAC-SHA256, 1 h Gültigkeit)

  • Rate-Limiting: max. 5 Fehlversuche in 5 Minuten → 15 Minuten Sperrung

  • Sichere Cookies (HttpOnly, SameSite=Strict, Secure im Produktionsmodus)

  • IP-basiertes Login-Tracking

Admin – Dashboard und Konten

Modul: app/src/routes_admin.py

Route

Methode

Beschreibung

/admin

GET

Dashboard mit Statistik (Woche, Monat, Jahr, Gesamt)

/admin/accounts

GET

Benutzerkontenverwaltung

/admin/accounts/create

POST

Neues Benutzerkonto anlegen (Rolle: Admin oder Meldezentrale)

/admin/accounts/{id}/update

POST

Benutzerkonto bearbeiten

/admin/accounts/{id}/delete

POST

Benutzerkonto löschen

/admin/kommunikation

GET

Element-/Matrix-Integrations-Einstellungen

/admin/kommunikation/test

POST

Test-Nachricht an konfiguriertem Element-Raum senden

/admin/kommunikation/rooms

GET

Matrix-Räume abrufen (AJAX)

Admin – Erscheinungsbild und Anpassungen

Modul: app/src/routes_admin_settings.py

Route

Methode

Beschreibung

/admin/anpassungen

GET

Anpassungsseite anzeigen

/admin/anpassungen/logo

POST

Logo hochladen (PNG/JPG/SVG/WebP, max. 2 MB)

/admin/anpassungen/logo/delete

POST

Logo entfernen

/admin/anpassungen/favicon

POST

Favicon hochladen und Tab-Titel setzen

/admin/anpassungen/favicon/delete

POST

Favicon entfernen

/admin/anpassungen/tab-title

POST

Browser-Tab-Titel ändern

/admin/anpassungen/organisation

POST

Organisationsname, Wirkungsbereich, Slogan

/admin/anpassungen/introtext

POST

Einleitungstext des Meldeformulars

/admin/anpassungen/subheadline

POST

Unterüberschrift im Header-Bereich

/admin/anpassungen/hinweise

POST

Hinweisbox (Titel und Inhalt)

/admin/anpassungen/header-buttons

POST

Zusätzliche Header-Buttons (Text + URLs)

/admin/anpassungen/farben

POST

Farbschema (Primär, Dunkel, Hell, Akzent)

/admin/anpassungen/links

POST

Datenschutz- und Impressums-URLs

Admin – Formular und Katalogdaten

Modul: app/src/routes_admin_settings.py

Route

Methode

Beschreibung

/admin/meldeformular

GET

Formularfeld-Konfiguration anzeigen

/admin/meldeformular/save

POST

Pflichtfelder-Einstellungen speichern (Name, Vorname, E-Mail, Telefon, Kontaktweg)

/admin/vogelarten

GET

Vogelarten-Katalog anzeigen

/admin/vogelarten/create

POST

Neue Vogelart anlegen

/admin/vogelarten/{id}/update

POST

Vogelart umbenennen

/admin/vogelarten/{id}/delete

POST

Vogelart löschen

/admin/abdruckgroessen

GET

Abdruckgrößen-Katalog anzeigen

/admin/abdruckgroessen/create

POST

Neue Abdruckgröße anlegen

/admin/abdruckgroessen/{id}/update

POST

Abdruckgröße bearbeiten

/admin/abdruckgroessen/{id}/delete

POST

Abdruckgröße löschen

Admin – Karte und Gefahrenkarte

Modul: app/src/routes_admin_settings.py

Route

Methode

Beschreibung

/admin/karte

GET

Karten-Konfiguration anzeigen

/admin/karte/save

POST

Kartenmittelpunkt (Lat/Lng), Zoom-Stufe und Radius speichern

/admin/gefahrenkarte

GET

Heatmap-Konfiguration anzeigen

/admin/gefahrenkarte/save

POST

Heatmap-Einstellungen speichern (Sichtbarkeit, Rastergröße, Schwellwerte, Farben)

Admin – Historische Daten

Modul: app/src/routes_admin_data.py

Route

Methode

Beschreibung

/admin/historisch

GET

Historische Daten mit Import-/Exportfunktion anzeigen

/admin/historisch/settings

POST

Historische Daten in Statistik einbeziehen (ja/nein)

/admin/historisch/upload

POST

CSV-Import (Spalten: Latitude, Longitude, Straße, Hausnummer, PLZ, Stadt, Hinweise, Anzahl Meldungen, Seite der Kollision)

/admin/historisch/delete-all

POST

Alle historischen Datensätze löschen

/admin/historisch/anlegen

POST

Einzelnen historischen Datensatz manuell anlegen

/admin/historisch/{id}

GET

Bearbeitungsformular für historischen Datensatz

/admin/historisch/{id}/update

POST

Historischen Datensatz aktualisieren

/admin/historisch/{id}/delete

POST

Einzelnen historischen Datensatz löschen

Admin – Widgets, Infoseite und Einstellungssicherung

Modul: app/src/routes_admin_data.py

Route

Methode

Beschreibung

/admin/widgets

GET

Widget-Konfiguration (Platzhalter)

/admin/custom-page

GET

Infoseiten-Editor anzeigen

/admin/custom-page/save

POST

Infoseite speichern (JSON-Blöcke: Text, Bild, Video, Abstandshalter)

/admin/einstellungen/export

GET

Alle Einstellungen als ZIP-Backup exportieren

/admin/einstellungen/import

POST

Einstellungen aus ZIP-Backup importieren

Meldezentrale – Meldungsverwaltung

Modul: app/src/routes_meldezentrale.py

Route

Methode

Beschreibung

/meldezentrale

GET

Weiterleitung auf /meldezentrale/meldungen

/meldezentrale/meldungen

GET

Meldungsliste mit erweiterter Filter- und Paginierungsfunktion

/meldezentrale/meldungen/{id}

GET

Detailansicht einer Meldung

/meldezentrale/meldungen/{id}/update

POST

Meldung bearbeiten (Ort, Kontaktdaten, Status)

/meldezentrale/meldungen/{id}/mark-verified

POST

Meldung als geprüft markieren

/meldezentrale/meldungen/{id}/mark-poorly

POST

Meldung als ungenügend markieren

/meldezentrale/meldungen/{id}/mark-duplicate

POST

Meldung als Duplikat markieren

/meldezentrale/meldungen/{id}/delete

POST

Meldung löschen

/meldezentrale/meldungen/{id}/image/{file}/delete

POST

Einzelnes Bild einer Meldung löschen

Filterparameter (Query-String):

Parameter

Beschreibung

page, page_size

Seitenzahl und Elemente pro Seite (10, 25, 50, 100)

hide_duplicates

Duplikate ausblenden

hide_poorly

Ungenügende Meldungen ausblenden

hide_verified

Bereits geprüfte Meldungen ausblenden

date_from, date_to

Zeitraumfilter (ISO-8601)

search

Volltextsuche (Name, E-Mail, Telefon, Adresse, Vogelart …)

north, south, east, west

Geografische Begrenzung

saved_filter_id

Gespeicherten Filter laden

Meldezentrale – Gespeicherte Filter

Modul: app/src/routes_meldezentrale.py

Route

Methode

Beschreibung

/meldezentrale/filters/save

POST

Aktuelle Filtereinstellungen mit Name speichern

/meldezentrale/filters/{id}/delete

POST

Gespeicherten Filter löschen

/meldezentrale/filters/{id}/load

GET

Gespeicherten Filter laden (Weiterleitung mit angewandtem Filter)

Meldezentrale – Datenexport und Statistik

Modul: app/src/routes_export.py

Route

Methode

Beschreibung

Format

/meldezentrale/export

GET

Exportseite mit Filteroptionen

HTML

/meldezentrale/statistik

GET

Statistikseite mit Diagrammen und Tabellen

HTML

/meldezentrale/export/csv

GET/POST

Gefilterte Meldungen als CSV exportieren

CSV (Semikolon-getrennt)

/meldezentrale/export/bilder

GET

Bilder gefilterter Meldungen als ZIP exportieren

ZIP

/meldezentrale/export/bereich

GET

Meldungen innerhalb eines Kartenausschnitts als CSV

CSV

/meldezentrale/export/bereich/bilder

GET

Bilder eines Kartenausschnitts als ZIP

ZIP

CSV-Spalten: ID, Datum, Uhrzeit, Latitude, Longitude, Straße, Hausnummer, PLZ, Stadt, Vogelzustand, Vogelart, Abdruckgröße, Fassadenrichtung, Hinweise zum Ort, Name, Vorname, E-Mail, Telefon, Bilder, Duplikat, Referenz-ID, Geprüft.


Hintergrunddienste

Diese Komponenten sind keine HTTP-Routen, sondern werden intern beim Absenden einer Meldung (POST /meldung) ausgelöst.

E-Mail-Benachrichtigungen

Modul: app/src/notifications.py

Beim Eingang einer neuen Meldung wird eine E-Mail an alle in AdminSettings.notification_emails hinterlegten Adressen gesendet. Die Nachricht enthält einen HTML-formatierten Bericht mit Link zur OpenStreetMap-Position.

Voraussetzung: Gültige SMTP-Konfiguration über Umgebungsvariablen.

Element-/Matrix-Benachrichtigungen

Module: app/src/notifications.py, app/src/element_connector.py

Wenn die Element-Integration aktiviert ist (ElementSettings.is_enabled), wird bei jeder neuen Meldung eine HTML-formatierte Nachricht an den konfigurierten Matrix-Raum gesendet.

Funktionen des Element-Connectors:

Funktion

Beschreibung

fetch_joined_rooms()

Beitretene Matrix-Räume abrufen

send_message()

Text-/HTML-Nachricht an einen Raum senden

send_test_message()

Testbenachrichtigung senden

is_configured()

Prüfen, ob die Integration vollständig konfiguriert ist


Datenbank

Datenbanksystem: SQLite
Pfad: /app/data/vogelschlagmelder.db

Tabellen

Tabelle

Beschreibung

report

Vogelschlagmeldungen (Koordinaten, Zeitstempel, Vogelstatus, Kontaktdaten, Bilder, Duplikat-/Prüfstatus)

historicalreport

Importierte historische Daten (Standort, Anzahl Meldungen)

sitesettings

Website-Konfiguration (Logo, Favicon, Farben, Pflichtfelder, Funktionsschalter)

mapsettings

Kartenmittelpunkt, Zoom-Stufe, maximaler Radius

heatmapsettings

Gefahrenkarte (Sichtbarkeit, Rastergröße, Schwellwerte, Farbwerte)

historicaldatasettings

Einstellung, ob historische Daten in Statistiken einfließen

adminsettings

Admin-Konfiguration (Benachrichtigungs-E-Mails als JSON)

elementsettings

Matrix-Integration (Homeserver-URL, Access-Token, Raum-ID, Aktivierungsstatus)

useraccount

Datenbankbasierte Benutzerkonten (Benutzername, Passwort-Hash, Rollen)

birdspecies

Vogelarten-Katalog

imprintsize

Abdruckgrößen-Katalog (Name, Sortierung)

apikey

REST-API-Schlüssel (Schlüssel, Name, Aktivierungsstatus)

savedfilter

Gespeicherte Tabellenfilter (Name, Parameter als JSON)

Initialisierung beim Start

Beim Anwendungsstart werden automatisch folgende Schritte ausgeführt:

  1. init_database() – Tabellen erstellen, falls nicht vorhanden

  2. ensure_report_schema() – Fehlende Spalten nachträglich hinzufügen (Migrationen)

  3. ensure_bird_species_defaults() – Vogelarten aus bird_list_germany.txt einspielen

  4. ensure_imprint_size_defaults() – Standard-Abdruckgrößen anlegen


Sicherheitsmechanismen

Modul: app/src/security.py

Mechanismus

Beschreibung

CSRF-Schutz

Token-Generierung und -Validierung mit HMAC-SHA256 (1 h Gültigkeit). Origin/Referer-Prüfung auf allen schreibenden Endpunkten (außer /api/*).

Rate-Limiting

Max. 5 fehlgeschlagene Login-Versuche pro IP in 5 Minuten → 15 Minuten Sperre.

Datei-Upload-Validierung

Prüfung von Dateityp (Magic Bytes) und Dateigröße. Erlaubt: PNG, JPG, GIF, WebP, HEIC.

HTTP-Security-Header

X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Strict-Transport-Security, restriktive Content-Security-Policy, Permissions-Policy.

HTML-Sanitisierung

Entfernung potenziell schädlicher Inhalte in Benutzereingaben über Jinja2-Filter sanitize_html.

Passwort-Hashing

PBKDF2-SHA256 mit 120.000 Iterationen für Datenbankkonten.


Übersicht aller Entry Points

Kategorie

Anzahl

Beispiele

Öffentliche Webseiten

5

/, /meldung, /gefahrenkarte

Öffentliche API

2

/api/heatmap-data, /api/map-settings

API mit Schlüssel

3

/api/v1/meldungen/heute, /api/v1/statistik

Authentifizierung

8

/anmelden, /admin/logout

Admin-Routen

~50

/admin, /admin/anpassungen/*, /admin/vogelarten/*

Meldezentrale-Routen

~15

/meldezentrale/meldungen, /meldezentrale/filters/*

Export-Routen

6

/meldezentrale/export/csv, /meldezentrale/export/bilder

Hintergrunddienste

2

E-Mail-Benachrichtigungen, Element-/Matrix-Benachrichtigungen

Gesamt HTTP-Endpunkte

~90