Files
Final-Year-Project/Backend/README.md

189 lines
7.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.
# backend
## Overview
Backend for the video upload prototype providing:
- Better Auth email/password authentication
- Presigned MinIO uploads/downloads
- An authenticated video administration surface at `/admin`
## Requirements
- [Bun](https://bun.sh) (tooling used for running scripts & dependency management)
- Postgres reachable via `DATABASE_URL`
- MinIO-compatible storage reachable via `MINIO_*` env vars
- `.env` file populated with secrets and credentials
## Install
```bash
bun install
```
## Configuration
Copy the example environment file and adjust the values:
```bash
cp .env.example .env
```
Required env vars:
| Name | Purpose |
| --- | --- |
| `DATABASE_URL` | Postgres connection string |
| `BETTER_AUTH_SECRET` | Secret used to sign sessions |
| `BETTER_AUTH_BASE_URL` | Public base URL for the backend (e.g., `http://localhost:3000`) |
| `BETTER_AUTH_TRUSTED_ORIGINS` | Comma-separated list of allowed frontend origins |
| `PORT` | HTTP port (default `3000`) |
| `MEDIA_MODE` | Media runtime mode (`legacy` default, `single_server_sfu` scaffold mode) |
| `MEDIA_PROVIDER` | Media backend provider (`mock` by default) |
| `TURN_URLS` / `TURN_USERNAME` / `TURN_CREDENTIAL` | TURN/STUN configuration used by single-server SFU mode |
| `MEDIA_RECORDINGS_DIR` | Local output directory for server-side recording workers (planned in SFU mode) |
| `MEDIA_MAX_PUBLISHERS` / `MEDIA_MAX_SUBSCRIBERS_PER_ROOM` | Soft concurrency limits for single-server media mode (planned) |
| `MINIO_*` | Connection settings for the MinIO/S3 endpoint |
| `ADMIN_USERNAME` / `ADMIN_PASSWORD` | Basic auth for `/admin` dashboard |
`BETTER_AUTH_URL` is still accepted as a legacy fallback, but `BETTER_AUTH_BASE_URL` is preferred.
## Running
- Start the server in development:
```bash
bun run dev
```
- Server boots after ensuring the configured MinIO bucket exists.
## Database (Drizzle ORM)
- Generate a migration:
```bash
bun run db:generate
```
- Apply migrations:
```bash
bun run db:migrate
```
- Backfill Better Auth credential accounts for existing users:
```bash
bun run auth:migrate
```
- Open Drizzle Studio:
```bash
bun run db:studio
```
## API
All `/videos` and `/admin` routes require a valid Better Auth session except for the admin dashboard access, which uses HTTP Basic auth with `ADMIN_USERNAME`/`ADMIN_PASSWORD`.
### Authentication
Authentication is handled by Better Auth under `/api/auth/*` (for example `/api/auth/sign-in` and `/api/auth/sign-up`).
### Authorization
All authenticated endpoints expect a Better Auth session cookie sent by the client.
### Video Management
| Endpoint | Purpose |
| --- | --- |
| `POST /videos/upload-url` | Request a presigned PUT URL for a new video |
| `GET /videos/download-url` | Generate a signed GET URL to download a video |
| `GET /videos` | List objects in the configured bucket |
| `DELETE /videos` | Delete an object by `objectKey` |
`POST /videos/upload-url` request body requires `fileName` and `deviceId` (UUID belonging to the authenticated user), with optional `prefix`.
### Device Management (Phase 1)
| Endpoint | Purpose |
| --- | --- |
| `POST /devices/register` | Register a user-owned device as `camera` or `client` and issue bearer device token |
| `GET /devices` | List all devices for the authenticated user |
| `PATCH /devices/:deviceId` | Update device role/metadata/status |
| `POST /devices/:deviceId/heartbeat` | Device-token authenticated presence heartbeat |
### Camera-Client Linking (Phase 1)
| Endpoint | Purpose |
| --- | --- |
| `POST /device-links` | Link one client device to one camera device |
| `GET /device-links` | List links for the authenticated user |
| `DELETE /device-links/:linkId` | Remove a camera-client link |
### Realtime Commands (Phase 2)
| Endpoint | Purpose |
| --- | --- |
| `POST /commands` | Queue and dispatch command from a linked client device to camera |
| `GET /commands` | Inspect command status/history |
| `POST /commands/:commandId/ack` | Device-token ack/reject command fallback |
Socket.IO channel:
- Devices connect with bearer device token (`auth.token` or `Authorization: Bearer ...`).
- Camera receives `command:received`.
- Camera sends `command:ack` with `acknowledged` or `rejected`.
- Source client receives `command:status`.
### Motion Events (Phase 3)
| Endpoint | Purpose |
| --- | --- |
| `POST /events/motion/start` | Camera device creates motion event and fan-outs notification to linked clients |
| `POST /events/:eventId/motion/end` | Camera device closes a motion event and broadcasts end state |
| `GET /events` | Authenticated user fetches event history |
Motion realtime events:
- Linked clients receive `motion:detected` as soon as camera starts event.
- Linked clients receive `motion:ended` when camera ends event.
### On-Demand Streams + Media Credentials (Phase 4 + 5)
| Endpoint | Purpose |
| --- | --- |
| `POST /streams/request` | Client device requests a linked camera to start a live stream |
| `POST /streams/:streamSessionId/accept` | Camera device accepts and transitions stream session to `streaming` |
| `GET /streams/:streamSessionId/publish-credentials` | Camera fetches media ingest credentials for the active stream session |
| `GET /streams/:streamSessionId/subscribe-credentials` | Viewer fetches media subscribe credentials for the active stream session |
| `POST /streams/:streamSessionId/end` | Requester/camera ends an existing stream session |
| `GET /streams/:streamSessionId/playback-token` | Obtain short-lived playback token for active stream |
| `GET /streams/me/list` | List stream sessions for the current device |
Stream realtime events:
- Client receives `stream:requested` after request creation.
- Client receives `stream:started` when camera accepts.
- Both devices receive `stream:ended` when session is closed.
#### Streaming Scale Tradeoffs (Current Prototype)
- The current implementation is **not production-grade at scale**.
- Video quality and reliability currently depend on direct browser-to-browser WebRTC success, with a low-fps frame relay fallback in the simulator.
- This backend currently acts as a control plane (commands, session state, credentials, events), not a full media plane/SFU.
- Running live transport + fan-out + recording on the same web server is possible for small loads but introduces significant CPU, RAM, and network egress pressure under concurrency.
- For larger deployments, use a dedicated media plane (managed or self-hosted SFU + recorder) and keep this service focused on auth/session/control APIs.
- For a pragmatic prototype path that keeps media on the current server, see `docs/streaming-on-web-server-plan.md`.
- `MEDIA_MODE=single_server_sfu` currently enables scaffolding only (interfaces/config/health visibility), not full SFU media routing yet.
### API Docs
OpenAPI docs are generated from Zod/OpenAPI definitions:
| Endpoint | Purpose |
| --- | --- |
| `GET /openapi.json` | OpenAPI 3 spec (JSON) |
| `GET /docs` | Swagger UI |
### Web Mobile Simulator
Use `GET /sim/mobile-sim.html` to run a browser simulator that behaves like the mobile app:
- Register as `camera` or `client`
- Connect Socket.IO with bearer device token
- Camera: process incoming `start_stream` commands, fetch publish credentials, start/end motion events
- Client: create links, request streams, fetch subscribe credentials, and fetch playback tokens
### Admin Dashboard
Access `/admin` with Basic auth to:
- Request presigned upload URLs
- Upload files directly via the generated URL
- List and delete objects within the MinIO bucket
The dashboard UI submits to `/admin/upload-url`, `/admin/objects`, and `/admin/object`.
## Schema
- `users` email/username/password and timestamps
- `events` user-created events with a unique `videoUrl`
- `videos` upload metadata including `objectKey`, bucket, URLs, status, and timestamps
## Notes
- MinIO bucket creation happens during startup, so the service must be able to reach the endpoint.
- Keep Better Auth and MinIO secrets out of source control.