# 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
