mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 02:43:49 +08:00
fix(api): resolve plugin external user ids in backwards invocation (#38098)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com> Co-authored-by: Harsh Kashyap <harshkashyap@Harshs-MacBook-Pro.local>
This commit is contained in:
parent
5aae5c15b3
commit
78ca1a8a76
@ -78,7 +78,11 @@ class PluginAppBackwardsInvocation(BaseBackwardsInvocation):
|
|||||||
if not user_id:
|
if not user_id:
|
||||||
user = EndUserService.get_or_create_end_user(app)
|
user = EndUserService.get_or_create_end_user(app)
|
||||||
else:
|
else:
|
||||||
user = cls._get_user(user_id, app)
|
try:
|
||||||
|
user = cls._get_user(user_id, app)
|
||||||
|
except ValueError:
|
||||||
|
# Plugins such as WeCom Bot pass external sender IDs rather than EndUser UUIDs.
|
||||||
|
user = EndUserService.get_or_create_end_user(app, user_id=user_id)
|
||||||
|
|
||||||
conversation_id = conversation_id or ""
|
conversation_id = conversation_id or ""
|
||||||
|
|
||||||
@ -232,6 +236,13 @@ class PluginAppBackwardsInvocation(BaseBackwardsInvocation):
|
|||||||
EndUser.app_id == app.id,
|
EndUser.app_id == app.id,
|
||||||
)
|
)
|
||||||
user = session.scalar(stmt)
|
user = session.scalar(stmt)
|
||||||
|
if not user:
|
||||||
|
stmt = select(EndUser).where(
|
||||||
|
EndUser.session_id == user_id,
|
||||||
|
EndUser.tenant_id == app.tenant_id,
|
||||||
|
EndUser.app_id == app.id,
|
||||||
|
)
|
||||||
|
user = session.scalar(stmt)
|
||||||
if not user:
|
if not user:
|
||||||
stmt = select(Account).where(
|
stmt = select(Account).where(
|
||||||
Account.id == user_id,
|
Account.id == user_id,
|
||||||
|
|||||||
@ -355,14 +355,32 @@ class TestPluginAppBackwardsInvocation:
|
|||||||
assert "end_users.app_id" in compiled
|
assert "end_users.app_id" in compiled
|
||||||
assert stmt.compile().params == {"id_1": "uid", "tenant_id_1": "tenant-1", "app_id_1": "app-1"}
|
assert stmt.compile().params == {"id_1": "uid", "tenant_id_1": "tenant-1", "app_id_1": "app-1"}
|
||||||
|
|
||||||
|
def test_get_user_returns_end_user_by_session_id(self, mocker: MockerFixture):
|
||||||
|
session = self.patch_create_session(mocker, side_effect=[None, MagicMock(id="session-user")])
|
||||||
|
app = SimpleNamespace(id="app-1", tenant_id="tenant-1")
|
||||||
|
|
||||||
|
user = PluginAppBackwardsInvocation._get_user("wecom-sender-1", app)
|
||||||
|
|
||||||
|
assert user.id == "session-user"
|
||||||
|
stmt = session.scalar.call_args_list[1].args[0]
|
||||||
|
compiled = str(stmt.compile(dialect=postgresql.dialect()))
|
||||||
|
assert "end_users.session_id" in compiled
|
||||||
|
assert "end_users.tenant_id" in compiled
|
||||||
|
assert "end_users.app_id" in compiled
|
||||||
|
assert stmt.compile().params == {
|
||||||
|
"session_id_1": "wecom-sender-1",
|
||||||
|
"tenant_id_1": "tenant-1",
|
||||||
|
"app_id_1": "app-1",
|
||||||
|
}
|
||||||
|
|
||||||
def test_get_user_falls_back_to_account_user(self, mocker: MockerFixture):
|
def test_get_user_falls_back_to_account_user(self, mocker: MockerFixture):
|
||||||
session = self.patch_create_session(mocker, side_effect=[None, MagicMock(id="account-user")])
|
session = self.patch_create_session(mocker, side_effect=[None, None, MagicMock(id="account-user")])
|
||||||
app = SimpleNamespace(id="app-1", tenant_id="tenant-1")
|
app = SimpleNamespace(id="app-1", tenant_id="tenant-1")
|
||||||
|
|
||||||
user = PluginAppBackwardsInvocation._get_user("uid", app)
|
user = PluginAppBackwardsInvocation._get_user("uid", app)
|
||||||
|
|
||||||
assert user.id == "account-user"
|
assert user.id == "account-user"
|
||||||
stmt = session.scalar.call_args_list[1].args[0]
|
stmt = session.scalar.call_args_list[2].args[0]
|
||||||
compiled = str(stmt.compile(dialect=postgresql.dialect()))
|
compiled = str(stmt.compile(dialect=postgresql.dialect()))
|
||||||
assert "accounts.id" in compiled
|
assert "accounts.id" in compiled
|
||||||
assert "tenant_account_joins.account_id" in compiled
|
assert "tenant_account_joins.account_id" in compiled
|
||||||
@ -370,12 +388,41 @@ class TestPluginAppBackwardsInvocation:
|
|||||||
assert stmt.compile().params == {"id_1": "uid", "tenant_id_1": "tenant-1"}
|
assert stmt.compile().params == {"id_1": "uid", "tenant_id_1": "tenant-1"}
|
||||||
|
|
||||||
def test_get_user_raises_when_user_not_found(self, mocker: MockerFixture):
|
def test_get_user_raises_when_user_not_found(self, mocker: MockerFixture):
|
||||||
self.patch_create_session(mocker, side_effect=[None, None])
|
self.patch_create_session(mocker, side_effect=[None, None, None])
|
||||||
app = SimpleNamespace(id="app-1", tenant_id="tenant-1")
|
app = SimpleNamespace(id="app-1", tenant_id="tenant-1")
|
||||||
|
|
||||||
with pytest.raises(ValueError, match="user not found"):
|
with pytest.raises(ValueError, match="user not found"):
|
||||||
PluginAppBackwardsInvocation._get_user("uid", app)
|
PluginAppBackwardsInvocation._get_user("uid", app)
|
||||||
|
|
||||||
|
def test_invoke_app_creates_end_user_for_unknown_external_user_id(self, mocker: MockerFixture):
|
||||||
|
app = MagicMock(mode=AppMode.WORKFLOW)
|
||||||
|
end_user = MagicMock()
|
||||||
|
workflow = MagicMock()
|
||||||
|
mocker.patch.object(PluginAppBackwardsInvocation, "_get_app", return_value=app)
|
||||||
|
mocker.patch.object(PluginAppBackwardsInvocation, "_get_workflow", return_value=workflow)
|
||||||
|
mocker.patch.object(PluginAppBackwardsInvocation, "_get_user", side_effect=ValueError("user not found"))
|
||||||
|
get_or_create = mocker.patch(
|
||||||
|
"core.plugin.backwards_invocation.app.EndUserService.get_or_create_end_user",
|
||||||
|
return_value=end_user,
|
||||||
|
)
|
||||||
|
route = mocker.patch.object(PluginAppBackwardsInvocation, "invoke_workflow_app", return_value={"ok": True})
|
||||||
|
|
||||||
|
result = PluginAppBackwardsInvocation.invoke_app(
|
||||||
|
MagicMock(),
|
||||||
|
app_id="app",
|
||||||
|
user_id="wecom-sender-1",
|
||||||
|
tenant_id="tenant",
|
||||||
|
conversation_id="",
|
||||||
|
query=None,
|
||||||
|
stream=True,
|
||||||
|
inputs={},
|
||||||
|
files=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result == {"ok": True}
|
||||||
|
get_or_create.assert_called_once_with(app, user_id="wecom-sender-1")
|
||||||
|
assert route.call_args.args[2] is end_user
|
||||||
|
|
||||||
def test_get_app_returns_app(self, mocker: MockerFixture):
|
def test_get_app_returns_app(self, mocker: MockerFixture):
|
||||||
app_obj = MagicMock(id="app")
|
app_obj = MagicMock(id="app")
|
||||||
self.patch_create_session(mocker, return_value=app_obj)
|
self.patch_create_session(mocker, return_value=app_obj)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user