mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
Refactor system API (#13958)
### What problem does this PR solve? - ping - token - log level ### Type of change - [x] Refactoring <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * System endpoints consolidated under /api/v1/system: ping, health check, and token management moved to the centralized API surface. * Token management unified at /api/v1/system/tokens with list/create/delete behavior. * **Documentation** * API reference updated to reflect the new /api/v1/system paths. * **Tests** * Client fixtures and test utilities updated to use /api/v1/system/tokens; one unit test for health/oceanbase status removed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
71
api/apps/restful_apis/config_api.py
Normal file
71
api/apps/restful_apis/config_api.py
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from api.apps import login_required
|
||||
from api.utils.api_utils import get_json_result, get_data_error_result
|
||||
from common.log_utils import get_log_levels, set_log_level
|
||||
|
||||
@manager.route("/config/log", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
async def get_logger_levels():
|
||||
"""
|
||||
Get current log levels for all packages.
|
||||
---
|
||||
tags:
|
||||
- System
|
||||
responses:
|
||||
200:
|
||||
description: Return current log levels
|
||||
"""
|
||||
return get_json_result(data=get_log_levels())
|
||||
|
||||
|
||||
@manager.route("/config/log", methods=["PUT"]) # noqa: F821
|
||||
@login_required
|
||||
async def set_logger_level():
|
||||
"""
|
||||
Set log level for a package.
|
||||
---
|
||||
tags:
|
||||
- System
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
pkg_name:
|
||||
type: string
|
||||
description: Package name (e.g., "rag.utils.es_conn")
|
||||
level:
|
||||
type: string
|
||||
description: Log level (DEBUG, INFO, WARNING, ERROR)
|
||||
responses:
|
||||
200:
|
||||
description: Log level updated successfully
|
||||
"""
|
||||
from quart import request
|
||||
data = await request.get_json()
|
||||
if not data or "pkg_name" not in data or "level" not in data:
|
||||
return get_data_error_result(message="pkg_name and level are required")
|
||||
pkg_name = data["pkg_name"]
|
||||
level = data["level"]
|
||||
success = set_log_level(pkg_name, level)
|
||||
if success:
|
||||
return get_json_result(data={"pkg_name": pkg_name, "level": level})
|
||||
else:
|
||||
return get_data_error_result(message=f"Invalid log level: {level}")
|
||||
@@ -14,10 +14,21 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from api.apps import login_required
|
||||
from quart import jsonify
|
||||
|
||||
from api.utils.api_utils import get_json_result
|
||||
from api.apps import login_required, current_user
|
||||
from api.utils.api_utils import get_json_result, get_data_error_result, server_error_response, generate_confirmation_token
|
||||
from api.utils.health_utils import run_health_checks
|
||||
from common.versions import get_ragflow_version
|
||||
from datetime import datetime
|
||||
from common.time_utils import current_timestamp, datetime_format
|
||||
from api.db.db_models import APIToken
|
||||
from api.db.services.api_service import APITokenService
|
||||
from api.db.services.user_service import UserTenantService
|
||||
|
||||
@manager.route("/system/ping", methods=["GET"]) # noqa: F821
|
||||
async def ping():
|
||||
return "pong", 200
|
||||
|
||||
@manager.route("/system/version", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
@@ -39,4 +50,144 @@ def version():
|
||||
type: string
|
||||
description: Version number.
|
||||
"""
|
||||
return get_json_result(data=get_ragflow_version())
|
||||
return get_json_result(data=get_ragflow_version())
|
||||
|
||||
@manager.route("/system/healthz", methods=["GET"]) # noqa: F821
|
||||
def healthz():
|
||||
result, all_ok = run_health_checks()
|
||||
return jsonify(result), (200 if all_ok else 500)
|
||||
|
||||
@manager.route("/system/tokens", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
def token_list():
|
||||
"""
|
||||
List all API tokens for the current user.
|
||||
---
|
||||
tags:
|
||||
- API Tokens
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
responses:
|
||||
200:
|
||||
description: List of API tokens.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
tokens:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: The API token.
|
||||
name:
|
||||
type: string
|
||||
description: Name of the token.
|
||||
create_time:
|
||||
type: string
|
||||
description: Token creation time.
|
||||
"""
|
||||
try:
|
||||
tenants = UserTenantService.query(user_id=current_user.id)
|
||||
if not tenants:
|
||||
return get_data_error_result(message="Tenant not found!")
|
||||
|
||||
tenant_id = [tenant for tenant in tenants if tenant.role == "owner"][0].tenant_id
|
||||
objs = APITokenService.query(tenant_id=tenant_id)
|
||||
objs = [o.to_dict() for o in objs]
|
||||
for o in objs:
|
||||
if not o["beta"]:
|
||||
o["beta"] = generate_confirmation_token().replace("ragflow-", "")[:32]
|
||||
APITokenService.filter_update([APIToken.tenant_id == tenant_id, APIToken.token == o["token"]], o)
|
||||
return get_json_result(data=objs)
|
||||
except Exception as e:
|
||||
return server_error_response(e)
|
||||
|
||||
|
||||
@manager.route("/system/tokens", methods=["POST"]) # noqa: F821
|
||||
@login_required
|
||||
def new_token():
|
||||
"""
|
||||
Generate a new API token.
|
||||
---
|
||||
tags:
|
||||
- API Tokens
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
parameters:
|
||||
- in: query
|
||||
name: name
|
||||
type: string
|
||||
required: false
|
||||
description: Name of the token.
|
||||
responses:
|
||||
200:
|
||||
description: Token generated successfully.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: The generated API token.
|
||||
"""
|
||||
try:
|
||||
tenants = UserTenantService.query(user_id=current_user.id)
|
||||
if not tenants:
|
||||
return get_data_error_result(message="Tenant not found!")
|
||||
|
||||
tenant_id = [tenant for tenant in tenants if tenant.role == "owner"][0].tenant_id
|
||||
obj = {
|
||||
"tenant_id": tenant_id,
|
||||
"token": generate_confirmation_token(),
|
||||
"beta": generate_confirmation_token().replace("ragflow-", "")[:32],
|
||||
"create_time": current_timestamp(),
|
||||
"create_date": datetime_format(datetime.now()),
|
||||
"update_time": None,
|
||||
"update_date": None,
|
||||
}
|
||||
|
||||
if not APITokenService.save(**obj):
|
||||
return get_data_error_result(message="Fail to new a dialog!")
|
||||
|
||||
return get_json_result(data=obj)
|
||||
except Exception as e:
|
||||
return server_error_response(e)
|
||||
|
||||
|
||||
@manager.route("/system/tokens/<token>", methods=["DELETE"]) # noqa: F821
|
||||
@login_required
|
||||
def rm(token):
|
||||
"""
|
||||
Remove an API token.
|
||||
---
|
||||
tags:
|
||||
- API Tokens
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: token
|
||||
type: string
|
||||
required: true
|
||||
description: The API token to remove.
|
||||
responses:
|
||||
200:
|
||||
description: Token removed successfully.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
description: Deletion status.
|
||||
"""
|
||||
try:
|
||||
tenants = UserTenantService.query(user_id=current_user.id)
|
||||
if not tenants:
|
||||
return get_data_error_result(message="Tenant not found!")
|
||||
|
||||
tenant_id = tenants[0].tenant_id
|
||||
APITokenService.filter_delete([APIToken.tenant_id == tenant_id, APIToken.token == token])
|
||||
return get_json_result(data=True)
|
||||
except Exception as e:
|
||||
return server_error_response(e)
|
||||
@@ -17,25 +17,17 @@ import logging
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
from api.apps import login_required, current_user
|
||||
from api.apps import login_required
|
||||
|
||||
from api.db.db_models import APIToken
|
||||
from api.db.services.api_service import APITokenService
|
||||
from api.db.services.knowledgebase_service import KnowledgebaseService
|
||||
from api.db.services.user_service import UserTenantService
|
||||
from api.utils.api_utils import (
|
||||
get_json_result,
|
||||
get_data_error_result,
|
||||
server_error_response,
|
||||
generate_confirmation_token,
|
||||
)
|
||||
from common.time_utils import current_timestamp, datetime_format
|
||||
from common.log_utils import get_log_levels, set_log_level
|
||||
|
||||
from timeit import default_timer as timer
|
||||
|
||||
from rag.utils.redis_conn import REDIS_CONN
|
||||
from quart import jsonify
|
||||
from api.utils.health_utils import run_health_checks, get_oceanbase_status
|
||||
from api.utils.health_utils import get_oceanbase_status
|
||||
from common import settings
|
||||
|
||||
@manager.route("/status", methods=["GET"]) # noqa: F821
|
||||
@@ -146,18 +138,6 @@ def status():
|
||||
|
||||
return get_json_result(data=res)
|
||||
|
||||
|
||||
@manager.route("/healthz", methods=["GET"]) # noqa: F821
|
||||
def healthz():
|
||||
result, all_ok = run_health_checks()
|
||||
return jsonify(result), (200 if all_ok else 500)
|
||||
|
||||
|
||||
@manager.route("/ping", methods=["GET"]) # noqa: F821
|
||||
async def ping():
|
||||
return "pong", 200
|
||||
|
||||
|
||||
@manager.route("/oceanbase/status", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
def oceanbase_status():
|
||||
@@ -194,142 +174,6 @@ def oceanbase_status():
|
||||
)
|
||||
|
||||
|
||||
@manager.route("/new_token", methods=["POST"]) # noqa: F821
|
||||
@login_required
|
||||
def new_token():
|
||||
"""
|
||||
Generate a new API token.
|
||||
---
|
||||
tags:
|
||||
- API Tokens
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
parameters:
|
||||
- in: query
|
||||
name: name
|
||||
type: string
|
||||
required: false
|
||||
description: Name of the token.
|
||||
responses:
|
||||
200:
|
||||
description: Token generated successfully.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: The generated API token.
|
||||
"""
|
||||
try:
|
||||
tenants = UserTenantService.query(user_id=current_user.id)
|
||||
if not tenants:
|
||||
return get_data_error_result(message="Tenant not found!")
|
||||
|
||||
tenant_id = [tenant for tenant in tenants if tenant.role == "owner"][0].tenant_id
|
||||
obj = {
|
||||
"tenant_id": tenant_id,
|
||||
"token": generate_confirmation_token(),
|
||||
"beta": generate_confirmation_token().replace("ragflow-", "")[:32],
|
||||
"create_time": current_timestamp(),
|
||||
"create_date": datetime_format(datetime.now()),
|
||||
"update_time": None,
|
||||
"update_date": None,
|
||||
}
|
||||
|
||||
if not APITokenService.save(**obj):
|
||||
return get_data_error_result(message="Fail to new a dialog!")
|
||||
|
||||
return get_json_result(data=obj)
|
||||
except Exception as e:
|
||||
return server_error_response(e)
|
||||
|
||||
|
||||
@manager.route("/token_list", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
def token_list():
|
||||
"""
|
||||
List all API tokens for the current user.
|
||||
---
|
||||
tags:
|
||||
- API Tokens
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
responses:
|
||||
200:
|
||||
description: List of API tokens.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
tokens:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: The API token.
|
||||
name:
|
||||
type: string
|
||||
description: Name of the token.
|
||||
create_time:
|
||||
type: string
|
||||
description: Token creation time.
|
||||
"""
|
||||
try:
|
||||
tenants = UserTenantService.query(user_id=current_user.id)
|
||||
if not tenants:
|
||||
return get_data_error_result(message="Tenant not found!")
|
||||
|
||||
tenant_id = [tenant for tenant in tenants if tenant.role == "owner"][0].tenant_id
|
||||
objs = APITokenService.query(tenant_id=tenant_id)
|
||||
objs = [o.to_dict() for o in objs]
|
||||
for o in objs:
|
||||
if not o["beta"]:
|
||||
o["beta"] = generate_confirmation_token().replace("ragflow-", "")[:32]
|
||||
APITokenService.filter_update([APIToken.tenant_id == tenant_id, APIToken.token == o["token"]], o)
|
||||
return get_json_result(data=objs)
|
||||
except Exception as e:
|
||||
return server_error_response(e)
|
||||
|
||||
|
||||
@manager.route("/token/<token>", methods=["DELETE"]) # noqa: F821
|
||||
@login_required
|
||||
def rm(token):
|
||||
"""
|
||||
Remove an API token.
|
||||
---
|
||||
tags:
|
||||
- API Tokens
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: token
|
||||
type: string
|
||||
required: true
|
||||
description: The API token to remove.
|
||||
responses:
|
||||
200:
|
||||
description: Token removed successfully.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
description: Deletion status.
|
||||
"""
|
||||
try:
|
||||
tenants = UserTenantService.query(user_id=current_user.id)
|
||||
if not tenants:
|
||||
return get_data_error_result(message="Tenant not found!")
|
||||
|
||||
tenant_id = tenants[0].tenant_id
|
||||
APITokenService.filter_delete([APIToken.tenant_id == tenant_id, APIToken.token == token])
|
||||
return get_json_result(data=True)
|
||||
except Exception as e:
|
||||
return server_error_response(e)
|
||||
|
||||
|
||||
@manager.route("/config", methods=["GET"]) # noqa: F821
|
||||
def get_config():
|
||||
"""
|
||||
@@ -351,56 +195,3 @@ def get_config():
|
||||
"registerEnabled": settings.REGISTER_ENABLED,
|
||||
"disablePasswordLogin": settings.DISABLE_PASSWORD_LOGIN,
|
||||
})
|
||||
|
||||
|
||||
@manager.route("/log_levels", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
async def get_logger_levels():
|
||||
"""
|
||||
Get current log levels for all packages.
|
||||
---
|
||||
tags:
|
||||
- System
|
||||
responses:
|
||||
200:
|
||||
description: Return current log levels
|
||||
"""
|
||||
return get_json_result(data=get_log_levels())
|
||||
|
||||
|
||||
@manager.route("/log_levels", methods=["PUT"]) # noqa: F821
|
||||
@login_required
|
||||
async def set_logger_level():
|
||||
"""
|
||||
Set log level for a package.
|
||||
---
|
||||
tags:
|
||||
- System
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
pkg_name:
|
||||
type: string
|
||||
description: Package name (e.g., "rag.utils.es_conn")
|
||||
level:
|
||||
type: string
|
||||
description: Log level (DEBUG, INFO, WARNING, ERROR)
|
||||
responses:
|
||||
200:
|
||||
description: Log level updated successfully
|
||||
"""
|
||||
from quart import request
|
||||
data = await request.get_json()
|
||||
if not data or "pkg_name" not in data or "level" not in data:
|
||||
return get_data_error_result(message="pkg_name and level are required")
|
||||
pkg_name = data["pkg_name"]
|
||||
level = data["level"]
|
||||
success = set_log_level(pkg_name, level)
|
||||
if success:
|
||||
return get_json_result(data={"pkg_name": pkg_name, "level": level})
|
||||
else:
|
||||
return get_data_error_result(message=f"Invalid log level: {level}")
|
||||
|
||||
@@ -290,7 +290,7 @@ def get_redis_info():
|
||||
def check_ragflow_server_alive():
|
||||
start_time = timer()
|
||||
try:
|
||||
url = f'http://{settings.HOST_IP}:{settings.HOST_PORT}/v1/system/ping'
|
||||
url = f'http://{settings.HOST_IP}:{settings.HOST_PORT}/api/v1/system/ping'
|
||||
if '0.0.0.0' in url:
|
||||
url = url.replace('0.0.0.0', '127.0.0.1')
|
||||
response = requests.get(url)
|
||||
|
||||
@@ -6841,14 +6841,14 @@ Failure
|
||||
|
||||
### Check system health
|
||||
|
||||
**GET** `/v1/system/healthz`
|
||||
**GET** `/api/v1/system/healthz`
|
||||
|
||||
Check the health status of RAGFlow’s dependencies (database, Redis, document engine, object storage).
|
||||
|
||||
#### Request
|
||||
|
||||
- Method: GET
|
||||
- URL: `/v1/system/healthz`
|
||||
- URL: `/api/v1/system/healthz`
|
||||
- Headers:
|
||||
- 'Content-Type: application/json'
|
||||
(no Authorization required)
|
||||
@@ -6857,7 +6857,7 @@ Check the health status of RAGFlow’s dependencies (database, Redis, document e
|
||||
|
||||
```bash
|
||||
curl --request GET
|
||||
--url http://{address}/v1/system/healthz
|
||||
--url http://{address}/api/v1/system/healthz
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ def get_api_key_fixture():
|
||||
except Exception as e:
|
||||
print(e)
|
||||
auth = login()
|
||||
url = HOST_ADDRESS + "/v1/system/new_token"
|
||||
url = HOST_ADDRESS + "/v1/system/tokens"
|
||||
auth = {"Authorization": auth}
|
||||
response = requests.post(url=url, headers=auth)
|
||||
res = response.json()
|
||||
|
||||
@@ -45,7 +45,7 @@ def login_user(client: HttpClient, email: str, password_enc: str) -> str:
|
||||
def create_api_token(client: HttpClient, login_token: str, token_name: Optional[str] = None) -> str:
|
||||
client.login_token = login_token
|
||||
params = {"name": token_name} if token_name else None
|
||||
res = client.request_json("POST", "/system/new_token", use_api_base=False, auth_kind="login", params=params)
|
||||
res = client.request_json("POST", "/system/tokens", use_api_base=False, auth_kind="login", params=params)
|
||||
if res.get("code") != 0:
|
||||
raise AuthError(f"API token creation failed: {res.get('message')}")
|
||||
token = res.get("data", {}).get("token")
|
||||
|
||||
@@ -160,7 +160,7 @@ def auth():
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def token(auth):
|
||||
url = HOST_ADDRESS + f"/{VERSION}/system/new_token"
|
||||
url = HOST_ADDRESS + f"/api/{VERSION}/system/tokens"
|
||||
auth = {"Authorization": auth}
|
||||
response = requests.post(url=url, headers=auth)
|
||||
res = response.json()
|
||||
|
||||
@@ -94,17 +94,17 @@ def api_stats(auth, params=None, *, headers=HEADERS):
|
||||
|
||||
# SYSTEM APP
|
||||
def system_new_token(auth, payload=None, *, headers=HEADERS, data=None):
|
||||
res = requests.post(url=f"{HOST_ADDRESS}{SYSTEM_APP_URL}/new_token", headers=headers, auth=auth, json=payload, data=data)
|
||||
res = requests.post(url=f"{HOST_ADDRESS}{SYSTEM_API_URL}/tokens", headers=headers, auth=auth, json=payload, data=data)
|
||||
return res.json()
|
||||
|
||||
|
||||
def system_token_list(auth, params=None, *, headers=HEADERS):
|
||||
res = requests.get(url=f"{HOST_ADDRESS}{SYSTEM_APP_URL}/token_list", headers=headers, auth=auth, params=params)
|
||||
res = requests.get(url=f"{HOST_ADDRESS}{SYSTEM_API_URL}/tokens", headers=headers, auth=auth, params=params)
|
||||
return res.json()
|
||||
|
||||
|
||||
def system_delete_token(auth, token, *, headers=HEADERS):
|
||||
res = requests.delete(url=f"{HOST_ADDRESS}{SYSTEM_APP_URL}/token/{token}", headers=headers, auth=auth)
|
||||
res = requests.delete(url=f"{HOST_ADDRESS}{SYSTEM_API_URL}/tokens/{token}", headers=headers, auth=auth)
|
||||
return res.json()
|
||||
|
||||
|
||||
|
||||
@@ -214,106 +214,6 @@ def test_status_branch_matrix_unit(monkeypatch):
|
||||
assert "Lost connection!" in res["data"]["redis"]["error"]
|
||||
assert res["data"]["task_executor_heartbeats"] == {}
|
||||
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_healthz_and_oceanbase_status_matrix_unit(monkeypatch):
|
||||
module = _load_system_module(monkeypatch)
|
||||
|
||||
monkeypatch.setattr(module, "run_health_checks", lambda: ({"status": "ok"}, True))
|
||||
payload, status = module.healthz()
|
||||
assert status == 200
|
||||
assert payload["status"] == "ok"
|
||||
|
||||
monkeypatch.setattr(module, "run_health_checks", lambda: ({"status": "degraded"}, False))
|
||||
payload, status = module.healthz()
|
||||
assert status == 500
|
||||
assert payload["status"] == "degraded"
|
||||
|
||||
monkeypatch.setattr(module, "get_oceanbase_status", lambda: {"status": "alive", "latency_ms": 8})
|
||||
res = module.oceanbase_status()
|
||||
assert res["code"] == 0
|
||||
assert res["data"]["status"] == "alive"
|
||||
|
||||
monkeypatch.setattr(module, "get_oceanbase_status", lambda: (_ for _ in ()).throw(RuntimeError("ocean boom")))
|
||||
res = module.oceanbase_status()
|
||||
assert res["code"] == 500
|
||||
assert res["data"]["status"] == "error"
|
||||
assert "ocean boom" in res["data"]["message"]
|
||||
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_system_token_routes_matrix_unit(monkeypatch):
|
||||
module = _load_system_module(monkeypatch)
|
||||
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: [])
|
||||
res = module.new_token()
|
||||
assert res["message"] == "Tenant not found!"
|
||||
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: [SimpleNamespace(role="owner", tenant_id="tenant-1")])
|
||||
monkeypatch.setattr(module.APITokenService, "save", lambda **_kwargs: False)
|
||||
res = module.new_token()
|
||||
assert res["message"] == "Fail to new a dialog!"
|
||||
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: (_ for _ in ()).throw(RuntimeError("tenant query boom")))
|
||||
res = module.new_token()
|
||||
assert res["code"] == 100
|
||||
assert "tenant query boom" in res["message"]
|
||||
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: [])
|
||||
res = module.token_list()
|
||||
assert res["message"] == "Tenant not found!"
|
||||
|
||||
class _Token:
|
||||
def __init__(self, token, beta):
|
||||
self.token = token
|
||||
self.beta = beta
|
||||
|
||||
def to_dict(self):
|
||||
return {"token": self.token, "beta": self.beta}
|
||||
|
||||
filter_updates = []
|
||||
monkeypatch.setattr(module, "generate_confirmation_token", lambda: "ragflow-abcdefghijklmnopqrstuvwxyz0123456789")
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: [SimpleNamespace(role="owner", tenant_id="tenant-9")])
|
||||
monkeypatch.setattr(module.APITokenService, "query", lambda **_kwargs: [_Token("tok-1", ""), _Token("tok-2", "beta-2")])
|
||||
monkeypatch.setattr(module.APITokenService, "filter_update", lambda conds, payload: filter_updates.append((conds, payload)))
|
||||
res = module.token_list()
|
||||
assert res["code"] == 0
|
||||
assert len(res["data"]) == 2
|
||||
assert len(res["data"][0]["beta"]) == 32
|
||||
assert res["data"][1]["beta"] == "beta-2"
|
||||
assert len(filter_updates) == 1
|
||||
|
||||
monkeypatch.setattr(
|
||||
module.APITokenService,
|
||||
"query",
|
||||
lambda **_kwargs: (_ for _ in ()).throw(RuntimeError("token list boom")),
|
||||
)
|
||||
res = module.token_list()
|
||||
assert res["code"] == 100
|
||||
assert "token list boom" in res["message"]
|
||||
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: [])
|
||||
res = module.rm("tok-1")
|
||||
assert res["message"] == "Tenant not found!"
|
||||
|
||||
deleted = []
|
||||
monkeypatch.setattr(module.UserTenantService, "query", lambda **_kwargs: [SimpleNamespace(role="owner", tenant_id="tenant-3")])
|
||||
monkeypatch.setattr(module.APITokenService, "filter_delete", lambda conds: deleted.append(conds))
|
||||
res = module.rm("tok-1")
|
||||
assert res["code"] == 0
|
||||
assert res["data"] is True
|
||||
assert deleted
|
||||
|
||||
monkeypatch.setattr(
|
||||
module.APITokenService,
|
||||
"filter_delete",
|
||||
lambda _conds: (_ for _ in ()).throw(RuntimeError("delete boom")),
|
||||
)
|
||||
res = module.rm("tok-1")
|
||||
assert res["code"] == 100
|
||||
assert "delete boom" in res["message"]
|
||||
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_get_config_returns_register_enabled_unit(monkeypatch):
|
||||
module = _load_system_module(monkeypatch)
|
||||
|
||||
@@ -171,9 +171,9 @@ export default {
|
||||
|
||||
// system
|
||||
getSystemVersion: `${restAPIv1}/system/version`,
|
||||
getSystemTokenList: `${webAPI}/system/token_list`,
|
||||
createSystemToken: `${webAPI}/system/new_token`,
|
||||
removeSystemToken: `${webAPI}/system/token`,
|
||||
getSystemTokenList: `${restAPIv1}/system/tokens`,
|
||||
createSystemToken: `${restAPIv1}/system/tokens`,
|
||||
removeSystemToken: `${restAPIv1}/system/tokens`,
|
||||
getSystemConfig: `${webAPI}/system/config`,
|
||||
setLangfuseConfig: `${webAPI}/langfuse/api_key`,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user