Files
Mieterportal/kimi.md
T
ah-admin fbe033ebd6 v1.1: Rebrand Hinterstein Immobilien + echtes Auth-System
- Rebrand: Kunden-Logo, Joseph-Hinterstein-Portrait, Kontakt-Banner, Texte
- Login-Pflicht auf /login (Route-Guard), Gruppen Verwaltung/Mieter
- Mieter-Registrierung per einmaligem Registrierungscode
- Benutzerverwaltung als 6. Modul (/benutzer, nur Verwaltung)
- Demo-Zugänge mit Passwort 0815 (j.hinterstein, a.berger, m.wolf)
- Mail-Server-API: Token-Auth (/send, X-Api-Token), Mail-Stack live auf Server
- Store-Key hinterstein-mieterportal-v2, Doku (kimi.md, README) nachgeführt
2026-10-02 12:11:43 +02:00

190 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Kimi-Kontext: Hinterstein Immobilien · Mieterportal (mieterportal.hocks.eu)
> Projekt-Kontextdatei für Kimi Work. Stand: 02.10.2026, 14:30 Uhr.
> Bitte bei größeren Änderungen am Projekt aktualisieren.
> Konventionen und Workflow sind am Projekt Schulportal (sfg.hocks.eu) orientiert.
## 1. Projektüberblick
Mieterportal der **Hinterstein Immobilien** (Demo, Inhaber Joseph Hinterstein) für
**50 Wohnungen in 3 Häusern** (Hauptstraße 12 · Ringweg 3 · Am Park 5). Analog zum
Schulportal: alle Mietangelegenheiten digital an einem Ort.
**Authentifizierung (echtes Login seit v1.1):** Startseite `/login` mit
Login-Pflicht (Route-Guard `RequireAuth` in `App.tsx` leitet unangemeldete Besucher
auf `/login` um). **Gruppen:** `verwaltung` und `mieter`. Mieter können sich über
einen **Registrierungscode** selbst registrieren (`/registrieren`); Codes legt die
Verwaltung in der Benutzerverwaltung an (einmalig nutzbar, Wohnungsbezug).
Passwörter als **SHA-256-Hash** in localStorage, Session 8 h
(Key `mp_benutzer_session`). Demo-Zugänge (Passwort `0815`):
`j.hinterstein` (Verwaltung, Joseph Hinterstein), `a.berger` (Mieterin,
Hauptstraße 12 Whg. 7), `m.wolf` (Mieter). Demo-Registrierungscode: `MP-2026-0815`.
**Die 6 Module:**
1. **Dashboard** (`/`) – Mieter: Begrüßung, nächste Zahlung, Mietdiagramm, Ankündigungen,
offene Meldungen. Verwaltung: Kennzahlen (Vermietungsquote, Miet-Soll, Rückstände),
Einnahmenverlauf + Belegung pro Haus (Recharts).
2. **Mietkonto & Zahlungen** (`/mietkonto`) – Buchungsverlauf 2026 mit Statusfilter,
Nebenkostenguthaben, Zahlungsdaten. Verwaltung: Zahlungsstatus aller Wohnungen,
Rückstandsliste, Haus-Filter.
3. **Schadensmeldungen** (`/schadensmeldungen`) – Tickets mit Kategorie, Dringlichkeit,
Status; Neuanlage per Dialog; Verwaltung pflegt Status per Select.
4. **Dokumente** (`/dokumente`) – Verträge/Abrechnungen/Hausordnung/Protokolle,
Suche + Kategorie-Chips. Mieter sieht eigene + Hausdokumente (unitId=null).
5. **Nachrichten** (`/nachrichten`) – Chat Mieter ↔ Verwaltung, Ungelesen-Markierung,
neue Unterhaltungen.
6. **Benutzerverwaltung** (`/benutzer`, nur Gruppe `verwaltung`) – Nutzerliste mit
Gruppen und Wohnungsbezug, Registrierungscodes erzeugen/deaktivieren,
Demo-Zugänge zurücksetzen.
## 2. Technischer Stack
| Teil | Technologie |
|---|---|
| Frontend | React 18 + TypeScript, Vite 7, Tailwind v3.4 + shadcn/ui (Radix), React Router 7 (BrowserRouter), Recharts |
| State | React Context + useReducer, Persistenz in localStorage (`hinterstein-mieterportal-v2`) |
| Daten | `src/data/seed.ts` (handschriftlich) + `src/data/generated.json` (maschinell via `beispieldaten.py`) |
| Auth | `src/lib/auth.ts` (SHA-256, Session 8 h, Keys `mp_benutzer`/`mp_benutzer_session`), Route-Guard in `App.tsx` |
| Branding | Kunde: `src/assets/hinterstein/` (logo.png, joseph-hinterstein.jpg, kontakt.jpg); KI-generiert: `src/assets/logo.png`, `hero.jpg`, `modules.jpg` |
| Webserver (Ziel) | Docker-Container `mp-portal` (nginx), statisches `dist/`, gemountet `/opt/mieterportal/dist` |
| Mail | `mail-server/`: Postfix-Relay (`mp-mail`) + Python-API (`mp-mail-api`) – **live auf dem Server** unter `/opt/mp-mail` |
| Server | Root-VPS hocks.eu (IONOS), Docker + Portainer, Subdomain via NPM (Nginx Proxy Manager, Let's Encrypt) |
## 3. Wichtige Dateien
Projektverzeichnis: `C:\Users\ah\Documents\Kimi\Workspaces\Mieterportal`
**Git:** `https://git.hocks.eu/ah-admin/Mieterportal` (Branch `main`). Secrets
ausgesperrt via `.gitignore` (`mail-server/mail.env` etc.).
| Datei | Inhalt |
|---|---|
| `src/store/store.tsx` | Store-Provider, Reducer, Actions (setRole/addTicket/setTicketStatus/addMessage/newThread/markThreadRead), `fmtEUR` |
| `src/data/seed.ts` | Tickets, Dokumente, Nachrichten-Threads, Ankündigungen + Re-Export units/transactions aus generated.json |
| `src/data/generated.json` | 50 Wohnungen + 552 Buchungen, erzeugt von `beispieldaten.py` (Seed 20261002) |
| `beispieldaten.py` | Deterministischer Generator: `python beispieldaten.py [seed]` |
| `src/types/index.ts` | Alle Typen (Unit, Transaction, Ticket, DocumentItem, Thread, Announcement) |
| `src/components/AppLayout.tsx` | Sidebar (Desktop) + Mobile Top-Bar/Nav, Rollenwechsel, Ungelesen-Badge, ThemeToggle |
| `src/components/ThemeToggle.tsx` | Dark-Mode-Umschalter (Sonne/Mond) |
| `src/lib/theme.ts` | `mp-theme` in localStorage, Init vor erstem Render (main.tsx) |
| `src/pages/Login.tsx` | Login-Pflicht: Hero mit Joseph-Hinterstein-Portrait, Logo, Feature-Liste, Login-Formular + Registrierung-Link + Demo-Einstiege |
| `src/pages/Benutzer.tsx` | Benutzerverwaltung (nur Verwaltung): Nutzer, Gruppen, Registrierungscodes |
| `Dockerfile` | Optionaler All-in-One-Build (node build → nginx) für `docker build`-Workflow |
| `docker/nginx.conf` | nginx-Site: SPA-Fallback, Gzip, Cache-Header für /assets/, Security-Header |
| `docker-compose.yml` | `mp-portal` (nginx + gemountetes dist) im externen Netz `npm_default`; Mail-Stack separat |
| `deploy.sh` | Bewährter Deploy-Workflow (s. Kap. 4) |
| `mail-server/` | Postfix-Relay + schlanke Mail-API (Muster Schulportal, angepasst) |
## 4. Deploy-Workflow (bewährt, aus Schulportal übernommen)
```bash
# 1. Bauen (im Projektverzeichnis)
npm run build
# 2. Paketieren + Hochladen (pscp braucht cwd = Projektverzeichnis)
tar -czf mp-dist.tar.gz -C dist .
"/c/Program Files/PuTTY/pscp.exe" -batch \
-hostkey "SHA256:4G3UxsugNkHH6BrPXScLXh+vX8P1sLgWKn8cZBKSRxw" \
-i "Z:\Devel\ssh\priv_ionos_hocks_vps.ppk" -P 38592 \
mp-dist.tar.gz root@hocks.eu:/tmp/
# 3. Entpacken + Container neu starten + Hash prüfen
"/c/Program Files/PuTTY/plink.exe" -batch -hostkey "SHA256:4G3UxsugNkHH6BrPXScLXh+vX8P1sLgWKn8cZBKSRxw" \
-i "Z:\Devel\ssh\priv_ionos_hocks_vps.ppk" -P 38592 root@hocks.eu \
"rm -rf /opt/mieterportal/dist && mkdir -p /opt/mieterportal/dist && \
tar -xzf /tmp/mp-dist.tar.gz -C /opt/mieterportal/dist && \
cd /opt/mieterportal && docker compose up -d && sleep 2 && \
curl -s https://mieterportal.hocks.eu/ | grep -o 'index-[^\"]*\.js'"
# Alternativ alles in einem Schritt:
./deploy.sh
```
- SSH: Port **38592**, Key `Z:\Devel\ssh\priv_ionos_hocks_vps.ppk` (Pageant), Hostkey-Flag zwingend.
- **Vorsicht Fail2Ban:** zu viele gescheiterte SSH-Versuche von einer IP führen zu einem
Ban (Timeout-Verbindungsbild). Ban aufheben auf dem Server: `fail2ban-client unban --all`.
- **Live (seit 02.10.2026):** Container `mp-portal` läuft auf hocks.eu, statisches `dist/`
unter `/opt/mieterportal/dist` (gemountet). NPM-Proxy-Host **id 7** (Datei
`/data/compose/1/data/nginx/proxy_host/7.conf`, DB-Tabelle proxy_host), Zertifikat
**npm-9** (Let's Encrypt, läuft bis 31.12.2026; via certbot/webroot erstellt, liegt im
npm-Container unter `/etc/letsencrypt/live/npm-9/`). HTTP→HTTPS-Redirect aktiv
(HSTS, Block-Exploits, HTTP/2). Änderungen am Proxy-Host im NPM-UI werden die
DB-Konfiguration konsistent halten; manuelle Conf-Edits werden beim nächsten
UI-Speichern überschrieben.
- HTML wird mit `no-cache` geliefert (nginx-Config), Assets hash-benannt → Reload genügt.
Der eingebettete Kimi-Browser cached hart → beim Testen Cache-Buster anhängen: `?v=X`.
## 5. Zugänge & Konfiguration
- **Demo-Zugänge (Passwort `0815`):** `j.hinterstein` (Verwaltung), `a.berger`
(Mieterin, Hauptstraße 12 Whg. 7), `m.wolf` (Mieter). Demo-Registrierungscode:
`MP-2026-0815`. Passwörter werden als SHA-256-Hash gespeichert; Store-Reset über
Browser-DevTools (localStorage-Keys `mp_benutzer`, `mp_benutzer_session`,
`hinterstein-mieterportal-v2` löschen).
- **Mail-API-Token:** bewusst nicht hier dokumentiert – liegt auf dem Server in
`/opt/mp-mail/mail.env` (Vorlage `mail.env.example` im Repo).
- **Mail-Stack live (seit 02.10.2026):** Container `mp-mail` + `mp-mail-api` laufen
auf hocks.eu unter `/opt/mp-mail` (Relay über `hocks-eu.mail.protection.outlook.com`).
Testmail und API-`/send` (mit `X-Api-Token`) verifiziert (status=sent); ohne Token 401.
Noch nicht mit dem Portal-Frontend verkabelt (keine automatischen Benachrichtigungen).
## 6. Konventionen & Besonderheiten
- **Dark Mode:** class-Strategie, Präferenz `mp-theme`, Init vor erstem Render.
Feste Farbklassen werden in `index.css` für `.dark` umrechnen
(`.dark .bg-white`/`.bg-slate-50`/`.bg-teal-50`); Sidebar ist eigenes Dunkel-Teal.
- **Barrierefreiheit:** aria-pressed/labels am ThemeToggle und Rollenwechsel, Fokus-Ringe.
- **Formatierung:** Beträge via `fmtEUR` (Intl de-DE), Datumsformate TT.MM.JJJJ.
- **Datenpflege:** Bestandsdaten ändern → `beispieldaten.py` anpassen und neu ausführen,
nicht generated.json von Hand editieren.
- **Sicherheit:** kein offenes Relay (Postfix mynetworks loopback + Docker-Netz,
sender_canonical zentral). Upload/Download-Funktionen sind Demo-Darstellungen.
- **Keine destruktiven Aktionen auf dem Server ohne ausdrückliche Bestätigung.**
## 7. Testing
- `npm run build` (`tsc -b`) ist die echte Typprüfung; `npx tsc --noEmit` prüft wegen
Solution-tsconfig ggf. nichts.
- Headless-Screenshots (Dark Mode = Systempräferenz):
`"/c/Program Files/Google/Chrome/Application/chrome.exe" --headless --disable-gpu --screenshot=... --window-size=WxH "URL"`
- Screenshots ausgeliefert nach `preview/`.
## 8. Verlauf / offene Punkte
**Erledigt 02.10. (v1.0):** Portal komplett neu aufgesetzt (5 Module, Mieter-/Verwaltungsansicht,
KI-Branding: Logo/Hero/Illustration), Docker-Setup (Dockerfile, nginx, compose),
Repo in git.hocks.eu angelegt, Deploy-Workflow + Dark Mode + beispieldaten.py aus dem
Schulportal übernommen, mail-server-Struktur angelegt (noch nicht live verkabelt).
**Erledigt 02.10. (v1.0 live):** Deployment auf hocks.eu durchgeführt: Container `mp-portal`
läuft (`/opt/mieterportal`, compose + gemountetes dist), NPM-Proxy-Host id 7 + LE-Zertifikat
npm-9 eingerichtet (per certbot/webroot, DB-Insert, 7.conf aus 5.conf abgeleitet, nginx reload).
Live geprüft: `https://mieterportal.hocks.eu/` → HTTP 200, Titel korrekt, SPA-Routing
(`/mietkonto`) 200, HTTP→HTTPS-Redirect 301, Zertifikat CN=mieterportal.hocks.eu gültig
bis 31.12.2026. Zertifikatsdateien liegen im npm-Container unter `/etc/letsencrypt/live/npm-9/`
(Backup der Zertifikate auf dem Host: `/root/le-mp/`). Fail2Ban-Ban nach frühen
Fehlversuchen ist nach ~40 min automatisch ausgelaufen.
**Erledigt 02.10. (v1.1 live):** Rebrand auf „Hinterstein Immobilien" (Kunden-Logo,
Joseph-Hinterstein-Portrait auf der Login-Seite, Kontakt-Banner), echtes
Authentifizierungssystem (Login-Pflicht, Gruppen Verwaltung/Mieter, SHA-256,
Session 8 h), Mieter-Registrierung per einmaligem Code, Benutzerverwaltung als
6. Modul (`/benutzer`), Demo-Zugänge mit Passwort `0815`. Mail-Stack auf dem Server
aktiviert (`/opt/mp-mail`, Testmail + API-/send verifiziert). Store-Key auf
`hinterstein-mieterportal-v2` gehoben. Live deployed und geprüft (HTTP 200, Titel
„Hinterstein Immobilien · Mieterportal").
**Offen:**
- Zertifikatserneuerung prüfen (per 01.12.2026): NPM-Renewer sollte cert 9 über HTTP-Challenge
erneuern; sonst certbot/webroot + Kopie nach npm-9 wiederholen.
- Portal-Frontend an Mail-API verkabeln: automatische E-Mail an die Verwaltung bei neuen
Schadensmeldungen und an Mieter bei Antworten.
- Mögliche nächste Schritte: serverseitige Datenbank (PostgreSQL/Node-API) statt localStorage,
Mehrseitigkeit für 50 echte Mietverhältnisse.
## 9. Sonstiges
- User kommuniziert auf Deutsch; alle UI-Texte und Antworten auf Deutsch.
- Dateien außerhalb des Workspaces immer erst in den Workspace kopieren.
- Vorsicht mit destruktiven Aktionen (Explizite Bestätigung einholen).