refactor(api): migrate console.datasets.metadata to BaseModel (#36450)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
chariri
2026-05-21 15:04:42 +00:00
committed by GitHub
co-authored by autofix-ci[bot]
parent c50d504c44
commit 092c8bca81
18 changed files with 461 additions and 425 deletions
+39 -15
View File
@@ -1,14 +1,18 @@
from typing import Literal
from flask_restx import Resource, marshal_with
from flask_restx import Resource
from werkzeug.exceptions import NotFound
from controllers.common.controller_schemas import MetadataUpdatePayload
from controllers.common.fields import SimpleResultResponse
from controllers.common.schema import register_response_schema_models, register_schema_models
from controllers.console import console_ns
from controllers.console.wraps import account_initialization_required, enterprise_license_required, setup_required
from fields.dataset_fields import dataset_metadata_fields
from fields.dataset_fields import (
DatasetMetadataBuiltInFieldsResponse,
DatasetMetadataListResponse,
DatasetMetadataResponse,
)
from libs.helper import dump_response
from libs.login import current_account_with_tenant, login_required
from services.dataset_service import DatasetService
from services.entities.knowledge_entities.knowledge_entities import (
@@ -22,7 +26,12 @@ from services.metadata_service import MetadataService
register_schema_models(
console_ns, MetadataArgs, MetadataOperationData, MetadataUpdatePayload, DocumentMetadataOperation, MetadataDetail
)
register_response_schema_models(console_ns, SimpleResultResponse)
register_response_schema_models(
console_ns,
DatasetMetadataBuiltInFieldsResponse,
DatasetMetadataListResponse,
DatasetMetadataResponse,
)
@console_ns.route("/datasets/<uuid:dataset_id>/metadata")
@@ -31,7 +40,7 @@ class DatasetMetadataCreateApi(Resource):
@login_required
@account_initialization_required
@enterprise_license_required
@marshal_with(dataset_metadata_fields)
@console_ns.response(201, "Metadata created successfully", console_ns.models[DatasetMetadataResponse.__name__])
@console_ns.expect(console_ns.models[MetadataArgs.__name__])
def post(self, dataset_id):
current_user, _ = current_account_with_tenant()
@@ -44,18 +53,22 @@ class DatasetMetadataCreateApi(Resource):
DatasetService.check_dataset_permission(dataset, current_user)
metadata = MetadataService.create_metadata(dataset_id_str, metadata_args)
return metadata, 201
return dump_response(DatasetMetadataResponse, metadata), 201
@setup_required
@login_required
@account_initialization_required
@enterprise_license_required
@console_ns.response(
200, "Metadata retrieved successfully", console_ns.models[DatasetMetadataListResponse.__name__]
)
def get(self, dataset_id):
dataset_id_str = str(dataset_id)
dataset = DatasetService.get_dataset(dataset_id_str)
if dataset is None:
raise NotFound("Dataset not found.")
return MetadataService.get_dataset_metadatas(dataset), 200
metadata = MetadataService.get_dataset_metadatas(dataset)
return dump_response(DatasetMetadataListResponse, metadata), 200
@console_ns.route("/datasets/<uuid:dataset_id>/metadata/<uuid:metadata_id>")
@@ -64,7 +77,7 @@ class DatasetMetadataApi(Resource):
@login_required
@account_initialization_required
@enterprise_license_required
@marshal_with(dataset_metadata_fields)
@console_ns.response(200, "Metadata updated successfully", console_ns.models[DatasetMetadataResponse.__name__])
@console_ns.expect(console_ns.models[MetadataUpdatePayload.__name__])
def patch(self, dataset_id, metadata_id):
current_user, _ = current_account_with_tenant()
@@ -79,7 +92,7 @@ class DatasetMetadataApi(Resource):
DatasetService.check_dataset_permission(dataset, current_user)
metadata = MetadataService.update_metadata_name(dataset_id_str, metadata_id_str, name)
return metadata, 200
return dump_response(DatasetMetadataResponse, metadata), 200
@setup_required
@login_required
@@ -96,7 +109,8 @@ class DatasetMetadataApi(Resource):
DatasetService.check_dataset_permission(dataset, current_user)
MetadataService.delete_metadata(dataset_id_str, metadata_id_str)
return {"result": "success"}, 204
# Frontend callers only await success and invalidate metadata caches; no response body is consumed.
return "", 204
@console_ns.route("/datasets/metadata/built-in")
@@ -105,9 +119,14 @@ class DatasetMetadataBuiltInFieldApi(Resource):
@login_required
@account_initialization_required
@enterprise_license_required
@console_ns.response(
200,
"Built-in fields retrieved successfully",
console_ns.models[DatasetMetadataBuiltInFieldsResponse.__name__],
)
def get(self):
built_in_fields = MetadataService.get_built_in_fields()
return {"fields": built_in_fields}, 200
return dump_response(DatasetMetadataBuiltInFieldsResponse, {"fields": built_in_fields}), 200
@console_ns.route("/datasets/<uuid:dataset_id>/metadata/built-in/<string:action>")
@@ -116,7 +135,7 @@ class DatasetMetadataBuiltInFieldActionApi(Resource):
@login_required
@account_initialization_required
@enterprise_license_required
@console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__])
@console_ns.response(204, "Action completed successfully")
def post(self, dataset_id, action: Literal["enable", "disable"]):
current_user, _ = current_account_with_tenant()
dataset_id_str = str(dataset_id)
@@ -130,7 +149,8 @@ class DatasetMetadataBuiltInFieldActionApi(Resource):
MetadataService.enable_built_in_field(dataset)
case "disable":
MetadataService.disable_built_in_field(dataset)
return {"result": "success"}, 200
# Frontend callers only await success and invalidate metadata caches; no response body is consumed.
return "", 204
@console_ns.route("/datasets/<uuid:dataset_id>/documents/metadata")
@@ -140,7 +160,10 @@ class DocumentMetadataEditApi(Resource):
@account_initialization_required
@enterprise_license_required
@console_ns.expect(console_ns.models[MetadataOperationData.__name__])
@console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__])
@console_ns.response(
204,
"Documents metadata updated successfully",
)
def post(self, dataset_id):
current_user, _ = current_account_with_tenant()
dataset_id_str = str(dataset_id)
@@ -153,4 +176,5 @@ class DocumentMetadataEditApi(Resource):
MetadataService.update_documents_metadata(dataset, metadata_args)
return {"result": "success"}, 200
# Frontend callers only await success and invalidate caches; no response body is consumed.
return "", 204
+38 -14
View File
@@ -1,15 +1,19 @@
from typing import Literal
from flask_login import current_user
from flask_restx import marshal
from werkzeug.exceptions import NotFound
from controllers.common.controller_schemas import MetadataUpdatePayload
from controllers.common.fields import SimpleResultResponse
from controllers.common.schema import register_response_schema_models, register_schema_model, register_schema_models
from controllers.service_api import service_api_ns
from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_rate_limit_check
from fields.dataset_fields import dataset_metadata_fields
from fields.dataset_fields import (
DatasetMetadataActionResponse,
DatasetMetadataBuiltInFieldsResponse,
DatasetMetadataListResponse,
DatasetMetadataResponse,
)
from libs.helper import dump_response
from services.dataset_service import DatasetService
from services.entities.knowledge_entities.knowledge_entities import (
DocumentMetadataOperation,
@@ -27,7 +31,13 @@ register_schema_models(
DocumentMetadataOperation,
MetadataOperationData,
)
register_response_schema_models(service_api_ns, SimpleResultResponse)
register_response_schema_models(
service_api_ns,
DatasetMetadataActionResponse,
DatasetMetadataBuiltInFieldsResponse,
DatasetMetadataListResponse,
DatasetMetadataResponse,
)
@service_api_ns.route("/datasets/<uuid:dataset_id>/metadata")
@@ -43,6 +53,9 @@ class DatasetMetadataCreateServiceApi(DatasetApiResource):
404: "Dataset not found",
}
)
@service_api_ns.response(
201, "Metadata created successfully", service_api_ns.models[DatasetMetadataResponse.__name__]
)
@cloud_edition_billing_rate_limit_check("knowledge", "dataset")
def post(self, tenant_id, dataset_id):
"""Create metadata for a dataset."""
@@ -55,7 +68,7 @@ class DatasetMetadataCreateServiceApi(DatasetApiResource):
DatasetService.check_dataset_permission(dataset, current_user)
metadata = MetadataService.create_metadata(dataset_id_str, metadata_args)
return marshal(metadata, dataset_metadata_fields), 201
return dump_response(DatasetMetadataResponse, metadata), 201
@service_api_ns.doc("get_dataset_metadata")
@service_api_ns.doc(description="Get all metadata for a dataset")
@@ -67,13 +80,17 @@ class DatasetMetadataCreateServiceApi(DatasetApiResource):
404: "Dataset not found",
}
)
@service_api_ns.response(
200, "Metadata retrieved successfully", service_api_ns.models[DatasetMetadataListResponse.__name__]
)
def get(self, tenant_id, dataset_id):
"""Get all metadata for a dataset."""
dataset_id_str = str(dataset_id)
dataset = DatasetService.get_dataset(dataset_id_str)
if dataset is None:
raise NotFound("Dataset not found.")
return MetadataService.get_dataset_metadatas(dataset), 200
metadata = MetadataService.get_dataset_metadatas(dataset)
return dump_response(DatasetMetadataListResponse, metadata), 200
@service_api_ns.route("/datasets/<uuid:dataset_id>/metadata/<uuid:metadata_id>")
@@ -89,6 +106,9 @@ class DatasetMetadataServiceApi(DatasetApiResource):
404: "Dataset or metadata not found",
}
)
@service_api_ns.response(
200, "Metadata updated successfully", service_api_ns.models[DatasetMetadataResponse.__name__]
)
@cloud_edition_billing_rate_limit_check("knowledge", "dataset")
def patch(self, tenant_id, dataset_id, metadata_id):
"""Update metadata name."""
@@ -102,7 +122,7 @@ class DatasetMetadataServiceApi(DatasetApiResource):
DatasetService.check_dataset_permission(dataset, current_user)
metadata = MetadataService.update_metadata_name(dataset_id_str, metadata_id_str, payload.name)
return marshal(metadata, dataset_metadata_fields), 200
return dump_response(DatasetMetadataResponse, metadata), 200
@service_api_ns.doc("delete_dataset_metadata")
@service_api_ns.doc(description="Delete metadata")
@@ -114,6 +134,7 @@ class DatasetMetadataServiceApi(DatasetApiResource):
404: "Dataset or metadata not found",
}
)
@service_api_ns.response(204, "Metadata deleted successfully")
@cloud_edition_billing_rate_limit_check("knowledge", "dataset")
def delete(self, tenant_id, dataset_id, metadata_id):
"""Delete metadata."""
@@ -138,10 +159,15 @@ class DatasetMetadataBuiltInFieldServiceApi(DatasetApiResource):
401: "Unauthorized - invalid API token",
}
)
@service_api_ns.response(
200,
"Built-in fields retrieved successfully",
service_api_ns.models[DatasetMetadataBuiltInFieldsResponse.__name__],
)
def get(self, tenant_id, dataset_id):
"""Get all built-in metadata fields."""
built_in_fields = MetadataService.get_built_in_fields()
return {"fields": built_in_fields}, 200
return dump_response(DatasetMetadataBuiltInFieldsResponse, {"fields": built_in_fields}), 200
@service_api_ns.route("/datasets/<uuid:dataset_id>/metadata/built-in/<string:action>")
@@ -157,9 +183,7 @@ class DatasetMetadataBuiltInFieldActionServiceApi(DatasetApiResource):
}
)
@service_api_ns.response(
200,
"Action completed successfully",
service_api_ns.models[SimpleResultResponse.__name__],
200, "Action completed successfully", service_api_ns.models[DatasetMetadataActionResponse.__name__]
)
@cloud_edition_billing_rate_limit_check("knowledge", "dataset")
def post(self, tenant_id, dataset_id, action: Literal["enable", "disable"]):
@@ -175,7 +199,7 @@ class DatasetMetadataBuiltInFieldActionServiceApi(DatasetApiResource):
MetadataService.enable_built_in_field(dataset)
case "disable":
MetadataService.disable_built_in_field(dataset)
return {"result": "success"}, 200
return dump_response(DatasetMetadataActionResponse, {"result": "success"}), 200
@service_api_ns.route("/datasets/<uuid:dataset_id>/documents/metadata")
@@ -194,7 +218,7 @@ class DocumentMetadataEditServiceApi(DatasetApiResource):
@service_api_ns.response(
200,
"Documents metadata updated successfully",
service_api_ns.models[SimpleResultResponse.__name__],
service_api_ns.models[DatasetMetadataActionResponse.__name__],
)
@cloud_edition_billing_rate_limit_check("knowledge", "dataset")
def post(self, tenant_id, dataset_id):
@@ -209,4 +233,4 @@ class DocumentMetadataEditServiceApi(DatasetApiResource):
MetadataService.update_documents_metadata(dataset, metadata_args)
return {"result": "success"}, 200
return dump_response(DatasetMetadataActionResponse, {"result": "success"}), 200
-23
View File
@@ -1,23 +0,0 @@
from flask_restx import fields
from libs.helper import TimestampField
class HiddenAPIKey(fields.Raw):
def output(self, key, obj, **kwargs):
api_key = obj.api_key
# If the length of the api_key is less than 8 characters, show the first and last characters
if len(api_key) <= 8:
return api_key[0] + "******" + api_key[-1]
# If the api_key is greater than 8 characters, show the first three and the last three characters
else:
return api_key[:3] + "******" + api_key[-3:]
api_based_extension_fields = {
"id": fields.String,
"name": fields.String,
"api_endpoint": fields.String,
"api_key": HiddenAPIKey,
"created_at": TimestampField,
}
+33 -6
View File
@@ -1,5 +1,6 @@
from flask_restx import fields
from fields.base import ResponseModel
from libs.helper import TimestampField
dataset_fields = {
@@ -13,6 +14,38 @@ dataset_fields = {
"created_at": TimestampField,
}
class DatasetMetadataResponse(ResponseModel):
id: str
type: str
name: str
class DatasetMetadataListItemResponse(ResponseModel):
id: str
name: str
type: str
count: int = 0
class DatasetMetadataListResponse(ResponseModel):
doc_metadata: list[DatasetMetadataListItemResponse]
built_in_field_enabled: bool
class DatasetMetadataBuiltInFieldResponse(ResponseModel):
name: str
type: str
class DatasetMetadataBuiltInFieldsResponse(ResponseModel):
fields: list[DatasetMetadataBuiltInFieldResponse]
class DatasetMetadataActionResponse(ResponseModel):
result: str
reranking_model_fields = {"reranking_provider_name": fields.String, "reranking_model_name": fields.String}
keyword_setting_fields = {"keyword_weight": fields.Float}
@@ -133,9 +166,3 @@ dataset_query_detail_fields = {
"created_by": fields.String,
"created_at": TimestampField,
}
dataset_metadata_fields = {
"id": fields.String,
"type": fields.String,
"name": fields.String,
}
-26
View File
@@ -1,26 +0,0 @@
from flask_restx import fields
from libs.helper import AppIconUrlField, TimestampField
app_fields = {
"id": fields.String,
"name": fields.String,
"mode": fields.String,
"icon_type": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"icon_url": AppIconUrlField,
"use_icon_as_answer_icon": fields.Boolean,
}
installed_app_fields = {
"id": fields.String,
"app": fields.Nested(app_fields),
"app_owner_tenant_id": fields.String,
"is_pinned": fields.Boolean,
"last_used_at": TimestampField,
"editable": fields.Boolean,
"uninstallable": fields.Boolean,
}
installed_app_list_fields = {"installed_apps": fields.List(fields.Nested(installed_app_fields))}
-142
View File
@@ -1,142 +0,0 @@
from __future__ import annotations
from datetime import datetime
from typing import Any
from flask_restx import Namespace, fields
from pydantic import field_validator
from fields.base import ResponseModel
from fields.end_user_fields import SimpleEndUser, simple_end_user_fields
from fields.member_fields import SimpleAccount, simple_account_fields
from fields.workflow_run_fields import (
WorkflowRunForArchivedLogResponse,
WorkflowRunForLogResponse,
build_workflow_run_for_archived_log_model,
build_workflow_run_for_log_model,
workflow_run_for_archived_log_fields,
workflow_run_for_log_fields,
)
from libs.helper import TimestampField, to_timestamp
workflow_app_log_partial_fields = {
"id": fields.String,
"workflow_run": fields.Nested(workflow_run_for_log_fields, attribute="workflow_run", allow_null=True),
"details": fields.Raw(attribute="details"),
"created_from": fields.String,
"created_by_role": fields.String,
"created_by_account": fields.Nested(simple_account_fields, attribute="created_by_account", allow_null=True),
"created_by_end_user": fields.Nested(simple_end_user_fields, attribute="created_by_end_user", allow_null=True),
"created_at": TimestampField,
}
def build_workflow_app_log_partial_model(api_or_ns: Namespace):
"""Build the workflow app log partial model for the API or Namespace."""
workflow_run_model = build_workflow_run_for_log_model(api_or_ns)
copied_fields = workflow_app_log_partial_fields.copy()
copied_fields["workflow_run"] = fields.Nested(workflow_run_model, attribute="workflow_run", allow_null=True)
return api_or_ns.model("WorkflowAppLogPartial", copied_fields)
workflow_archived_log_partial_fields = {
"id": fields.String,
"workflow_run": fields.Nested(workflow_run_for_archived_log_fields, allow_null=True),
"trigger_metadata": fields.Raw,
"created_by_account": fields.Nested(simple_account_fields, attribute="created_by_account", allow_null=True),
"created_by_end_user": fields.Nested(simple_end_user_fields, attribute="created_by_end_user", allow_null=True),
"created_at": TimestampField,
}
def build_workflow_archived_log_partial_model(api_or_ns: Namespace):
"""Build the workflow archived log partial model for the API or Namespace."""
workflow_run_model = build_workflow_run_for_archived_log_model(api_or_ns)
copied_fields = workflow_archived_log_partial_fields.copy()
copied_fields["workflow_run"] = fields.Nested(workflow_run_model, allow_null=True)
return api_or_ns.model("WorkflowArchivedLogPartial", copied_fields)
workflow_app_log_pagination_fields = {
"page": fields.Integer,
"limit": fields.Integer,
"total": fields.Integer,
"has_more": fields.Boolean,
"data": fields.List(fields.Nested(workflow_app_log_partial_fields)),
}
def build_workflow_app_log_pagination_model(api_or_ns: Namespace):
"""Build the workflow app log pagination model for the API or Namespace."""
# Build the nested partial model first
workflow_app_log_partial_model = build_workflow_app_log_partial_model(api_or_ns)
copied_fields = workflow_app_log_pagination_fields.copy()
copied_fields["data"] = fields.List(fields.Nested(workflow_app_log_partial_model))
return api_or_ns.model("WorkflowAppLogPagination", copied_fields)
workflow_archived_log_pagination_fields = {
"page": fields.Integer,
"limit": fields.Integer,
"total": fields.Integer,
"has_more": fields.Boolean,
"data": fields.List(fields.Nested(workflow_archived_log_partial_fields)),
}
def build_workflow_archived_log_pagination_model(api_or_ns: Namespace):
"""Build the workflow archived log pagination model for the API or Namespace."""
workflow_archived_log_partial_model = build_workflow_archived_log_partial_model(api_or_ns)
copied_fields = workflow_archived_log_pagination_fields.copy()
copied_fields["data"] = fields.List(fields.Nested(workflow_archived_log_partial_model))
return api_or_ns.model("WorkflowArchivedLogPagination", copied_fields)
class WorkflowAppLogPartialResponse(ResponseModel):
id: str
workflow_run: WorkflowRunForLogResponse | None = None
details: Any = None
created_from: str | None = None
created_by_role: str | None = None
created_by_account: SimpleAccount | None = None
created_by_end_user: SimpleEndUser | None = None
created_at: int | None = None
@field_validator("created_at", mode="before")
@classmethod
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return to_timestamp(value)
class WorkflowArchivedLogPartialResponse(ResponseModel):
id: str
workflow_run: WorkflowRunForArchivedLogResponse | None = None
trigger_metadata: Any = None
created_by_account: SimpleAccount | None = None
created_by_end_user: SimpleEndUser | None = None
created_at: int | None = None
@field_validator("created_at", mode="before")
@classmethod
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return to_timestamp(value)
class WorkflowAppLogPaginationResponse(ResponseModel):
page: int
limit: int
total: int
has_more: bool
data: list[WorkflowAppLogPartialResponse]
class WorkflowArchivedLogPaginationResponse(ResponseModel):
page: int
limit: int
total: int
has_more: bool
data: list[WorkflowArchivedLogPartialResponse]
-25
View File
@@ -1,25 +0,0 @@
from flask_restx import fields
trigger_fields = {
"id": fields.String,
"trigger_type": fields.String,
"title": fields.String,
"node_id": fields.String,
"provider_name": fields.String,
"icon": fields.String,
"status": fields.String,
"created_at": fields.DateTime(dt_format="iso8601"),
"updated_at": fields.DateTime(dt_format="iso8601"),
}
triggers_list_fields = {"data": fields.List(fields.Nested(trigger_fields))}
webhook_trigger_fields = {
"id": fields.String,
"webhook_id": fields.String,
"webhook_url": fields.String,
"webhook_debug_url": fields.String,
"node_id": fields.String,
"created_at": fields.DateTime(dt_format="iso8601"),
}
+55 -18
View File
@@ -4413,9 +4413,9 @@ Initialize dataset with documents
#### GET
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Success |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Built-in fields retrieved successfully | [DatasetMetadataBuiltInFieldsResponse](#datasetmetadatabuiltinfieldsresponse) |
### /datasets/notion-indexing-estimate
@@ -4730,9 +4730,9 @@ then asynchronously generates summary indexes for the provided documents.
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Success | [SimpleResultResponse](#simpleresultresponse) |
| Code | Description |
| ---- | ----------- |
| 204 | Documents metadata updated successfully |
### /datasets/{dataset_id}/documents/status/{action}/batch
@@ -5342,9 +5342,9 @@ Get dataset indexing status
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Success |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Metadata retrieved successfully | [DatasetMetadataListResponse](#datasetmetadatalistresponse) |
#### POST
##### Parameters
@@ -5356,9 +5356,9 @@ Get dataset indexing status
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Success |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 201 | Metadata created successfully | [DatasetMetadataResponse](#datasetmetadataresponse) |
### /datasets/{dataset_id}/metadata/built-in/{action}
@@ -5372,9 +5372,9 @@ Get dataset indexing status
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Success | [SimpleResultResponse](#simpleresultresponse) |
| Code | Description |
| ---- | ----------- |
| 204 | Action completed successfully |
### /datasets/{dataset_id}/metadata/{metadata_id}
@@ -5403,9 +5403,9 @@ Get dataset indexing status
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Success |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Metadata updated successfully | [DatasetMetadataResponse](#datasetmetadataresponse) |
### /datasets/{dataset_id}/notion/sync
@@ -11733,6 +11733,43 @@ Condition detail
| ---- | ---- | ----------- | -------- |
| keyword_weight | number | | No |
#### DatasetMetadataBuiltInFieldResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| name | string | | Yes |
| type | string | | Yes |
#### DatasetMetadataBuiltInFieldsResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| fields | [ [DatasetMetadataBuiltInFieldResponse](#datasetmetadatabuiltinfieldresponse) ] | | Yes |
#### DatasetMetadataListItemResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| count | integer | | No |
| id | string | | Yes |
| name | string | | Yes |
| type | string | | Yes |
#### DatasetMetadataListResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| built_in_field_enabled | boolean | | Yes |
| doc_metadata | [ [DatasetMetadataListItemResponse](#datasetmetadatalistitemresponse) ] | | Yes |
#### DatasetMetadataResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| id | string | | Yes |
| name | string | | Yes |
| type | string | | Yes |
#### DatasetPermissionEnum
| Name | Type | Description | Required |
+64 -21
View File
@@ -877,7 +877,7 @@ Update metadata for multiple documents
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Documents metadata updated successfully | [SimpleResultResponse](#simpleresultresponse) |
| 200 | Documents metadata updated successfully | [DatasetMetadataActionResponse](#datasetmetadataactionresponse) |
| 401 | Unauthorized - invalid API token | |
| 404 | Dataset not found | |
@@ -1378,11 +1378,11 @@ Get all metadata for a dataset
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Metadata retrieved successfully |
| 401 | Unauthorized - invalid API token |
| 404 | Dataset not found |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Metadata retrieved successfully | [DatasetMetadataListResponse](#datasetmetadatalistresponse) |
| 401 | Unauthorized - invalid API token | |
| 404 | Dataset not found | |
#### POST
##### Summary
@@ -1402,11 +1402,11 @@ Create metadata for a dataset
##### Responses
| Code | Description |
| ---- | ----------- |
| 201 | Metadata created successfully |
| 401 | Unauthorized - invalid API token |
| 404 | Dataset not found |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 201 | Metadata created successfully | [DatasetMetadataResponse](#datasetmetadataresponse) |
| 401 | Unauthorized - invalid API token | |
| 404 | Dataset not found | |
### /datasets/{dataset_id}/metadata/built-in
@@ -1427,10 +1427,10 @@ Get all built-in metadata fields
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Built-in fields retrieved successfully |
| 401 | Unauthorized - invalid API token |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Built-in fields retrieved successfully | [DatasetMetadataBuiltInFieldsResponse](#datasetmetadatabuiltinfieldsresponse) |
| 401 | Unauthorized - invalid API token | |
### /datasets/{dataset_id}/metadata/built-in/{action}
@@ -1454,7 +1454,7 @@ Enable or disable built-in metadata field
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Action completed successfully | [SimpleResultResponse](#simpleresultresponse) |
| 200 | Action completed successfully | [DatasetMetadataActionResponse](#datasetmetadataactionresponse) |
| 401 | Unauthorized - invalid API token | |
| 404 | Dataset not found | |
@@ -1503,11 +1503,11 @@ Update metadata name
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Metadata updated successfully |
| 401 | Unauthorized - invalid API token |
| 404 | Dataset or metadata not found |
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Metadata updated successfully | [DatasetMetadataResponse](#datasetmetadataresponse) |
| 401 | Unauthorized - invalid API token | |
| 404 | Dataset or metadata not found | |
### /datasets/{dataset_id}/pipeline/datasource-plugins
@@ -2314,6 +2314,49 @@ Condition detail
| page | integer | Page number | No |
| tag_ids | [ string ] | Filter by tag IDs | No |
#### DatasetMetadataActionResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| result | string | | Yes |
#### DatasetMetadataBuiltInFieldResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| name | string | | Yes |
| type | string | | Yes |
#### DatasetMetadataBuiltInFieldsResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| fields | [ [DatasetMetadataBuiltInFieldResponse](#datasetmetadatabuiltinfieldresponse) ] | | Yes |
#### DatasetMetadataListItemResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| count | integer | | No |
| id | string | | Yes |
| name | string | | Yes |
| type | string | | Yes |
#### DatasetMetadataListResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| built_in_field_enabled | boolean | | Yes |
| doc_metadata | [ [DatasetMetadataListItemResponse](#datasetmetadatalistitemresponse) ] | | Yes |
#### DatasetMetadataResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| id | string | | Yes |
| name | string | | Yes |
| type | string | | Yes |
#### DatasetPermissionEnum
| Name | Type | Description | Required |
@@ -117,12 +117,13 @@ class TestDatasetMetadataCreateApi:
patch.object(
MetadataService,
"create_metadata",
return_value={"id": "m1", "name": "author"},
return_value={"id": "m1", "type": "string", "name": "author"},
),
):
result, status = method(api, dataset_id)
assert status == 201
assert result["type"] == "string"
assert result["name"] == "author"
def test_create_metadata_dataset_not_found(self, app: Flask, current_user, dataset_id):
@@ -176,13 +177,17 @@ class TestDatasetMetadataGetApi:
patch.object(
MetadataService,
"get_dataset_metadatas",
return_value=[{"id": "m1"}],
return_value={
"doc_metadata": [{"id": "m1", "name": "author", "type": "string", "count": 0}],
"built_in_field_enabled": False,
},
),
):
result, status = method(api, dataset_id)
assert status == 200
assert isinstance(result, list)
assert result["doc_metadata"] == [{"id": "m1", "name": "author", "type": "string", "count": 0}]
assert result["built_in_field_enabled"] is False
def test_get_metadata_dataset_not_found(self, app: Flask, dataset_id):
api = DatasetMetadataCreateApi()
@@ -231,12 +236,13 @@ class TestDatasetMetadataApi:
patch.object(
MetadataService,
"update_metadata_name",
return_value={"id": "m1", "name": "updated-name"},
return_value={"id": "m1", "type": "string", "name": "updated-name"},
),
):
result, status = method(api, dataset_id, metadata_id)
assert status == 200
assert result["type"] == "string"
assert result["name"] == "updated-name"
def test_delete_metadata_success(self, app: Flask, current_user, dataset, dataset_id, metadata_id):
@@ -266,7 +272,7 @@ class TestDatasetMetadataApi:
result, status = method(api, dataset_id, metadata_id)
assert status == 204
assert result["result"] == "success"
assert result == ""
class TestDatasetMetadataBuiltInFieldApi:
@@ -279,13 +285,19 @@ class TestDatasetMetadataBuiltInFieldApi:
patch.object(
MetadataService,
"get_built_in_fields",
return_value=["title", "source"],
return_value=[
{"name": "document_name", "type": "string"},
{"name": "source", "type": "string"},
],
),
):
result, status = method(api)
assert status == 200
assert result["fields"] == ["title", "source"]
assert result["fields"] == [
{"name": "document_name", "type": "string"},
{"name": "source", "type": "string"},
]
class TestDatasetMetadataBuiltInFieldActionApi:
@@ -315,8 +327,8 @@ class TestDatasetMetadataBuiltInFieldActionApi:
):
result, status = method(api, dataset_id, "enable")
assert status == 200
assert result["result"] == "success"
assert status == 204
assert result == ""
class TestDocumentMetadataEditApi:
@@ -359,5 +371,5 @@ class TestDocumentMetadataEditApi:
):
result, status = method(api, dataset_id)
assert status == 200
assert result["result"] == "success"
assert status == 204
assert result == ""
@@ -11,7 +11,7 @@ from flask.views import MethodView as FlaskMethodView
_NEEDS_METHOD_VIEW_CLEANUP = False
if not hasattr(builtins, "MethodView"):
builtins.MethodView = FlaskMethodView
builtins.__dict__["MethodView"] = FlaskMethodView
_NEEDS_METHOD_VIEW_CLEANUP = True
from constants import HIDDEN_VALUE
@@ -22,7 +22,7 @@ from controllers.console.extension import (
)
if _NEEDS_METHOD_VIEW_CLEANUP:
del builtins.MethodView
del builtins.__dict__["MethodView"]
from models.account import AccountStatus
from models.api_based_extension import APIBasedExtension
@@ -67,7 +67,6 @@ class TestDatasetMetadataCreatePost:
def _call_post(api, **kwargs):
return _unwrap(api.post)(api, **kwargs)
@patch("controllers.service_api.dataset.metadata.marshal")
@patch("controllers.service_api.dataset.metadata.MetadataService")
@patch("controllers.service_api.dataset.metadata.DatasetService")
@patch("controllers.service_api.dataset.metadata.current_user")
@@ -76,7 +75,6 @@ class TestDatasetMetadataCreatePost:
mock_current_user,
mock_dataset_svc,
mock_meta_svc,
mock_marshal,
app: Flask,
mock_tenant,
mock_dataset,
@@ -84,9 +82,8 @@ class TestDatasetMetadataCreatePost:
"""Test successful metadata creation."""
mock_dataset_svc.get_dataset.return_value = mock_dataset
mock_dataset_svc.check_dataset_permission.return_value = None
mock_metadata = Mock()
mock_metadata = {"id": "meta-1", "type": "string", "name": "Author"}
mock_meta_svc.create_metadata.return_value = mock_metadata
mock_marshal.return_value = {"id": "meta-1", "name": "Author"}
with app.test_request_context(
f"/datasets/{mock_dataset.id}/metadata",
@@ -101,6 +98,7 @@ class TestDatasetMetadataCreatePost:
)
assert status == 201
assert response == {"id": "meta-1", "type": "string", "name": "Author"}
mock_meta_svc.create_metadata.assert_called_once()
@patch("controllers.service_api.dataset.metadata.DatasetService")
@@ -143,7 +141,10 @@ class TestDatasetMetadataCreateGet:
):
"""Test successful metadata list retrieval."""
mock_dataset_svc.get_dataset.return_value = mock_dataset
mock_meta_svc.get_dataset_metadatas.return_value = [{"id": "m1"}]
mock_meta_svc.get_dataset_metadatas.return_value = {
"doc_metadata": [{"id": "m1", "name": "Author", "type": "string", "count": 0}],
"built_in_field_enabled": False,
}
with app.test_request_context(
f"/datasets/{mock_dataset.id}/metadata",
@@ -156,6 +157,10 @@ class TestDatasetMetadataCreateGet:
)
assert status == 200
assert response == {
"doc_metadata": [{"id": "m1", "name": "Author", "type": "string", "count": 0}],
"built_in_field_enabled": False,
}
@patch("controllers.service_api.dataset.metadata.DatasetService")
def test_get_metadata_dataset_not_found(
@@ -192,7 +197,6 @@ class TestDatasetMetadataServiceApiPatch:
def _call_patch(api, **kwargs):
return _unwrap(api.patch)(api, **kwargs)
@patch("controllers.service_api.dataset.metadata.marshal")
@patch("controllers.service_api.dataset.metadata.MetadataService")
@patch("controllers.service_api.dataset.metadata.DatasetService")
@patch("controllers.service_api.dataset.metadata.current_user")
@@ -201,7 +205,6 @@ class TestDatasetMetadataServiceApiPatch:
mock_current_user,
mock_dataset_svc,
mock_meta_svc,
mock_marshal,
app: Flask,
mock_tenant,
mock_dataset,
@@ -210,8 +213,7 @@ class TestDatasetMetadataServiceApiPatch:
metadata_id = str(uuid.uuid4())
mock_dataset_svc.get_dataset.return_value = mock_dataset
mock_dataset_svc.check_dataset_permission.return_value = None
mock_meta_svc.update_metadata_name.return_value = Mock()
mock_marshal.return_value = {"id": metadata_id, "name": "New Name"}
mock_meta_svc.update_metadata_name.return_value = {"id": metadata_id, "type": "string", "name": "New Name"}
with app.test_request_context(
f"/datasets/{mock_dataset.id}/metadata/{metadata_id}",
@@ -227,6 +229,7 @@ class TestDatasetMetadataServiceApiPatch:
)
assert status == 200
assert response == {"id": metadata_id, "type": "string", "name": "New Name"}
mock_meta_svc.update_metadata_name.assert_called_once()
@patch("controllers.service_api.dataset.metadata.DatasetService")
@@ -357,7 +360,7 @@ class TestDatasetMetadataBuiltInFieldGet:
)
assert status == 200
assert "fields" in response
assert response == {"fields": [{"name": "source", "type": "string"}]}
# ---------------------------------------------------------------------------