325 lines
14 KiB
Python
325 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import socket
|
|
import logging
|
|
import inspect
|
|
from app.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def validate_email_config():
|
|
"""Validates email configuration settings"""
|
|
issues = []
|
|
|
|
# Check for required email settings
|
|
if not getattr(settings, 'email_host', None):
|
|
issues.append("EMAIL_HOST is not configured")
|
|
if not getattr(settings, 'email_port', None):
|
|
issues.append("EMAIL_PORT is not configured")
|
|
|
|
# Test SMTP server connectivity if host is configured
|
|
if getattr(settings, 'email_host', None) and getattr(settings, 'email_port', None):
|
|
try:
|
|
# Attempt to resolve the hostname
|
|
socket.gethostbyname(settings.email_host)
|
|
except socket.gaierror:
|
|
issues.append(f"Cannot resolve email host: {settings.email_host}")
|
|
|
|
# Check for authentication settings
|
|
if not getattr(settings, 'email_username', None):
|
|
issues.append("EMAIL_USERNAME is not configured")
|
|
if not getattr(settings, 'email_password', None):
|
|
issues.append("EMAIL_PASSWORD is not configured")
|
|
|
|
return issues
|
|
|
|
def validate_storage_configs():
|
|
"""Validates configuration for all storage providers"""
|
|
issues = {}
|
|
|
|
# Validate Dropbox config
|
|
dropbox_issues = []
|
|
if not (getattr(settings, 'dropbox_app_key', None) and
|
|
getattr(settings, 'dropbox_app_secret', None) and
|
|
getattr(settings, 'dropbox_refresh_token', None)):
|
|
dropbox_issues.append("Dropbox credentials are not fully configured")
|
|
issues['dropbox'] = dropbox_issues
|
|
|
|
# Validate Nextcloud config
|
|
nextcloud_issues = []
|
|
if not (getattr(settings, 'nextcloud_upload_url', None) and
|
|
getattr(settings, 'nextcloud_username', None) and
|
|
getattr(settings, 'nextcloud_password', None)):
|
|
nextcloud_issues.append("Nextcloud credentials are not fully configured")
|
|
issues['nextcloud'] = nextcloud_issues
|
|
|
|
# Validate SFTP config
|
|
sftp_issues = []
|
|
if not getattr(settings, 'sftp_host', None):
|
|
sftp_issues.append("SFTP_HOST is not configured")
|
|
|
|
sftp_key_path = getattr(settings, 'sftp_private_key', None)
|
|
if sftp_key_path and not os.path.exists(sftp_key_path):
|
|
sftp_issues.append(f"SFTP_KEY_PATH file not found: {sftp_key_path}")
|
|
|
|
if not sftp_key_path and not getattr(settings, 'sftp_password', None):
|
|
sftp_issues.append("Neither SFTP_KEY_PATH nor SFTP_PASSWORD is configured")
|
|
|
|
issues['sftp'] = sftp_issues
|
|
|
|
# Validate Email sending
|
|
email_issues = []
|
|
if not getattr(settings, 'email_host', None):
|
|
email_issues.append("EMAIL_HOST is not configured")
|
|
if not getattr(settings, 'email_default_recipient', None):
|
|
email_issues.append("EMAIL_DEFAULT_RECIPIENT is not configured")
|
|
issues['email'] = email_issues
|
|
|
|
# Validate S3
|
|
s3_issues = []
|
|
if not getattr(settings, 's3_bucket_name', None):
|
|
s3_issues.append("S3_BUCKET_NAME is not configured")
|
|
if not (getattr(settings, 'aws_access_key_id', None) and
|
|
getattr(settings, 'aws_secret_access_key', None)):
|
|
s3_issues.append("AWS credentials are not configured")
|
|
issues['s3'] = s3_issues
|
|
|
|
# Validate FTP
|
|
ftp_issues = []
|
|
if not getattr(settings, 'ftp_host', None):
|
|
ftp_issues.append("FTP_HOST is not configured")
|
|
if not getattr(settings, 'ftp_username', None):
|
|
ftp_issues.append("FTP_USERNAME is not configured")
|
|
if not getattr(settings, 'ftp_password', None):
|
|
ftp_issues.append("FTP_PASSWORD is not configured")
|
|
issues['ftp'] = ftp_issues
|
|
|
|
# Validate WebDAV
|
|
webdav_issues = []
|
|
if not getattr(settings, 'webdav_url', None):
|
|
webdav_issues.append("WEBDAV_URL is not configured")
|
|
if not getattr(settings, 'webdav_username', None):
|
|
webdav_issues.append("WEBDAV_USERNAME is not configured")
|
|
if not getattr(settings, 'webdav_password', None):
|
|
webdav_issues.append("WEBDAV_PASSWORD is not configured")
|
|
issues['webdav'] = webdav_issues
|
|
|
|
# Validate Google Drive
|
|
gdrive_issues = []
|
|
if not getattr(settings, 'google_drive_credentials_json', None):
|
|
gdrive_issues.append("GOOGLE_DRIVE_CREDENTIALS_JSON is not configured")
|
|
if not getattr(settings, 'google_drive_folder_id', None):
|
|
gdrive_issues.append("GOOGLE_DRIVE_FOLDER_ID is not configured")
|
|
issues['google_drive'] = gdrive_issues
|
|
|
|
# Validate Paperless
|
|
paperless_issues = []
|
|
if not getattr(settings, 'paperless_host', None):
|
|
paperless_issues.append("PAPERLESS_HOST is not configured")
|
|
if not getattr(settings, 'paperless_ngx_api_token', None):
|
|
paperless_issues.append("PAPERLESS_NGX_API_TOKEN is not configured")
|
|
issues['paperless'] = paperless_issues
|
|
|
|
# Validate OneDrive
|
|
onedrive_issues = []
|
|
if not (getattr(settings, 'onedrive_client_id', None) and
|
|
getattr(settings, 'onedrive_client_secret', None) and
|
|
getattr(settings, 'onedrive_refresh_token', None)):
|
|
onedrive_issues.append("OneDrive credentials are not fully configured")
|
|
issues['onedrive'] = onedrive_issues
|
|
|
|
return issues
|
|
|
|
def get_provider_status():
|
|
"""Get the status of each provider for the dashboard"""
|
|
providers = {
|
|
"Email": {
|
|
"configured": bool(getattr(settings, 'email_host', None) and
|
|
getattr(settings, 'email_username', None) and
|
|
getattr(settings, 'email_password', None)),
|
|
"icon": "mail",
|
|
"url": getattr(settings, 'email_host', None) or "",
|
|
"description": f"Send to {getattr(settings, 'email_default_recipient', 'Not configured')}"
|
|
},
|
|
"Dropbox": {
|
|
"configured": bool(getattr(settings, 'dropbox_app_key', None) and
|
|
getattr(settings, 'dropbox_app_secret', None) and
|
|
getattr(settings, 'dropbox_refresh_token', None)),
|
|
"icon": "dropbox",
|
|
"url": "https://dropbox.com",
|
|
"description": f"Upload to folder: {getattr(settings, 'dropbox_folder', 'Root')}"
|
|
},
|
|
"Nextcloud": {
|
|
"configured": bool(getattr(settings, 'nextcloud_upload_url', None) and
|
|
getattr(settings, 'nextcloud_username', None)),
|
|
"icon": "cloud",
|
|
"url": getattr(settings, 'nextcloud_upload_url', "").split('/remote.php')[0] if getattr(settings, 'nextcloud_upload_url', None) else "",
|
|
"description": f"Upload to folder: {getattr(settings, 'nextcloud_folder', 'Root')}"
|
|
},
|
|
"SFTP": {
|
|
"configured": bool(getattr(settings, 'sftp_host', None) and
|
|
getattr(settings, 'sftp_username', None) and
|
|
(getattr(settings, 'sftp_password', None) or getattr(settings, 'sftp_private_key', None))),
|
|
"icon": "server",
|
|
"url": f"sftp://{getattr(settings, 'sftp_host', '')}:{getattr(settings, 'sftp_port', 22)}",
|
|
"description": f"Upload to {getattr(settings, 'sftp_host', 'Not configured')}:{getattr(settings, 'sftp_folder', '/')}"
|
|
},
|
|
"Paperless": {
|
|
"configured": bool(getattr(settings, 'paperless_host', None) and
|
|
getattr(settings, 'paperless_ngx_api_token', None)),
|
|
"icon": "file-text",
|
|
"url": getattr(settings, 'paperless_host', ""),
|
|
"description": "Document management system"
|
|
},
|
|
"S3": {
|
|
"configured": bool(getattr(settings, 's3_bucket_name', None) and
|
|
getattr(settings, 'aws_access_key_id', None)),
|
|
"icon": "database",
|
|
"url": f"https://s3.console.aws.amazon.com/s3/buckets/{getattr(settings, 's3_bucket_name', '')}",
|
|
"description": f"Bucket: {getattr(settings, 's3_bucket_name', 'Not configured')}"
|
|
},
|
|
"FTP": {
|
|
"configured": bool(getattr(settings, 'ftp_host', None) and
|
|
getattr(settings, 'ftp_username', None)),
|
|
"icon": "hard-drive",
|
|
"url": f"ftp://{getattr(settings, 'ftp_host', '')}:{getattr(settings, 'ftp_port', 21)}",
|
|
"description": f"Upload to {getattr(settings, 'ftp_host', 'Not configured')}:{getattr(settings, 'ftp_folder', '/')}"
|
|
},
|
|
"WebDAV": {
|
|
"configured": bool(getattr(settings, 'webdav_url', None) and
|
|
getattr(settings, 'webdav_username', None)),
|
|
"icon": "globe",
|
|
"url": getattr(settings, 'webdav_url', ""),
|
|
"description": f"Upload to {getattr(settings, 'webdav_folder', '/')}"
|
|
},
|
|
"Google Drive": {
|
|
"configured": bool(getattr(settings, 'google_drive_credentials_json', None)),
|
|
"icon": "google",
|
|
"url": "https://drive.google.com",
|
|
"description": f"Folder ID: {getattr(settings, 'google_drive_folder_id', 'Not configured')}"
|
|
},
|
|
"OneDrive": {
|
|
"configured": bool(getattr(settings, 'onedrive_client_id', None) and
|
|
getattr(settings, 'onedrive_refresh_token', None)),
|
|
"icon": "microsoft",
|
|
"url": "https://onedrive.live.com",
|
|
"description": f"Upload to folder: {getattr(settings, 'onedrive_folder_path', 'Not configured')}"
|
|
}
|
|
}
|
|
|
|
return providers
|
|
|
|
def dump_all_settings():
|
|
"""Dump all settings to the log for debugging"""
|
|
logger.info("================ SETTINGS DUMP ================")
|
|
|
|
# Get all attributes from settings object
|
|
attributes = inspect.getmembers(settings, lambda a: not inspect.isroutine(a))
|
|
settings_dict = {a[0]: a[1] for a in attributes
|
|
if not a[0].startswith('_') and not callable(a[1])}
|
|
|
|
# Sort keys for better readability
|
|
for key in sorted(settings_dict.keys()):
|
|
value = settings_dict[key]
|
|
# Hide sensitive values
|
|
if any(sensitive in key.lower() for sensitive in ['password', 'secret', 'token', 'key']):
|
|
if value:
|
|
value = "******** [HIDDEN FOR SECURITY]"
|
|
logger.info(f" {key} = {value}")
|
|
|
|
# Also log all environment variables
|
|
logger.info("----------- ENVIRONMENT VARIABLES -----------")
|
|
env_vars_to_log = {}
|
|
for key in sorted(os.environ.keys()):
|
|
value = os.environ[key]
|
|
# Hide sensitive values
|
|
if any(sensitive in key.lower() for sensitive in ['password', 'secret', 'token', 'key']):
|
|
if value:
|
|
value = "******** [HIDDEN FOR SECURITY]"
|
|
env_vars_to_log[key] = value
|
|
|
|
for key in sorted(env_vars_to_log.keys()):
|
|
logger.info(f" {key} = {env_vars_to_log[key]}")
|
|
|
|
logger.info("=============================================")
|
|
|
|
def get_settings_for_display(show_values=False):
|
|
"""Get all settings organized by category for display in UI"""
|
|
# Get all attributes from settings object
|
|
attributes = inspect.getmembers(settings, lambda a: not inspect.isroutine(a))
|
|
settings_dict = {a[0]: a[1] for a in attributes
|
|
if not a[0].startswith('_') and not callable(a[1])}
|
|
|
|
# Categorize settings
|
|
categories = {
|
|
"Core": [],
|
|
"Email": [],
|
|
"IMAP": [],
|
|
"Storage": [],
|
|
"Authentication": [],
|
|
"Integration": [],
|
|
"Other": []
|
|
}
|
|
|
|
# Sort keys for better readability
|
|
for key in sorted(settings_dict.keys()):
|
|
value = settings_dict[key]
|
|
# Mask sensitive values if show_values is False
|
|
display_value = value
|
|
if not show_values or any(sensitive in key.lower() for sensitive in ['password', 'secret', 'token', 'key']):
|
|
if value:
|
|
display_value = "******** [HIDDEN]"
|
|
else:
|
|
display_value = None
|
|
|
|
# Categorize by key prefix
|
|
setting_item = {"name": key, "value": display_value, "is_configured": value is not None and value != ""}
|
|
|
|
if key.startswith(('email_', 'smtp_')):
|
|
categories["Email"].append(setting_item)
|
|
elif key.startswith('imap'):
|
|
categories["IMAP"].append(setting_item)
|
|
elif key.startswith(('s3_', 'aws_', 'dropbox_', 'nextcloud_', 'sftp_', 'ftp_', 'google_drive_')):
|
|
categories["Storage"].append(setting_item)
|
|
elif key.startswith(('auth_', 'jwt_', 'oauth_')):
|
|
categories["Authentication"].append(setting_item)
|
|
elif key.startswith(('paperless_', 'tesseract_', 'azure_')):
|
|
categories["Integration"].append(setting_item)
|
|
elif key in ('workdir', 'external_hostname', 'debug', 'version', 'env', 'log_level'):
|
|
categories["Core"].append(setting_item)
|
|
else:
|
|
categories["Other"].append(setting_item)
|
|
|
|
# Remove empty categories
|
|
return {k: v for k, v in categories.items() if v}
|
|
|
|
def check_all_configs():
|
|
"""Run all configuration validations and log results"""
|
|
logger.info("Validating application configuration...")
|
|
|
|
# Check if debug is enabled and dump all settings if it is
|
|
if hasattr(settings, 'debug') and settings.debug:
|
|
dump_all_settings()
|
|
|
|
# Check email config
|
|
email_issues = validate_email_config()
|
|
if email_issues:
|
|
logger.warning(f"Email configuration issues: {', '.join(email_issues)}")
|
|
else:
|
|
logger.info("Email configuration OK")
|
|
|
|
# Check storage configs
|
|
storage_issues = validate_storage_configs()
|
|
for provider, issues in storage_issues.items():
|
|
if issues:
|
|
logger.warning(f"{provider.capitalize()} configuration issues: {', '.join(issues)}")
|
|
else:
|
|
logger.info(f"{provider.capitalize()} configuration OK")
|
|
|
|
# Return all identified issues
|
|
return {
|
|
'email': email_issues,
|
|
'storage': storage_issues
|
|
}
|