# Test REST API (CakePHP 5) Testowy serwis REST API: klienci (`customers`), ich auta (`cars`) i użytkownicy (`users`), uwierzytelnianie tokenem JWT, dokumentacja Swagger UI. ## Uruchomienie ```bash composer install bin/cake migrations migrate # tworzy tabele users, customers, cars bin/cake seeds run DatabaseSeed # 2 konta, 100 klientów, 1-5 aut na klienta (czyści tabele!) bin/cake server -p 8765 ``` Dokumentacja i konsola testowa: **http://localhost:8765/docs** (specyfikacja: `webroot/openapi.yaml`). Konfiguracja bazy i sekretu JWT: `config/app_local.php` (`Datasources.default`, `Jwt.secret`, `Jwt.ttl`). Sekret można też podać zmienną środowiskową `JWT_SECRET`. ## Konta testowe | Rola | E-mail | Hasło | |-------|-------------------|-----------| | admin | admin@example.com | Admin123! | | user | user@example.com | User1234! | * **admin** – wszystko, w tym CRUD użytkowników. * **user** – logowanie, własny profil, CRUD klientów i aut. ## Endpointy | Metoda | Ścieżka | Opis | |----------------------|--------------------------------------|---------------------------------------| | POST | `/api/auth/login` | logowanie, zwraca token JWT | | GET / PUT / PATCH | `/api/auth/me` | własny profil | | GET / POST | `/api/customers` | lista (filtry, paginacja) / dodanie | | GET / PUT / PATCH / DELETE | `/api/customers/{id}` | klient (GET zwraca też auta) | | GET / POST | `/api/customers/{id}/cars` | auta klienta / dodanie auta klientowi | | GET / POST | `/api/cars` | lista aut / dodanie | | GET / PUT / PATCH / DELETE | `/api/cars/{id}` | auto (GET zwraca też właściciela) | | GET / POST | `/api/users` | użytkownicy (tylko admin) | | GET / PUT / PATCH / DELETE | `/api/users/{id}` | użytkownik (tylko admin) | Przykład: ```bash TOKEN=$(curl -s -X POST http://localhost:8765/api/auth/login \ -H 'Content-Type: application/json' \ -d '{"email":"user@example.com","password":"User1234!"}' | jq -r .data.token) curl -s "http://localhost:8765/api/customers?q=nowak&with_cars=1" -H "Authorization: Bearer $TOKEN" ``` ## Pola **Klient** – wymagane: `first_name`, `last_name`, `email` (unikalny), `phone`; opcjonalne: `type` (`individual`/`company`, dla `company` wymagane `company_name`), `company_name`, `tax_id` (NIP, 10 cyfr), `street`, `city`, `postal_code` (`00-000`), `country` (ISO, domyślnie `PL`), `birth_date` (`YYYY-MM-DD`), `notes`. **Auto** – wymagane: `customer_id`, `make`, `model`, `production_year`, `vin` (17 znaków, unikalny), `registration_number` (unikalny), `fuel_type` (`petrol`/`diesel`/`lpg`/`hybrid`/`electric`); opcjonalne: `color`, `engine_capacity` (cm³), `power_hp`, `transmission` (`manual`/`automatic`), `mileage` (km), `notes`. **Użytkownik** – wymagane: `email` (unikalny), `password` (min. 8 znaków), `first_name`, `last_name`; opcjonalne: `role` (`admin`/`user`, domyślnie `user`), `active` (nieaktywny nie może się zalogować). ## Format odpowiedzi * sukces: `{"success": true, "data": ..., "meta": {...paginacja}}` * błąd: `{"success": false, "error": {"code": 422, "message": "Validation failed.", "fields": {...}}}` * kody: `200`, `201` (+ nagłówek `Location`), `204` (DELETE), `400`, `401`, `403`, `404`, `405`, `422`