- Add config/allowed_users.yaml as the source of truth for access control (email → role mapping, case-insensitive) - New backend/app/services/allowlist.py loads the YAML and provides lookup() - auth.py checks the allowlist on every SSO login; denies with 403 if not listed; syncs AppUser.role from YAML on each login - PyYAML added to requirements.txt - docker-compose mounts ./config:/app/config into the backend container - Frontend: axios response interceptor catches 403 not_allowlisted and fires a custom DOM event; AuthProvider renders a NoAccessPage with Sign out button - .env.example: clarify DEV_AUTH_BYPASS usage, document ALLOWED_USERS_PATH Azure AD: add https://optical-dev.oliver.solutions/oliver-sales-ops-platform/ as a SPA redirect URI in app registration 9079054c (done separately by zlalani). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
88 lines
2.9 KiB
YAML
88 lines
2.9 KiB
YAML
name: oliver-sales-ops-platform
|
|
|
|
services:
|
|
db:
|
|
image: postgres:16-alpine
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_DB: oliver_sales_ops
|
|
POSTGRES_USER: osop_user
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-osop_pass_2026}
|
|
volumes:
|
|
- osop_pgdata:/var/lib/postgresql/data
|
|
ports:
|
|
- "127.0.0.1:${OSOP_DB_PORT:-5435}:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U osop_user -d oliver_sales_ops"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:${OSOP_REDIS_PORT:-6380}:6379"
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
|
|
backend:
|
|
build: ./backend
|
|
restart: unless-stopped
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
environment:
|
|
DATABASE_URL: postgresql+asyncpg://osop_user:${POSTGRES_PASSWORD:-osop_pass_2026}@db:5432/oliver_sales_ops
|
|
DATABASE_URL_SYNC: postgresql://osop_user:${POSTGRES_PASSWORD:-osop_pass_2026}@db:5432/oliver_sales_ops
|
|
REDIS_URL: redis://redis:6379/0
|
|
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
|
AZURE_TENANT_ID: ${AZURE_TENANT_ID}
|
|
AZURE_CLIENT_ID: ${AZURE_CLIENT_ID}
|
|
DEV_AUTH_BYPASS: ${DEV_AUTH_BYPASS:-}
|
|
DEV_AUTH_EMAIL: ${DEV_AUTH_EMAIL:-dev@localhost}
|
|
DEV_AUTH_NAME: ${DEV_AUTH_NAME:-Dev User}
|
|
DEV_AUTH_ROLE: ${DEV_AUTH_ROLE:-editor}
|
|
MAILGUN_API_KEY: ${MAILGUN_API_KEY:-}
|
|
MAILGUN_DOMAIN: ${MAILGUN_DOMAIN:-}
|
|
MAILGUN_FROM: ${MAILGUN_FROM:-OLIVER Sales Ops <noreply@example.com>}
|
|
MAILGUN_REGION: ${MAILGUN_REGION:-us}
|
|
APP_PUBLIC_URL: ${APP_PUBLIC_URL:-http://localhost:3011}
|
|
APP_PATH_PREFIX: ${APP_PATH_PREFIX:-/oliver-sales-ops-platform}
|
|
ports:
|
|
- "127.0.0.1:${OSOP_BACKEND_PORT:-8003}:8000"
|
|
volumes:
|
|
- ${DATA_DIR:-./data}:/app/data
|
|
- ./backend/app:/app/app
|
|
- ./backend/alembic:/app/alembic
|
|
- ./backend/alembic.ini:/app/alembic.ini
|
|
- ./config:/app/config
|
|
|
|
# Vite dev-server container — used for local development only.
|
|
# In production (deploy server) we build the static SPA via deploy.sh
|
|
# and Apache serves it from /var/www/html/oliver-sales-ops-platform/.
|
|
# Activate locally with: COMPOSE_PROFILES=dev docker compose up -d
|
|
frontend:
|
|
build: ./frontend
|
|
restart: unless-stopped
|
|
profiles: ["dev"]
|
|
depends_on:
|
|
- backend
|
|
environment:
|
|
VITE_DEV_AUTH_BYPASS: ${VITE_DEV_AUTH_BYPASS:-}
|
|
ports:
|
|
- "127.0.0.1:${OSOP_FRONTEND_PORT:-3011}:3000"
|
|
volumes:
|
|
- ./frontend/src:/app/src
|
|
- ./frontend/index.html:/app/index.html
|
|
- ./frontend/vite.config.ts:/app/vite.config.ts
|
|
- ./frontend/tsconfig.json:/app/tsconfig.json
|
|
- ./frontend/tsconfig.node.json:/app/tsconfig.node.json
|
|
|
|
volumes:
|
|
osop_pgdata:
|