140 lines
4.6 KiB
Markdown
140 lines
4.6 KiB
Markdown
# Upgrade: REST API sync i.p.v. WebDAV
|
|
|
|
Vervang WebDAV-sync door een eigen REST API op `weegschaal.eddydevink.nl`,
|
|
met MariaDB-backend en Bearer token-authenticatie. Incrementele sync i.p.v. volledig bestand.
|
|
|
|
## Fase 1 — Server-side: PHP API
|
|
|
|
### Subdomein & nginx
|
|
|
|
- DNS: `weegschaal.eddydevink.nl` → zelfde server als `git.eddydevink.nl`
|
|
- nginx server block in `/etc/nginx/conf.d/weegschaal-api.conf`
|
|
- SSL via Let's Encrypt (`sudo certbot`)
|
|
- Document root: `/usr/share/nginx/html/weegschaal-api/`
|
|
|
|
### MariaDB
|
|
|
|
```sql
|
|
CREATE DATABASE weegschaal;
|
|
CREATE USER 'weegschaal'@'localhost' IDENTIFIED BY '<random>';
|
|
GRANT ALL ON weegschaal.* TO 'weegschaal'@'localhost';
|
|
|
|
CREATE TABLE users (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE auth_tokens (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
user_id INT NOT NULL REFERENCES users(id),
|
|
token VARCHAR(64) NOT NULL UNIQUE,
|
|
description VARCHAR(255),
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE measurements (
|
|
id VARCHAR(36) NOT NULL,
|
|
user_id INT NOT NULL,
|
|
weight DECIMAL(5,2) NOT NULL,
|
|
bmi DECIMAL(4,1) NOT NULL,
|
|
body_fat_percentage DECIMAL(4,1) NOT NULL,
|
|
fat_mass DECIMAL(5,2) NOT NULL,
|
|
muscle_percentage DECIMAL(4,1) NOT NULL,
|
|
muscle_mass DECIMAL(5,2) NOT NULL,
|
|
visceral_fat TINYINT NOT NULL,
|
|
bmr DECIMAL(6,1) NOT NULL,
|
|
measured_at DATE NOT NULL,
|
|
created_at DATETIME NOT NULL,
|
|
updated_at DATETIME NOT NULL,
|
|
PRIMARY KEY (user_id, id),
|
|
INDEX idx_updated_at (user_id, updated_at)
|
|
);
|
|
```
|
|
|
|
### PHP API endpoints (Slim Framework via Composer)
|
|
|
|
| Methode | Pad | Beschrijving |
|
|
|---------|-----|-------------|
|
|
| `POST` | `/api/v1/auth/register` | (later) Nieuwe gebruiker |
|
|
| `POST` | `/api/v1/auth/tokens` | (later) Nieuwe token aanmaken |
|
|
| `GET` | `/api/v1/measurements` | Alle metingen (of `?since=ISO` voor delta) |
|
|
| `POST` | `/api/v1/measurements` | Nieuwe meting aanmaken |
|
|
| `PUT` | `/api/v1/measurements/:id` | Meting bijwerken |
|
|
| `DELETE` | `/api/v1/measurements/:id` | Meting verwijderen |
|
|
|
|
Authenticatie: `Authorization: Bearer <token>`, gevalideerd tegen `auth_tokens`-tabel.
|
|
|
|
Sync-logica server:
|
|
- `GET /api/v1/measurements?since=2025-01-01T12:00:00Z` → alleen metingen met `updated_at > since`
|
|
- Bij PUT/DELETE: controleer `updated_at` client, bij conflict → HTTP 409 met server-versie
|
|
|
|
### Bestandsstructuur API
|
|
|
|
```
|
|
/usr/share/nginx/html/weegschaal-api/
|
|
├── composer.json
|
|
├── public/
|
|
│ └── index.php ← Entry point, routing
|
|
├── src/
|
|
│ ├── Database.php ← PDO singleton
|
|
│ ├── Auth.php ← Token validation middleware
|
|
│ ├── Measurements.php ← CRUD + sync queries
|
|
│ └── helpers.php
|
|
└── config.php ← DB credentials (uit .env of env vars)
|
|
```
|
|
|
|
## Fase 2 — Client-side: App aanpassen
|
|
|
|
### Types (`src/types.ts`)
|
|
|
|
- Vervang `WebDAVConfig` door `ApiConfig { url: string; token: string }`
|
|
- Verwijder `SyncStatus` (niet meer nodig — sync status volgt uit `updatedAt`)
|
|
|
|
### SettingsScreen (`src/screens/SettingsScreen.tsx`)
|
|
|
|
- Vervang URL/username/password door API-URL + token (met oogje)
|
|
- Opslaan → SecureStore
|
|
- Wissen → SecureStore verwijderen
|
|
- 'Nu synchroniseren' knop blijft
|
|
|
|
### Nieuwe module `src/sync/api.ts`
|
|
|
|
```typescript
|
|
const api = (config: ApiConfig) => ({
|
|
getMeasurements: (since?: string) => GET /api/v1/measurements?since=...
|
|
createMeasurement: (m: Measurement) => POST /api/v1/measurements
|
|
updateMeasurement: (m: Measurement) => PUT /api/v1/measurements/:id
|
|
deleteMeasurement: (id: string) => DELETE /api/v1/measurements/:id
|
|
})
|
|
```
|
|
|
|
### syncService.ts — volledig herschreven
|
|
|
|
Nieuwe sync-flow:
|
|
|
|
| Stap | Actie |
|
|
|------|-------|
|
|
| 1 | Lees lokale `lastSyncAt` (uit SecureStore) |
|
|
| 2 | `GET ?since=lastSyncAt` → alleen wijzigingen ophalen |
|
|
| 3 | Upsert remote wijzigingen lokaal (last-writer-wins) |
|
|
| 4 | Voor elke lokale meting met `updatedAt > lastSyncAt`: push naar API |
|
|
| 5 | Update `lastSyncAt` naar server-tijd |
|
|
|
|
Bij opslaan in `NewMeasurementScreen`:
|
|
1. Direct naar lokale SQLite (offline-first)
|
|
2. Direct erna: push naar API (async, niet-blokkerend via `Promise.allSettled`)
|
|
|
|
## Fase 3 — Migratie
|
|
|
|
Eerste keer na API-setup:
|
|
1. App stuurt alle lokale metingen naar de API (1-voor-1 via POST)
|
|
2. Alle metingen nu in MariaDB
|
|
3. Vanaf dan: alleen delta-sync
|
|
|
|
## Benodigde server-toegang
|
|
|
|
- SSH naar nextcloud (`aiaiaiaiagent@nextcloud`) — key werkte niet
|
|
- `sudo -A mysql` voor DB + user aanmaken
|
|
- nginx config aanpassen (`/etc/nginx/conf.d/`)
|
|
- DNS controleren voor subdomein
|