diff --git a/TODO.md b/TODO.md deleted file mode 100644 index b453f47..0000000 --- a/TODO.md +++ /dev/null @@ -1,431 +0,0 @@ -# To-do — Repository-Audit vom 2026-09-06 - -Abarbeitungsliste aus dem Repository-Audit. Reihenfolge ist bewusst gewählt: -schnelle Sicherheitsgewinne zuerst, das große Refactoring zuletzt. - -Abhaken mit `[x]`. Die Nummern in Klammern entsprechen den Punkten aus dem Audit. - ---- - -## Block A — Schnell erledigt, sofortiger Gewinn - -### A1. Tote Mock-Login-Route entfernen (Audit 3) -- [x] `src/app/api/auth/login/route.ts` löschen -- [x] Prüfen, dass niemand sie aufruft (`grep -rn "api/auth/login" src/`) -- [ ] Commit + Version bumpen - -**Warum:** Altcode aus der Anfangszeit. Vergleicht gegen ein hartcodiertes Fake-Passwort -(`$2b$10$examplehashedpassword`), erzeugt ein bedeutungsloses `mock-jwt-token-…` und setzt es -als Cookie. Weil die Middleware `/api/auth/*` bewusst durchlässt, ist die Route **ohne Login -von außen erreichbar** und schreibt jede probierte E-Mail per `console.log` ins Log. -Kein Login-Bypass (der Vergleich schlägt immer fehl), aber unnötige Angriffsfläche. - -### A2. `npm test` reparieren (Audit 6) -- [x] Entscheiden: Jest raus oder Jest einrichten -- [x] `package.json`: `"test"` auf das zeigen lassen, was wirklich existiert -- [x] `"test:e2e"` für Playwright ergänzen -- [x] Debug-Skripte in `tests/` aussortieren -- [x] **63 Unit-Tests** für die ausgelagerten reinen Funktionen (`tests/unit/`), laufen in - ~170 ms ohne Browser und ohne Datenbank über Nodes eingebauten Test-Runner -- [ ] E2E-Tests mit echtem Login schreiben (braucht laufende App + Datenbank) -- [ ] Testlauf in den nächtlichen Qualitätslauf aufnehmen (`scripts/quality-check.sh`) - -**Warum:** `"test": "jest"` — aber es gibt **keine Jest-Config und keinen einzigen Jest-Test**. -Die 15 Dateien in `tests/` sind Playwright-Specs, und die Namen verraten den Charakter: -`login-debug.spec.ts`, `css-debug-test.spec.ts`, `login-simple-debug.spec.ts`. Wegwerf-Skripte, -keine Regressionstests. `npm test` läuft ins Leere. - -**Aufräumen:** Die reinen Debug-Skripte löschen, die brauchbaren behalten und benennen. - -### A3. `dev`-Branch auflösen (Audit 5) -- [ ] Die vier Maßnahmen aus `f6c4a21` frisch auf `main` anwenden (siehe A1, B1, B2) -- [ ] `dev` auf `main` zurücksetzen **oder** löschen -- [ ] `CLAUDE.md`: Branch-Strategie an die gelebte Praxis anpassen - -**Warum:** Commit `f6c4a21` vom 04.07.2026 behebt bereits Rate-Limiting, Token-Hashing, -die Mock-Route und die Secret-Datei — wurde aber nie gemerged. `dev` fehlen inzwischen -**70 Commits** von `main`, ein Merge würde alte Dateistände zurückholen. Deshalb: -Commit als *Vorlage* nehmen, Änderungen neu anwenden, `dev` danach entsorgen. - -`CLAUDE.md` beschreibt einen `dev` → `main`-Workflow, der faktisch nicht gelebt wird -(alles läuft direkt auf `main`). Doku an die Realität anpassen ist ehrlicher. - ---- - -## Block B — Sicherheit - -### B1. Rate-Limiting auf den Auth-Endpunkten (Audit 4) -- [x] Sliding-Window-Limiter in `src/lib/rate-limit.ts` anlegen -- [x] Einbinden in `signup` -- [x] Einbinden in `resend-verification` -- [x] Einbinden in `reset-password` -- [x] Einbinden in `verify-email` -- [x] Limits dokumentieren (Vorschlag: 5 Versuche / 15 Minuten je IP) - -**Warum:** Im gesamten `src/` ist **kein Limiter** vorhanden. Signup, Passwort-Reset und -Verification-Mails sind unbegrenzt aufrufbar — Einladung zum Missbrauch deines SMTP-Zugangs. - -### B2. Passwort-Reset-Token nur als SHA-256-Hash speichern (Audit 4) -- [x] Beim Erzeugen: Klartext per Mail, **Hash** in die DB -- [x] Beim Einlösen: eingehenden Token hashen, dann vergleichen -- [ ] Migration für bestehende Tokens (einfachster Weg: alle invalidieren) - -**Warum:** `src/app/api/auth/reset-password/route.ts:28` legt `passwordResetToken` im -**Klartext** ab. Wer Lesezugriff auf die Datenbank hat, kann fremde Konten übernehmen. -Der Token selbst kommt aus `crypto.randomUUID()` — das ist in Ordnung, nur die Ablage nicht. - -### B3. Secrets aus dem Git entfernen und rotieren (Audit 2) -- [x] `.env.production.save` und `.env.local` gelöscht (mit `shred` überschrieben) -- [x] `.gitignore` auf `.env*` erweitert (Ausnahme `.env.example`) -- [x] `NEXTAUTH_SECRET` neu erzeugt — 44 Zeichen, geprüft -- [x] `SMTP_PASSWORD` neu gesetzt -- [x] `deployment-notes.md` und `INFRASTRUCTURE_REQUIREMENTS.md` aus dem Index entfernt -- [x] Klartext-Werte in beiden Dateien durch Platzhalter ersetzt -- [x] Passwort aus `tests/debug/db-connection-test.spec.ts` entfernt -- [x] Nach dem Wechsel neu eingeloggt -- [ ] Entscheiden: Historie umschreiben oder belassen (Empfehlung: belassen) -- [ ] Prüfen, ob eines der geleakten DB-Passwörter noch aktiv ist (siehe F1) - -**Warum:** `.env.production.save` ist eingecheckt und enthält **echte Werte** — -`DATABASE_URL` (70 Zeichen), `NEXTAUTH_SECRET` (20 Zeichen), `SMTP_PASSWORD` (20 Zeichen). -`.gitignore` listet `.env.production`, die `.save`-Endung fällt durchs Raster. -Drin seit Commit `da8d019`. - -**Entwarnung:** Das GitHub-Repo ist **privat** — nicht öffentlich abgreifbar. Die Werte -stehen aber in der kompletten Historie, in jedem Klon und auf Gitea. - -Anleitung siehe [`docs/secret-rotation.md`](docs/secret-rotation.md). - ---- - -## Block C — Build und Typsicherheit - -### C1. Build darf Fehler nicht mehr verschlucken (Audit 1) -- [x] **Schritt 1:** `eslint.ignoreDuringBuilds` in `next.config.js` auf `false` -- [x] Gemeldete ESLint-Fehler abarbeiten — es waren nur **2** (`prefer-const` in - `SettingsSidebar.tsx`), verifiziert: `next lint` endet jetzt mit Exit 0 -- [x] **Schritt 2:** `npm run type-check` — es waren **7 Fehler**, alle behoben -- [x] **Schritt 3:** `typescript.ignoreBuildErrors` auf `false` — Build prüft jetzt Typen -- [x] `tsconfig.json`: `include` von `**/*` auf `src/**/*` eingegrenzt. **Das war die - Ursache der Langsamkeit**, nicht die Dateigröße: Der Lauf dauert jetzt **19 Sekunden** - statt über 30 Minuten. Meine gegenteilige Vermutung war falsch. -- [x] **3 Dateien mit `@ts-nocheck`** entschärft — im Projekt gibt es jetzt **kein einziges - `@ts-nocheck` mehr**. `calendar-cache.ts` brauchte es gar nicht (0 Fehler), in - `microsoft-todo.ts` fehlten Typannotationen, und in `outlook-calendar.ts` steckte - ein möglicher Laufzeitfehler dahinter. -- [ ] `any`-Stellen reduzieren — ESLint zählt **470** `no-explicit-any` — fortlaufend, kein Blocker -- [ ] **209** ungenutzte Variablen (`no-unused-vars`) aufräumen — fortlaufend -- [ ] **11** unvollständige Hook-Abhängigkeiten (`react-hooks/exhaustive-deps`) prüfen — - die sind die gefährlichsten der Warnungen, weil daraus echte Bugs entstehen - -**Warum:** `next.config.js` hat `ignoreDuringBuilds: true` **und** `ignoreBuildErrors: true`. -`tsconfig.json` sagt zwar `strict: true`, das ist aber wirkungslos, weil der Build die Fehler -gar nicht meldet. **Ein Typfehler fällt nicht beim Bauen auf, sondern erst als kaputte Seite -im Browser.** Ein erfolgreicher Build ist derzeit *kein* Beweis, dass der Code korrekt ist. - -**Achtung Reihenfolge:** Erst ESLint, dann TypeScript. Beides gleichzeitig abzuschalten -blockiert jeden Deploy, bis alles behoben ist. - ---- - -## Block D — Struktur - -### D1. Dateien über 4000 Zeilen aufteilen (Audit 7) - -Betroffen sind genau zwei Dateien: - -| Datei | Zeilen | -|---|---:| -| `src/components/WeeklyView.tsx` | **9.711** *(war 11.906)* | -| `src/components/SettingsSidebar.tsx` | 5.445 | - -**Voraussetzung:** C1 muss laufen — ohne Typecheck ist ein Refactoring dieser Größe -Blindflug. Ebenso hilfreich: A2, damit es überhaupt Tests gibt. - -#### WeeklyView.tsx → Zielstruktur -- [x] Typen nach `src/lib/weekly/types.ts` (7 Typen, 97 Zeilen) — Build verifiziert -- [x] `src/components/weekly/` angelegt -- [x] **Entdeckung:** In `WeeklyView.tsx` steckten **acht eigenständige Komponenten**, die - gar nichts mit der Wochenansicht zu tun haben — zusammen rund 1.870 Zeilen. Drei davon - sind heraus: `ProjectIcon`, `ProjectsSidebar`, `NotesSidebar`. -- [x] Restliche fünf herausgelöst: `TaskInput`, `SomedayAddTask`, `TaskItem`, - `ListVisualsPopover`, `TabVisualsPopover` — dazu die Prioritäts-Abzeichen, die - `GridTaskBlock` von `WeeklyView` importierte -- [ ] Someday-Listen aus dem Haupt-JSX herauslösen (jetzt echtes Props-Design nötig) -- [ ] All-Day-Leiste herauslösen -- [ ] Zeitraster und Tagesspalten herauslösen -- [ ] Einstellungs-Flyouts herauslösen -- [ ] Drag & Drop in einen Hook (~15 Abhängigkeiten — erst sinnvoll, wenn der State - geordneter ist; ein Hook mit 15 Parametern wäre keine Verbesserung) -- [x] Datums-/Zeitraster-Helfer nach `src/lib/weekly/date-utils.ts` (13 Funktionen, 202 Zeilen) -- [x] Cookie-/Geräteeinstellungen nach `src/lib/weekly/device-settings.ts` -- [x] Formatierungs-Helfer nach `src/lib/weekly/format.ts` -- [ ] `getWeekNumber` existiert **dreimal** im Projekt (WeeklyView, `WeekPrintModal.tsx`, - `api/user/export-week-view/route.ts`) — Duplikate gegen `date-utils.ts` ersetzen, - vorher die drei Implementierungen auf Gleichheit prüfen -- [ ] `calendar-cache.ts` hat mit `getWeekStart` eine **vierte** eigene Wochenlogik — - ebenfalls gegen `date-utils.ts` ersetzen -- [ ] Daten-Laden in `useWeeklyData.ts` -- [ ] `WeeklyView.tsx` bleibt als Orchestrator übrig - -#### SettingsSidebar.tsx → Zielstruktur -- [ ] `src/components/settings/` anlegen -- [ ] Ein Panel pro Themenbereich als eigene Datei -- [ ] Gemeinsame Bausteine (Farbwähler, Schalterzeile) in `settings/controls/` - -**Vorgehen:** In kleinen Schritten, jeder Schritt ein eigener Commit, nach jedem Schritt -`npm run build`. Kein "großer Wurf" — die Datei ist zu zentral. - -**Zwischenstand nach drei Schnitten:** 11.906 → 11.556 Zeilen, also **rund 3 %**. Damit sind -die reinen Funktionen ohne Komponenten-State weitgehend heraus — das war der leichte Teil. - -Die verbleibenden ~11.500 Zeilen sind die Komponente selbst: JSX und Event-Handler, die auf -gemeinsamen State zugreifen. Jeder weitere Schnitt braucht echtes Props-Design statt -Verschieben. Realistisch pro Schnitt ein eigener Durchgang, und **erst mit Tests (A2) oder -zumindest laufendem Typecheck sinnvoll** — ein Fehler beim Herauslösen von Drag & Drop fällt -sonst wieder erst im Browser auf. - -**Warum:** `WeeklyView.tsx` ist ein Viertel des gesamten Quellcodes. Der Weekday-Bug von -Anfang September saß genau dort und war nur deshalb schwer zu finden. - ---- - -## Block E — Dauerhafte Absicherung - -### E1. Regelmäßige automatische Prüfung (Audit 8) -- [x] SonarQube-Analyse gegen https://sq.martin-bierschenk.de einrichten -- [x] Regelmäßigen Lauf aufsetzen — nightly 03:00, `todo-sonar.timer` (systemd user unit) -- [x] `npm audit` in denselben Lauf aufnehmen (`scripts/quality-check.sh`) -- [ ] `todo-sonar.timer` auf `scripts/quality-check.sh` umstellen statt nur `todo-sonar-scan` -- [ ] Playwright-Tests in den nächtlichen Lauf aufnehmen (braucht laufende App — erst nach A2) -- [ ] Quality Gate im SonarQube definieren -- [ ] Ergebnis irgendwohin melden, wo es auffällt (bisher nur Konsolenausgabe) -- [ ] **Entscheiden:** `.github/workflows/sonarqube.yml` löschen oder behalten - -**Stand:** Die Analyse läuft bereits — nächtlich um 03:00 auf dem Spark, per systemd-Timer, -Ergebnis auf https://sq.martin-bierschenk.de. Was fehlte, war `npm audit` (Sicherheitslücken -in Abhängigkeiten findet SonarQube nicht) und ein Bündel-Skript. Beides ist jetzt da. - -**Zur Entscheidung:** GitHub Actions wurde am 02.09. bewusst verworfen — das Repo ist privat, -Actions-Minuten kosten, und der SonarQube-Server läuft ohnehin selbst gehostet. Trotzdem liegt -seit dem 03.09. ein Workflow im Repo, der bei jedem Push auf `main` anspringt. Er ruft -`npm run type-check` und `npm run lint` auf — beides schlägt derzeit fehl (siehe C1), der -Workflow wäre also dauerhaft rot. Sein Projekt-Key war zudem falsch und hätte in ein zweites, -leeres SonarQube-Projekt geschrieben; das ist korrigiert. Entweder löschen (passt zur -Entscheidung vom 02.09.) oder bewusst behalten und C1 vorziehen. - -**Warum:** Bisher fallen Regressionen erst in Produktion auf. In Kombination mit C1 -(Build meldet Fehler) und A2 (Tests laufen) entsteht daraus ein echtes Netz. - -### E2. Abhängigkeiten auf Sicherheitslücken prüfen -- [ ] `npm audit` auf dem Container ausführen -- [ ] Kritische Funde beheben - -**Warum:** Konnte im Audit **nicht** geprüft werden — `node_modules` ist auf dem -CIFS-Share nicht installierbar (keine Symlinks). Zu bekannten Lücken in den -Abhängigkeiten liegt daher **keine Aussage** vor. Muss nachgeholt werden. - ---- - -## Block F — Zurückgestellt - -### F1. Datenbank-Passwort rotieren *(bewusst nach hinten geschoben)* -- [ ] Prüfen, ob eines der geleakten Passwörter noch aktiv ist -- [ ] Falls ja: rotieren nach [`docs/secret-rotation.md`](docs/secret-rotation.md), Schritt 2 -- [ ] Falls nein: nichts zu tun, Haken dran - -**Warum zurückgestellt:** Von den drei Zugangsdaten ist dieses das am wenigsten dringende. -Die Datenbank hört auf einer **privaten LAN-Adresse**, nicht am Internet. Wer das Passwort -aus dem Git holen will, braucht Zugriff auf das **private** Repository — und ist damit -ohnehin schon im Netz. `NEXTAUTH_SECRET` und `SMTP_PASSWORD` waren die kritischen, beide -sind erledigt. - -**Und es ist riskant:** Supabase läuft selbst gehostet per Docker. Dasselbe Passwort steckt -in `supabase/docker/.env` **und** in Postgres. Ein halb durchgeführter Wechsel legt die -Datenbank und damit die App lahm. Das gehört an einen ruhigen Abend, nicht nebenbei. - -**Zwei verschiedene Passwörter liegen im Git** (Fingerabdrücke, keine Klartexte): - -| Fingerabdruck | Wo | Stand | -|---|---|---| -| `59fb583eaae9` | ehem. `deployment-notes.md`, `INFRASTRUCTURE_REQUIREMENTS.md` | altes Docker-Compose-Setup (`@db:5432`); Dateien bereinigt | -| `9dbb40b14c4d` | ehem. `.env.production.save` | Supabase-Zugang, **Status offen** — Datei gelöscht, Wert steht noch in der Historie | - -Vom Nutzer bestätigt: das alte `NEXTAUTH_SECRET` (20 Zeichen) und das alte `SMTP_PASSWORD` -sind **nicht mehr in Verwendung**, beide wurden rotiert. Offen ist allein das -Datenbank-Passwort. - -Prüfen lässt sich das auf dem Container, ohne einen Wert auszugeben: - -```bash -cd /root/My-Weekly-ToDo-List -grep '^DATABASE_URL=' .env | sed -E 's|.*://[^:]+:([^@]+)@.*|\1|' | tr -d '\n' | sha256sum | cut -c1-12 -``` - -Ergibt der Befehl `9dbb40b14c4d`, ist das geleakte Passwort noch in Benutzung — dann lohnt -F1. Kommt etwas anderes heraus, wurde es längst getauscht und du kannst F1 abhaken. - ---- - -## Block H — Aus dem scharfen Typecheck - -### H1. Notion-Anbindung war defekt *(migriert, aber ungetestet)* -- [ ] Migration praktisch prüfen (braucht Notion-Zugang) -- [ ] Betroffene Nutzer informieren: Notion-Verbindung muss neu eingerichtet werden - -**Warum:** Der Code rief `notion.databases.query()` auf. Die Methode gibt es in -`@notionhq/client` v5 nicht mehr (nur noch retrieve/create/update) — der Aufruf lief zur -Laufzeit in ein "is not a function". **Die Notion-Anbindung war damit schlicht kaputt**, und -das ist niemandem aufgefallen, weil der Build Typfehler verschluckte. - -Umgestellt auf `dataSources.query()`; die Suche filtert jetzt auf `data_source` statt -`database`. Das ist in sich konsistent, aber **mangels Notion-Zugang nicht erprobt**. - -⚠️ **Gespeicherte Verbindungen enthalten alte `database_id`s. Das sind keine -`data_source_id`s** — betroffene Nutzer müssen Notion einmal neu verbinden. - ---- - -## Block K — Deploy-Sicherheit ✅ - -### K1. Build zerstört nicht mehr die laufende App ✅ *(v1.120.0)* -- [x] Build läuft nach `.next-build`, das laufende `.next` bleibt unberührt -- [x] Smoke-Test vor dem Umschalten — der neue Build muss einmal geantwortet haben -- [x] Umschalten erst danach, alter Stand bleibt als `.next-previous` liegen -- [x] Beide Fälle getestet: Fehlschlag lässt `.next` unangetastet, Erfolg schaltet sauber um -- [x] Build-Erkennung an den gebauten Commit gekoppelt (`.next/BUILD_COMMIT`) statt an - `HEAD` vs. `origin/main` — sonst überspringt das Skript den Build, wenn jemand vorher - von Hand `git pull` ausführt -- [x] Smoke-Test-Server wird zuverlässig beendet (`exec`, sonst überlebt `node` als Waise - und blockiert Port 3999 für alle weiteren Deploys) - -**Warum:** `next build` lief direkt auf `.next` — also auf dem Verzeichnis, aus dem die -laufende App bedient wird. Scheiterte der Build, war nicht nur das Update weg, sondern die -laufende Instanz gleich mit: PM2 fand `server.js` nicht mehr -(`MODULE_NOT_FOUND`) und geriet in eine Neustartschleife mit über 790 Versuchen. -Am 07.09. war die Seite dadurch rund eine Stunde unbrauchbar. - -**Zurückrollen** (falls ein Deploy doch mal Mist ausliefert): - -```bash -pm2 stop my-weekly-todo -cd /root/My-Weekly-ToDo-List -rm -rf .next && mv .next-previous .next -pm2 restart my-weekly-todo -``` - ---- - -## Block J — Build-Speicher auf dem Container - -### J1. Container-RAM erhöhen *(empfohlen)* -- [ ] LXC 202 von 3 GB auf 6 GB anheben (Proxmox → Container → Resources → Memory) - -**Warum:** `next build` braucht **rund 2,6 GB Spitzenspeicher** (gemessen). Bei 3 GB -Container-RAM bleibt fast nichts übrig — der laufende PM2-Prozess und das System teilen -sich den Rest. Der Deploy vom 07.09. starb deshalb mit -`FATAL ERROR: Ineffective mark-compacts near heap limit`. - -`scripts/update-app.sh` setzt jetzt `NODE_OPTIONS="--max-old-space-size=2048"`, weil Nodes -Standard-Heap auf diesem Container bei nur rund 1,5 GB liegt. Das ist die Sofortmaßnahme, -aber bei 2,6 GB Bedarf bleibt es knapp. **Mehr RAM ist die eigentliche Lösung** und in -Proxmox ein Klick. - -**Nicht die Ursache — geprüft:** ESLint im Build. Gemessener Spitzenspeicher mit ESLint -2.590 MB, ohne 2.595 MB. Kein Unterschied. - -### J2. Alternative: woanders bauen -- [ ] Erwägen, den Build auf dem Spark laufen zu lassen und nur `.next/standalone` zu - übertragen - -**Warum:** Dann braucht der Produktionscontainer überhaupt keinen Build-Speicher mehr — -er würde nur noch fertige Dateien erhalten und PM2 neu starten. Grösserer Umbau des -Deploy-Wegs, aber die sauberste Trennung. - ---- - -## Block I — UI-Wünsche - -### I1. Aktuellen Tag auch im Spaltenkopf hervorheben ✅ *(vom Nutzer bestätigt)* -- [x] Hervorhebungsfarbe zusätzlich hinter Wochentagsname und Datum gelegt - -**Wunsch:** Der laufende Tag soll deutlicher auffallen. Aktuell ist nur der Spaltenkörper -eingefärbt, der Kopfbereich mit "SEP 7 / MONDAY" bleibt weiß. - -**Wo:** `globals.css:666` färbt `.weekly-day-column.is-today` mit -`var(--weekly-today-highlight)`. Der Kopf ist ein eigenes `
` -([WeeklyView.tsx:7089](src/components/WeeklyView.tsx#L7089)) und übermalt die Farbe -offenbar mit eigenem Hintergrund. Der Wochentagsname hat bereits eine eigene Regel -(`globals.css:708`, `.weekly-day-name.is-today` setzt nur die Schriftfarbe). - -**Zu klären:** Der Kopf ist vermutlich `sticky` und braucht deshalb einen deckenden -Hintergrund — die Farbe muss also gesetzt, nicht nur geerbt werden. - -### I2. Symbole in Kalenderterminen nach oben rechts ✅ *(vom Nutzer bestätigt, Freiraum reicht)* -- [x] `.event-icons-row` nach oben rechts verschoben, Titel bekommt rechts Freiraum - -**Wunsch:** Die kleinen Symbole (Wiederholung, Anbieter) sitzen unten rechts im Termin und -sollen nach oben rechts. - -**Wo:** `globals.css:3183` — `.event-icons-row` hat `bottom: 2px; right: 4px;`. Für oben -rechts wird daraus `top: 2px; right: 4px;`. - -**Achtung:** Der Titel beginnt oben links; bei kurzen Terminen könnten sich Symbole und -Titel überlappen. Vermutlich braucht die Titelzeile rechts etwas Freiraum -(`padding-right`), damit nichts verdeckt wird. - ---- - -## Block G — Infrastruktur (Supabase-LXC 201) - -### G1. Container läuft privilegiert *(Sicherheitsthema)* -- [ ] Entscheiden, ob `unprivileged: 0` so bleiben soll -- [ ] Falls nicht: Container neu aufsetzen und Daten übernehmen - -**Warum:** `pct config 201` meldet `unprivileged: 0`. Wer aus diesem Container ausbricht, ist -**root auf dem NUC** — bei einem Container, der die Datenbank betreibt, die relevantere -Baustelle als ein fehlendes Root-Passwort. Meist wird das umgestellt, weil Docker im -unprivilegierten Container zickt; nachvollziehbar, aber ein bewusster Kompromiss. - -### G2. Besitzverhältnisse im Dateisystem sind schief -- [ ] Kurzfix, falls SSH-Zugang zum Container gebraucht wird: - `pct exec 201 -- chown 0:0 /etc/passwd` und `pct exec 201 -- chown 0:42 /etc/shadow` -- [ ] Langfristig: Container sauber neu aufsetzen - -**Warum:** Das Dateisystem stammt aus einem **unprivilegierten** Container (alles liegt mit -UID 100000 auf der Platte), läuft aber jetzt **privilegiert**, also ohne UID-Mapping. root -besitzt dadurch praktisch keine Datei im System. Zeitstempel belegen es: alles vom 26.02.2026 -mit UID 100000, nur `/etc/hostname` vom 06.09. mit `0:0` — das schreibt Proxmox von außen. - -Symptom war `passwd: Authentication token manipulation error`. Das System läuft trotzdem, -weil root per `CAP_DAC_OVERRIDE` die Rechteprüfung überspringt; Werkzeuge wie `passwd`, die -strenger prüfen, fallen darüber. Weitere solche Merkwürdigkeiten sind zu erwarten. - -⚠️ **Kein `chown -R` über das ganze Dateisystem** — nicht am laufenden Container und schon -gar nicht mit Docker darin. Postgres und die Supabase-Container haben eigene UIDs (999, 70, …), -die dabei zerschossen würden. - -**Kein Blocker:** `pct enter 201` gibt jederzeit eine Root-Shell ohne Passwort. Ein -Root-Passwort wird nur für direkten SSH-Zugang gebraucht. - -### G3. Supabase Studio ist nicht erreichbar -- [ ] Auf 201 prüfen: `docker compose ps` — laufen die Container? -- [ ] Port klären: Studio hängt hinter Kong auf **8000**, nicht 8001 -- [ ] `scripts/supabase-setup.sh` korrigieren: falsche Port-Ausgabe und Shebang `#!/bash` - -**Warum:** `http://:8001` antwortet nicht. Die Zahl stammt aus einer `echo`-Zeile in -`scripts/supabase-setup.sh`, die nirgends eine Portfreigabe setzt — beim offiziellen -`supabase/docker`-Stack ist Studio nur über Kong auf 8000 erreichbar. Zusätzlich hat das -Skript `#!/bash` statt `#!/bin/bash` und ist so gar nicht direkt ausführbar. - ---- - -## Kleinkram (ohne Eile) - -- [ ] 114 `console.log` aus dem Produktionscode entfernen (die 275 `console.error` sind in Ordnung) -- [ ] `NEXTAUTH_SECRET` auf 32 Byte verlängern (erledigt sich mit B3) -- [ ] API-Routen: JSON-401 statt HTML-Redirect für nicht angemeldete Aufrufe -- [ ] `deploy.sh` und `docker-compose.yml` löschen oder als veraltet markieren — sie - beschreiben ein Portainer-Setup, das nicht mehr verwendet wird -- [ ] Eigener Auth-Check in `apple/sync` und `weather/geocode` (aktuell nur durch die - Middleware geschützt — zusätzliche Absicherung schadet nicht) diff --git a/package.json b/package.json index 0097a5e..de7249d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.121.0", + "version": "1.121.1", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "main": "index.js", "scripts": { diff --git a/src/app/api/calendar/apple/sync/route.ts b/src/app/api/calendar/apple/sync/route.ts index d434d68..da39833 100644 --- a/src/app/api/calendar/apple/sync/route.ts +++ b/src/app/api/calendar/apple/sync/route.ts @@ -1,8 +1,18 @@ import { NextResponse } from 'next/server'; +import { getServerSession } from 'next-auth'; import { getUpcomingEvents } from '@/lib/apple-calendar'; +import { authOptions } from "@/lib/auth"; export async function POST(req: Request) { try { + // Ohne Anmeldung war diese Route ein offener Relay: beliebige Apple-Zugangsdaten + // liessen sich hier gegen Apple durchprobieren. Gleiche Pruefung wie in + // /api/calendar/apple/connect. + const session = await getServerSession(authOptions); + if (!session?.user?.email) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + } + const body = await req.json(); const { email, password, calendarId, timeMin, timeMax } = body; diff --git a/src/components/AuthForm.tsx b/src/components/AuthForm.tsx index c091bc8..6fa965d 100644 --- a/src/components/AuthForm.tsx +++ b/src/components/AuthForm.tsx @@ -14,13 +14,9 @@ const AuthForm: React.FC = ({ type, onSubmit, isLoading, error }) const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - console.log('📝 AuthForm handleSubmit called with:', { email, password }); - console.log('📝 onSubmit function is:', typeof onSubmit); + // Kein Logging der Formulardaten: hier stand das Passwort im Klartext in der Browser-Konsole. if (typeof onSubmit === 'function') { - console.log('🚀 Calling onSubmit function...'); onSubmit({ email, password }); - } else { - console.error('❌ onSubmit is not a function!', onSubmit); } };