Skip to content

Improve epics finder group authorizations

Felipe Artur requested to merge issue_327901 into master

What does this MR do and why?

Small refactoring that allows saving some queries skipping authorization checks for groups when a user has access and can read epics on their parent.

This is a temporary improvement until transversal ids are not enabled to query groups.

Sample logs

No queries are going to be changed with this MR. We are actually skipping queries
for group descendants array when checking permissions, the array is already loaded into memory. To compare queries ran I did set up a hierarchy of groups with 40 descendants, which produced the following results:

Query saved for each descendant group
SELECT Max("members"."access_level") AS maximum_access_level,
       "members"."user_id"           AS members_user_id
FROM   (
       (
                       SELECT          "members"."id",
                                       "members"."access_level",
                                       "members"."source_id",
                                       "members"."source_type",
                                       "members"."user_id",
                                       "members"."notification_level",
                                       "members"."type",
                                       "members"."created_at",
                                       "members"."updated_at",
                                       "members"."created_by_id",
                                       "members"."invite_email",
                                       "members"."invite_token",
                                       "members"."invite_accepted_at",
                                       "members"."requested_at",
                                       "members"."expires_at",
                                       "members"."ldap",
                                       "members"."override",
                                       "members"."state",
                                       "members"."invite_email_success",
                                       "members"."member_namespace_id"
                       FROM            "members"
                       LEFT OUTER JOIN "users"
                       ON              "users"."id" = "members"."user_id"
                       WHERE           "members"."type" = 'GroupMember'
                       AND             "members"."source_type" = 'Namespace'
                       AND             "users"."state" = 'active'
                       AND             "members"."state" = 0
                       AND             "members"."requested_at" IS NULL
                       AND             "members"."invite_token" IS NULL
                       AND             (
                                                       members.access_level > 5)
                       AND             (
                                                       members.access_level > 5)
                       AND             "members"."source_id" IN
                                       (
                                              SELECT "namespaces"."id"
                                              FROM   "namespaces"
                                              WHERE  "namespaces"."type" = 'Group'
                                              AND    "namespaces"."id" IN (184,
                                                                           197,
                                                                           198,
                                                                           199,
                                                                           200,
                                                                           201,
                                                                           202,
                                                                           203,
                                                                           204,
                                                                           205,
                                                                           206,
                                                                           207,
                                                                           208,
                                                                           209,
                                                                           210,
                                                                           211,
                                                                           212)))
UNION
      (WITH "group_group_links_cte" AS materialized
      (
             SELECT "group_group_links".*
             FROM   "group_group_links"
             WHERE  "group_group_links"."shared_group_id" IN
                    (
                           SELECT "namespaces"."id"
                           FROM   "namespaces"
                           WHERE  "namespaces"."type" = 'Group'
                           AND    "namespaces"."id" IN (184,
                                                        197,
                                                        198,
                                                        199,
                                                        200,
                                                        201,
                                                        202,
                                                        203,
                                                        204,
                                                        205,
                                                        206,
                                                        207,
                                                        208,
                                                        209,
                                                        210,
                                                        211,
                                                        212)))SELECT   "members"."id",
         Least("group_group_links"."group_access", "members"."access_level") AS access_level,
         "members"."source_id",
         "members"."source_type",
         "members"."user_id",
         "members"."notification_level",
         "members"."type",
         "members"."created_at",
         "members"."updated_at",
         "members"."created_by_id",
         "members"."invite_email",
         "members"."invite_token",
         "members"."invite_accepted_at",
         "members"."requested_at",
         "members"."expires_at",
         "members"."ldap",
         "members"."override",
         "members"."state",
         "members"."invite_email_success",
         "members"."member_namespace_id"
FROM     "members",
         "group_group_links_cte" AS "group_group_links"
WHERE    "members"."type" = 'GroupMember'
AND      "members"."source_type" = 'Namespace'
AND      "members"."requested_at" IS NULL
AND      "members"."source_id" = "group_group_links"."shared_with_group_id"
AND      "members"."source_type" = 'Namespace'
AND      "members"."state" = 0
AND      (
                  members.access_level > 5))) members
WHERE    "members"."type" = 'GroupMember'
AND      "members"."source_type" = 'Namespace'
AND      "members"."user_id" = 85
GROUP BY "members"."user_id"

The new filter will give us some advantage in some specific scenarios, especially when the user is fetching epics on a group in which it has membership and has too many descendants.

This filtering is a bit sensitive, so the new filtering method with improvements is behind a feature flag: :find_epics_performance_improvement.

related to #327901 (closed)

How to set up and validate locally

Run the spec added to ee/spec/finders/epics_finder_spec.rb and check for logs/test.log

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Felipe Artur

Merge request reports