Neuer abhängigkeitsfreier Node-22-Dienst in deploy/api/ (appwrite.js, app.js,
server.js), der alle Galerie-Schreibzugriffe mit dem Appwrite-Server-Key
ausführt: POST /api/veroeffentlichen, /zurueckziehen, /melden (Rate-Limit
10/h je Melder, IPv6 auf /64, Auto-Ausblenden ab 3), /admin/sichtbarkeit und
GET /api/gesundheit.
- JWT-Prüfung über GET /account (Header X-Aircard-Jwt), Admin = Label admin
- IDs per Muster geprüft, Pfadsegmente kodiert, "." und ".." abgelehnt
- deterministische Zeilen-IDs (Galerie, Meldung): Appwrite-409 ersetzt jede
Doppelt-Prüfung; Sperre je Karte gegen verlorene Zählerstände
- Dateiprüfung: Bucket, delete("user:<ich>"), PNG/WebP, höchstens 5 MiB
- Appwrite-Aufrufe mit 10-s-Zeitlimit, Logs ohne Key, Salz, JWT und IPs
- Tests gegen einen Fake-Appwrite im Speicher (70 Tests), Compose-Service
aircard-api (Router aircard-gallery-api) und README ergänzt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
93 lines
4.3 KiB
Markdown
93 lines
4.3 KiB
Markdown
# AirCard-IOS
|
||
|
||
Inoffizielles Hobbyprojekt, mit dem man eigene Kartenmotive für Apple Wallet unter https://aircard-ios.org gestalten kann. Bilder hochladen, Vorlage und Netzwerk-Logo wählen, herunterladen – oder mit Konto speichern. Keine Verbindung zu Apple, Visa, Mastercard, UnionPay, American Express, JCB oder Discover.
|
||
|
||
## Aufbau
|
||
|
||
**`web/`** – Vite + TypeScript ohne Framework. Frontend-Module in `src/`:
|
||
- `card/` – Geometrie, Zuschnitt, Canvas-Rendering (keine DOM-Abhängigkeiten, einzeln testbar)
|
||
- `editor/` – UI (Vorlagen, Vorschau, Download, Speichern)
|
||
- `account/` – Appwrite-Client, Auth, Kartenverwaltung
|
||
- `pages/` – Routen (`/`, `/karten`, `/passwort-neu` via History-API)
|
||
|
||
**`deploy/`** – Webhook-Router (Port 8087), Build-Skript (`deploy.sh`), nginx-Config, Traefik-Route für Appwrite.
|
||
|
||
**`docs/`** – Spec, Plan, Appwrite-Konfiguration.
|
||
|
||
## Lokal entwickeln
|
||
|
||
```sh
|
||
cd web
|
||
npm ci
|
||
npm run dev # Entwicklungsserver http://localhost:5173
|
||
```
|
||
|
||
Login und Speichern brauchen die Appwrite-API. Ohne Einstellung gilt als Endpoint `${location.origin}/v1` (der Entwicklungsserver hat keinen Proxy dafür, es würde also der Vite-Server selbst gefragt). Für die lokale Entwicklung deshalb in `web/.env.local` (steht über `.env*` in `.gitignore`) den Endpoint setzen:
|
||
|
||
```sh
|
||
VITE_APPWRITE_ENDPOINT=https://appwrite.webklar.com/v1
|
||
```
|
||
|
||
Die Projekt-ID ist als Standard im Code hinterlegt (`6ac2130a00289343d6d5`, `VITE_APPWRITE_PROJECT_ID` überschreibt sie). Damit Appwrite den lokalen Host akzeptiert, muss die Web-Plattform `localhost` in der Appwrite-Console eingetragen sein (Projekt → Overview → Integrations → Platforms). Der Produktions-Build bekommt `VITE_APPWRITE_ENDPOINT=https://aircard-ios.org/v1` aus der Container-Umgebung (`deploy/compose-snippet.yml`).
|
||
|
||
## Tests
|
||
|
||
Im Frontend (`web/`):
|
||
|
||
```sh
|
||
cd web
|
||
npx vitest run # Unit-Tests (card/*, editor/*, account/*, pages/*)
|
||
npx tsc --noEmit # TypeScript-Prüfung
|
||
```
|
||
|
||
Im Repo-Wurzelverzeichnis:
|
||
|
||
```sh
|
||
node --test deploy/webhook-server.test.js # Webhook-Server (deploy.sh wird dort durch einen Stub ersetzt)
|
||
node --test deploy/deploy.test.js # deploy.sh (echtes Skript, lokaler git-Remote, npm-Stub)
|
||
node --test web/scripts/appwrite-setup.test.mjs # Appwrite-Schema-Skript
|
||
```
|
||
|
||
## Deploy
|
||
|
||
**Automatisch:** Push auf `main` → Gitea-Webhook → Container `webklar-aircard-build` führt `npm ci` und `vite build` aus → Ergebnis nach `out/` → nginx `webklar-aircard` liefert.
|
||
|
||
**Manuell:**
|
||
```sh
|
||
docker exec webklar-aircard-build sh /deploy.sh
|
||
```
|
||
|
||
Starten nur mit:
|
||
```sh
|
||
docker compose up -d aircard-build aircard aircard-api
|
||
```
|
||
|
||
`aircard-api` ist der kleine API-Dienst der Community-Galerie (`deploy/api/`, Route `aircard-ios.org/api`, siehe `deploy/api/README.md`).
|
||
|
||
Die Appwrite-API wird über `/home/webklar/apps/traefik/dynamic/aircard.yml` geroutet (Vorlage: `deploy/traefik/aircard.yml`): Requests auf `aircard-ios.org/v1` mit Header `X-Appwrite-Project: 6ac2130a00289343d6d5` gehen an den Appwrite-Container. Ohne diesen Header antwortet der nginx der Seite mit 404.
|
||
|
||
## Appwrite
|
||
|
||
Projekt „AirCard“ auf `appwrite.webklar.com`:
|
||
- Projekt-ID (öffentlich, von Appwrite generiert): `6ac2130a00289343d6d5`. Sie steht in `deploy/traefik/aircard.yml`, in `/home/webklar/apps/.env` (`AIRCARD_APPWRITE_PROJECT_ID`) und als Standard in `web/src/account/appwrite.ts`.
|
||
- Datenbank: `aircard`, Tabelle: `cards`, Bucket: `card-images` (das Skript unten legt sie an und prüft sie)
|
||
- Console-Einstellungen laut `docs/appwrite-console.md` (Soll-Stand, nicht maschinell geprüft; `--check` prüft nur das Schema): Auth mit E-Mail + Passwort, Sitzungsdauer 30 Tage, max. 5 Sitzungen pro Nutzer, Nutzerlimit 2000, Web-Plattformen `aircard-ios.org` und `localhost`. Schritte 3 und 4 dort (Auth-Härtung, Dienste abschalten) sind optional und am Live-Projekt unbestätigt.
|
||
|
||
**Schema prüfen:**
|
||
```sh
|
||
node --env-file=/home/webklar/apps/.env web/scripts/appwrite-setup.mjs --check
|
||
```
|
||
|
||
**Schema erstmalig anlegen:**
|
||
```sh
|
||
node --env-file=/home/webklar/apps/.env web/scripts/appwrite-setup.mjs
|
||
```
|
||
|
||
Umgebungsvariablen (in `/home/webklar/apps/.env`):
|
||
- `AIRCARD_APPWRITE_PROJECT_ID` – Projekt-ID (idempotent im Skript lesbar)
|
||
- `AIRCARD_APPWRITE_API_KEY` – API-Key `aircard-provision` (nur für Setup)
|
||
|
||
## Hinweis
|
||
|
||
Inoffizielles Hobbyprojekt. Alle Marken gehören ihren Inhabern.
|