feat: add admin dashboard with basic auth and update README for configuration and API details
This commit is contained in:
@@ -1,126 +1,99 @@
|
||||
# backend
|
||||
|
||||
## Install
|
||||
## Overview
|
||||
Backend for the video upload prototype providing:
|
||||
|
||||
- JWT-based 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
|
||||
```
|
||||
|
||||
## Environment
|
||||
|
||||
Create a `.env` file:
|
||||
## Configuration
|
||||
Copy the example environment file and adjust the values:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Set:
|
||||
Required env vars:
|
||||
|
||||
```bash
|
||||
DATABASE_URL=postgres://username:password@localhost:5432/database_name
|
||||
JWT_SECRET=replace_with_a_long_random_secret
|
||||
JWT_EXPIRES_IN=7d
|
||||
PORT=3000
|
||||
MINIO_ENDPOINT=localhost
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=minioadmin
|
||||
MINIO_SECRET_KEY=minioadmin
|
||||
MINIO_BUCKET=videos
|
||||
MINIO_REGION=us-east-1
|
||||
MINIO_PRESIGNED_EXPIRY_SECONDS=600
|
||||
```
|
||||
| Name | Purpose |
|
||||
| --- | --- |
|
||||
| `DATABASE_URL` | Postgres connection string |
|
||||
| `JWT_SECRET` | Secret used to sign access tokens |
|
||||
| `JWT_EXPIRES_IN` | Token expiry (e.g., `7d`) |
|
||||
| `PORT` | HTTP port (default `3000`) |
|
||||
| `MINIO_*` | Connection settings for the MinIO/S3 endpoint |
|
||||
| `ADMIN_USERNAME` / `ADMIN_PASSWORD` | Basic auth for `/admin` dashboard |
|
||||
|
||||
## Run app
|
||||
## Running
|
||||
- Start the server in development:
|
||||
|
||||
```bash
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Drizzle ORM
|
||||
- Server boots after ensuring the configured MinIO bucket exists.
|
||||
|
||||
Generate migrations:
|
||||
## Database (Drizzle ORM)
|
||||
- Generate a migration:
|
||||
```bash
|
||||
bun run db:generate
|
||||
```
|
||||
- Apply migrations:
|
||||
```bash
|
||||
bun run db:migrate
|
||||
```
|
||||
- Open Drizzle Studio:
|
||||
```bash
|
||||
bun run db:studio
|
||||
```
|
||||
|
||||
```bash
|
||||
bun run db:generate
|
||||
```
|
||||
## API
|
||||
All `/videos` and `/admin` routes require a valid JWT Bearer token except for the admin dashboard access, which uses HTTP Basic auth with `ADMIN_USERNAME`/`ADMIN_PASSWORD`.
|
||||
|
||||
Apply migrations:
|
||||
### Authentication
|
||||
| Endpoint | Description |
|
||||
| --- | --- |
|
||||
| `POST /auth/register` | Create a user (`email`, `password`, `name`) |
|
||||
| `POST /auth/login` | Receive a token using `email`/`password` |
|
||||
| `GET /auth/me` | Get the current user ([Authorization](#authorization)) |
|
||||
|
||||
```bash
|
||||
bun run db:migrate
|
||||
```
|
||||
### Authorization
|
||||
All authenticated endpoints expect an `Authorization: Bearer <token>` header containing the JWT issued at login.
|
||||
|
||||
Open Drizzle Studio:
|
||||
### 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` |
|
||||
|
||||
```bash
|
||||
bun run db:studio
|
||||
```
|
||||
### Admin Dashboard
|
||||
Access `/admin` with Basic auth to:
|
||||
|
||||
## Auth API
|
||||
- Request presigned upload URLs
|
||||
- Upload files directly via the generated URL
|
||||
- List and delete objects within the MinIO bucket
|
||||
|
||||
Register:
|
||||
The dashboard UI submits to `/admin/upload-url`, `/admin/objects`, and `/admin/object`.
|
||||
|
||||
```bash
|
||||
POST /auth/register
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "password123",
|
||||
"name": "User Name"
|
||||
}
|
||||
```
|
||||
## 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
|
||||
|
||||
Login:
|
||||
|
||||
```bash
|
||||
POST /auth/login
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "password123"
|
||||
}
|
||||
```
|
||||
|
||||
Get current user:
|
||||
|
||||
```bash
|
||||
GET /auth/me
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
## Video API (Dummy MinIO S3 Integration)
|
||||
|
||||
All routes require a JWT Bearer token.
|
||||
|
||||
Create a presigned upload URL:
|
||||
|
||||
```bash
|
||||
POST /videos/upload-url
|
||||
Authorization: Bearer <token>
|
||||
{
|
||||
"fileName": "sample.mp4",
|
||||
"prefix": "raw"
|
||||
}
|
||||
```
|
||||
|
||||
Get a presigned download URL:
|
||||
|
||||
```bash
|
||||
GET /videos/download-url?objectKey=raw/<user-id>/<timestamp>-sample.mp4
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
List video objects:
|
||||
|
||||
```bash
|
||||
GET /videos?prefix=raw&limit=20
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
Delete a video object:
|
||||
|
||||
```bash
|
||||
DELETE /videos?objectKey=raw/<user-id>/<timestamp>-sample.mp4
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Self-hosted MinIO note** Make sure the backend can reach your MinIO endpoint (network, TLS, credentials) and mirror any bucket changes you make outside of the app in `MINIO_BUCKET`, otherwise uploads/downloads fail.
|
||||
## Notes
|
||||
- MinIO bucket creation happens during startup, so the service must be able to reach the endpoint.
|
||||
- Keep JWT and MinIO secrets out of source control.
|
||||
|
||||
Reference in New Issue
Block a user