This commit is contained in:
Oliver Hofmann 2026-04-27 08:33:43 +02:00
commit 4fbcb99743
14 changed files with 255 additions and 0 deletions

8
.env.example Normal file
View File

@ -0,0 +1,8 @@
APP_ENV=development
APP_PREFIX=
DATABASE_URL=sqlite:///./app.db
# Produktion (MariaDB):
# APP_ENV=production
# APP_PREFIX=/uph
# DATABASE_URL=mysql+pymysql://user:password@db:3306/efihub

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Environments (Virtualenvs)
.env
.venv
env/
venv/
ENV/
# Database (Wichtig: Verhindert, dass die lokale SQLite-DB committet wird)
*.sqlite3
*.db
# macOS System Files
.DS_Store
.AppleDouble
.LSOverride
# PyCharm / JetBrains IDE
.idea/
!.idea/runConfigurations/
*.iws
*.iml
*.ipr
# Project specific
docker-compose.override.yml

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

10
.idea/efihub.iml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.12 (efihub)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,28 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="84" name="Python" />
</Languages>
</inspection_tool>
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="E302" />
<option value="E111" />
<option value="E201" />
<option value="E222" />
<option value="E303" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="clean.ShoppingCart.*" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/efihub.iml" filepath="$PROJECT_DIR$/.idea/efihub.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

68
CLAUDE.md Normal file
View File

@ -0,0 +1,68 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project
**University Process Hub (UPH)** — modulares FastAPI-Backend für Fakultätsprozesse (TH Nürnberg). Einstieg ist ein RSS-Server, erweiterbar durch Module in `app/modules/`. Dient als Basis für studentische Arbeiten.
## Commands
```bash
# Abhängigkeiten installieren
pip install -r requirements.txt
# Entwicklungsserver starten
uvicorn app.main:app --reload
# Mit APP_PREFIX (Traefik-Simulation)
APP_PREFIX=/uph uvicorn app.main:app --reload
# Tests ausführen
pytest
# Einzelnen Test ausführen
pytest tests/test_foo.py::test_bar -v
# Formatting & Linting
black app/
flake8 app/
```
## Architektur
### Konfiguration (`app/core/config.py`)
Zentrale `Settings`-Klasse via `pydantic-settings`. Werte kommen aus `.env` oder Umgebungsvariablen:
- `APP_PREFIX` — Traefik-Pfadpräfix (z. B. `/uph`). Wird als `root_path` an FastAPI übergeben, damit alle Routen inkl. WebSockets und Swagger UI automatisch korrekt geroutet werden.
- `DATABASE_URL``sqlite:///./app.db` lokal, `mysql+pymysql://...` in Produktion. Kein separates Flag nötig — SQLAlchemy erkennt den Dialekt aus der URL.
- Singleton via `@lru_cache``get_settings()` als FastAPI-Dependency injizierbar.
### App-Entrypoint (`app/main.py`)
`FastAPI(root_path=settings.APP_PREFIX)` — das ist der einzige Ort, an dem `APP_PREFIX` angewendet wird. Kein Prefix-Middleware-Hack nötig.
### Modulstruktur
Jedes Feature liegt in `app/modules/<name>/` mit:
- `router.py``APIRouter`, wird in `main.py` per `app.include_router()` eingebunden
- `service.py` — Businesslogik (keine direkten FastAPI-Abhängigkeiten)
- `models.py` — SQLAlchemy-Models
Module müssen ohne tiefgreifende Core-Abhängigkeiten exportierbar sein (für studentische Arbeiten).
### Datenbank (`app/core/database.py`, noch zu erstellen)
Zentrales `database.py` mit SQLAlchemy 2.0 Engine und Session-Factory. Sessions werden als FastAPI-Dependency (`Depends(get_db)`) injiziert.
### Authentifizierung (`app/core/auth.py`, noch zu erstellen)
OAuth2/JWT als FastAPI-Dependencies. Referenzimplementierung liegt in `/Users/oliver/Development/Operations/django-app/authstuff` (Django-Logik, muss auf FastAPI portiert werden).
## Deployment
- Traefik-basiertes pfadbasiertes Routing via `APP_PREFIX`
- Docker & Docker Compose (Configs in `docker/`)
- Celery + Redis als Task-Queue (`app/worker/`)
- Admin-UI via `sqladmin`

46
README.md Normal file
View File

