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
82 lines
3.2 KiB
Python
82 lines
3.2 KiB
Python
import os
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
|
|
class Config:
|
|
SECRET_KEY = os.environ.get('SECRET_KEY', 'change-this-secret-in-production-use-a-long-random-string')
|
|
|
|
# MySQL
|
|
MYSQL_HOST = os.environ.get('MYSQL_HOST', 'localhost')
|
|
MYSQL_PORT = int(os.environ.get('MYSQL_PORT', 3306))
|
|
MYSQL_USER = os.environ.get('MYSQL_USER', 'itasset_user')
|
|
MYSQL_PASSWORD = os.environ.get('MYSQL_PASSWORD', 'itasset_pass')
|
|
MYSQL_DB = os.environ.get('MYSQL_DB', 'itasset_db')
|
|
|
|
# Allow SQLALCHEMY_DATABASE_URI env var to override (used for SQLite in local dev)
|
|
_mysql_uri = (
|
|
f"mysql+pymysql://{os.environ.get('MYSQL_USER', 'itasset_user')}:"
|
|
f"{os.environ.get('MYSQL_PASSWORD', 'itasset_pass')}@"
|
|
f"{os.environ.get('MYSQL_HOST', 'localhost')}:"
|
|
f"{os.environ.get('MYSQL_PORT', 3306)}/"
|
|
f"{os.environ.get('MYSQL_DB', 'itasset_db')}?charset=utf8mb4"
|
|
)
|
|
SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI', _mysql_uri)
|
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
|
|
# LDAP / Active Directory
|
|
LDAP_SERVER = os.environ.get('LDAP_SERVER', '')
|
|
LDAP_PORT = int(os.environ.get('LDAP_PORT', 389))
|
|
LDAP_USE_SSL = os.environ.get('LDAP_USE_SSL', 'false').lower() == 'true'
|
|
LDAP_BIND_USER = os.environ.get('LDAP_BIND_USER', '')
|
|
LDAP_BIND_PASSWORD = os.environ.get('LDAP_BIND_PASSWORD', '')
|
|
LDAP_BASE_DN = os.environ.get('LDAP_BASE_DN', '')
|
|
LDAP_USER_SEARCH_FILTER = os.environ.get(
|
|
'LDAP_USER_SEARCH_FILTER', '(&(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))'
|
|
)
|
|
# AD attribute that stores the numeric Windows ID (e.g. employeeID)
|
|
LDAP_WINDOWS_ID_ATTR = os.environ.get('LDAP_WINDOWS_ID_ATTR', 'employeeID')
|
|
|
|
# File storage
|
|
UPLOAD_FOLDER = os.environ.get('UPLOAD_FOLDER', 'uploads')
|
|
PDF_FOLDER = os.environ.get('PDF_FOLDER', 'pdfs')
|
|
TEMPLATE_FOLDER = os.environ.get('TEMPLATE_FOLDER', 'doc_templates')
|
|
DOCX_FOLDER = os.environ.get('DOCX_FOLDER', 'docx_output')
|
|
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16 MB
|
|
|
|
# Company info used in generated PDFs
|
|
COMPANY_NAME = os.environ.get('COMPANY_NAME', 'Your Company Name')
|
|
COMPANY_ADDRESS = os.environ.get('COMPANY_ADDRESS', '')
|
|
COMPANY_LOGO = os.environ.get('COMPANY_LOGO', '') # path to logo file
|
|
|
|
# Portal SSO
|
|
PORTAL_LOGIN_URL = os.environ.get('PORTAL_LOGIN_URL', 'http://localhost:8080/login')
|
|
PORTAL_LOGOUT_URL = os.environ.get('PORTAL_LOGOUT_URL', 'http://localhost:8080/logout')
|
|
|
|
# Internal service-to-service sync secret — must match portal's INTERNAL_SYNC_SECRET
|
|
INTERNAL_SYNC_SECRET = os.environ.get('INTERNAL_SYNC_SECRET', 'change-this-internal-secret')
|
|
|
|
# Pagination
|
|
ITEMS_PER_PAGE = int(os.environ.get('ITEMS_PER_PAGE', 25))
|
|
|
|
# Dell TechDirect API (for service-tag auto-lookup)
|
|
# Register at https://tdm.dell.com → API Services → Create credentials
|
|
DELL_CLIENT_ID = os.environ.get('DELL_CLIENT_ID', '')
|
|
DELL_CLIENT_SECRET = os.environ.get('DELL_CLIENT_SECRET', '')
|
|
|
|
|
|
class DevelopmentConfig(Config):
|
|
DEBUG = True
|
|
|
|
|
|
class ProductionConfig(Config):
|
|
DEBUG = False
|
|
|
|
|
|
config = {
|
|
'development': DevelopmentConfig,
|
|
'production': ProductionConfig,
|
|
'default': DevelopmentConfig,
|
|
}
|