[Task] Tools: `PortletID.TOOLS`, tools catalog endpoints and custom-tool gate on `/v1/portlet`
@hassandotcms is already working on this.
Since Sep 16, 2026.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Context
The Tools portlet's Available Tools panel lists every tool that can be placed in a navigation section and offers New Tool, Edit and Delete for custom content tools. Today the list of placeable tools is available only through the Dojo remoting layer behind the Roles & Tools screen, which the Angular portlet cannot call. Custom content tools can already be created, updated and deleted over REST, but only by users who hold the Roles portlet, there is no way to read one back in the shape the Edit dialog needs, and the delete does not check that its target is a custom tool. There is no tools portlet id to gate any of this on.
This task delivers the portlet-side backend for that panel. The section endpoints under /v1/layouts are #37353, which depends on the portlet id added here.
Requirements
Tools catalog
- The system exposes a catalog of every tool that can be placed in a navigation section. It applies the same inclusion rules as the legacy Roles & Tools picker: tools the product marks as not placeable are excluded, and the legacy Languages tool is excluded while the configuration that hides it is on.
- Each catalog entry carries the tool's id, its title localized to the caller's language, and an
isCustomflag. Entries are unique and sorted by title, ignoring letter case. isCustomis true only for tools created at runtime as custom content tools. It is determined by how the tool was registered, not by the spelling of its id; thec_prefix is a convention, not a contract.- When a title has no translation for the caller's language, the entry shows the name the tool was given at creation (custom tools only), and failing that its id. It never shows a raw translation key.
- A tool created, updated or deleted through any operation below appears, changes or disappears in the next catalog read.
Custom content tool read
- The system exposes a read of one custom content tool by id returning its id, name, base types and content types as lists, and its data view mode as stored (
listorcard, lowercase). An unknown id, or the id of a tool that is not a custom content tool, is answered with not found.
Tools portlet id
- The product's portlet id registry contains an entry resolving to
tools, so this task and #37353 have an id to gate on and #37356 has an id to promote to.
Access
- The catalog and the single-tool read require an authenticated backend user who holds a granted section containing
toolsortools-beta, or is a CMS Administrator. Both ids are required because access is exact membership of the id in the user's sections and the portlet admins add during Beta istools-beta. Any other caller is rejected with 401, the response every portlet-gated endpoint gives today. - Custom-tool create, update and delete accept a caller who holds
roles,toolsortools-beta, or is a CMS Administrator, so Roles admins keep working and Tools-only admins can create custom tools. Their request and response contracts do not change. The gate moves totoolsalone in #37356, once the Dojo tab that creates tools from the Roles screen is retired. - The custom-tool delete refuses, with not found and without changing any data, any id that is not a custom content tool. Today it removes whatever id it is given, shipped or custom, from every section on the instance.
- The operation that adds a tool to a section the caller holds keeps its Roles-only gate. It accepts any placeable tool, so widening it would let a Tools holder add the Roles or Users tool to their own section. The Tools portlet does not use it.
Documentation
- Every endpoint added or changed is described in the generated API documentation with response schemas that match what is returned.
Must keep working
- The Dojo Roles & Tools screen, which creates and deletes custom tools through the same REST operations and fetches the catalog through remoting.
- The Angular Add to menu dialog on the Content Types listing, which creates a custom tool and adds it to a section. It sends the data view mode in lowercase.
- The
PortletResourcePostman collection.
The frontend PR #37481 currently sends the data view mode as List / Card and maps its delete to the role-scoped remove; both change when it wires the real endpoints.
Out of scope
- Section create, update, delete, reorder and tool assignment (#37353).
- The Dojo JSPs and
RoleAjaxremoting methods. - The role-scoped removes
DELETE /v1/portlet/portletId/{id}and.../roleId/{roleId}. - A licence check; no sibling admin endpoint has one.
- The equivalent
roles-betaversusrolesgate gap.
Acceptance criteria
- The catalog returns only placeable tools, sorted by title, with
isCustomtrue only for custom tools, and omits the legacy Languages tool when the hide flag is on. - The single-tool read returns name, id, base types, content types and data view mode; not found for an unknown or non-custom id.
- Catalog and single read reject an unauthenticated caller and a backend user with neither
toolsnortools-betawith 401; a non-admin with onlytools-betapasses. - A non-admin with only
tools-betacan create, update and delete a custom tool; one with onlyrolesstill can; one with onlytools-betais still rejected when adding a tool to a section. - Deleting
rolesthrough the custom-tool delete returns not found androlesremains in every section that had it; deleting a custom id works as before. - The Dojo screen and the Add to menu dialog still create, add and delete custom tools for a Roles holder.
- The Postman collection stays green.
- Response schemas match; the regenerated
openapi.yamlis committed.
Definition of Done
- New:
GET /v1/portlet(catalog) andGET /v1/portlet/custom/{portletId}(single custom tool), gated ontools/tools-beta. - Modified:
POST/PUT /v1/portlet/customandDELETE /v1/portlet/custom/{portletId}acceptrolesortools/tools-beta; the delete refuses non-custom ids. Contracts otherwise unchanged. TOOLSadded to the portlet id registry.- Every endpoint annotated for the API documentation;
openapi.yamlregenerated and committed. - Integration tests for catalog filtering and
isCustom, the single-tool read, the delete guard and every access combination above, registered in aMainSuiteso CI runs them. - Dojo screen, remoting methods and Add to menu unchanged in behaviour.
Refs #37353
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.