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

# 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:

# 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://<your-domain>/<module-prefix>/api/<endpoint>

DigiServer — digital signage players

Each player stores a "server URL" in its config. Change it to:

http://<your-domain>/digiserver

The player then calls paths such as:

Action Full URL
Authenticate POST http://<your-domain>/digiserver/api/auth/player
Fetch playlist GET http://<your-domain>/digiserver/api/playlists/<player_id>
Send feedback POST http://<your-domain>/digiserver/api/player-feedback

Server Monitor — Raspberry Pi / Linux agents

Each agent script (or cron job) sends logs to:

POST http://<your-domain>/srvmonitor/api/logs/submit

Example payload (no auth token needed — this path bypasses portal SSO):

{
  "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://<your-domain>/srvmonitor/api/logs/submit
Upload log file POST http://<your-domain>/srvmonitor/api/logs/file
Query logs GET http://<your-domain>/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
S
Description
No description provided
Readme 908 KiB
Languages
HTML 43.3%
Python 38.7%
TypeScript 7.9%
Shell 3.7%
CSS 3.7%
Other 2.7%