# Enterprise Digital Platform Unified umbrella project that brings together three independent services behind a single portal with SSO. ## Architecture ``` Browser └── nginx (ports 80 / 443) ← umbrella reverse proxy ├── / ← Portal dashboard (Flask, new service) ├── /digiserver/ ← DigiServer v2 (Flask) ├── /itassets/ ← IT Asset Management (Flask) ├── /networkview/ ← NetworkView frontend (React/Vite SPA) └── /networkview/api/ ← NetworkView backend (Node/Express) ``` ## Quick Start ```bash # 1. Copy and fill in secrets cp .env.example .env # Edit .env — at minimum change PORTAL_JWT_SECRET and all *_SECRET_KEY values. # 2. Create data directories for DigiServer (it expects them as bind mounts) mkdir -p ../digiserver-v2/data/instance ../digiserver-v2/data/uploads # 3. Build and start everything docker compose up --build -d # 4. Open http://localhost — default credentials: admin / admin123 ``` ## Services | Container | Internal port | External URL | |-------------------------|---------------|--------------------------| | `edp-portal` | 5001 | `http://host/` | | `edp-digiserver` | 5000 | `http://host/digiserver/`| | `edp-itassets` | 5000 | `http://host/itassets/` | | `edp-networkview-backend`| 3001 | `http://host/networkview/api/` | | `edp-networkview-frontend`| 80 | `http://host/networkview/`| | `edp-nginx` | 80 / 443 | Public entry point | ## Authentication & SSO 1. Users log in **once** at the portal (`/login`). 2. The portal signs a **JWT cookie** (`edp_portal_token`) that contains the username, role, and list of permitted apps. 3. Every request to a sub-app path goes through nginx `auth_request` → the portal's `/api/verify-token` endpoint. 4. If the token is valid **and** the user has access to that app, nginx forwards the `X-Auth-Username` / `X-Auth-Role` headers to the sub-app. 5. Each Flask sub-app auto-creates a local session for that user (creating the account on first access if needed). ## Access Management Visit `http://host/settings` (admin only) to: - **Create portal users** and assign them access to one or more apps. - **Toggle app access** per user with a single checkbox. - **Generate / revoke API keys** for programmatic access. ## Project Structure ``` Enterprise_digital-platform/ ├── docker-compose.yml ← Orchestrates all 5 services ├── .env.example ← Copy to .env and fill in secrets ├── nginx/ │ └── nginx.conf ← Umbrella reverse proxy config └── portal/ ← New portal dashboard service ├── Dockerfile ├── requirements.txt ├── run.py ├── config.py └── app/ ├── models/ ← PortalUser, AppAccess, ApiKey ├── routes/ ← auth, dashboard, settings, api (verify-token) ├── templates/ └── static/css/ # Existing projects (referenced by docker-compose relative paths) ../digiserver-v2/ ← app/utils/portal_sso.py + script_name_fix.py added ../IT_asset_management/ ← app/utils/portal_sso.py + script_name_fix.py added ../NetworkView/ backend/Dockerfile ← added frontend/ Dockerfile ← added (multi-stage Vite build + nginx) nginx.conf ← added src/App.tsx ← BrowserRouter basename set from BASE_URL src/api.ts ← API base set from VITE_API_BASE env var vite.config.ts ← base path driven by VITE_BASE_PATH env var ``` ## Development (without Docker) Each project still works standalone: ```bash # Portal cd Enterprise_digital-platform/portal pip install -r requirements.txt FLASK_ENV=development python run.py # DigiServer v2 cd digiserver-v2 # ... existing setup unchanged # IT Asset Management cd IT_asset_management # ... existing setup unchanged # NetworkView cd NetworkView/backend && npm start cd NetworkView/frontend && npm run dev ``` ## HTTPS Place your certificate and key in `nginx/ssl/cert.pem` and `nginx/ssl/key.pem`, then add an HTTPS server block to `nginx/nginx.conf`. --- ## Deployment: Client URL Configuration nginx routes traffic **purely by URL path prefix** on port 80. The port number alone carries no routing information — every client device must include the correct module prefix in its server URL. ### URL pattern ``` http:////api/ ``` ### DigiServer — digital signage players Each player stores a "server URL" in its config. Change it to: ``` http:///digiserver ``` The player then calls paths such as: | Action | Full URL | |---|---| | Authenticate | `POST http:///digiserver/api/auth/player` | | Fetch playlist | `GET http:///digiserver/api/playlists/` | | Send feedback | `POST http:///digiserver/api/player-feedback` | ### Server Monitor — Raspberry Pi / Linux agents Each agent script (or cron job) sends logs to: ``` POST http:///srvmonitor/api/logs/submit ``` Example payload (no auth token needed — this path bypasses portal SSO): ```json { "hostname": "rpi-kitchen-01", "device_ip": "192.168.1.42", "nume_masa": "Masa-01", "log_message": "Card detected: ABC123", "severity": "info" } ``` Other agent endpoints: | Action | Full URL | |---|---| | Submit log (JSON) | `POST http:///srvmonitor/api/logs/submit` | | Upload log file | `POST http:///srvmonitor/api/logs/file` | | Query logs | `GET http:///srvmonitor/api/logs/query` | ### Why the prefix is required Without the prefix, nginx cannot distinguish between modules and the request falls through to the portal (which returns 401/302). There is no routing by port — all traffic enters on port 80 (or 443 for HTTPS). ``` ✅ http://yourdomain.com/digiserver/api/auth/player → DigiServer ✅ http://yourdomain.com/srvmonitor/api/logs/submit → Server Monitor ❌ http://yourdomain.com/api/logs/submit → Portal (wrong!) ❌ http://yourdomain.com:5002/api/auth/player → Direct port, bypasses nginx (blocked in prod) ``` ### Development vs production URLs | Environment | Port | Example base URL | |---|---|---| | Development | 8080 | `http://localhost:8080/srvmonitor` | | Production | 80 | `http://yourdomain.com/srvmonitor` | | Production HTTPS | 443 | `https://yourdomain.com/srvmonitor` |