mirror of
https://github.com/langgenius/dify.git
synced 2026-03-13 03:07:09 +00:00
Compare commits
3 Commits
fix/enterp
...
release/e-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f12505386 | ||
|
|
5c018184e7 | ||
|
|
b4227b195e |
@@ -19,6 +19,10 @@ class EnterpriseFeatureConfig(BaseSettings):
|
||||
default=False,
|
||||
)
|
||||
|
||||
ENTERPRISE_REQUEST_TIMEOUT: int = Field(
|
||||
ge=1, description="Maximum timeout in seconds for enterprise requests", default=5
|
||||
)
|
||||
|
||||
|
||||
class EnterpriseTelemetryConfig(BaseSettings):
|
||||
"""
|
||||
|
||||
@@ -60,7 +60,6 @@ def get_trace_task_to_case() -> dict:
|
||||
"""Return TraceTaskName → TelemetryCase (inverse of _get_case_to_trace_task)."""
|
||||
return {v: k for k, v in _get_case_to_trace_task().items()}
|
||||
|
||||
|
||||
def _get_case_routing() -> dict:
|
||||
global _case_routing
|
||||
if _case_routing is None:
|
||||
@@ -91,7 +90,6 @@ def _get_case_routing() -> dict:
|
||||
CASE_TO_TRACE_TASK = _get_case_to_trace_task()
|
||||
CASE_ROUTING = _get_case_routing()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -3,6 +3,7 @@ import logging
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from configs import dify_config
|
||||
from services.enterprise.base import EnterprisePluginManagerRequest
|
||||
from services.errors.base import BaseServiceError
|
||||
|
||||
@@ -69,6 +70,7 @@ class PluginManagerService:
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json=body.model_dump(),
|
||||
timeout=dify_config.ENTERPRISE_REQUEST_TIMEOUT,
|
||||
)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
|
||||
@@ -30,6 +30,7 @@ from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.provider import ProviderCredential
|
||||
from models.provider_ids import GenericProviderID
|
||||
from services.enterprise.plugin_manager_service import PluginManagerService, PreUninstallPluginRequest
|
||||
from services.errors.plugin import PluginInstallationForbiddenError
|
||||
from services.feature_service import FeatureService, PluginInstallationScope
|
||||
|
||||
@@ -518,6 +519,13 @@ class PluginService:
|
||||
if plugin:
|
||||
plugin_id = plugin.plugin_id
|
||||
logger.info("Deleting credentials for plugin: %s", plugin_id)
|
||||
if dify_config.ENTERPRISE_ENABLED:
|
||||
PluginManagerService.try_pre_uninstall_plugin(
|
||||
PreUninstallPluginRequest(
|
||||
tenant_id=tenant_id,
|
||||
plugin_unique_identifier=plugin.plugin_unique_identifier,
|
||||
)
|
||||
)
|
||||
|
||||
# Delete provider credentials that match this plugin
|
||||
credentials = db.session.scalars(
|
||||
|
||||
@@ -14,73 +14,82 @@ from services.enterprise.plugin_manager_service import (
|
||||
PreUninstallPluginRequest,
|
||||
)
|
||||
|
||||
_FAKE_TIMEOUT = 30
|
||||
|
||||
|
||||
_SEND_REQUEST_PATH = (
|
||||
"services.enterprise.plugin_manager_service.EnterprisePluginManagerRequest.send_request"
|
||||
)
|
||||
_DIFY_CONFIG_PATH = "services.enterprise.plugin_manager_service.dify_config"
|
||||
_LOGGER_PATH = "services.enterprise.plugin_manager_service.logger"
|
||||
|
||||
|
||||
class TestTryPreUninstallPlugin:
|
||||
def test_try_pre_uninstall_plugin_success(self):
|
||||
@patch(_DIFY_CONFIG_PATH)
|
||||
@patch(_SEND_REQUEST_PATH)
|
||||
def test_try_pre_uninstall_plugin_success(self, mock_send_request, mock_config):
|
||||
body = PreUninstallPluginRequest(
|
||||
tenant_id="tenant-123",
|
||||
plugin_unique_identifier="com.example.my_plugin",
|
||||
)
|
||||
mock_config.ENTERPRISE_REQUEST_TIMEOUT = _FAKE_TIMEOUT
|
||||
mock_send_request.return_value = {}
|
||||
|
||||
with patch(
|
||||
"services.enterprise.plugin_manager_service.EnterprisePluginManagerRequest.send_request"
|
||||
) as mock_send_request:
|
||||
mock_send_request.return_value = {}
|
||||
PluginManagerService.try_pre_uninstall_plugin(body)
|
||||
|
||||
PluginManagerService.try_pre_uninstall_plugin(body)
|
||||
mock_send_request.assert_called_once_with(
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json={"tenant_id": "tenant-123", "plugin_unique_identifier": "com.example.my_plugin"},
|
||||
timeout=_FAKE_TIMEOUT,
|
||||
)
|
||||
|
||||
mock_send_request.assert_called_once_with(
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json={"tenant_id": "tenant-123", "plugin_unique_identifier": "com.example.my_plugin"},
|
||||
)
|
||||
|
||||
def test_try_pre_uninstall_plugin_http_error_soft_fails(self):
|
||||
@patch(_DIFY_CONFIG_PATH)
|
||||
@patch(_LOGGER_PATH)
|
||||
@patch(_SEND_REQUEST_PATH)
|
||||
def test_try_pre_uninstall_plugin_http_error_soft_fails(
|
||||
self, mock_send_request, mock_logger, mock_config
|
||||
):
|
||||
body = PreUninstallPluginRequest(
|
||||
tenant_id="tenant-456",
|
||||
plugin_unique_identifier="com.example.other_plugin",
|
||||
)
|
||||
mock_config.ENTERPRISE_REQUEST_TIMEOUT = _FAKE_TIMEOUT
|
||||
mock_send_request.side_effect = HTTPStatusError(
|
||||
"502 Bad Gateway",
|
||||
request=None,
|
||||
response=None,
|
||||
)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"services.enterprise.plugin_manager_service.EnterprisePluginManagerRequest.send_request"
|
||||
) as mock_send_request,
|
||||
patch("services.enterprise.plugin_manager_service.logger") as mock_logger,
|
||||
):
|
||||
mock_send_request.side_effect = HTTPStatusError(
|
||||
"502 Bad Gateway",
|
||||
request=None,
|
||||
response=None,
|
||||
)
|
||||
PluginManagerService.try_pre_uninstall_plugin(body)
|
||||
|
||||
PluginManagerService.try_pre_uninstall_plugin(body)
|
||||
mock_send_request.assert_called_once_with(
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json={"tenant_id": "tenant-456", "plugin_unique_identifier": "com.example.other_plugin"},
|
||||
timeout=_FAKE_TIMEOUT,
|
||||
)
|
||||
mock_logger.exception.assert_called_once()
|
||||
|
||||
mock_send_request.assert_called_once_with(
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json={"tenant_id": "tenant-456", "plugin_unique_identifier": "com.example.other_plugin"},
|
||||
)
|
||||
mock_logger.exception.assert_called_once()
|
||||
|
||||
def test_try_pre_uninstall_plugin_generic_exception_soft_fails(self):
|
||||
@patch(_DIFY_CONFIG_PATH)
|
||||
@patch(_LOGGER_PATH)
|
||||
@patch(_SEND_REQUEST_PATH)
|
||||
def test_try_pre_uninstall_plugin_generic_exception_soft_fails(
|
||||
self, mock_send_request, mock_logger, mock_config
|
||||
):
|
||||
body = PreUninstallPluginRequest(
|
||||
tenant_id="tenant-789",
|
||||
plugin_unique_identifier="com.example.failing_plugin",
|
||||
)
|
||||
mock_config.ENTERPRISE_REQUEST_TIMEOUT = _FAKE_TIMEOUT
|
||||
mock_send_request.side_effect = ConnectionError("network unreachable")
|
||||
|
||||
with (
|
||||
patch(
|
||||
"services.enterprise.plugin_manager_service.EnterprisePluginManagerRequest.send_request"
|
||||
) as mock_send_request,
|
||||
patch("services.enterprise.plugin_manager_service.logger") as mock_logger,
|
||||
):
|
||||
mock_send_request.side_effect = ConnectionError("network unreachable")
|
||||
PluginManagerService.try_pre_uninstall_plugin(body)
|
||||
|
||||
PluginManagerService.try_pre_uninstall_plugin(body)
|
||||
|
||||
mock_send_request.assert_called_once_with(
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json={"tenant_id": "tenant-789", "plugin_unique_identifier": "com.example.failing_plugin"},
|
||||
)
|
||||
mock_logger.exception.assert_called_once()
|
||||
mock_send_request.assert_called_once_with(
|
||||
"POST",
|
||||
"/pre-uninstall-plugin",
|
||||
json={"tenant_id": "tenant-789", "plugin_unique_identifier": "com.example.failing_plugin"},
|
||||
timeout=_FAKE_TIMEOUT,
|
||||
)
|
||||
mock_logger.exception.assert_called_once()
|
||||
|
||||
Reference in New Issue
Block a user