Skip to content

Abilities API: Name the author of a core/content-query post only to users who may see them - #14654

Closed
jorgefilipecosta wants to merge 1 commit into
WordPress:trunkfrom
jorgefilipecosta:fix/content-query-author-visibility
Closed

jorgefilipecosta wants to merge 1 commit into
WordPress:trunkfrom
jorgefilipecosta:fix/content-query-author-visibility

Conversation

@jorgefilipecosta

@jorgefilipecosta jorgefilipecosta commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Follow up to https://core.trac.wordpress.org/changeset/64388 and https://core.trac.wordpress.org/changeset/64680.

What

  • author.name and author.slug of a core/content-query post are now null for an author the current user may not see, as they already are for an author who no longer exists. The author ID is still returned.
  • The author slug filter matches no post for such a user, as it already does for a slug that names no user, so the filter cannot confirm a slug the field withholds. The author ID filter still matches the stored author.

Why

  • The ability returned the name and slug for every readable post, and the slug filter named any user of the site. The rule is now one: the current user may see themselves, the users they can edit, every user when they can list users, and otherwise the authors of published posts in a post type exposed to abilities (show_in_abilities), where the ability already returns the author. Which post types the REST API exposes plays no part.

How

  • A private get_visible_author() holds the rule and is used by the author field and by the author slug filter. The post count is kept per author for the query, since count_user_posts() is not cached, and only runs when the name or slug is requested or the slug filter is given.
  • The output and filter descriptions and the class description say so.
  • Tests: one data provider over the roles and post statuses, with the author reading their own post, which also checks the slug filter agrees with the field; one over a post type exposed to abilities only and one exposed to the REST API only; one that the count runs once per author, is shared by the filter and the field, and does not run for author.id alone.

The change was drafted with AI assistance and reviewed by me.

Trac ticket: https://core.trac.wordpress.org/ticket/66268

Testing

Verify unit tests are passing:

npm run test:php -- --filter test_author_

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

Core Committers: Use this line as a base for the props when committing in SVN:

Props jorgefilipecosta, gziolo.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@jorgefilipecosta
jorgefilipecosta force-pushed the fix/content-query-author-visibility branch from 0705f0e to 82cdce2 Compare October 21, 2026 16:49
* @param int $user_id The author's user ID.
* @return WP_User|null The author, or null when they no longer exist or may not be seen.
*/
private function get_visible_author( int $user_id ): ?WP_User {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! Hiding the name and slug of authors the user may not see makes sense.

I have one concern. This rule depends on show_in_rest, but this ability should not depend on REST API settings. A post type can be exposed to abilities without being exposed to REST.

This class also already has a visibility rule in get_author_by_slug(), which the author_slug filter uses. The two rules give different results. For example, an Editor gets null for the author of a Contributor's pending post. But the same Editor can filter with where[author_slug]=hidden-contributor and get that post back. So the slug is still exposed.

Could we move the rule from get_author_by_slug() into one shared helper and use it in both places? Then the filter and the output always agree, with no link to REST.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @gziolo, thank you, the feedback was applied. get_author_by_slug() was already replaced by the author object filter in https://core.trac.wordpress.org/changeset/64680, so the shared rule now lives in get_visible_author(), used by both the author field and the author slug filter. The rule counts published posts in the post types exposed to abilities (show_in_abilities) instead of the REST ones, since the ability already returns those posts with their author. Tests cover the filter agreeing with the field for each role, and a post type exposed to abilities only against one exposed to the REST API only.

@jorgefilipecosta
jorgefilipecosta force-pushed the fix/content-query-author-visibility branch from 82cdce2 to 7a8f585 Compare October 22, 2026 15:05
… users who may see them.

The `core/content-query` ability returned the author's display name and
slug for every post the current user can read, and its `author` slug
filter named any user of the site.

Return them only to users who may see the author: the author themselves,
users who can edit them or list users, and otherwise users who can read
a published post of theirs in a post type exposed to abilities, where
the ability already returns the author. `author.name` and `author.slug`
are null for other users, as they already are for an author who no
longer exists, and the `author` slug filter matches no post for them, as
it already does for a slug that names no user, so the filter cannot
confirm a slug the field withholds. The author ID is still returned, and
the `author` ID filter still matches the stored author. The lookup runs
once per author and query, and only when the name or slug is requested
or the slug filter is given.

Follow-up to [64388], [64680].

See #66268.
@jorgefilipecosta
jorgefilipecosta force-pushed the fix/content-query-author-visibility branch from 7a8f585 to 79a8d16 Compare October 22, 2026 15:21
@jorgefilipecosta jorgefilipecosta changed the title Abilities API: Match the REST users controller for the author of a core/content-query post Abilities API: Name the author of a core/content-query post only to users who may see them Oct 22, 2026

@gziolo gziolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for addressing all feedback.

@jorgefilipecosta

Copy link
Copy Markdown
Member Author

Committed at 38a613a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants