# Laravel Jukebox API - Quick Reference ## 🔐 Authentication - **Method**: Laravel Sanctum (Bearer Token) - **Register**: `POST /register` - Creates user with 'user' role - **Login**: `POST /login` - Returns Bearer token - **Logout**: `POST /logout` - Deletes token - **Me**: `GET /me` - Current user info ## 📊 Database ``` Roles (id, name) Users (id, name, email, password, role_id) ├─ belongs_to: Role └─ belongs_to_many: Track (likes table) Labels (id, name) ├─ has_many: Artist └─ has_many: Album Genres (id, name) └─ belongs_to_many: Track (track_genre table) Artists (id, name, cover_path, release_date, label_id, duration) ├─ belongs_to: Label └─ belongs_to_many: Track (artist_track table) Albums (id, title, cover_path, release_date, duration_seconds, type, label_id) ├─ belongs_to: Label └─ has_many: Track Tracks (id, title, file_path, duration_seconds, album_id) ├─ belongs_to: Album ├─ belongs_to_many: Artist (artist_track table) ├─ belongs_to_many: Genre (track_genre table) └─ belongs_to_many: User (likes table) ``` ## 🔓 Public Endpoints ``` POST /register POST /login ``` ## 🔒 Authenticated Endpoints (All require Bearer token) ### Account Management ``` POST /logout GET /me PUT /me (User update - not implemented yet) ``` ### User Likes ``` GET /me/likes - Get liked tracks POST /tracks/{id}/like - Like a track DELETE /tracks/{id}/like - Unlike a track ``` ### Browse (Read-only) ``` GET /labels GET /labels/{id} GET /genres GET /genres/{id} GET /artists GET /artists/{id} (includes: label, tracks.album, tracks.genres) GET /albums GET /albums/{id} (includes: label, tracks.artists, tracks.genres) GET /tracks GET /tracks/{id} (includes: album.label, artists, genres) ``` ## 👑 Admin-Only Endpoints (role_id where role.name='admin') ### Create/Update/Delete ``` POST /labels POST /genres POST /artists PUT /labels/{id} PUT /genres/{id} PUT /artists/{id} DELETE /labels/{id} DELETE /genres/{id} DELETE /artists/{id} POST /albums POST /tracks PUT /albums/{id} PUT /tracks/{id} DELETE /albums/{id} DELETE /tracks/{id} POST /users GET /users PUT /users/{id} GET /users/{id} DELETE /users/{id} ``` ## 📝 Controllers | Controller | Methods | Purpose | |-----------|---------|---------| | AuthController | register, login, logout, me | User authentication | | UserController | index, show, update, destroy | User management (admin) | | ArtistController | index, show, store, update, destroy | Artist CRUD | | AlbumController | index, show, store, update, destroy | Album CRUD | | TrackController | index, show, store, update, destroy | Track CRUD with pivot syncing | | GenreController | index, show, store, update, destroy | Genre CRUD | | LabelController | index, show, store, update, destroy | Label CRUD | | LikeController | index, like, unlike | User favorites | ## 🛡️ Middleware - `auth:sanctum` - All authenticated routes - `admin` - Admin-only routes (checks role.name === 'admin') ## 🔑 Key Validation Rules ### Registration - name: required, string, max:255 - email: required, email, unique:users - password: required, string, min:8, confirmed ### Artist/Album/Track Creation - Supports partial nullable fields - Artist: name (required), cover_path, release_date, label_id, duration - Album: title (required), cover_path, release_date, duration_seconds, type, label_id - Track: title (required), file_path (required), duration_seconds, album_id, artist_ids[], genre_ids[] ## ⚠️ Notable Limitations - ❌ No pagination on list endpoints (returns all records) - ❌ No search/filtering capabilities - ❌ No rate limiting - ❌ No API resources/transformers (direct model JSON) - ❌ No CORS config file (relying on Sanctum defaults) - ❌ No endpoint documentation/OpenAPI spec - ❌ Minimal test coverage - ❌ Only UserFactory (no factories for other models) ## 🚀 Quick Start ```bash # Register curl -X POST http://localhost/api/register \ -H "Content-Type: application/json" \ -d '{"name":"User","email":"user@example.com","password":"password123","password_confirmation":"password123"}' # Response { "token": "1|abc123...", "user": { "id": 1, "name": "User", "email": "user@example.com", "role": {"id": 1, "name": "user"} } } # Use token in subsequent requests curl -X GET http://localhost/api/me \ -H "Authorization: Bearer 1|abc123..." # Like a track curl -X POST http://localhost/api/tracks/1/like \ -H "Authorization: Bearer 1|abc123..." # Get liked tracks curl -X GET http://localhost/api/me/likes \ -H "Authorization: Bearer 1|abc123..." ``` ## 📁 Directory Structure ``` /app /Http /Controllers (8 controllers) /Middleware (EnsureAdmin) /Models (7 models) /Providers /routes /api.php (main API routes) /web.php (minimal web routes) /database /migrations (11 migrations) /seeders (DatabaseSeeder - creates 1 test user) /factories (UserFactory only) /config /sanctum.php (token auth config) /auth.php (authentication guards) ``` ## 🔄 Response Formats ### Success (Single Resource) ```json { "id": 1, "name": "Artist Name", "created_at": "2026-04-21T...", "updated_at": "2026-04-21T..." } ``` ### Success (List) ```json [ { "id": 1, "name": "Item 1" }, { "id": 2, "name": "Item 2" } ] ``` ### Delete (204 No Content) ``` No body ``` ### Error (ValidationException) ```json { "message": "The given data was invalid.", "errors": { "email": ["The email has already been taken."] } } ``` ### Error (403 Forbidden - Admin Only) ```json { "message": "Forbidden." } ``` ## 🔗 Relationship Eager Loading (Controllers) - Artist show: `with(['label', 'tracks.album', 'tracks.genres'])` - Album show: `with(['label', 'tracks.artists', 'tracks.genres'])` - Track show: `with(['album.label', 'artists', 'genres'])` - Track index: `with(['album', 'artists', 'genres'])` - Likes index: `with(['album', 'artists', 'genres'])` ## 🗄️ Database Connection - Type: MySQL - Host: 172.17.0.1 (Docker) - Port: 3306 - Database: jukebox - User: jukebox_admin - Password: Super --- **Full documentation available in: `/API_DOCUMENTATION.md`**