# NEDA Backend NEDA is a FastAPI backend for real-time group voice communication. It includes authentication, user/group management, WebSocket signaling, Redis for real-time state, and PostgreSQL for persistent data. ## Tech Stack - FastAPI + Uvicorn - SQLAlchemy (Async) + asyncpg - PostgreSQL - Redis - Alembic - LiveKit ## Project Structure ```text core/ config, security, deps alembic/ database migrations db/ database/redis setup domains/ domain modules (auth, users, admin, groups, realtime, notifications) integrations/ external integrations (LiveKit) scripts/ utility scripts (create_admin) main.py FastAPI app entrypoint ``` ## Active Routes - `POST /auth/login` - `GET /users/` - `POST /admin/users` - `POST /admin/users/{user_id}/logout` - `POST /admin/users/{user_id}/reset-secret` - `GET /admin/users` - `GET /admin/groups` - `POST /groups/` - `GET /groups/my` - `GET /groups/admin/all` - `GET /groups/{group_id}/members` - `POST /groups/{group_id}/invite` - `DELETE /groups/{group_id}/members/{user_id}` - `WS /ws/groups/{group_id}` ## Environment Variables Create a `.env` file in the project root: ```env APP_NAME=NEDA DEBUG=False SECRET_KEY=change-me ACCESS_TOKEN_EXPIRE_MINUTES=30 ALGORITHM=HS256 SECRET_PASS_LENGTH=32 POSTGRES_DB=neda POSTGRES_USER=neda_user POSTGRES_PASSWORD=neda_pass DATABASE_URL=postgresql+asyncpg://neda_user:neda_pass@postgres:5432/neda REDIS_URL=redis://redis:6379/0 LIVEKIT_API_KEY=neda_key LIVEKIT_API_SECRET=neda_secret LIVEKIT_HOST=http://livekit:7880 LIVEKIT_PORT=7880 LIVEKIT_TCP_PORT=7881 LIVEKIT_UDP_PORT=7882 ``` LiveKit note: - `livekit.yaml.template` is a template, not a direct runtime config. - The `livekit` container generates `/etc/livekit.yaml` from env values at startup. - Raw YAML does not automatically resolve `${...}` placeholders unless templated first. ## Run With Docker ```bash docker compose up --build -d ``` Services: - API: `http://localhost:8000` - Swagger Docs: `http://localhost:8000/docs` - LiveKit: `http://localhost:7880` - Postgres: `localhost:5432` - Redis: `localhost:6379` API logs: ```bash docker compose logs -f api ``` ## Create Admin (Inside Docker) After services are up, create the initial admin user inside the API container: ```bash docker compose exec api python -m scripts.create_admin ``` The script asks for `username` and optional `phone_number`, creates the user with `is_admin=True`, and prints the initial `secret`. ## Admin API Hardening - `POST /admin/users` creates only non-admin users. - Sending `is_admin` in the payload is not allowed and returns `422`. - Admin creation is only allowed through the server-side script: `scripts/create_admin.py`. Invalid payload example: ```json { "username": "new_user", "phone_number": "09123456789", "is_admin": true } ``` Admin login: - Endpoint: `POST /auth/login` - Body: ```json { "username": "admin_username", "secret": "printed_secret" } ``` ## Database Migrations (Alembic) This project uses Alembic, and `env.py` reads `DATABASE_URL` from `.env`. Apply migrations (inside Docker): ```bash docker compose exec api alembic upgrade head ``` Create a new migration (autogenerate): ```bash docker compose exec api alembic revision --autogenerate -m "your_message" ``` Check current DB revision: ```bash docker compose exec api alembic current ``` Show migration history: ```bash docker compose exec api alembic history ``` Important: run `alembic upgrade head` before starting the API in a new environment. ## Local Development (Without Docker) ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` Run migrations: ```bash alembic upgrade head ``` Start API: ```bash uvicorn main:app --reload ``` ## Realtime Notes - Presence is stored in Redis. - Speaker lock is managed atomically in Redis. - LiveKit tokens for listener/speaker roles are issued during the WebSocket flow.