`User#authorized_groups` does not return every group the user is authorized to see
If we take a closer look at how User#authorized_groups
is implemented we can see that it only returns groups where the user has direct access, or one of the user projects belongs to a certain group.
The behavior should instead be:
-
User#authorized_groups
returns all expanded groups- For a sub-group, it will return its parent/s and child groups
This can be done by changing the implementation to make use of the Gitlab::GroupHierarchy#all_groups
method which expands all groups the user has access to. This method is already being used by GroupsFinder
.
We could change the User#authorized_groups
implementation to something like the following:
def authorized_groups
union = Gitlab::SQL::Union
.new([groups.select(:id), authorized_projects.select(:namespace_id)])
groups_for_ancestors = Group.where("namespaces.id IN (#{union.to_sql})")
groups_for_descendants = groups
Gitlab::GroupHierarchy.new(groups_for_ancestors, groups_for_descendants).all_groups
end
There is one caveat though, this approach is extremely inefficient (EXPLAIN_authorized_groups__1_.txt)
Based on a previous discussion with @DouweM and @yorickpeterse, we previously had a similar problem with the authorized projects, which we solved by making an intermediate table that holds the authorized_projects
for a user, maybe we could do something like this for the groups as well?