Authorize group milestones in milestone search
What
Let group milestone documents pass the authorization filter so they show up in results, and route group-level milestone searches by both routing keys.
Changes
ee/lib/search/elastic/milestone_query_builder.rbandee/lib/gitlab/elastic/search_results.rb: group milestone documents don't haveissues_access_level/merge_requests_access_level, so the currentfeatures: [:issues, :merge_requests]filter drops them. Add group-level authorization based on group membership and group visibility, modeled on work items (by_combined_search_level_and_membership).- Add
group: :routeto the milestone eager load inee/lib/gitlab/elastic/search_results.rb, to avoid an N+1 when rendering group milestones. - Route group-level milestone searches by both keys:
n_<root_ancestor_id>for group milestones andproject_<id>for the group's projects, as a comma-separated routing list.Elastic::Latest::Routingcaps this at 128 values; beyond that, leave routing off. Project milestones keepproject_<id>and group milestones usen_<root_ancestor_id>since #630654 (closed).
Why project and group milestones need different authorization
A project milestone is only readable if the user can access the project's issues or merge requests. ProjectPolicy (app/policies/project_policy.rb):
rule { issues_disabled & merge_requests_disabled }.policy do
prevent :read_milestone"Disabled" is per user: a feature set to "Only project members" counts as disabled for a non-member. This is why project milestone documents index issues_access_level and merge_requests_access_level, and why milestone search passes features: [:issues, :merge_requests]. The filter checks those fields on every access path: public/internal projects need ENABLED for non-members, members need ENABLED or PRIVATE plus the feature's minimum role (with a relaxed merge requests rule that lets Guest and Planner members see milestones), and admins need ENABLED or PRIVATE.
A group milestone works differently. It is readable by anyone who can read the group. GroupPolicy (app/policies/group_policy.rb):
rule { can?(:read_group) }.policy do
enable :read_milestoneGroups have no issues or merge requests feature settings, so group milestone documents don't have, and shouldn't get, those two fields. The new filter branch for group milestones must mirror read_group instead: group visibility for non-members, and the same membership rules as read_group for private groups, with no dependency on *_access_level fields. Project milestones keep their current rules unchanged.
This also means the earlier thread comment saying "the same *_access_level fields will apply" doesn't hold for group milestones.
Depends on
#630654 (closed) (group milestone fields, routing, indexing and sync).
Notes
This corrects the implementation plan, which says the query builder needs no changes.
Part of #428589. Based on the implementation plan.