feat: intégration TikTak #197-200 + scoped tokens, webhooks filtrés, listes mtime/size ; fix e2e-server BUG-112
This commit is contained in:
@@ -43,6 +43,7 @@ from backend.auth.middleware import get_current_user, is_auth_enabled
|
||||
from backend.services.files import read_file_text
|
||||
from backend.services.vaults import list_accessible_vaults
|
||||
from backend.tools.api import (
|
||||
FILES_SCOPE_TOOLS,
|
||||
ToolContext,
|
||||
ToolError,
|
||||
ToolMode,
|
||||
@@ -191,6 +192,14 @@ def _tool_definitions() -> list[types.Tool]:
|
||||
return definitions
|
||||
|
||||
|
||||
def _mcp_base_name(mcp_name: str) -> str:
|
||||
"""Strip the ``propose_``/``apply_`` prefix back to the registry tool name."""
|
||||
for prefix in ("propose_", "apply_"):
|
||||
if mcp_name.startswith(prefix):
|
||||
return mcp_name[len(prefix):]
|
||||
return mcp_name
|
||||
|
||||
|
||||
def _parse_vault_uri(uri: str) -> tuple[str, str]:
|
||||
"""Split ``vault://name/path`` into ``(vault, path)``."""
|
||||
parsed = urlparse(uri)
|
||||
@@ -208,6 +217,10 @@ def build_server() -> Server:
|
||||
# ── Tools ──────────────────────────────────────────────────────────
|
||||
@server.list_tools()
|
||||
async def _list_tools() -> list[types.Tool]:
|
||||
# #199 : un token à portée "files" ne voit que les outils fichiers.
|
||||
user = _user_from_context(server)
|
||||
if (user.get("_token_scope") or "full") == "files":
|
||||
return [t for t in _tool_definitions() if _mcp_base_name(t.name) in FILES_SCOPE_TOOLS]
|
||||
return _tool_definitions()
|
||||
|
||||
@server.call_tool()
|
||||
@@ -262,6 +275,7 @@ def build_server() -> Server:
|
||||
user = _user_from_context(server)
|
||||
vault, path = _parse_vault_uri(str(uri))
|
||||
ctx = ToolContext(user=user, mode=ToolMode.MCP)
|
||||
ctx.require_tool_allowed("read_file") # #199 : portée inconnue → refus
|
||||
ctx.require_vault_access(vault)
|
||||
data = read_file_text(vault, path, redact=True, max_bytes=MAX_RESOURCE_BYTES)
|
||||
mime = "text/markdown" if Path(path).suffix.lower() == ".md" else "text/plain"
|
||||
@@ -352,6 +366,12 @@ def _propose(user: dict[str, Any], tool: str, arguments: dict[str, Any]) -> list
|
||||
params = spec.input_model.model_validate(arguments)
|
||||
vault = getattr(params, "vault", None)
|
||||
ctx = ToolContext(user=user, mode=ToolMode.MCP)
|
||||
# #199 : les tokens à portée limitée ne peuvent proposer que les outils
|
||||
# fichiers (même garde que call_tool, qui couvre apply_).
|
||||
try:
|
||||
ctx.require_tool_allowed(tool)
|
||||
except ToolError as e:
|
||||
return _text(e.to_dict())
|
||||
if vault and vault != "all":
|
||||
ctx.require_vault_access(vault)
|
||||
if spec.risk == ToolRisk.DANGEROUS:
|
||||
|
||||
Reference in New Issue
Block a user