fdd70fc20d
Kein Host-Port-Mapping mehr, stattdessen Anbindung an das externe Docker-Netzwerk "coolify" mit caddy-Labels für domainbasiertes Routing und automatisches TLS über ressourceksr.bbundco.de. README entsprechend aktualisiert (Coolify-Deployment ohne manuelle Port-Konfiguration). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
187 lines
8.3 KiB
Markdown
187 lines
8.3 KiB
Markdown
# Ressourcenplanung
|
||
|
||
Leichtgewichtige App zur Planung von Projekten, Aufgaben, Mitarbeitern, Teams und
|
||
Urlaub – mit Zeitplan (Gantt), Auslastungs-Heatmap, Team-Verwaltung und Login mit
|
||
Rollen/Rechten. Daten liegen in SQLite.
|
||
|
||
**Breaking Change:** Seit Einführung der Benutzerverwaltung erfordert jeder
|
||
API-Zugriff eine angemeldete Sitzung (`/health` bleibt für den Docker-Healthcheck
|
||
offen).
|
||
|
||
## Rollen & Rechte
|
||
|
||
| Rolle | Rechte |
|
||
|---|---|
|
||
| Admin | lesend + schreibend auf alles, inkl. Benutzerverwaltung |
|
||
| Teamleiter | schreibend auf Mitarbeiter/Teams/Projekte/Aufgaben und eigenen Urlaub; lesend auf Urlaub anderer |
|
||
| Mitarbeiter | schreibend nur auf eigenen Urlaub (mit Vertreterpflicht) und den Status eigener zugewiesener Aufgaben; sonst lesend |
|
||
| Beobachter | nur lesend, sieht ausschließlich Zeitplan/Auslastung/Urlaub |
|
||
|
||
**Passwort-Vergabe:** Neue Benutzerkonten (auch der Start-Admin) werden ohne
|
||
Passwort angelegt. Beim allerersten Login wird das eingegebene Passwort als
|
||
neues Passwort übernommen.
|
||
|
||
**Urlaubsvertretung:** Jeder Urlaubseintrag benötigt einen Vertreter aus der
|
||
Mitarbeiterliste. Eine Person darf nicht gleichzeitig (überlappender Zeitraum)
|
||
als Vertreter für zwei Urlaube *innerhalb derselben Berechtigungsrolle* der
|
||
jeweils antragstellenden Person eingetragen sein.
|
||
|
||
## Aufbau
|
||
|
||
```
|
||
ressourcenplanung/
|
||
├── server/ Node/Express + SQLite (better-sqlite3)
|
||
│ ├── schema.sql Tabellen & Beziehungen (inkl. users, sessions, vacations)
|
||
│ ├── db.js DB-Init, Beispieldaten, Start-Admin-Bootstrap
|
||
│ ├── auth.js Passwort-Hashing, Sessions, requireAuth/requireRole
|
||
│ ├── index.js REST-API (CRUD + Auslastungsberechnung)
|
||
│ └── scripts/
|
||
│ ├── reset-admin.js Admin-Zugang anlegen/zurücksetzen (CLI)
|
||
│ └── migrate-team-accounts.js Login-Konten für bestehende Mitarbeiter anlegen (CLI)
|
||
└── client/ Vue 3 + Vite
|
||
└── src/
|
||
├── App.vue Login-Gate + rollenbasierte Tab-Navigation
|
||
├── LoginPanel.vue Login (Erstanmeldung vergibt Passwort)
|
||
├── SchedulePanel.vue Gantt-Zeitplan
|
||
├── UtilizationPanel.vue Auslastungs-Heatmap (urlaubsbereinigt)
|
||
├── VacationPanel.vue Urlaubsplanung inkl. Vertreterregelung
|
||
├── ProjectsPanel.vue Projekte/Aufgaben inkl. Zuweisungen
|
||
├── EmployeesPanel.vue Mitarbeiter
|
||
├── TeamsPanel.vue Teams (n:m-Mitgliedschaft)
|
||
├── UsersPanel.vue Benutzerverwaltung (nur Admin)
|
||
├── store.js Reaktiver State + CRUD gegen die API
|
||
├── api.js API-Client + Token-Handling
|
||
└── helpers.js Datum-/Gantt-/Farbberechnung
|
||
```
|
||
|
||
## Lokale Entwicklung
|
||
|
||
Zwei Terminals.
|
||
|
||
**1) Backend**
|
||
```bash
|
||
cd server
|
||
npm install
|
||
npm run dev # startet auf http://localhost:8080
|
||
```
|
||
Beim ersten Start wird `server/data/data.db` angelegt und mit Beispieldaten befüllt.
|
||
Mit der Umgebungsvariable `ADMIN_EMAIL` (muss zur `email` eines bestehenden
|
||
Mitarbeiters passen) wird zusätzlich automatisch ein Start-Admin-Konto angelegt,
|
||
z. B.:
|
||
```bash
|
||
ADMIN_EMAIL=tom.fischer@example.com npm run dev
|
||
```
|
||
Ohne `ADMIN_EMAIL` wird kein Admin-Konto erzeugt — dann per
|
||
`node scripts/reset-admin.js --employee-id <id>` nachholen (siehe unten).
|
||
|
||
**2) Frontend**
|
||
```bash
|
||
cd client
|
||
npm install
|
||
npm run dev # startet auf http://localhost:5173
|
||
```
|
||
|
||
Browser auf http://localhost:5173 öffnen. Vite leitet `/api` und `/health`
|
||
per Proxy an das Backend weiter.
|
||
|
||
## Deployment (Docker)
|
||
|
||
Die App läuft als ein Container: Das Backend serviert die REST-API und das
|
||
gebaute Frontend intern über Port 8080. `docker-compose.yml` ist auf den in
|
||
Coolify installierten Caddy-Proxy zugeschnitten (siehe Abschnitt
|
||
"Deployment in Coolify") — es wird kein Host-Port mehr veröffentlicht,
|
||
stattdessen hängt sich der Container über das externe Docker-Netzwerk
|
||
`coolify` in den Proxy ein und ist über die im `caddy`-Label hinterlegte
|
||
Domain erreichbar.
|
||
|
||
Für einen rein lokalen Test außerhalb von Coolify muss das Netzwerk zuerst
|
||
angelegt werden, danach ist die App (ohne Domain/TLS) nur über die
|
||
Container-IP oder testweise per Port-Override erreichbar:
|
||
|
||
```bash
|
||
docker network create coolify # einmalig, falls nicht vorhanden
|
||
docker compose up --build
|
||
```
|
||
|
||
Die SQLite-Datenbank liegt im Docker-Volume `data`. `ADMIN_EMAIL` vor dem
|
||
ersten Start setzen (z. B. in einer `.env`-Datei neben `docker-compose.yml`),
|
||
damit ein Start-Admin für
|
||
einen bestehenden Mitarbeiter angelegt wird.
|
||
|
||
## Umstieg von der alten Version (ohne Login)
|
||
|
||
Bestehende Projekte, Aufgaben, Zuweisungen, Teams und Mitarbeiter bleiben beim
|
||
Update unverändert erhalten — alle neuen Tabellen (`users`, `sessions`,
|
||
`vacations`) werden vom Server additiv angelegt (`CREATE TABLE IF NOT EXISTS`).
|
||
|
||
Damit nicht jedes bestehende Teammitglied einzeln über die Benutzerverwaltung
|
||
angelegt werden muss, legt folgendes Skript für alle Mitarbeiter mit
|
||
hinterlegter E-Mail automatisch ein Login-Konto an (Rolle `mitarbeiter`,
|
||
Passwort wird wie gewohnt beim ersten Login vergeben):
|
||
|
||
```bash
|
||
# lokal
|
||
node server/scripts/migrate-team-accounts.js
|
||
|
||
# im laufenden Container (Docker/Coolify)
|
||
docker exec <container> node scripts/migrate-team-accounts.js
|
||
```
|
||
|
||
Mitarbeiter ohne hinterlegte E-Mail werden übersprungen (Ausgabe zeigt wer) und
|
||
müssen die E-Mail zunächst im Mitarbeiter-Tab nachtragen. Mit `--role
|
||
teamleiter` (oder `admin`/`beobachter`) lässt sich eine andere Standardrolle als
|
||
`mitarbeiter` vergeben; einzelne Rollen danach jederzeit über die
|
||
Benutzerverwaltung anpassen. Empfohlene Reihenfolge beim Umstieg: zuerst
|
||
`ADMIN_EMAIL` setzen bzw. `reset-admin.js` für den ersten Admin ausführen, dann
|
||
`migrate-team-accounts.js` für den Rest des Teams.
|
||
|
||
## Admin-Zugang anlegen/zurücksetzen
|
||
|
||
Falls kein `ADMIN_EMAIL` gesetzt war oder das Passwort verloren ging:
|
||
|
||
```bash
|
||
# lokal
|
||
node server/scripts/reset-admin.js --employee-id 3
|
||
|
||
# im laufenden Container (Docker/Coolify)
|
||
docker exec <container> node scripts/reset-admin.js --employee-id 3
|
||
```
|
||
|
||
Ohne `--password` wird das Konto (neu) angelegt/verknüpft; das Passwort wird
|
||
beim nächsten Login vergeben. Mit `--password` wird sofort ein Passwort gesetzt
|
||
(Notfall-Wiederherstellung).
|
||
|
||
## Deployment in Coolify
|
||
|
||
1. **Repository verbinden**: Dieses Repo (`admin/ressourcenplanung` auf Gitea)
|
||
in Coolify als neue Ressource hinzufügen (New Resource → Application →
|
||
Gitea-Repo auswählen).
|
||
2. **Build-Pack**: **Docker Compose** wählen. Das mitgelieferte
|
||
`docker-compose.yml` baut das `Dockerfile` (Multi-Stage: Vue-Build +
|
||
Node-Server) und startet einen einzelnen Container.
|
||
3. **Routing über den Caddy-Proxy**: Der Container veröffentlicht keinen
|
||
Host-Port mehr, sondern hängt sich über das externe Netzwerk `coolify`
|
||
(von Coolify automatisch angelegt) in den von Coolify verwalteten
|
||
Caddy-Proxy ein. Die Labels in `docker-compose.yml`
|
||
(`caddy: ressourceksr.bbundco.de` / `caddy.reverse_proxy:
|
||
"{{upstreams 8080}}"`) sorgen dafür, dass Caddy die Domain automatisch
|
||
auf Container-Port `8080` routet und ein TLS-Zertifikat besorgt. Damit
|
||
das funktioniert, muss die Domain per DNS (A/AAAA-Record) auf den
|
||
Coolify-Host zeigen; einen zusätzlichen Domain-/Port-Eintrag in der
|
||
Coolify-UI braucht es für dieses Setup nicht mehr. Soll die App unter
|
||
einer anderen Domain laufen, das `caddy`-Label entsprechend anpassen.
|
||
4. **Persistenz**: Das Docker-Volume `data` sichert `server/data/data.db`
|
||
(SQLite). Bei Redeploys bleiben die Daten erhalten, solange das Volume
|
||
nicht gelöscht wird. Coolifys eingebaute Volume-Backup-Funktion kann
|
||
dafür verwendet werden.
|
||
5. **Healthcheck**: Das Image bringt einen `HEALTHCHECK` gegen `/health`
|
||
mit; Coolify nutzt ihn automatisch, um den Container-Status anzuzeigen.
|
||
6. **Umgebungsvariable**: `ADMIN_EMAIL` in Coolify unter den
|
||
Environment-Variablen der Ressource setzen (E-Mail eines bestehenden
|
||
Mitarbeiters) — damit wird beim ersten Start automatisch ein Start-Admin
|
||
angelegt, der sein Passwort beim ersten Login selbst vergibt. Ohne
|
||
`ADMIN_EMAIL` bleibt die App ohne Admin-Konto; dann `reset-admin.js` per
|
||
`docker exec` nachholen (siehe oben).
|
||
7. **Deploy** klicken. Beim allerersten Start legt der Server automatisch
|
||
`data.db` an und befüllt sie mit Beispieldaten.
|