@ -0,0 +1,46 @@
# University Process Hub (UPH)
## 1. Vision & Goals
Modulares Backend für Fakultätsprozesse. Startpunkt ist ein RSS-Server, erweiterbar um REST-APIs und Websockets für Echtzeit-Kommunikation. Das System dient als Basis für studentische Arbeiten.
## 2. Tech-Stack
* **Framework:** FastAPI (Python 3.11+)
* **Kommunikation:** REST & Websockets (native FastAPI Implementation)
* **Datenbank:** SQLAlchemy 2.0 (Support für SQLite lokal & MariaDB produktiv)
* **Task-Queue:** Celery mit Redis als Broker
* **Deployment:** Docker & Docker Compose
* **Proxy:** Traefik-ready mit pfadbasiertem Routing (`APP_PREFIX`)
## 3. Architektur-Richtlinien für Claude Code
* **Modularität:** Jedes Modul (z.B. `rss_feed`) liegt in `app/modules/`. Es muss ohne tiefgreifende Core-Abhängigkeiten exportierbar sein.
* **Routing:** Nutze `APIRouter`. Implementiere eine globale Middleware oder eine Prefix-Logik, die die `APP_PREFIX` Umgebungsvariable nutzt, damit alle Routen (inkl. Websockets) unter Traefik funktionieren.
* **Database:** Zentrale `database.py`. Studierende nutzen SQLite, der Server nutzt MariaDB via `DATABASE_URL`.
* **Authentifizierung:** Übernimm das Logik-Konzept aus `/Users/oliver/Development/Operations/django-app/authstuff`, implementiere es aber als FastAPI-Dependencies (OAuth2/JWT).
* **Admin-UI:** Nutze `sqladmin` oder `fastapi-users`, um eine einfache Weboberfläche zur Datenpflege bereitzustellen.
* **Testing:** Schreibe Unit-Tests mit `pytest` für alle Module. Teste auch die Websocket-Kommunikation mit `websockets` oder `httpx`.
* **Documentation:** Nutze FastAPI's automatische Dokumentation (Swagger UI) und ergänze sie mit ausführlichen Docstrings. Erstelle zusätzlich ein `docs/` Verzeichnis für weiterführende Spezifikationen und Anleitungen.
* **Code-Style:** Halte dich an PEP 8. Nutze `black` für automatisches Formatting und `flake8` für Linting. Vermeide komplexe Funktionen (>20 Zeilen) und setze auf klare, sprechende Namen.
* **UX:** Orientiere Dich bei der Visualisierung am Vorläufer, zu erreichen unter `https://medinf.efi.th-nuernberg.de/app/`. Ersetze aber Bootstrap durch Tailwind CSS für eine modernere und flexiblere Gestaltung. Alle UI-Komponenten sollten responsive sein und auf verschiedenen Bildschirmgrößen gut funktionieren.
## 4. Struktur
.
├── app/
│ ├── __init__.py
│ ├── main.py # App-Entrypoint & FastAPI Initialisierung
│ ├── core/ # Übergreifende Logik
│ │ ├── config.py # APP_PREFIX, DB_URL, Secrets
│ │ ├── database.py # SQLAlchemy Engine & Session
│ │ └── auth.py # JWT & Berechtigungen (ex-Django Logik)
│ ├── modules/ # Abgeschlossene Module (für Studierende)
│ │ └── rss_feed/ # Das erste Modul
│ │ ├── router.py
│ │ ├── service.py
│ │ └── models.py
│ ├── schemas/ # Pydantic Models (REST/WS Validierung)
│ └── worker/ # Celery Tasks & Scheduler
├── legacy_django/ # Referenzcode (nicht aktiv)
├── docker/
│ ├── Dockerfile
│ └── docker-compose.yml
├── requirements.txt
└── .env.example

0
app/__init__.py Normal file
View File

22
app/main.py Normal file
View File

@ -0,0 +1,22 @@
from fastapi import FastAPI, WebSocket
from app.core.config import get_settings
settings = get_settings()
app = FastAPI(
title="University Process Hub",
root_path=settings.APP_PREFIX,
)
@app.get("/")
async def root():
return {"status": "ok", "env": settings.APP_ENV}
@app.websocket("/ws/hello/{name}")
async def websocket_hello(websocket: WebSocket, name: str):
await websocket.accept()
await websocket.send_text(f"Hello, {name}!")
await websocket.close()

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
fastapi
uvicorn[standard]
pydantic-settings
sqlalchemy

11
test_main.http Normal file
View File

@ -0,0 +1,11 @@
# Test your FastAPI endpoints
GET http://127.0.0.1:8000/
Accept: application/json
###
GET http://127.0.0.1:8000/hello/User
Accept: application/json
###