# 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 --- ### `GET /auth/logout` Session beenden und Cookie löschen. **Response:** Redirect auf `/` --- ### `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 (SQLite) ```sql CREATE TABLE user ( id INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER UNIQUE, username TEXT UNIQUE, password BLOB, created_at INTEGER, last_login INTEGER ); CREATE TABLE session ( id INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER, value TEXT UNIQUE, created_at INTEGER, expires INTEGER, description TEXT ); CREATE TABLE entry ( id INTEGER PRIMARY KEY AUTOINCREMENT, pid INTEGER UNIQUE, uid INTEGER, created_at INTEGER, content TEXT, filepath TEXT ); CREATE TABLE vote ( id INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER, pid INTEGER, mode TEXT -- 'left' | 'right' ); ``` --- ## 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