Files
Kontrollverlust/notes/api.md
T
irrlichtandClaude Opus 5.5 2714fdb1a5 Datenbank von SQLite auf Postgres umgestellt
Verbindung über KVER_DSN; Tabelle user heißt jetzt account (reserviertes
Wort in Postgres). kver import-sqlite übernimmt die alte Datei einmalig in
einer Transaktion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
2026-09-26 22:22:07 +02:00

229 lines
4.4 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.
# kver API Definition
Abgeleitet aus dem bestehenden Flask-Code. Basis für die Go-Reimplementierung.
---
## Authentifizierung
Sessions werden als Cookie (`session`) übertragen. Alle geschützten Endpunkte erwarten diesen Cookie.
---
## Auth
### `POST /auth/login`
Einloggen.
**Request (form-encoded):**
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `user` | string | Nutzername |
| `pass` | string | Passwort |
| `timeout` | int | Session-Dauer in Sekunden |
**Response:**
- `200` + setzt `session`-Cookie → Redirect auf `/`
- `200` + Fehlertext bei falschen Credentials
---
### `GET /auth/login`
Login-Seite anzeigen (wird in der Go-API nicht benötigt, Frontend übernimmt das).
---
### `POST /auth/newuser`
Neuen Account registrieren.
**Request (form-encoded):**
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `user` | string | Nutzername (3–32 Zeichen, `[a-zA-Z0-9._\s-]`) |
| `pass1` | string | Passwort (min. 10 Zeichen) |
| `pass2` | string | Passwort-Bestätigung |
**Response:**
- `200` bei Erfolg
- `200` + Fehlerliste bei Validierungsfehler
---
### `POST /auth/logout`
Session beenden und Cookie löschen. POST statt GET: SameSite=Lax schützt
GET-Navigationen nicht, ein fremder Link könnte Nutzer sonst ausloggen (CSRF).
**Response:** `200` `{"status": "ok"}`
---
### `GET /auth/headerbar`
Gibt zurück ob der Nutzer eingeloggt ist (für die UI-Headerleiste).
**Response:** HTML-Partial (in Go-API: JSON)
---
### `GET /auth/sessioninfo`
Infos zur aktuellen Session.
**Auth:** erforderlich
**Response:**
```json
{
"uid": 123456,
"created_at": 1700000000,
"expires": 1700086400,
"description": ""
}
```
---
## Entries (Beiträge)
### `GET /entry/feed/:page`
Paginierter Feed aller Beiträge, neueste zuerst.
**Parameter:**
| Name | Typ | Beschreibung |
|------|-----|--------------|
| `page` | int | Seite (0–100), 20 Einträge pro Seite |
**Response:**
```json
[
{
"pid": 123456789,
"created_at": 1700000000,
"uid": 42,
"content": "...",
"filepath": "static/media/...",
"username": "max"
}
]
```
Leeres Array `[]` wenn keine weiteren Einträge vorhanden.
---
### `POST /entry/create`
Neuen Beitrag erstellen.
**Auth:** erforderlich
**Request (multipart/form-data):**
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `content` | string | Text (max. 1000 Zeichen) |
| `file` | file (optional) | Bild (JPG oder GIF, wird auf max. 1024px skaliert) |
Mindestens `content` oder `file` muss vorhanden sein.
**Response:**
- `201` bei Erfolg
- `400` bei leerem Beitrag
- `401` wenn nicht eingeloggt
---
### `GET /entry/:pid/votes`
Abstimmungsstand eines Beitrags lesen (read-only).
**Response:**
```json
{ "pid": 123, "left": 4, "right": 2, "selected": "left" }
```
`selected` ist `none`, wenn nicht eingeloggt oder keine Stimme abgegeben.
---
### `POST /entry/:pid/vote`
Eigene Stimme abgeben oder umschalten.
**Auth:** erforderlich
**Request (form-encoded):**
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `mode` | string | `left` oder `right` |
**Voting-Logik:**
- keine bisherige Stimme → neue Stimme
- gleiche Stimme erneut → Stimme zurückziehen (Toggle)
- andere Stimme → auf neuen Modus wechseln
**Response:** wie `GET /entry/:pid/votes` (aktualisierter Stand)
- `400` bei ungültigem Modus
- `401` ohne Login
---
## User
### `GET /u/:username`
Öffentliche Profilseite eines Nutzers.
**Response:** Nutzerprofil + Beiträge (Details noch offen)
---
### `GET /user/info`
Eigene Account-Informationen.
**Auth:** erforderlich
**Response:**
```json
{
"uid": 42,
"username": "max",
"created_at": 1700000000
}
```
---
### `POST /user/delete`
Eigenen Account dauerhaft löschen. Beiträge, Votes und Sessions werden
mitgelöscht, zugehörige Mediendateien best effort entfernt.
**Auth:** erforderlich
**Request (form-encoded):**
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `pass1` | string | Passwort zur Bestätigung |
**Response:**
- `200` `{"status": "deleted"}` + löscht den `session`-Cookie
- `403` bei falschem Passwort
---
## Datenbankschema
Postgres; maßgeblich ist die Konstante `schema` in `db.go`.
---
## Offene Punkte
- Kein Rate-Limiting außer dem zufälligen `sleep` beim Login
- `session`-Token ist nur `randbelow(999999999) + timestamp` — sollte auf `crypto/rand` umgestellt werden
- Fehler-Responses sind aktuell Plaintext/HTML — in der Go-API einheitlich JSON