7d24e7f527
Auth: - Fix local login (was redirecting to portal; now authenticates AdminUser directly) - Portal SSO still takes priority in production via nginx headers Role system (admin | editor | readonly): - New app/utils/decorators.py with editor_required and admin_required decorators - All write routes protected with editor_required (create/edit/delete/import/mask) - Settings user management protected with admin_required - Sidebar hides write-only links for readonly users - Dashboard quick actions and list page buttons hidden for readonly Settings page: - Role colour badges (admin=red, editor=blue, readonly=grey) - Inline role changer per user (dropdown auto-submit) - Reset password modal per user - Delete user button with confirmation - Add user form includes role selector with legend Portal user sync: - New /internal/sync-user endpoint receives user pre-creation from portal - INTERNAL_SYNC_SECRET added to config - portal/config.py: added internal_url for itassets app so _sync_user_to_app works
80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
import os
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
|
|
class Config:
|
|
SECRET_KEY = os.environ.get('SECRET_KEY', 'change-this-portal-secret')
|
|
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///portal.db')
|
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
|
|
# JWT settings for platform-wide SSO token
|
|
PORTAL_JWT_SECRET = os.environ.get('PORTAL_JWT_SECRET', 'change-this-jwt-secret')
|
|
JWT_EXPIRY_HOURS = int(os.environ.get('JWT_EXPIRY_HOURS', 8))
|
|
PORTAL_COOKIE_NAME = 'edp_portal_token'
|
|
|
|
# Initial admin seeded on first run
|
|
ADMIN_USERNAME = os.environ.get('ADMIN_USERNAME', 'admin')
|
|
ADMIN_PASSWORD = os.environ.get('ADMIN_PASSWORD', 'admin123')
|
|
ADMIN_EMAIL = os.environ.get('ADMIN_EMAIL', 'admin@localhost')
|
|
|
|
# App registry — display metadata for the three sub-apps
|
|
REGISTERED_APPS = [
|
|
{
|
|
'id': 'digiserver',
|
|
'name': 'DigiServer',
|
|
'description': 'Digital signage player & content management platform.',
|
|
'icon': '🖥️',
|
|
'url': '/digiserver/',
|
|
'color': '#22c55e',
|
|
# Internal URL for portal→app user sync (not through nginx)
|
|
'internal_url': os.environ.get('DIGISERVER_INTERNAL_URL', 'http://localhost:5002'),
|
|
},
|
|
{
|
|
'id': 'networkview',
|
|
'name': 'NetworkView',
|
|
'description': 'Infrastructure topology — sites, rooms, racks & cabling.',
|
|
'icon': '🌐',
|
|
'url': '/networkview/',
|
|
'color': '#3b82f6',
|
|
},
|
|
{
|
|
'id': 'itassets',
|
|
'name': 'IT Asset Management',
|
|
'description': 'Track hardware assets, assignments and compliance.',
|
|
'icon': '💼',
|
|
'url': '/itassets/',
|
|
'color': '#f59e0b',
|
|
# Internal URL for portal→app user sync (not through nginx)
|
|
'internal_url': os.environ.get('ITASSETS_INTERNAL_URL', 'http://localhost:5003'),
|
|
},
|
|
{
|
|
'id': 'srvmonitor',
|
|
'name': 'Server Monitor',
|
|
'description': 'Real-time monitoring for Raspberry Pi clients — logs, devices & Ansible automation.',
|
|
'icon': '📡',
|
|
'url': '/srvmonitor/',
|
|
'color': '#a855f7',
|
|
},
|
|
]
|
|
|
|
# Internal service-to-service sync secret — must match INTERNAL_SYNC_SECRET in sub-apps
|
|
INTERNAL_SYNC_SECRET = os.environ.get('INTERNAL_SYNC_SECRET', 'change-this-internal-secret')
|
|
|
|
|
|
class DevelopmentConfig(Config):
|
|
DEBUG = True
|
|
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///portal_dev.db')
|
|
|
|
|
|
class ProductionConfig(Config):
|
|
DEBUG = False
|
|
|
|
|
|
config = {
|
|
'development': DevelopmentConfig,
|
|
'production': ProductionConfig,
|
|
'default': ProductionConfig,
|
|
}
|