Files
project-manager/README.md
T
aneurinandClaude Sonnet 5 7faef6fbff Add stage 1: authentication REST API
Slim 4 + SQLite todo-list API providing email/password registration,
login, and an authenticated GET /me endpoint. Stateless HS256 JWTs,
bcrypt password hashing, uniform JSON error envelope, and a SQL
migration runner. Includes PHPUnit feature tests and stage-1 docs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 17:35:10 +01:00

158 lines
3.9 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.
# PHP Todo List
A small todo-list application: a REST API written in PHP (Slim 4) backed by an
SQLite file, plus a single-page frontend (added in a later stage).
## Status
| Stage | Scope | State |
|-------|-------|-------|
| 1 | Auth API — register, login, `GET /me` | ✅ done |
| 2 | Todo CRUD API | planned |
| 3 | Single-page frontend | planned |
## Requirements
- PHP 8.1+ with the `pdo_sqlite` and `mbstring` extensions
- [Composer](https://getcomposer.org/)
On Fedora:
```bash
sudo dnf install php-cli php-pdo php-mbstring composer
```
## Setup
```bash
composer install
cp .env.example .env # optional; sane defaults are used without it
composer migrate # creates storage/database.sqlite and its tables
```
## Running
```bash
composer serve # http://localhost:8080 (php -S localhost:8080 -t public)
```
Any web server can serve the app as long as the document root is `public/` and
unknown paths fall through to `public/index.php`.
## Configuration
All settings are optional environment variables (read from `.env` or the real
environment). See [.env.example](.env.example).
| Variable | Default | Purpose |
|----------|---------|---------|
| `APP_DEBUG` | `false` | Include exception details in error responses |
| `DATABASE_PATH` | `storage/database.sqlite` | SQLite file location |
| `JWT_SECRET` | auto-generated into `storage/secret.key` | Token signing key |
| `JWT_TTL` | `86400` | Token lifetime in seconds |
## API
Base path: `/api`. All request and response bodies are JSON; send
`Content-Type: application/json`.
### `GET /api/health`
```json
{ "status": "ok" }
```
### `POST /api/auth/register`
Request:
```json
{ "email": "ada@example.com", "password": "correct horse battery staple" }
```
`201 Created`:
```json
{
"user": { "id": 1, "email": "ada@example.com", "created_at": "2026-09-03T12:00:00Z" },
"token": "<jwt>",
"expires_at": "2026-09-04T12:00:00+00:00"
}
```
Errors: `422` invalid input, `409` email already registered.
Validation: `email` must be a valid address (≤ 255 chars); `password` must be
872 characters.
### `POST /api/auth/login`
Request:
```json
{ "email": "ada@example.com", "password": "correct horse battery staple" }
```
`200 OK`: same shape as register. `401` on bad credentials (the message does not
say whether it was the email or the password that was wrong).
### `GET /api/me`
Requires `Authorization: Bearer <jwt>`.
`200 OK`:
```json
{ "user": { "id": 1, "email": "ada@example.com", "created_at": "2026-09-03T12:00:00Z" } }
```
`401` if the header is missing, malformed, or the token is invalid/expired.
### Error shape
Every error response looks like:
```json
{ "error": { "message": "The submitted data was invalid.", "details": { "email": ["Email must be a valid address."] } } }
```
`details` is present only when relevant (e.g. validation).
## Try it
```bash
BASE=http://localhost:8080
curl -s -X POST $BASE/api/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"ada@example.com","password":"password123"}'
TOKEN=$(curl -s -X POST $BASE/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"ada@example.com","password":"password123"}' | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
curl -s $BASE/api/me -H "Authorization: Bearer $TOKEN"
```
## Tests
```bash
composer install # installs phpunit (require-dev)
vendor/bin/phpunit
```
## Layout
```
public/index.php Front controller
src/bootstrap.php App wiring and route definitions
src/Support/Config.php Environment-driven configuration
src/Support/Database.php PDO/SQLite connection
src/Auth/JwtService.php Issue/verify JWTs
src/Auth/AuthMiddleware.php Bearer-token authentication
src/Http/JsonErrorHandler.php Uniform JSON error envelope
src/Http/Controllers/ Request handlers
src/Repository/ Database access
migrations/*.sql Schema, applied by bin/migrate.php
```