mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
tools service: restore FilterFactory + per-hit auth parity for lazy listings and search
This commit is contained in:
@@ -41,10 +41,7 @@ from galaxy.tool_util.toolbox.base import ToolConfRepository
|
||||
from galaxy.util.tool_version import remove_version_from_guid
|
||||
from galaxy.tool_util.parser import get_tool_source
|
||||
from galaxy.tool_util.toolbox.lineages.interface import ToolLineage
|
||||
from galaxy.tool_util.toolbox.panel import (
|
||||
panel_item_types,
|
||||
ToolSection,
|
||||
)
|
||||
from galaxy.tool_util.toolbox.panel import ToolSection
|
||||
from . import (
|
||||
create_tool_from_source,
|
||||
ToolBox,
|
||||
@@ -1240,33 +1237,7 @@ class LazyToolBox(ToolBox):
|
||||
]
|
||||
return []
|
||||
|
||||
# === Override to_dict for API responses ===
|
||||
|
||||
def to_dict(
|
||||
self, trans, in_panel: bool = True, tool_help: bool = False, view: Optional[str] = None, **kwds
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Toolbox API serialisation.
|
||||
|
||||
For ``in_panel=False`` (the flat ``/api/tools`` listing the
|
||||
Galaxy client uses), walk ``_tools_by_id`` directly: every value
|
||||
is a ``LazyTool`` stub or a real ``Tool``, both implement
|
||||
``ToolFilterContext`` (``allow_user_access``, ``require_login``,
|
||||
``tool_type``, ...) and ``to_dict(link_details=False)`` returns
|
||||
the listing-shaped dict from the entry without parsing XML.
|
||||
|
||||
For ``in_panel=True`` (the section-aware response), defer to the
|
||||
parent — it walks the eager-populated ``_tool_panel_view_rendered``
|
||||
which already holds ``LazyTool`` stubs from the seam-driven boot.
|
||||
"""
|
||||
if in_panel:
|
||||
return super().to_dict(trans, in_panel=True, tool_help=tool_help, view=view, **kwds)
|
||||
|
||||
filter_method = self._build_filter_method(trans)
|
||||
rval = []
|
||||
for _tool_id, tool in list(self._tools_by_id.items()):
|
||||
if not filter_method(tool, panel_item_types.TOOL):
|
||||
continue
|
||||
rval.append(tool.to_dict(trans, link_details=False))
|
||||
|
||||
log.debug("LazyToolBox.to_dict: returning %d tools (in_panel=False)", len(rval))
|
||||
return rval
|
||||
# ``to_dict`` is NOT overridden: ``AbstractToolBox.to_dict`` runs the
|
||||
# ``FilterFactory`` pass for both the panel and the flat listing, and
|
||||
# its ``get_tool_to_dict`` serves ``LazyTool`` stubs via
|
||||
# ``to_panel_entry`` — filtered AND non-materialising.
|
||||
|
||||
@@ -656,11 +656,12 @@ class ToolsService(ServiceBase):
|
||||
For panel listings or when the index is unavailable, falls back to the
|
||||
traditional toolbox.
|
||||
"""
|
||||
if not in_panel:
|
||||
lazy_toolbox = self._get_lazy_toolbox(trans)
|
||||
if lazy_toolbox and lazy_toolbox.tool_index:
|
||||
entries = lazy_toolbox.tool_index.list_all()
|
||||
return [entry.to_api_dict() for entry in entries]
|
||||
# Both modes go through ``AbstractToolBox.to_dict``: the flat listing
|
||||
# runs the ``FilterFactory`` pass (admin/user tool filters and
|
||||
# ``allow_user_access``) over every tool, and ``get_tool_to_dict``
|
||||
# serves ``LazyTool`` stubs from the index without materialising —
|
||||
# so lazy mode stays O(1) parses while honoring the same filters as
|
||||
# the eager toolbox.
|
||||
return trans.app.toolbox.to_dict(trans, in_panel=in_panel, tool_help=tool_help, view=view)
|
||||
|
||||
def search_tools(
|
||||
@@ -677,5 +678,21 @@ class ToolsService(ServiceBase):
|
||||
:class:`ToolBoxSearch` walking ``tool_cache``. Both expose the same
|
||||
``search(q, panel_view, config)`` interface, so this method doesn't
|
||||
branch on which toolbox flavour is active.
|
||||
|
||||
Every hit is resolved through :meth:`_get_tool` so per-tool access
|
||||
control (``allow_user_access``, e.g. ``require_login`` tools for
|
||||
anonymous users) filters the results — same contract as the old
|
||||
controller loop. In lazy mode ``get_tool`` returns the registered
|
||||
``LazyTool`` stub, so this does not materialise the hits.
|
||||
"""
|
||||
return list(self._search(query, view) or [])
|
||||
results: list[str] = []
|
||||
for hit in self._search(query, view) or []:
|
||||
try:
|
||||
tool = self._get_tool(trans, hit, user=trans.user)
|
||||
if tool:
|
||||
results.append(tool.id)
|
||||
except exceptions.AuthenticationFailed:
|
||||
pass
|
||||
except exceptions.ObjectNotFound:
|
||||
pass
|
||||
return results
|
||||
|
||||
Reference in New Issue
Block a user