82d67c56b3
Add iCloud Drive as a new storage destination using the pyicloud library. Includes upload task, configuration, user integration handler, provider status, onboarding support, and comprehensive tests. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
392 lines
17 KiB
Python
392 lines
17 KiB
Python
"""
|
||
Module for handling provider status information
|
||
"""
|
||
|
||
from app.config import settings
|
||
from app.utils.config_validator.masking import mask_sensitive_value
|
||
|
||
|
||
def get_provider_status() -> dict[str, dict[str, object]]:
|
||
"""
|
||
Returns status information for all configured providers
|
||
"""
|
||
providers = {}
|
||
|
||
# Add Authentication configuration
|
||
auth_enabled = getattr(settings, "auth_enabled", False)
|
||
using_oidc = bool(
|
||
getattr(settings, "authentik_client_id", None)
|
||
and getattr(settings, "authentik_client_secret", None)
|
||
and getattr(settings, "authentik_config_url", None)
|
||
)
|
||
|
||
auth_method = "OIDC" if using_oidc else "Basic Auth" if auth_enabled else "None"
|
||
|
||
providers["Authentication"] = {
|
||
"name": "Authentication",
|
||
"icon": "fa-solid fa-lock",
|
||
"configured": bool(auth_enabled and (getattr(settings, "admin_username", None) or using_oidc)),
|
||
"enabled": auth_enabled,
|
||
"description": "Access control and user authentication",
|
||
"details": {
|
||
"method": auth_method,
|
||
"provider_name": getattr(settings, "oauth_provider_name", "Not set") if using_oidc else "N/A",
|
||
"session_security": "Configured" if getattr(settings, "session_secret", None) else "Not configured",
|
||
},
|
||
}
|
||
|
||
# Add Notification configuration - Make sure this provider is near the top of the list
|
||
providers["Notifications"] = {
|
||
"name": "Notifications",
|
||
"icon": "fa-solid fa-bell",
|
||
"configured": bool(getattr(settings, "notification_urls", None)),
|
||
"enabled": True,
|
||
"description": "Send system notifications via various services",
|
||
"details": {
|
||
"services": (
|
||
str(len(getattr(settings, "notification_urls", []))) + " service(s) configured"
|
||
if getattr(settings, "notification_urls", None)
|
||
else "Not configured"
|
||
),
|
||
"task_failure": getattr(settings, "notify_on_task_failure", True),
|
||
"credential_failure": getattr(settings, "notify_on_credential_failure", True),
|
||
"startup": getattr(settings, "notify_on_startup", True),
|
||
"shutdown": getattr(settings, "notify_on_shutdown", False),
|
||
},
|
||
"testable": True,
|
||
"test_endpoint": "/api/diagnostic/test-notification",
|
||
}
|
||
|
||
# Add AI provider (dynamic – reflects whichever provider is configured)
|
||
ai_provider_name = getattr(settings, "ai_provider", "openai").lower()
|
||
model = getattr(settings, "ai_model", None) or getattr(settings, "openai_model", "gpt-4o-mini")
|
||
|
||
# Determine whether the active provider has its required credentials set
|
||
def _ai_configured() -> bool:
|
||
if ai_provider_name in ("openai", "azure", "litellm"):
|
||
return bool(getattr(settings, "openai_api_key", None))
|
||
elif ai_provider_name == "anthropic":
|
||
return bool(getattr(settings, "anthropic_api_key", None))
|
||
elif ai_provider_name == "gemini":
|
||
return bool(getattr(settings, "gemini_api_key", None))
|
||
elif ai_provider_name == "ollama":
|
||
return bool(getattr(settings, "ollama_base_url", None))
|
||
elif ai_provider_name == "openrouter":
|
||
return bool(getattr(settings, "openrouter_api_key", None))
|
||
elif ai_provider_name == "portkey":
|
||
return bool(getattr(settings, "portkey_api_key", None))
|
||
return False
|
||
|
||
# Build provider-specific detail rows
|
||
def _ai_details() -> dict:
|
||
base = {"provider": ai_provider_name, "model": model}
|
||
if ai_provider_name in ("openai", "azure", "litellm"):
|
||
base["api_key"] = mask_sensitive_value(getattr(settings, "openai_api_key", None))
|
||
base["base_url"] = getattr(settings, "openai_base_url", "https://api.openai.com/v1")
|
||
elif ai_provider_name == "anthropic":
|
||
base["api_key"] = mask_sensitive_value(getattr(settings, "anthropic_api_key", None))
|
||
elif ai_provider_name == "gemini":
|
||
base["api_key"] = mask_sensitive_value(getattr(settings, "gemini_api_key", None))
|
||
elif ai_provider_name == "ollama":
|
||
base["base_url"] = getattr(settings, "ollama_base_url", "http://localhost:11434")
|
||
elif ai_provider_name == "openrouter":
|
||
base["api_key"] = mask_sensitive_value(getattr(settings, "openrouter_api_key", None))
|
||
base["base_url"] = getattr(settings, "openrouter_base_url", "https://openrouter.ai/api/v1")
|
||
elif ai_provider_name == "portkey":
|
||
base["api_key"] = mask_sensitive_value(getattr(settings, "portkey_api_key", None))
|
||
if getattr(settings, "portkey_virtual_key", None):
|
||
base["virtual_key"] = mask_sensitive_value(settings.portkey_virtual_key)
|
||
if getattr(settings, "portkey_config", None):
|
||
base["config"] = settings.portkey_config
|
||
return base
|
||
|
||
_PROVIDER_ICONS = {
|
||
"openai": "fa-brands fa-openai",
|
||
"azure": "fa-brands fa-microsoft",
|
||
"anthropic": "fa-solid fa-robot",
|
||
"gemini": "fa-brands fa-google",
|
||
"ollama": "fa-solid fa-server",
|
||
"openrouter": "fa-solid fa-route",
|
||
"portkey": "fa-solid fa-key",
|
||
"litellm": "fa-solid fa-layer-group",
|
||
}
|
||
|
||
providers["AI Provider"] = {
|
||
"name": "AI Provider",
|
||
"icon": _PROVIDER_ICONS.get(ai_provider_name, "fa-solid fa-microchip"),
|
||
"configured": _ai_configured(),
|
||
"enabled": True,
|
||
"description": f"AI-powered metadata extraction and OCR refinement ({ai_provider_name})",
|
||
"details": _ai_details(),
|
||
"testable": True,
|
||
"test_endpoint": "/api/ai/test",
|
||
}
|
||
|
||
providers["Azure AI"] = {
|
||
"name": "Azure AI",
|
||
"icon": "fa-solid fa-robot",
|
||
"configured": bool(getattr(settings, "azure_ai_key", None) and getattr(settings, "azure_endpoint", None)),
|
||
"enabled": True,
|
||
"description": "Microsoft Azure Document Intelligence",
|
||
"details": {
|
||
"api_key": mask_sensitive_value(getattr(settings, "azure_ai_key", None)),
|
||
"endpoint": getattr(settings, "azure_endpoint", "Not set"),
|
||
"region": getattr(settings, "azure_region", "Not set"),
|
||
},
|
||
}
|
||
|
||
# Add Dropbox configuration - alphabetically ordered providers
|
||
providers["Dropbox"] = {
|
||
"name": "Dropbox",
|
||
"icon": "fa-brands fa-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": mask_sensitive_value(getattr(settings, "dropbox_app_secret", None)),
|
||
"refresh_token": mask_sensitive_value(getattr(settings, "dropbox_refresh_token", None)),
|
||
},
|
||
}
|
||
|
||
# Add Email destination configuration (dedicated settings for document delivery)
|
||
providers["Email"] = {
|
||
"name": "Email",
|
||
"icon": "fa-solid fa-envelope",
|
||
"configured": bool(
|
||
getattr(settings, "dest_email_host", None) and getattr(settings, "dest_email_default_recipient", None)
|
||
),
|
||
"enabled": True,
|
||
"description": "Send documents via email",
|
||
"details": {
|
||
"host": getattr(settings, "dest_email_host", "Not set"),
|
||
"port": getattr(settings, "dest_email_port", "Not set"),
|
||
"username": getattr(settings, "dest_email_username", "Not set"),
|
||
"password": mask_sensitive_value(getattr(settings, "dest_email_password", None)),
|
||
"use_tls": getattr(settings, "dest_email_use_tls", "Not set"),
|
||
"sender": getattr(settings, "dest_email_sender", "Not set"),
|
||
"default_recipient": getattr(settings, "dest_email_default_recipient", "Not set"),
|
||
},
|
||
}
|
||
|
||
# Add FTP configuration to providers
|
||
providers["FTP Storage"] = {
|
||
"name": "FTP Storage",
|
||
"icon": "fa-solid fa-server",
|
||
"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": {
|
||
"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
|
||
gdrive_oauth_configured = bool(
|
||
getattr(settings, "google_drive_client_id", None)
|
||
and getattr(settings, "google_drive_client_secret", None)
|
||
and getattr(settings, "google_drive_refresh_token", None)
|
||
)
|
||
|
||
gdrive_sa_configured = bool(getattr(settings, "google_drive_credentials_json", None))
|
||
|
||
# Determine if using OAuth or service account
|
||
use_oauth = getattr(settings, "google_drive_use_oauth", False)
|
||
|
||
is_configured = (use_oauth and gdrive_oauth_configured) or (not use_oauth and gdrive_sa_configured)
|
||
|
||
providers["Google Drive"] = {
|
||
"name": "Google Drive",
|
||
"icon": "fa-brands fa-google-drive",
|
||
"configured": is_configured and bool(getattr(settings, "google_drive_folder_id", None)),
|
||
"enabled": True,
|
||
"description": "Store documents in Google Drive",
|
||
"details": {
|
||
"auth_type": "OAuth" if use_oauth else "Service Account",
|
||
"client_id": getattr(settings, "google_drive_client_id", "Not set") if use_oauth else "N/A",
|
||
"client_secret": (
|
||
mask_sensitive_value(getattr(settings, "google_drive_client_secret", None)) if use_oauth else "N/A"
|
||
),
|
||
"refresh_token": (
|
||
mask_sensitive_value(getattr(settings, "google_drive_refresh_token", None)) if use_oauth else "N/A"
|
||
),
|
||
"credentials_json": (
|
||
mask_sensitive_value(getattr(settings, "google_drive_credentials_json", None))
|
||
if not use_oauth
|
||
else "N/A"
|
||
),
|
||
"folder_id": getattr(settings, "google_drive_folder_id", "Not set"),
|
||
"delegate": getattr(settings, "google_drive_delegate_to", "Not set") if not use_oauth else "N/A",
|
||
},
|
||
}
|
||
|
||
# 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)
|
||
nextcloud_base_url = nextcloud_url
|
||
if nextcloud_url != "Not set" and nextcloud_url is not None and "/remote.php" in nextcloud_url:
|
||
nextcloud_base_url = nextcloud_url.split("/remote.php")[0]
|
||
|
||
providers["NextCloud"] = {
|
||
"name": "NextCloud",
|
||
"icon": "fa-solid fa-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": "fa-brands fa-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": "fa-solid fa-file-lines",
|
||
"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": "fa-brands fa-aws",
|
||
"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": "fa-solid fa-lock",
|
||
"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": "fa-solid fa-heart-pulse",
|
||
"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": "fa-solid fa-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"),
|
||
"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"),
|
||
},
|
||
}
|
||
|
||
# Check iCloud Drive configuration
|
||
providers["iCloud Drive"] = {
|
||
"name": "iCloud Drive",
|
||
"icon": "fa-brands fa-apple",
|
||
"configured": bool(getattr(settings, "icloud_username", None) and getattr(settings, "icloud_password", None)),
|
||
"enabled": True,
|
||
"description": "Store documents in Apple iCloud Drive",
|
||
"details": {
|
||
"username": getattr(settings, "icloud_username", "Not set"),
|
||
"password": mask_sensitive_value(getattr(settings, "icloud_password", None)),
|
||
"folder": getattr(settings, "icloud_folder", "Not set"),
|
||
"cookie_directory": getattr(settings, "icloud_cookie_directory", "Not set"),
|
||
},
|
||
}
|
||
|
||
return providers
|