Init
This commit is contained in:
commit
4fbcb99743
8
.env.example
Normal file
8
.env.example
Normal 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
30
.gitignore
vendored
Normal 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
8
.idea/.gitignore
generated
vendored
Normal 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
10
.idea/efihub.iml
generated
Normal 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>
|
||||||
28
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
28
.idea/inspectionProfiles/Project_Default.xml
generated
Normal 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>
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal 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
8
.idea/modules.xml
generated
Normal 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
6
.idea/vcs.xml
generated
Normal 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
68
CLAUDE.md
Normal 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
46
README.md
Normal 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
0
app/__init__.py
Normal file
22
app/main.py
Normal file
22
app/main.py
Normal 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
4
requirements.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fastapi
|
||||||
|
uvicorn[standard]
|
||||||
|
pydantic-settings
|
||||||
|
sqlalchemy
|
||||||
11
test_main.http
Normal file
11
test_main.http
Normal 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
|
||||||
|
|
||||||
|
###
|
||||||
Loading…
x
Reference in New Issue
Block a user