mirror of
https://github.com/langgenius/dify.git
synced 2026-09-24 23:22:26 +08:00
fix(plugin): preserve credentials during local replacement (#39764)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
autofix-ci[bot]
parent
81fd1da3ff
commit
72c20daa61
@@ -597,19 +597,28 @@ class TestPluginInstallFromPkgApi:
|
||||
|
||||
|
||||
class TestPluginUninstallApi:
|
||||
def test_uninstall(self, app: Flask):
|
||||
@pytest.mark.parametrize("preserve_credentials", [False, True])
|
||||
def test_uninstall(self, app: Flask, preserve_credentials: bool):
|
||||
api = PluginUninstallApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
payload = {"plugin_installation_id": "x"}
|
||||
payload = {
|
||||
"plugin_installation_id": "x",
|
||||
"preserve_credentials": preserve_credentials,
|
||||
}
|
||||
|
||||
with (
|
||||
app.test_request_context("/", json=payload),
|
||||
patch("controllers.console.workspace.plugin.PluginService.uninstall", return_value=True),
|
||||
patch("controllers.console.workspace.plugin.PluginService.uninstall", return_value=True) as uninstall_mock,
|
||||
):
|
||||
result = method(api, "t1")
|
||||
|
||||
assert result["success"] is True
|
||||
uninstall_mock.assert_called_once_with(
|
||||
"t1",
|
||||
"x",
|
||||
preserve_credentials=preserve_credentials,
|
||||
)
|
||||
|
||||
|
||||
class TestPluginChangePermissionApi:
|
||||
|
||||
@@ -12,6 +12,7 @@ from sqlalchemy.orm import Session
|
||||
from core.helper.model_provider_cache import ProviderCredentialsCacheType
|
||||
from core.plugin.entities.plugin import PluginCategory, PluginInstallationSource
|
||||
from core.plugin.entities.plugin_daemon import PluginInstallTask, PluginInstallTaskStatus, PluginModelProviderEntity
|
||||
from core.provider_manager import ProviderConfigurationCacheSource
|
||||
from graphon.model_runtime.entities.common_entities import I18nObject
|
||||
from graphon.model_runtime.entities.provider_entities import ConfigurateMethod, ProviderEntity
|
||||
from models.provider import Provider, ProviderCredential, ProviderType, TenantPreferredModelProvider
|
||||
@@ -1224,6 +1225,7 @@ class TestPluginModelProviderCacheInvalidation:
|
||||
patch(f"{MODULE}.PluginInstaller") as installer_cls,
|
||||
patch(f"{MODULE}.ProviderCredentialsCache") as credentials_cache,
|
||||
patch(f"{MODULE}.PluginService.invalidate_plugin_model_providers_cache") as invalidate_cache,
|
||||
patch("core.provider_manager.ProviderManager.invalidate_configurations_cache") as invalidate_configurations,
|
||||
):
|
||||
mock_config.ENTERPRISE_ENABLED = False
|
||||
installer = installer_cls.return_value
|
||||
@@ -1237,6 +1239,13 @@ class TestPluginModelProviderCacheInvalidation:
|
||||
assert result is True
|
||||
installer.uninstall.assert_called_once_with(TENANT_ID, "installation-1")
|
||||
invalidate_cache.assert_called_once_with(TENANT_ID)
|
||||
invalidate_configurations.assert_called_once_with(
|
||||
TENANT_ID,
|
||||
sources=(
|
||||
ProviderConfigurationCacheSource.PREFERRED_MODEL_PROVIDERS,
|
||||
ProviderConfigurationCacheSource.PROVIDER_CREDENTIALS,
|
||||
),
|
||||
)
|
||||
credentials_cache.assert_called_once_with(
|
||||
tenant_id=TENANT_ID,
|
||||
identity_id=provider_id,
|
||||
|
||||
@@ -452,3 +452,78 @@ class TestUninstall:
|
||||
)
|
||||
).all()
|
||||
assert len(remaining_prefs) == 0
|
||||
|
||||
@patch("core.plugin.plugin_service.PluginInstaller")
|
||||
def test_preserves_credentials_when_replacing_plugin(
|
||||
self, mock_installer_cls: MagicMock, plugin_db: Session
|
||||
) -> None:
|
||||
tenant_id = str(uuid4())
|
||||
plugin_id = "org/myplugin"
|
||||
provider_name = f"{plugin_id}/model-provider"
|
||||
|
||||
credential = ProviderCredential(
|
||||
tenant_id=tenant_id,
|
||||
provider_name=provider_name,
|
||||
credential_name="default",
|
||||
encrypted_config="{}",
|
||||
)
|
||||
plugin_db.add(credential)
|
||||
plugin_db.flush()
|
||||
|
||||
provider = Provider(
|
||||
tenant_id=tenant_id,
|
||||
provider_name=provider_name,
|
||||
credential_id=credential.id,
|
||||
)
|
||||
plugin_db.add(provider)
|
||||
|
||||
preferred_provider = TenantPreferredModelProvider(
|
||||
tenant_id=tenant_id,
|
||||
provider_name=provider_name,
|
||||
preferred_provider_type=ProviderType.CUSTOM,
|
||||
)
|
||||
plugin_db.add(preferred_provider)
|
||||
plugin_db.commit()
|
||||
|
||||
plugin = MagicMock(installation_id="install-1", plugin_id=plugin_id)
|
||||
installer = mock_installer_cls.return_value
|
||||
installer.list_plugins.return_value = [plugin]
|
||||
installer.uninstall.return_value = True
|
||||
|
||||
with patch("core.plugin.plugin_service.dify_config") as mock_config:
|
||||
mock_config.ENTERPRISE_ENABLED = False
|
||||
result = PluginService.uninstall(tenant_id, "install-1", preserve_credentials=True)
|
||||
|
||||
assert result is True
|
||||
plugin_db.expire_all()
|
||||
assert plugin_db.get(ProviderCredential, credential.id) is not None
|
||||
assert plugin_db.get(Provider, provider.id).credential_id == credential.id
|
||||
assert plugin_db.get(TenantPreferredModelProvider, preferred_provider.id) is not None
|
||||
|
||||
@patch("core.plugin.plugin_service.PluginInstaller")
|
||||
def test_preserves_credentials_when_daemon_uninstall_fails(
|
||||
self, mock_installer_cls: MagicMock, plugin_db: Session
|
||||
) -> None:
|
||||
tenant_id = str(uuid4())
|
||||
plugin_id = "org/myplugin"
|
||||
credential = ProviderCredential(
|
||||
tenant_id=tenant_id,
|
||||
provider_name=f"{plugin_id}/model-provider",
|
||||
credential_name="default",
|
||||
encrypted_config="{}",
|
||||
)
|
||||
plugin_db.add(credential)
|
||||
plugin_db.commit()
|
||||
|
||||
plugin = MagicMock(installation_id="install-1", plugin_id=plugin_id)
|
||||
installer = mock_installer_cls.return_value
|
||||
installer.list_plugins.return_value = [plugin]
|
||||
installer.uninstall.return_value = False
|
||||
|
||||
with patch("core.plugin.plugin_service.dify_config") as mock_config:
|
||||
mock_config.ENTERPRISE_ENABLED = False
|
||||
result = PluginService.uninstall(tenant_id, "install-1")
|
||||
|
||||
assert result is False
|
||||
plugin_db.expire_all()
|
||||
assert plugin_db.get(ProviderCredential, credential.id) is not None
|
||||
|
||||
Reference in New Issue
Block a user