diff --git a/app/frontend.py b/app/frontend.py index b38befc1..35954cb7 100644 --- a/app/frontend.py +++ b/app/frontend.py @@ -70,6 +70,7 @@ async def status_dashboard(request: Request): { "request": request, "providers": providers, + "app_version": settings.version, # Add app version to the context "debug_enabled": getattr(settings, 'debug', False), "last_check": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } diff --git a/app/utils/config_validator.py b/app/utils/config_validator.py index 6bc87ea3..767a96aa 100644 --- a/app/utils/config_validator.py +++ b/app/utils/config_validator.py @@ -137,125 +137,223 @@ def validate_storage_configs(): return issues +def mask_sensitive_value(value): + """Helper function to mask sensitive values consistently""" + if not value: + return "Not set" + + if isinstance(value, str): + if len(value) > 10: + visible_start = max(1, len(value) // 3) + visible_end = max(1, len(value) // 4) + return f"{value[:visible_start]}{'*' * (len(value) - visible_start - visible_end)}{value[-visible_end:]}" + else: + return f"{value[:2]}{'*' * (len(value) - 4)}{value[-2:]}" if len(value) > 4 else "****" + elif not isinstance(value, (bool, int, float)): + return "**Configured Value**" + return str(value) + def get_provider_status(): """Returns status information for all configured providers""" providers = {} - # Check Dropbox configuration + # Add Dropbox configuration - alphabetically ordered providers providers["Dropbox"] = { "name": "Dropbox", + "icon": "dropbox", "configured": bool(getattr(settings, 'dropbox_app_key', None) and getattr(settings, 'dropbox_app_secret', None) and getattr(settings, 'dropbox_refresh_token', None)), "enabled": True, + "description": "Upload files to Dropbox cloud storage", "details": { "folder": getattr(settings, 'dropbox_folder', 'Not set'), "app_key": getattr(settings, 'dropbox_app_key', 'Not set'), - "app_secret": getattr(settings, 'dropbox_app_secret', None) and "Configured" or "Not set", - "refresh_token": getattr(settings, 'dropbox_refresh_token', None) and "Configured" or "Not set" + "app_secret": mask_sensitive_value(getattr(settings, 'dropbox_app_secret', None)), + "refresh_token": mask_sensitive_value(getattr(settings, 'dropbox_refresh_token', None)) } } - # Check Paperless configuration - providers["Paperless-ngx"] = { - "name": "Paperless-ngx", - "configured": bool(getattr(settings, 'paperless_host', None) and - getattr(settings, 'paperless_ngx_api_token', None)), + # Add Email configuration + providers["Email"] = { + "name": "Email", + "icon": "mail", + "configured": bool(getattr(settings, 'email_host', None) and + getattr(settings, 'email_default_recipient', None)), "enabled": True, + "description": "Send documents via email", "details": { - "host": getattr(settings, 'paperless_host', 'Not set') + "host": getattr(settings, 'email_host', 'Not set'), + "port": getattr(settings, 'email_port', 'Not set'), + "username": getattr(settings, 'email_username', 'Not set'), + "password": mask_sensitive_value(getattr(settings, 'email_password', None)), + "use_tls": getattr(settings, 'email_use_tls', 'Not set'), + "sender": getattr(settings, 'email_sender', 'Not set'), + "default_recipient": getattr(settings, 'email_default_recipient', 'Not set') } } - # Check NextCloud configuration - providers["NextCloud"] = { - "name": "NextCloud", - "configured": bool(getattr(settings, 'nextcloud_upload_url', None) and - getattr(settings, 'nextcloud_username', None) and - getattr(settings, 'nextcloud_password', None)), + # Add FTP configuration to providers + providers["FTP Storage"] = { + "name": "FTP Storage", + "icon": "ftp", + "configured": bool(getattr(settings, 'ftp_host', None) and + getattr(settings, 'ftp_username', None) and + getattr(settings, 'ftp_password', None)), "enabled": True, + "description": "Upload files to FTP server", "details": { - "url": getattr(settings, 'nextcloud_upload_url', 'Not set'), - "folder": getattr(settings, 'nextcloud_folder', 'Not set') - } - } - - # Check SFTP configuration - providers["SFTP Storage"] = { - "name": "SFTP Storage", - "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))), - "enabled": True, - "details": { - "host": getattr(settings, 'sftp_host', 'Not set'), - "folder": getattr(settings, 'sftp_folder', 'Not set') - } - } - - # Check S3 configuration - providers["S3 Storage"] = { - "name": "S3 Storage", - "configured": bool(getattr(settings, 's3_bucket_name', None) and - getattr(settings, 'aws_access_key_id', None) and - getattr(settings, 'aws_secret_access_key', None)), - "enabled": True, - "details": { - "bucket": getattr(settings, 's3_bucket_name', 'Not set'), - "region": getattr(settings, 'aws_region', 'Not set') + "host": getattr(settings, 'ftp_host', 'Not set'), + "port": getattr(settings, 'ftp_port', 'Not set'), + "username": getattr(settings, 'ftp_username', 'Not set'), + "password": mask_sensitive_value(getattr(settings, 'ftp_password', None)), + "folder": getattr(settings, 'ftp_folder', 'Not set'), + "tls": getattr(settings, 'ftp_use_tls', True), + "allow_plaintext": getattr(settings, 'ftp_allow_plaintext', True) } } # Check Google Drive configuration providers["Google Drive"] = { "name": "Google Drive", + "icon": "google", "configured": bool(getattr(settings, 'google_drive_credentials_json', None) and getattr(settings, 'google_drive_folder_id', None)), "enabled": True, + "description": "Store documents in Google Drive", "details": { + "credentials_json": mask_sensitive_value(getattr(settings, 'google_drive_credentials_json', None)), "folder_id": getattr(settings, 'google_drive_folder_id', 'Not set'), "delegate": getattr(settings, 'google_drive_delegate_to', 'Not set') } } + # Check NextCloud configuration + nextcloud_url = getattr(settings, 'nextcloud_upload_url', 'Not set') + # Extract base URL from WebDAV URL (remove the /remote.php part and everything after it) + if nextcloud_url != 'Not set' and '/remote.php' in nextcloud_url: + nextcloud_base_url = nextcloud_url.split('/remote.php')[0] + else: + nextcloud_base_url = nextcloud_url + + providers["NextCloud"] = { + "name": "NextCloud", + "icon": "cloud", + "configured": bool(getattr(settings, 'nextcloud_upload_url', None) and + getattr(settings, 'nextcloud_username', None) and + getattr(settings, 'nextcloud_password', None)), + "enabled": True, + "description": "Store documents in NextCloud", + "details": { + "url": getattr(settings, 'nextcloud_upload_url', 'Not set'), + "base_url": nextcloud_base_url, + "username": getattr(settings, 'nextcloud_username', 'Not set'), + "password": mask_sensitive_value(getattr(settings, 'nextcloud_password', None)), + "folder": getattr(settings, 'nextcloud_folder', 'Not set') + } + } + # Check OneDrive configuration providers["OneDrive"] = { "name": "OneDrive", + "icon": "microsoft", "configured": bool(getattr(settings, 'onedrive_client_id', None) and getattr(settings, 'onedrive_client_secret', None) and getattr(settings, 'onedrive_refresh_token', None)), "enabled": True, + "description": "Store documents in Microsoft OneDrive", "details": { + "client_id": getattr(settings, 'onedrive_client_id', 'Not set'), + "client_secret": mask_sensitive_value(getattr(settings, 'onedrive_client_secret', None)), + "tenant_id": getattr(settings, 'onedrive_tenant_id', 'Not set'), + "refresh_token": mask_sensitive_value(getattr(settings, 'onedrive_refresh_token', None)), "folder": getattr(settings, 'onedrive_folder_path', 'Not set') } } + + # Check Paperless configuration + providers["Paperless-ngx"] = { + "name": "Paperless-ngx", + "icon": "file-text", + "configured": bool(getattr(settings, 'paperless_host', None) and + getattr(settings, 'paperless_ngx_api_token', None)), + "enabled": True, + "description": "Document management system for digital archives", + "details": { + "host": getattr(settings, 'paperless_host', 'Not set'), + "api_token": mask_sensitive_value(getattr(settings, 'paperless_ngx_api_token', None)) + } + } + + # Check S3 configuration + providers["S3 Storage"] = { + "name": "S3 Storage", + "icon": "database", + "configured": bool(getattr(settings, 's3_bucket_name', None) and + getattr(settings, 'aws_access_key_id', None) and + getattr(settings, 'aws_secret_access_key', None)), + "enabled": True, + "description": "Store documents in S3-compatible object storage", + "details": { + "bucket": getattr(settings, 's3_bucket_name', 'Not set'), + "region": getattr(settings, 'aws_region', 'Not set'), + "access_key_id": getattr(settings, 'aws_access_key_id', 'Not set'), + "secret_access_key": mask_sensitive_value(getattr(settings, 'aws_secret_access_key', None)), + "folder_prefix": getattr(settings, 's3_folder_prefix', 'Not set'), + "storage_class": getattr(settings, 's3_storage_class', 'Not set'), + "acl": getattr(settings, 's3_acl', 'Not set') + } + } + + # Check SFTP configuration + providers["SFTP Storage"] = { + "name": "SFTP Storage", + "icon": "server", + "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))), + "enabled": True, + "description": "Upload files to SFTP server", + "details": { + "host": getattr(settings, 'sftp_host', 'Not set'), + "port": getattr(settings, 'sftp_port', 'Not set'), + "username": getattr(settings, 'sftp_username', 'Not set'), + "password": mask_sensitive_value(getattr(settings, 'sftp_password', None)), + "private_key": getattr(settings, 'sftp_private_key', 'Not set'), + "private_key_passphrase": mask_sensitive_value(getattr(settings, 'sftp_private_key_passphrase', None)), + "folder": getattr(settings, 'sftp_folder', 'Not set') + } + } + + # Add Uptime Kuma configuration + providers["Uptime Kuma"] = { + "name": "Uptime Kuma", + "icon": "activity", + "configured": bool(getattr(settings, 'uptime_kuma_url', None)), + "enabled": True, + "description": "Server monitoring and status page", + "details": { + "url": getattr(settings, 'uptime_kuma_url', 'Not set'), + "ping_interval": getattr(settings, 'uptime_kuma_ping_interval', 'Not set') + } + } # Check WebDAV configuration providers["WebDAV"] = { "name": "WebDAV", + "icon": "globe", "configured": bool(getattr(settings, 'webdav_url', None) and getattr(settings, 'webdav_username', None) and getattr(settings, 'webdav_password', None)), "enabled": True, + "description": "Store documents on WebDAV servers", "details": { "url": getattr(settings, 'webdav_url', 'Not set'), - "folder": getattr(settings, 'webdav_folder', 'Not set') - } - } - - # Add FTP configuration to providers - providers["FTP Storage"] = { - "name": "FTP Storage", - "configured": bool(getattr(settings, 'ftp_host', None) and - getattr(settings, 'ftp_username', None) and - getattr(settings, 'ftp_password', None)), - "enabled": True, - "details": { - "host": getattr(settings, 'ftp_host', 'Not set'), - "folder": getattr(settings, 'ftp_folder', 'Not set'), - "tls": getattr(settings, 'ftp_use_tls', True), - "allow_plaintext": getattr(settings, 'ftp_allow_plaintext', True) + "username": getattr(settings, 'webdav_username', 'Not set'), + "password": mask_sensitive_value(getattr(settings, 'webdav_password', None)), + "folder": getattr(settings, 'webdav_folder', 'Not set'), + "verify_ssl": getattr(settings, 'webdav_verify_ssl', 'Not set') } } @@ -270,7 +368,12 @@ def dump_all_settings(): # Mask sensitive values in logs if key.lower().find('password') >= 0 or key.lower().find('secret') >= 0 or key.lower().find('token') >= 0 or key.lower().find('key') >= 0: if value: - value = "********" + if isinstance(value, str) and len(value) > 10: + visible_start = max(1, len(value) // 3) + visible_end = max(1, len(value) // 4) + value = f"{value[:visible_start]}{'*' * (len(value) - visible_start - visible_end)}{value[-visible_end:]}" + else: + value = f"{value[:2]}{'*' * (len(value) - 4)}{value[-2:]}" if isinstance(value, str) and len(value) > 4 else "****" logger.info(f"{key}: {value}") logger.info("--- END OF SETTINGS DUMP ---") @@ -439,17 +542,26 @@ def get_settings_for_display(show_values=False): # List of patterns that indicate sensitive values sensitive_patterns = [ 'password', 'secret', 'token', 'api_key', 'private_key', - 'credentials', 'access_key', 'auth' + 'credentials', 'access_key', 'ai_key' ] # Check if this is a sensitive value that should be masked - is_sensitive = any(pattern in key.lower() for pattern in sensitive_patterns) + is_sensitive = any( + pattern in key.lower() for pattern in sensitive_patterns + ) + + # Special handling for "auth" to avoid matching prefixes like "authentik" + if not is_sensitive and "auth" in key.lower(): + # Only mark as sensitive if "auth" is a standalone word or at the end + # This avoids matching "authentik" as sensitive + parts = key.lower().split('_') + is_sensitive = any(part == "auth" for part in parts) or key.lower().endswith("auth") # Mask sensitive values regardless of debug mode # Other values are only hidden if debug mode is off AND show_values is False if (is_sensitive or not show_values) and value: if is_sensitive: - value = "********" + value = mask_sensitive_value(value) # Check if the setting is configured (has a non-None value) # For boolean settings, consider them configured even if False diff --git a/frontend/templates/base.html b/frontend/templates/base.html index 0bfa04f0..9122034c 100644 --- a/frontend/templates/base.html +++ b/frontend/templates/base.html @@ -36,35 +36,6 @@ Upload Files Status - - -
Use "common" for personal accounts or your organization's Tenant ID for corporate accounts
+Enter the folder path where files should be uploaded (e.g., Documents/Uploads)
+