rag/wwwroot/knowledge_bases_list/api_key_create.dspy
ymq 00262a6d2a feat(rag-api): 对外B2B API+内部tools包装
- wwwroot/api/ 六个对外端点(Bearer Key 鉴权,路由授 any、业务鉴权在 api_core):
  kb_create/kb_delete/doc_upload/doc_delete/tag_create/doc_set_tags/search
- rag/api_core.py: verify_api_key + make_api_env(org注入) + 六个业务核心
  (复用 init.py 底层检索/入库能力,杜绝双实现分叉)
- 统一返回格式 {"status":"ok"|"error","data":...}
- rag/ingest.py: 入库管线从 upload_file.dspy 抽出共享(UI/API同一引擎)
- rag/tools.py: RAG_TOOL_SCHEMAS + exec_rag_tool(与API同构,供内部助手调用)
- rag_api_keys 表 model(key 只存 SHA256);管理端 api_key_create/list/revoke
- load_path.py 注册 7 个 API 端点(any) + 3 个管理端点(logined)
2026-09-03 15:51:19 +08:00

43 lines
2.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 管理端:创建对外 API Key登录用户org 取自会话)
# POST /rag/knowledge_bases_list/api_key_create.dspy
# params: {name, scopes?, expires_days?}
# 返回 widget一次性展示明文 key库里只存 SHA256
import secrets
from rag import api_core as C
ns = params_kw.copy()
env = request._run_ns
org_id = await env.get_userorgid()
name = (ns.get('name') or '默认密钥').strip()
scopes = ns.get('scopes') or ''
if isinstance(scopes, (list, tuple)):
scopes = ','.join(str(x) for x in scopes)
scopes = str(scopes).strip() or 'kb.create,kb.delete,doc.upload,doc.delete,tag.write,search'
try:
exp_days = int(ns.get('expires_days') or 0)
except (TypeError, ValueError):
exp_days = 0
plain = 'rag-' + secrets.token_hex(24)
kid = str(uuid()).replace('-', '')[:16]
db = DBPools()
async with db.sqlorContext(get_module_dbname('rag')) as sor:
if exp_days > 0:
await sor.sqlExe(
"INSERT INTO rag_api_keys (id, org_id, name, key_hash, prefix, scopes, status, expires_at, created_at) "
"VALUES (${id}$, ${o}$, ${n}$, ${h}$, ${p}$, ${s}$, 'active', DATE_ADD(NOW(), INTERVAL ${d}$ DAY), NOW())",
{"id": kid, "o": org_id, "n": name, "h": C.hash_key(plain),
"p": plain[:12], "s": scopes, "d": exp_days})
else:
await sor.sqlExe(
"INSERT INTO rag_api_keys (id, org_id, name, key_hash, prefix, scopes, status, created_at) "
"VALUES (${id}$, ${o}$, ${n}$, ${h}$, ${p}$, ${s}$, 'active', NOW())",
{"id": kid, "o": org_id, "n": name, "h": C.hash_key(plain), "p": plain[:12], "s": scopes})
await sor.sqlExe("COMMIT", {})
return {"widgettype": "VBox", "options": {"padding": "12px", "spacing": "8px"}, "subwidgets": [
{"widgettype": "Text", "options": {"text": "✅ API Key 已创建(仅此一次展示,请立即保存)", "cfontsize": 15, "color": "#10b981"}},
{"widgettype": "Text", "options": {"text": plain, "cfontsize": 13, "bgcolor": "#f5f7fa", "padding": "8px", "css": "selectable monospace"}},
{"widgettype": "Text", "options": {"text": "名称: " + name + " · 范围: " + scopes, "cfontsize": 12, "color": "#888"}},
]}