7.5 KiB
FocusApp - Todo Application
Eine moderne, minimalistische Todo-Anwendung mit Drag & Drop, gebaut mit React und ASP.NET Core 8.0.
🚀 Features
-
✅ Todo-Verwaltung - Erstellen, Bearbeiten, Loschen von Aufgaben
-
🎯 Drag & Drop - Intuitive Neuordnung der Aufgaben
-
📱 Responsive Design - Optimiert fur Desktop und Mobile
-
🔄 RESTful API - Saubere Backend-Architektur
📋 Voraussetzungen
- Docker und Docker Compose
- MariaDB (externer Host, z.B. LXC Container)
- Git
🐳 Deployment
1. MariaDB initialisieren (einmalig)
Die FocusApp benötigt eine MariaDB Datenbank. Das Init-Script erstellt die Datenbank und den User auf dem externen MariaDB-Server.
# .env aus Template erstellen und editieren
cp .env.example .env
vim .env
# Init-Script als MariaDB Root ausfuehren
mysql -h $DB_HOST -u root -p < init-db.sql
Die .env.example enthalt:
DB_HOST=maria-db-server.domain.local
DB_PORT=3306
DB_NAME=focusapp
DB_USER=focusapp
DB_PASSWORD=<CHANGE_ME>
2. Docker Image bauen
docker compose build
Oder direkt aus dem GitHub Container Registry pullen (nach dem ersten CI-Run):
docker compose pull
3. App starten
docker compose up -d
Die App laeuft auf: http://localhost:5000
4. Logs anzeigen
docker compose logs -f
🔄 CI/CD mit GitHub Actions
Bei jedem Push auf main wird automatisch:
- Das Docker-Image gebaut (Multi-Stage: Node + .NET)
- Nach
ghcr.io(GitHub Container Registry) gepusht - Alte Images aufgeraeumt (letzte 4 bleiben erhalten)
Manuelles Deployment auf dem Host
# Neuestes Image pullen
docker compose pull
# Container neustarten
docker compose up -d
⚙️ Konfiguration
Die App wird ueber Umgebungsvariablen konfiguriert, die in docker-compose.yml gesetzt werden:
| Variable | Beschreibung |
|---|---|
ASPNETCORE_ENVIRONMENT |
Production oder Development |
ConnectionStrings__DefaultConnection |
MariaDB Connection String |
Der Connection-String wird aus der .env zusammengesetzt:
Server=${DB_HOST};Port=${DB_PORT};Database=${DB_NAME};User=${DB_USER};Password=${DB_PASSWORD}
📡 API Endpoints
Todos abrufen
GET /api/focustasks
Todo erstellen
POST /api/focustasks
Content-Type: application/json
{
"title": "Neue Aufgabe",
"description": "Optional"
}
Todo aktualisieren
PUT /api/focustasks/{id}
Content-Type: application/json
{
"id": 1,
"title": "Geaendert",
"description": "Neue Beschreibung"
}
Todo loeschen
DELETE /api/focustasks/{id}
Reihenfolge aktualisieren
POST /api/focustasks/reorder
Content-Type: application/json
[1, 3, 2, 4]
🎯 Entwicklung
Backend (Development)
dotnet run
API laeuft auf: http://localhost:5000
Frontend (Development)
cd client
npm install
npm run dev
React Dev Server laeuft auf: http://localhost:5173
API-Calls werden automatisch an http://localhost:5000 weitergeleitet (siehe vite.config.ts).
📦 Projektstruktur
FocusApp/
├── client/ # React Frontend (TypeScript, Vite)
│ ├── src/
│ │ ├── components/ # React Komponenten
│ │ ├── App.tsx # Haupt-App
│ │ ├── api.ts # Axios API Client
│ │ └── main.tsx # Entry Point
│ ├── build/ # Production Build
│ └── package.json
├── Controllers/
│ └── FocusTasksController.cs
├── Data/
│ └── FocusContext.cs # EF Core DbContext
├── Models/
│ ├── FocusTask.cs # Domain Model
│ └── Dtos.cs # API Data Transfer Objects
├── Program.cs # ASP.NET Startup
├── FocusApp.csproj # Projekt-Datei
├── appsettings.json # Config
├── Dockerfile # Multi-Stage Docker Build
├── docker-compose.yml # Docker Compose Konfiguration
├── .env.example # Environment Template
└── init-db.sql # MariaDB Init Script
🐛 Troubleshooting
Container startet nicht
# Logs pruefen
docker compose logs app
# Container Status
docker compose ps
Datenbank-Fehler
# Pruefen ob MariaDB erreichbar ist
mysql -h $DB_HOST -u $DB_USER -p
# DB neu initialisieren
mysql -h $DB_HOST -u root -p < init-db.sql
Port bereits belegt
Port in docker-compose.yml aendern:
ports:
- "5001:5000"
🔐 Sicherheit
Authentifizierung mit Authelia
Die FocusApp hat keine eigene Authentifizierung. Alle Endpoints sind offen zugänglich. Für einen Produktiveinsatz muss die App hinter einem Authentifizierungs-Proxy betrieben werden.
Authelia stellt Single Sign-On (SSO) bereit und schützt die App mit einem Reverse Proxy.
Architektur:
Browser → nginx + Authelia → FocusApp (Docker)
↓
MariaDB (extern)
Voraussetzungen:
- Authelia läuft als eigener Container/Dienst
- nginx als Reverse Proxy mit Authelia-Integration
nginx-Konfiguration mit Authelia:
# Authelia snippet einbinden
include /etc/nginx/authelia/authelia-location.conf;
server {
listen 443 ssl;
server_name focus.example.com;
ssl_certificate /etc/ssl/certs/focus.crt;
ssl_certificate_key /etc/ssl/private/focus.key;
# Schuetzt alle Routes hinter Authelia
location / {
include /etc/nginx/authelia/authelia-authrequest.conf;
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Remote-User $remote_user;
}
}
Authelia-Konfiguration (configuration.yml):
access_control:
default_policy: one_factor
rules:
# API-Endpoints ebenfalls schuetzen
- domain: focus.example.com
resources:
- "^/api/.*$"
policy: one_factor
session:
name: focusapp_session
secret: "your-session-secret"
cookies:
- domain: focus.example.com
authelia_url: https://auth.example.com
default_redirection_url: https://focus.example.com
identity_providers:
- id: ldap
# oder: - id: openid_connect
Wichtig:
- Ohne Authelia ist die App komplett offen — kein Schutz für API oder Frontend
- Authelia prüft vor jedem Request die Sitzung
- Der
/api/Pfad muss ebenfalls geschützt werden (nicht nur/) - Für API-Clients (z.B. Mobile Apps) kann eine API-Key-Lösung implementiert werden
Reverse Proxy (nginx) ohne Authelia
Für lokale Entwicklung/Tests ohne Auth:
server {
listen 443 ssl;
server_name focus.example.com;
ssl_certificate /etc/ssl/certs/focus.crt;
ssl_certificate_key /etc/ssl/private/focus.key;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Version: 2.0.0 Letzte Aktualisierung: 09. August 2026