mirror of
https://github.com/langgenius/dify.git
synced 2026-02-09 15:10:13 -05:00
feat: Service API - add end-user lookup endpoint (#32015)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -5,8 +5,6 @@ from enum import StrEnum
|
||||
from flask_restx import Namespace
|
||||
from pydantic import BaseModel, TypeAdapter
|
||||
|
||||
from controllers.console import console_ns
|
||||
|
||||
DEFAULT_REF_TEMPLATE_SWAGGER_2_0 = "#/definitions/{model}"
|
||||
|
||||
|
||||
@@ -24,6 +22,9 @@ def register_schema_models(namespace: Namespace, *models: type[BaseModel]) -> No
|
||||
|
||||
|
||||
def get_or_create_model(model_name: str, field_def):
|
||||
# Import lazily to avoid circular imports between console controllers and schema helpers.
|
||||
from controllers.console import console_ns
|
||||
|
||||
existing = console_ns.models.get(model_name)
|
||||
if existing is None:
|
||||
existing = console_ns.model(model_name, field_def)
|
||||
|
||||
@@ -34,6 +34,7 @@ from .dataset import (
|
||||
metadata,
|
||||
segment,
|
||||
)
|
||||
from .end_user import end_user
|
||||
from .workspace import models
|
||||
|
||||
__all__ = [
|
||||
@@ -44,6 +45,7 @@ __all__ = [
|
||||
"conversation",
|
||||
"dataset",
|
||||
"document",
|
||||
"end_user",
|
||||
"file",
|
||||
"file_preview",
|
||||
"hit_testing",
|
||||
|
||||
3
api/controllers/service_api/end_user/__init__.py
Normal file
3
api/controllers/service_api/end_user/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from . import end_user
|
||||
|
||||
__all__ = ["end_user"]
|
||||
41
api/controllers/service_api/end_user/end_user.py
Normal file
41
api/controllers/service_api/end_user/end_user.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from uuid import UUID
|
||||
|
||||
from flask_restx import Resource
|
||||
|
||||
from controllers.service_api import service_api_ns
|
||||
from controllers.service_api.end_user.error import EndUserNotFoundError
|
||||
from controllers.service_api.wraps import validate_app_token
|
||||
from fields.end_user_fields import EndUserDetail
|
||||
from models.model import App
|
||||
from services.end_user_service import EndUserService
|
||||
|
||||
|
||||
@service_api_ns.route("/end-users/<uuid:end_user_id>")
|
||||
class EndUserApi(Resource):
|
||||
"""Resource for retrieving end user details by ID."""
|
||||
|
||||
@service_api_ns.doc("get_end_user")
|
||||
@service_api_ns.doc(description="Get an end user by ID")
|
||||
@service_api_ns.doc(
|
||||
params={"end_user_id": "End user ID"},
|
||||
responses={
|
||||
200: "End user retrieved successfully",
|
||||
401: "Unauthorized - invalid API token",
|
||||
404: "End user not found",
|
||||
},
|
||||
)
|
||||
@validate_app_token
|
||||
def get(self, app_model: App, end_user_id: UUID):
|
||||
"""Get end user detail.
|
||||
|
||||
This endpoint is scoped to the current app token's tenant/app to prevent
|
||||
cross-tenant/app access when an end-user ID is known.
|
||||
"""
|
||||
|
||||
end_user = EndUserService.get_end_user_by_id(
|
||||
tenant_id=app_model.tenant_id, app_id=app_model.id, end_user_id=str(end_user_id)
|
||||
)
|
||||
if end_user is None:
|
||||
raise EndUserNotFoundError()
|
||||
|
||||
return EndUserDetail.model_validate(end_user).model_dump(mode="json")
|
||||
7
api/controllers/service_api/end_user/error.py
Normal file
7
api/controllers/service_api/end_user/error.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from libs.exception import BaseHTTPException
|
||||
|
||||
|
||||
class EndUserNotFoundError(BaseHTTPException):
|
||||
error_code = "end_user_not_found"
|
||||
description = "End user not found."
|
||||
code = 404
|
||||
@@ -1,7 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from flask_restx import fields
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
simple_end_user_fields = {
|
||||
"id": fields.String,
|
||||
@@ -10,6 +12,19 @@ simple_end_user_fields = {
|
||||
"session_id": fields.String,
|
||||
}
|
||||
|
||||
end_user_detail_fields = {
|
||||
"id": fields.String,
|
||||
"tenant_id": fields.String,
|
||||
"app_id": fields.String,
|
||||
"type": fields.String,
|
||||
"external_user_id": fields.String,
|
||||
"name": fields.String,
|
||||
"is_anonymous": fields.Boolean,
|
||||
"session_id": fields.String,
|
||||
"created_at": fields.DateTime,
|
||||
"updated_at": fields.DateTime,
|
||||
}
|
||||
|
||||
|
||||
class ResponseModel(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
@@ -26,3 +41,23 @@ class SimpleEndUser(ResponseModel):
|
||||
type: str
|
||||
is_anonymous: bool
|
||||
session_id: str | None = None
|
||||
|
||||
|
||||
class EndUserDetail(ResponseModel):
|
||||
"""Full EndUser record for API responses.
|
||||
|
||||
Note: The SQLAlchemy model defines an `is_anonymous` property for Flask-Login semantics
|
||||
(always False). The database column is exposed as `_is_anonymous`, so this DTO maps
|
||||
`is_anonymous` from `_is_anonymous` to return the stored value.
|
||||
"""
|
||||
|
||||
id: str
|
||||
tenant_id: str
|
||||
app_id: str | None = None
|
||||
type: str
|
||||
external_user_id: str | None = None
|
||||
name: str | None = None
|
||||
is_anonymous: bool = Field(validation_alias="_is_anonymous")
|
||||
session_id: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
@@ -16,6 +16,25 @@ class EndUserService:
|
||||
Service for managing end users.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_end_user_by_id(cls, *, tenant_id: str, app_id: str, end_user_id: str) -> EndUser | None:
|
||||
"""Get an end user by primary key.
|
||||
|
||||
This is scoped to the provided tenant and app to prevent cross-tenant/app access
|
||||
when an end-user ID is known.
|
||||
"""
|
||||
|
||||
with Session(db.engine, expire_on_commit=False) as session:
|
||||
return (
|
||||
session.query(EndUser)
|
||||
.where(
|
||||
EndUser.id == end_user_id,
|
||||
EndUser.tenant_id == tenant_id,
|
||||
EndUser.app_id == app_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_or_create_end_user(cls, app_model: App, user_id: str | None = None) -> EndUser:
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
from datetime import UTC, datetime
|
||||
from unittest.mock import Mock
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from controllers.service_api.end_user.end_user import EndUserApi
|
||||
from controllers.service_api.end_user.error import EndUserNotFoundError
|
||||
from models.model import App, EndUser
|
||||
|
||||
|
||||
class TestEndUserApi:
|
||||
@pytest.fixture
|
||||
def resource(self) -> EndUserApi:
|
||||
return EndUserApi()
|
||||
|
||||
@pytest.fixture
|
||||
def app_model(self) -> App:
|
||||
app = Mock(spec=App)
|
||||
app.id = str(uuid4())
|
||||
app.tenant_id = str(uuid4())
|
||||
return app
|
||||
|
||||
def test_get_end_user_returns_all_attributes(self, mocker, resource: EndUserApi, app_model: App) -> None:
|
||||
end_user = Mock(spec=EndUser)
|
||||
end_user.id = str(uuid4())
|
||||
end_user.tenant_id = app_model.tenant_id
|
||||
end_user.app_id = app_model.id
|
||||
end_user.type = "service_api"
|
||||
end_user.external_user_id = "external-123"
|
||||
end_user.name = "Alice"
|
||||
end_user._is_anonymous = True
|
||||
end_user.session_id = "session-xyz"
|
||||
end_user.created_at = datetime(2024, 1, 1, tzinfo=UTC)
|
||||
end_user.updated_at = datetime(2024, 1, 2, tzinfo=UTC)
|
||||
|
||||
get_end_user_by_id = mocker.patch(
|
||||
"controllers.service_api.end_user.end_user.EndUserService.get_end_user_by_id", return_value=end_user
|
||||
)
|
||||
|
||||
result = EndUserApi.get.__wrapped__(resource, app_model=app_model, end_user_id=UUID(end_user.id))
|
||||
|
||||
get_end_user_by_id.assert_called_once_with(
|
||||
tenant_id=app_model.tenant_id, app_id=app_model.id, end_user_id=end_user.id
|
||||
)
|
||||
assert result["id"] == end_user.id
|
||||
assert result["tenant_id"] == end_user.tenant_id
|
||||
assert result["app_id"] == end_user.app_id
|
||||
assert result["type"] == end_user.type
|
||||
assert result["external_user_id"] == end_user.external_user_id
|
||||
assert result["name"] == end_user.name
|
||||
assert result["is_anonymous"] is True
|
||||
assert result["session_id"] == end_user.session_id
|
||||
assert result["created_at"].startswith("2024-01-01T00:00:00")
|
||||
assert result["updated_at"].startswith("2024-01-02T00:00:00")
|
||||
|
||||
def test_get_end_user_not_found(self, mocker, resource: EndUserApi, app_model: App) -> None:
|
||||
mocker.patch("controllers.service_api.end_user.end_user.EndUserService.get_end_user_by_id", return_value=None)
|
||||
|
||||
with pytest.raises(EndUserNotFoundError):
|
||||
EndUserApi.get.__wrapped__(resource, app_model=app_model, end_user_id=uuid4())
|
||||
@@ -492,3 +492,45 @@ class TestEndUserServiceGetOrCreateEndUserByType:
|
||||
# Assert
|
||||
added_user = mock_session.add.call_args[0][0]
|
||||
assert added_user.type == invoke_type
|
||||
|
||||
|
||||
class TestEndUserServiceGetEndUserById:
|
||||
"""Unit tests for EndUserService.get_end_user_by_id."""
|
||||
|
||||
@patch("services.end_user_service.Session")
|
||||
@patch("services.end_user_service.db")
|
||||
def test_get_end_user_by_id_returns_end_user(self, mock_db, mock_session_class):
|
||||
tenant_id = "tenant-123"
|
||||
app_id = "app-456"
|
||||
end_user_id = "end-user-789"
|
||||
existing_user = MagicMock(spec=EndUser)
|
||||
|
||||
mock_session = MagicMock()
|
||||
mock_session_class.return_value.__enter__.return_value = mock_session
|
||||
|
||||
mock_query = MagicMock()
|
||||
mock_session.query.return_value = mock_query
|
||||
mock_query.where.return_value = mock_query
|
||||
mock_query.first.return_value = existing_user
|
||||
|
||||
result = EndUserService.get_end_user_by_id(tenant_id=tenant_id, app_id=app_id, end_user_id=end_user_id)
|
||||
|
||||
assert result == existing_user
|
||||
mock_session.query.assert_called_once_with(EndUser)
|
||||
mock_query.where.assert_called_once()
|
||||
assert len(mock_query.where.call_args[0]) == 3
|
||||
|
||||
@patch("services.end_user_service.Session")
|
||||
@patch("services.end_user_service.db")
|
||||
def test_get_end_user_by_id_returns_none(self, mock_db, mock_session_class):
|
||||
mock_session = MagicMock()
|
||||
mock_session_class.return_value.__enter__.return_value = mock_session
|
||||
|
||||
mock_query = MagicMock()
|
||||
mock_session.query.return_value = mock_query
|
||||
mock_query.where.return_value = mock_query
|
||||
mock_query.first.return_value = None
|
||||
|
||||
result = EndUserService.get_end_user_by_id(tenant_id="tenant", app_id="app", end_user_id="end-user")
|
||||
|
||||
assert result is None
|
||||
|
||||
@@ -273,6 +273,71 @@ The text generation application offers non-session support and is ideal for tran
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='Get End User'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Retrieve an end user by ID.
|
||||
|
||||
This is useful when other APIs return an end-user ID (e.g. `created_by` from File Upload).
|
||||
|
||||
### Path Parameters
|
||||
- `end_user_id` (uuid) Required
|
||||
End user ID.
|
||||
|
||||
### Response
|
||||
Returns an EndUser object.
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) Tenant ID
|
||||
- `app_id` (uuid) App ID
|
||||
- `type` (string) End user type
|
||||
- `external_user_id` (string) External user ID
|
||||
- `name` (string) Name
|
||||
- `is_anonymous` (boolean) Whether anonymous
|
||||
- `session_id` (string) Session ID
|
||||
- `created_at` (string) ISO 8601 datetime
|
||||
- `updated_at` (string) ISO 8601 datetime
|
||||
|
||||
### Errors
|
||||
- 404, `end_user_not_found`, end user not found
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### Response Example
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -272,6 +272,71 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='エンドユーザーを取得'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
エンドユーザー ID からエンドユーザー情報を取得します。
|
||||
|
||||
他の API がエンドユーザー ID(例:ファイルアップロードの `created_by`)を返す場合に利用できます。
|
||||
|
||||
### パスパラメータ
|
||||
- `end_user_id` (uuid) 必須
|
||||
エンドユーザー ID。
|
||||
|
||||
### レスポンス
|
||||
EndUser オブジェクトを返します。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) テナント ID
|
||||
- `app_id` (uuid) アプリ ID
|
||||
- `type` (string) エンドユーザー種別
|
||||
- `external_user_id` (string) 外部ユーザー ID
|
||||
- `name` (string) 名前
|
||||
- `is_anonymous` (boolean) 匿名ユーザーかどうか
|
||||
- `session_id` (string) セッション ID
|
||||
- `created_at` (string) ISO 8601 日時
|
||||
- `updated_at` (string) ISO 8601 日時
|
||||
|
||||
### エラー
|
||||
- 404, `end_user_not_found`, エンドユーザーが見つかりません
|
||||
- 500, 内部サーバーエラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### レスポンス例
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -249,6 +249,69 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='获取终端用户'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
通过终端用户 ID 获取终端用户信息。
|
||||
|
||||
当其他 API 返回终端用户 ID(例如:上传文件接口返回的 `created_by`)时,可使用该接口查询对应的终端用户信息。
|
||||
|
||||
### 路径参数
|
||||
- `end_user_id` (uuid) 必需
|
||||
终端用户 ID。
|
||||
|
||||
### Response
|
||||
返回 EndUser 对象。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) 工作空间(Tenant)ID
|
||||
- `app_id` (uuid) 应用 ID
|
||||
- `type` (string) 终端用户类型
|
||||
- `external_user_id` (string) 外部用户 ID
|
||||
- `name` (string) 名称
|
||||
- `is_anonymous` (boolean) 是否匿名
|
||||
- `session_id` (string) 会话 ID
|
||||
- `created_at` (string) ISO 8601 时间
|
||||
- `updated_at` (string) ISO 8601 时间
|
||||
|
||||
### Errors
|
||||
- 404,`end_user_not_found`,终端用户不存在
|
||||
- 500,内部服务器错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -392,6 +392,71 @@ Chat applications support session persistence, allowing previous chat history to
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='Get End User'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Retrieve an end user by ID.
|
||||
|
||||
This is useful when other APIs return an end-user ID (e.g. `created_by` from File Upload).
|
||||
|
||||
### Path Parameters
|
||||
- `end_user_id` (uuid) Required
|
||||
End user ID.
|
||||
|
||||
### Response
|
||||
Returns an EndUser object.
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) Tenant ID
|
||||
- `app_id` (uuid) App ID
|
||||
- `type` (string) End user type
|
||||
- `external_user_id` (string) External user ID
|
||||
- `name` (string) Name
|
||||
- `is_anonymous` (boolean) Whether anonymous
|
||||
- `session_id` (string) Session ID
|
||||
- `created_at` (string) ISO 8601 datetime
|
||||
- `updated_at` (string) ISO 8601 datetime
|
||||
|
||||
### Errors
|
||||
- 404, `end_user_not_found`, end user not found
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### Response Example
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -393,6 +393,71 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='エンドユーザーを取得'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
エンドユーザー ID からエンドユーザー情報を取得します。
|
||||
|
||||
他の API がエンドユーザー ID(例:ファイルアップロードの `created_by`)を返す場合に利用できます。
|
||||
|
||||
### パスパラメータ
|
||||
- `end_user_id` (uuid) 必須
|
||||
エンドユーザー ID。
|
||||
|
||||
### レスポンス
|
||||
EndUser オブジェクトを返します。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) テナント ID
|
||||
- `app_id` (uuid) アプリ ID
|
||||
- `type` (string) エンドユーザー種別
|
||||
- `external_user_id` (string) 外部ユーザー ID
|
||||
- `name` (string) 名前
|
||||
- `is_anonymous` (boolean) 匿名ユーザーかどうか
|
||||
- `session_id` (string) セッション ID
|
||||
- `created_at` (string) ISO 8601 日時
|
||||
- `updated_at` (string) ISO 8601 日時
|
||||
|
||||
### エラー
|
||||
- 404, `end_user_not_found`, エンドユーザーが見つかりません
|
||||
- 500, 内部サーバーエラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### レスポンス例
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -390,6 +390,69 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='获取终端用户'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
通过终端用户 ID 获取终端用户信息。
|
||||
|
||||
当其他 API 返回终端用户 ID(例如:上传文件接口返回的 `created_by`)时,可使用该接口查询对应的终端用户信息。
|
||||
|
||||
### 路径参数
|
||||
- `end_user_id` (uuid) 必需
|
||||
终端用户 ID。
|
||||
|
||||
### Response
|
||||
返回 EndUser 对象。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) 工作空间(Tenant)ID
|
||||
- `app_id` (uuid) 应用 ID
|
||||
- `type` (string) 终端用户类型
|
||||
- `external_user_id` (string) 外部用户 ID
|
||||
- `name` (string) 名称
|
||||
- `is_anonymous` (boolean) 是否匿名
|
||||
- `session_id` (string) 会话 ID
|
||||
- `created_at` (string) ISO 8601 时间
|
||||
- `updated_at` (string) ISO 8601 时间
|
||||
|
||||
### Errors
|
||||
- 404,`end_user_not_found`,终端用户不存在
|
||||
- 500,内部服务器错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -362,6 +362,71 @@ Chat applications support session persistence, allowing previous chat history to
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='Get End User'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Retrieve an end user by ID.
|
||||
|
||||
This is useful when other APIs return an end-user ID (e.g. `created_by` from File Upload).
|
||||
|
||||
### Path Parameters
|
||||
- `end_user_id` (uuid) Required
|
||||
End user ID.
|
||||
|
||||
### Response
|
||||
Returns an EndUser object.
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) Tenant ID
|
||||
- `app_id` (uuid) App ID
|
||||
- `type` (string) End user type
|
||||
- `external_user_id` (string) External user ID
|
||||
- `name` (string) Name
|
||||
- `is_anonymous` (boolean) Whether anonymous
|
||||
- `session_id` (string) Session ID
|
||||
- `created_at` (string) ISO 8601 datetime
|
||||
- `updated_at` (string) ISO 8601 datetime
|
||||
|
||||
### Errors
|
||||
- 404, `end_user_not_found`, end user not found
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### Response Example
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -362,6 +362,71 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='エンドユーザーを取得'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
エンドユーザー ID からエンドユーザー情報を取得します。
|
||||
|
||||
他の API がエンドユーザー ID(例:ファイルアップロードの `created_by`)を返す場合に利用できます。
|
||||
|
||||
### パスパラメータ
|
||||
- `end_user_id` (uuid) 必須
|
||||
エンドユーザー ID。
|
||||
|
||||
### レスポンス
|
||||
EndUser オブジェクトを返します。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) テナント ID
|
||||
- `app_id` (uuid) アプリ ID
|
||||
- `type` (string) エンドユーザー種別
|
||||
- `external_user_id` (string) 外部ユーザー ID
|
||||
- `name` (string) 名前
|
||||
- `is_anonymous` (boolean) 匿名ユーザーかどうか
|
||||
- `session_id` (string) セッション ID
|
||||
- `created_at` (string) ISO 8601 日時
|
||||
- `updated_at` (string) ISO 8601 日時
|
||||
|
||||
### エラー
|
||||
- 404, `end_user_not_found`, エンドユーザーが見つかりません
|
||||
- 500, 内部サーバーエラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### レスポンス例
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -368,6 +368,69 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='获取终端用户'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
通过终端用户 ID 获取终端用户信息。
|
||||
|
||||
当其他 API 返回终端用户 ID(例如:上传文件接口返回的 `created_by`)时,可使用该接口查询对应的终端用户信息。
|
||||
|
||||
### 路径参数
|
||||
- `end_user_id` (uuid) 必需
|
||||
终端用户 ID。
|
||||
|
||||
### Response
|
||||
返回 EndUser 对象。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) 工作空间(Tenant)ID
|
||||
- `app_id` (uuid) 应用 ID
|
||||
- `type` (string) 终端用户类型
|
||||
- `external_user_id` (string) 外部用户 ID
|
||||
- `name` (string) 名称
|
||||
- `is_anonymous` (boolean) 是否匿名
|
||||
- `session_id` (string) 会话 ID
|
||||
- `created_at` (string) ISO 8601 时间
|
||||
- `updated_at` (string) ISO 8601 时间
|
||||
|
||||
### Errors
|
||||
- 404,`end_user_not_found`,终端用户不存在
|
||||
- 500,内部服务器错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
|
||||
@@ -740,6 +740,71 @@ Workflow applications offers non-session support and is ideal for translation, a
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='Get End User'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Retrieve an end user by ID.
|
||||
|
||||
This is useful when other APIs return an end-user ID (e.g. `created_by` from File Upload).
|
||||
|
||||
### Path Parameters
|
||||
- `end_user_id` (uuid) Required
|
||||
End user ID.
|
||||
|
||||
### Response
|
||||
Returns an EndUser object.
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) Tenant ID
|
||||
- `app_id` (uuid) App ID
|
||||
- `type` (string) End user type
|
||||
- `external_user_id` (string) External user ID
|
||||
- `name` (string) Name
|
||||
- `is_anonymous` (boolean) Whether anonymous
|
||||
- `session_id` (string) Session ID
|
||||
- `created_at` (string) ISO 8601 datetime
|
||||
- `updated_at` (string) ISO 8601 datetime
|
||||
|
||||
### Errors
|
||||
- 404, `end_user_not_found`, end user not found
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### Response Example
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/workflows/logs'
|
||||
method='GET'
|
||||
|
||||
@@ -736,6 +736,71 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='エンドユーザーを取得'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
エンドユーザー ID からエンドユーザー情報を取得します。
|
||||
|
||||
他の API がエンドユーザー ID(例:ファイルアップロードの `created_by`)を返す場合に利用できます。
|
||||
|
||||
### パスパラメータ
|
||||
- `end_user_id` (uuid) 必須
|
||||
エンドユーザー ID。
|
||||
|
||||
### レスポンス
|
||||
EndUser オブジェクトを返します。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) テナント ID
|
||||
- `app_id` (uuid) アプリ ID
|
||||
- `type` (string) エンドユーザー種別
|
||||
- `external_user_id` (string) 外部ユーザー ID
|
||||
- `name` (string) 名前
|
||||
- `is_anonymous` (boolean) 匿名ユーザーかどうか
|
||||
- `session_id` (string) セッション ID
|
||||
- `created_at` (string) ISO 8601 日時
|
||||
- `updated_at` (string) ISO 8601 日時
|
||||
|
||||
### エラー
|
||||
- 404, `end_user_not_found`, エンドユーザーが見つかりません
|
||||
- 500, 内部サーバーエラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
### レスポンス例
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/workflows/logs'
|
||||
method='GET'
|
||||
@@ -1047,4 +1112,3 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Col>
|
||||
</Row>
|
||||
___
|
||||
|
||||
|
||||
@@ -727,6 +727,69 @@ Workflow 应用无会话支持,适合用于翻译/文章写作/总结 AI 等
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/end-users/:end_user_id'
|
||||
method='GET'
|
||||
title='获取终端用户'
|
||||
name='#end-user'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
通过终端用户 ID 获取终端用户信息。
|
||||
|
||||
当其他 API 返回终端用户 ID(例如:上传文件接口返回的 `created_by`)时,可使用该接口查询对应的终端用户信息。
|
||||
|
||||
### 路径参数
|
||||
- `end_user_id` (uuid) 必需
|
||||
终端用户 ID。
|
||||
|
||||
### Response
|
||||
返回 EndUser 对象。
|
||||
- `id` (uuid) ID
|
||||
- `tenant_id` (uuid) 工作空间(Tenant)ID
|
||||
- `app_id` (uuid) 应用 ID
|
||||
- `type` (string) 终端用户类型
|
||||
- `external_user_id` (string) 外部用户 ID
|
||||
- `name` (string) 名称
|
||||
- `is_anonymous` (boolean) 是否匿名
|
||||
- `session_id` (string) 会话 ID
|
||||
- `created_at` (string) ISO 8601 时间
|
||||
- `updated_at` (string) ISO 8601 时间
|
||||
|
||||
### Errors
|
||||
- 404,`end_user_not_found`,终端用户不存在
|
||||
- 500,内部服务器错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
<CodeGroup
|
||||
title="Request"
|
||||
tag="GET"
|
||||
label="/end-users/:end_user_id"
|
||||
targetCode={`curl -X GET '${props.appDetail.api_base_url}/end-users/6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13' \\
|
||||
--header 'Authorization: Bearer {api_key}'`}
|
||||
/>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "6ad1ab0a-73ff-4ac1-b9e4-cdb312f71f13",
|
||||
"tenant_id": "8c0f3f3a-66b0-4b55-a0bf-8b8e0d6aee7d",
|
||||
"app_id": "6c8c3f41-2c6f-4e1b-8f4f-7f11c8f2ad2a",
|
||||
"type": "service_api",
|
||||
"external_user_id": "abc-123",
|
||||
"name": "Alice",
|
||||
"is_anonymous": false,
|
||||
"session_id": "abc-123",
|
||||
"created_at": "2024-01-01T00:00:00Z",
|
||||
"updated_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/workflows/logs'
|
||||
method='GET'
|
||||
|
||||
Reference in New Issue
Block a user