from __future__ import annotations import time import pytest from .conftest import ReleaseDatasetSeed, TenantSeed from .helpers import ReleaseApiClient def _dataset_ids(items: list[dict]) -> set[int]: return {int(item["id"]) for item in items if item.get("id") is not None} def _app_ids(items: list[dict]) -> set[str]: return {str(item["appId"]) for item in items if item.get("appId") is not None} @pytest.mark.release def test_g5_rag_dataset_admin_scope_is_limited_to_own_tenant( admin_client: ReleaseApiClient, tenant_admin_api: ReleaseApiClient, tenant_admin_api_b: ReleaseApiClient, tenant_a: TenantSeed, tenant_b: TenantSeed, make_release_dataset, ) -> None: dataset_a = make_release_dataset( tenant=tenant_a, dataset_name=f"Pytest G5 A {int(time.time())}", ) dataset_b = make_release_dataset( tenant=tenant_b, dataset_name=f"Pytest G5 B {int(time.time())}", ) global_admin_list = ReleaseApiClient.json_data(admin_client.get("/api/v3/rag/datasets/admin?page=1&pageSize=100")) ids_a = _dataset_ids(global_admin_list["data"]) assert dataset_a.dataset_id in ids_a assert dataset_b.dataset_id in ids_a tenant_admin_list = ReleaseApiClient.json_data( tenant_admin_api.get("/api/v3/rag/datasets/admin?page=1&pageSize=100") ) tenant_admin_ids = _dataset_ids(tenant_admin_list["data"]) assert dataset_a.dataset_id in tenant_admin_ids assert dataset_b.dataset_id not in tenant_admin_ids forbidden_query = tenant_admin_api.get( f"/api/v3/rag/datasets/admin?page=1&pageSize=100&tenant_code={tenant_b.tenant_code}", expected_status=403, ) assert "本地区知识库配置" in forbidden_query.text or "本租户知识库" in forbidden_query.text @pytest.mark.release def test_g5_rag_dataset_detail_and_update_respect_tenant_boundary( admin_client: ReleaseApiClient, tenant_admin_api: ReleaseApiClient, tenant_a: TenantSeed, tenant_b: TenantSeed, make_release_dataset, ) -> None: dataset_a = make_release_dataset( tenant=tenant_a, dataset_name=f"Pytest G5 Detail A {int(time.time())}", ) dataset_b = make_release_dataset( tenant=tenant_b, dataset_name=f"Pytest G5 Detail B {int(time.time())}", ) own_detail = ReleaseApiClient.json_data(tenant_admin_api.get(f"/api/v3/rag/datasets/{dataset_a.dataset_id}")) assert int(own_detail["id"]) == dataset_a.dataset_id assert str(own_detail.get("tenantCode") or "") == tenant_a.tenant_code hidden_detail = ReleaseApiClient.json_data(tenant_admin_api.get(f"/api/v3/rag/datasets/{dataset_b.dataset_id}")) assert hidden_detail is None own_update = ReleaseApiClient.json_data( tenant_admin_api.patch( f"/api/v3/rag/datasets/{dataset_a.dataset_id}", json={"name": f"{dataset_a.dataset_name}-tenant-updated"}, expected_status=200, ) ) assert str(own_update["name"]).endswith("-tenant-updated") hidden_update = ReleaseApiClient.json_data( tenant_admin_api.patch( f"/api/v3/rag/datasets/{dataset_b.dataset_id}", json={"name": "should-not-work"}, expected_status=200, ) ) assert hidden_update is None admin_update = ReleaseApiClient.json_data( admin_client.patch( f"/api/v3/rag/datasets/{dataset_a.dataset_id}", json={"name": f"{dataset_a.dataset_name}-updated"}, expected_status=200, ) ) assert str(admin_update["name"]).endswith("-updated") @pytest.mark.release def test_g5_rag_apps_and_public_dataset_visibility( tenant_admin_api: ReleaseApiClient, tenant_admin_api_b: ReleaseApiClient, common_api_a: ReleaseApiClient, common_api_b: ReleaseApiClient, tenant_a: TenantSeed, tenant_b: TenantSeed, make_release_dataset, ) -> None: dataset_a = make_release_dataset( tenant=tenant_a, dataset_name=f"Pytest G5 App A {int(time.time())}", is_default=True, ) dataset_b = make_release_dataset( tenant=tenant_b, dataset_name=f"Pytest G5 App B {int(time.time())}", is_default=True, ) public_dataset = make_release_dataset( tenant=tenant_a, dataset_name=f"Pytest G5 Public {int(time.time())}", is_public=True, is_default=False, ) apps_a = ReleaseApiClient.json_data(common_api_a.get("/api/v3/rag/apps")) app_ids_a = _app_ids(apps_a["data"]) assert dataset_a.app_id is not None assert str(dataset_a.app_id) in app_ids_a assert dataset_b.app_id is not None assert str(dataset_b.app_id) not in app_ids_a assert public_dataset.app_id is not None assert str(public_dataset.app_id) in app_ids_a apps_b = ReleaseApiClient.json_data(common_api_b.get("/api/v3/rag/apps")) app_ids_b = _app_ids(apps_b["data"]) assert str(dataset_b.app_id) in app_ids_b assert str(dataset_a.app_id) not in app_ids_b assert str(public_dataset.app_id) in app_ids_b default_app_a = ReleaseApiClient.json_data(common_api_a.get("/api/v3/rag/apps/default")) assert default_app_a is not None assert str(default_app_a.get("tenantCode") or "") in {tenant_a.tenant_code, public_dataset.tenant_code} @pytest.mark.release def test_g5_common_user_cannot_access_rag_admin_endpoints( common_api_a: ReleaseApiClient, tenant_a: TenantSeed, ) -> None: forbidden_admin_list = common_api_a.get("/api/v3/rag/datasets/admin?page=1&pageSize=20", expected_status=403) assert "管理知识库权限" in forbidden_admin_list.text forbidden_create = common_api_a.post( "/api/v3/rag/datasets/admin", json={ "tenant_code": tenant_a.tenant_code, "tenant_name": tenant_a.tenant_name, "area": tenant_a.tenant_name, "name": f"should-forbid-{int(time.time())}", "description": "forbidden", "status": 1, }, expected_status=403, ) assert "创建知识库权限" in forbidden_create.text