# SERENA API ## Authentication This system uses JWT-like tokens generated automatically during key actions: - **Creating a radio station** generates an **owner token**. - **Joining a radio station** generates a **client token**. All subsequent requests require this token in the `Authorization` header: ``` Authorization: Bearer ``` ### Token Generation Endpoints #### Create Radio Station → Owner Token - **POST** `/api/radio-stations` - **No authentication required** - **Body**: ```json { "name": "My Radio Station", "description": "A cool radio station" } ``` **Response:** ```json { "success": true, "message": "Radio station created successfully", "data": { "station": { /* station object */ }, "ownerToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } } ``` #### Connect to Radio Station → Client Token - **POST** `/api/clients/connect` - **No authentication required** - **Body Options**: - With Station ID + Join Code ```json { "username": "john_doe", "radioStationId": "station123", "joinCode": "ABC123" } ``` - With Join Code only ```json { "username": "john_doe", "joinCode": "ABC123" } ``` **Response:** ```json { "success": true, "message": "Successfully connected to radio station", "data": { "client": { /* client object */ }, "clientToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } } ``` --- ## API Endpoints ### Radio Station Management - **Create Station** – `POST /api/radio-stations` (No auth; returns owner token) - **Get All Stations** – `GET /api/radio-stations` (Auth: owner or client) - Optional query param: `activeOnly=true` - **Get by ID** – `GET /api/radio-stations/{stationId}` (Auth required) - **Get by Join Code** – `GET /api/radio-stations/join/{joinCode}` (Public) - **Update Station** – `PUT /api/radio-stations/{stationId}` (Owner only) - **Delete Station** – `DELETE /api/radio-stations/{stationId}` (Owner only) ### Client Management - **Connect Client** – `POST /api/clients/connect` (No auth; returns client token) - **Disconnect Client** – `DELETE /api/clients/{clientId}/disconnect` (Owner only) - **Get Client Info** – `GET /api/clients/{clientId}` (Auth required) - **Get Station Clients** – `GET /api/clients/station/{radioStationId}` (Auth required) ### Song Management > All endpoints require a valid **owner** or **client** token unless specified. - **Add Song** – `POST /api/radio-stations/{stationId}/songs` - **Get Queue** – `GET /api/radio-stations/{stationId}/songs/queue` - **Get Current Song** – `GET /api/radio-stations/{stationId}/songs/current` - **Play Next Song** – `POST /api/radio-stations/{stationId}/songs/next` (Owner only) - **Vote on Song** – `POST /api/radio-stations/{stationId}/songs/{songId}/vote` ```json { "voteType": "UPVOTE" } ``` `voteType` can be `"UPVOTE"` or `"DOWNVOTE"`. - **Remove Vote** – `DELETE /api/radio-stations/{stationId}/songs/{songId}/vote` --- ## Models ### RadioStation - `id`, `name`, `description`, `ownerId`, `joinCode`, `createdAt`, `isActive`, `connectedClients`, `songQueue`, `currentlyPlaying` ### Song - `id`, `title`, `artist`, `album`, `duration`, `url`, `addedBy`, `addedAt`, `votes`, `upvotes`, `downvotes` ### Client - `id`, `username`, `radioStationId`, `connectedAt`, `isActive` --- ## Authentication & Authorization - **Public**: Join stations via join code, connect clients. - **Authenticated User**: Add/vote on songs, view stations, connect to stations. - **Station Owner**: Manage station (update/delete), control playback, disconnect clients. --- ## Features - JWT-based authentication for most operations. - Join code–based client connection. - Owner-only management (updates, deletes, playback). - Song queue sorted by votes. - Full CORS support. --- ## Example Flow 1. User registers/logs in → gets JWT. 2. Owner creates station → gets join code + owner token. 3. Clients join via join code → get client token. 4. Authenticated users add/vote on songs. 5. Owner controls playback & manages station. --- ## Running the Application ```bash cd backend ./gradlew bootRun ``` Server runs on port `8080`. ### Quick Auth Test ```bash curl -X POST http://localhost:8080/api/auth/register -H "Content-Type: application/json" -d '{"username":"testuser","password":"password123","email":"test@example.com"}' curl -X POST http://localhost:8080/api/auth/login -H "Content-Type: application/json" -d '{"username":"testuser","password":"password123"}' curl -X GET http://localhost:8080/api/radio-stations -H "Authorization: Bearer " ``` --- ### **SERENA API Endpoint Table** | Method | Endpoint | Description | Auth Required | Notes | | ---------- | ------------------------------------- | ------------------------ | ------------- | -------------------------- | | **POST** | `/api/radio-stations` | Create a radio station | ❌ | Returns **owner token** | | **GET** | `/api/radio-stations` | Get all stations | ✅ | `activeOnly=true` optional | | **GET** | `/api/radio-stations/{stationId}` | Get station by ID | ✅ | — | | **GET** | `/api/radio-stations/join/{joinCode}` | Get station by join code | ❌ | Public lookup | | **PUT** | `/api/radio-stations/{stationId}` | Update station | ✅ (Owner) | Owner only | | **DELETE** | `/api/radio-stations/{stationId}` | Delete station | ✅ (Owner) | Owner only | #### 👥 **Client Management** | Method | Endpoint | Description | Auth Required | Notes | | ---------- | --------------------------------------- | -------------------------- | ------------- | ------------------------ | | **POST** | `/api/clients/connect` | Connect to station | ❌ | Returns **client token** | | **DELETE** | `/api/clients/{clientId}/disconnect` | Disconnect client | ✅ (Owner) | Owner only | | **GET** | `/api/clients/{clientId}` | Get client info | ✅ | — | | **GET** | `/api/clients/station/{radioStationId}` | Get all clients in station | ✅ | — | #### 🎵 **Song Management** | Method | Endpoint | Description | Auth Required | Notes | | ---------- | ----------------------------------------------------- | -------------------------- | ------------- | --------------------------- | | **POST** | `/api/radio-stations/{stationId}/songs` | Add song to queue | ✅ | Client or Owner | | **GET** | `/api/radio-stations/{stationId}/songs/queue` | Get song queue | ✅ | Sorted by votes | | **GET** | `/api/radio-stations/{stationId}/songs/current` | Get currently playing song | ✅ | — | | **POST** | `/api/radio-stations/{stationId}/songs/next` | Play next song | ✅ (Owner) | Moves top song to “current” | | **POST** | `/api/radio-stations/{stationId}/songs/{songId}/vote` | Vote on song | ✅ | `voteType`: UPVOTE/DOWNVOTE | | **DELETE** | `/api/radio-stations/{stationId}/songs/{songId}/vote` | Remove vote | ✅ | Removes user’s vote | ---