Paperclip CTO dafbfa2bc4 feat(TRA-372): live groupcall backend — WebRTC signaling + session control
- Add Django Channels 4 + channels-redis to requirements and INSTALLED_APPS
- Upgrade ASGI config to ProtocolTypeRouter with JWT-authenticated WebSocket routing
- Add JWTAuthMiddleware for WebSocket token auth via query param
- Add CallSession, CallParticipant, CallEvent models with migration 0004
- MeetingCallConsumer: join/leave, P2P SDP/ICE relay via per-user groups,
  instructor mute/unmute/kick with DB audit and WS broadcast
- REST endpoints: GET/POST/DELETE /meetings/{id}/call/ (session lifecycle),
  POST /moderate/ (mute/unmute/kick), POST /screen-share/, GET /events/ (audit log)
- IsMeetingModerator permission (accepts training:signoff or meeting:moderate)
- Services: get_or_create_call_session, end_call_session, apply_moderation_action,
  toggle_screen_share with full CallEvent audit trail
- Integration tests covering REST lifecycle, moderation, and WebSocket signaling

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-18 14:12:48 +02:00

Training Software

This repository contains a Django-based training platform backend plus a static customer portal frontend.

Features for customer environment setup

  • Per-customer organization profile with configurable license user limits (20, 50, 100, 1000)
  • Per-customer branding via company name and logo URL
  • Static frontend that can be hosted on Nginx and configured with the backend API domain at deploy time
  • CI pipeline for tests, linting, and container build

Production deployment with nginx

docker-compose.prod.yml starts the full stack in one command:

  • nginx — public-facing web server on port 80; serves the frontend SPA and Django static files directly; proxies all backend routes to gunicorn
  • web — Django/gunicorn (prod settings, 4 workers)
  • celery / celery-beat — background task workers
  • db — PostgreSQL 16
  • redis — Redis 7

1. Prerequisites

  • Docker Engine 24+ with Compose v2

2. Environment variables

cp .env.example .env.prod

Edit .env.prod and set at minimum:

Variable Notes
DJANGO_SECRET_KEY Long random string
DJANGO_ALLOWED_HOSTS Comma-separated hostnames, e.g. training.example.com
DB_PASSWORD PostgreSQL password
SECURE_SSL_REDIRECT Set false for HTTP-only; set true (or omit) when TLS is terminated at nginx or an upstream proxy

3. Start the stack

docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --build

4. Run migrations and create admin user

docker compose -f docker-compose.prod.yml exec web python manage.py migrate
docker compose -f docker-compose.prod.yml exec web python manage.py createsuperuser

5. Verify health

curl http://<host>/healthz/

HTTPS

To enable HTTPS, add ssl_certificate and ssl_certificate_key directives to nginx/nginx.conf and expose port 443 in docker-compose.prod.yml, or place a TLS-terminating reverse proxy (Traefik, Caddy, etc.) in front and set SECURE_SSL_REDIRECT=true.


Local development

1. Prerequisites

  • Python 3.12
  • PostgreSQL 16+
  • Redis 7+
  • Docker (recommended for containerised dev)

2. Environment variables

Create environment variables based on .env.example.

Required minimum values:

  • DJANGO_SECRET_KEY
  • DJANGO_ALLOWED_HOSTS
  • DATABASE_URL
  • REDIS_URL
  • DJANGO_SETTINGS_MODULE (use config.settings.local for dev)

3. Build and run with Docker Compose

docker compose up -d --build

4. Run migrations

docker compose exec web python manage.py migrate

5. Verify health

curl http://localhost:8000/healthz/

Organization profile API (license + branding)

Admin-only endpoint (requires admin role):

  • GET /api/v1/accounts/organizations/{org_id}/profile/
  • PATCH /api/v1/accounts/organizations/{org_id}/profile/

Fields

Field Type Description
company_name string Customer company name shown in the UI
license_user_limit integer Maximum number of active users — any positive integer (e.g. 20, 50, 100, 250, 1000)
brand_logo_url string (URL) URL of the customer's logo, displayed in the frontend header

Setting the license limit

license_user_limit accepts any positive integer — there are no fixed tiers. Set it to exactly the number of users your customer has licensed:

curl -X PATCH https://api.example.com/api/v1/accounts/organizations/<org_id>/profile/ \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "Acme Corp",
    "license_user_limit": 250,
    "brand_logo_url": "https://cdn.example.com/acme-logo.svg"
  }'

Common values: 20 · 50 · 100 · 250 · 500 · 1000 — but any number works.

Frontend deployment on Nginx

The static frontend is under frontend/public.

1. Set backend API domain

Edit frontend/public/config.js and set:

window.APP_CONFIG = {
  API_BASE_URL: "https://api.example.com"
};

2. Serve via Nginx

Use frontend/nginx.conf as a reference server config and copy the frontend/public files to your Nginx web root.

CI for Gitea

Gitea Actions workflow file:

  • .gitea/workflows/ci.yml

It runs:

  • Ruff lint
  • Django test suite
  • Docker image build
Description
No description provided
Readme 705 KiB
Languages
Python 81.5%
JavaScript 10.4%
HTML 3.4%
CSS 3.3%
Shell 0.9%
Other 0.5%