Skip to content

Fix approval groups finder

Marcos Rocha requested to merge mc_rocha-fix-approval-groups-finder into master

What does this MR do and why?

This MR updates the query to find the accessible groups to the user in the approval group finder.

Database queries

This MR relies on the scope accessible_to_user introduced by this MR.

SELECT
    namespaces.*
FROM
    "namespaces"
WHERE
    "namespaces"."type" = 'Group'
    AND "namespaces"."id" IN (70820400, 86692579)

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/28694/commands/89387

app/models/preloaders/user_max_access_level_in_groups_preloader.rb:24:

def preload_with_traversal_ids
      # Diagrammatic representation of this step:
      # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111157#note_1271550140
      max_access_levels = GroupMember.from_union(all_memberships)
                            .joins("INNER JOIN (#{traversal_join_sql}) as hierarchy ON members.source_id = hierarchy.traversal_id")
                            .group('hierarchy.id')
                            .maximum(:access_level)

      @groups.each do |group|
        max_access_level = max_access_levels[group.id] || Gitlab::Access::NO_ACCESS
        group.merge_value_to_request_store(User, @user.id, max_access_level)
      end
    end
SELECT
    MAX("members"."access_level") AS "maximum_access_level",
    "hierarchy"."id" AS "hierarchy_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",
            "members"."member_role_id",
            "members"."expiry_notified_at",
            "members"."request_accepted_at",
            "members"."last_activity_on"
        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"."user_id" = 9430722
    /* allow_cross_joins_across_databases */)
UNION (
    SELECT
        "members"."id",
        LEAST ("group_group_links"."group_access", "members"."access_level") AS access_level,
        "group_group_links"."shared_group_id" AS 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",
        "members"."member_role_id",
        "members"."expiry_notified_at",
        "members"."request_accepted_at",
        "members"."last_activity_on"
    FROM
        "members"
    LEFT OUTER JOIN "users" ON "users"."id" = "members"."user_id"
INNER JOIN group_group_links ON members.source_id = group_group_links.shared_with_group_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"."user_id" = 9430722
    /* allow_cross_joins_across_databases */)) members
    INNER JOIN (
        SELECT
            id,
            unnest(traversal_ids) AS traversal_id
        FROM
            "namespaces"
        WHERE
            "namespaces"."id" IN (70820400, 86692579)) AS hierarchy ON members.source_id = hierarchy.traversal_id
WHERE
    "members"."type" = 'GroupMember'
    AND "members"."source_type" = 'Namespace'
GROUP BY
    "hierarchy"."id"

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/28694/commands/89393

SELECT
    namespaces.*,
    root_query.id AS source_id
FROM
    "namespaces"
    INNER JOIN (
        SELECT
            id,
            traversal_ids[1] AS root_id
        FROM
            "namespaces"
        WHERE
            "namespaces"."type" = 'Group'
            AND "namespaces"."id" IN (70820400, 86692579)) AS root_query ON root_query.root_id = namespaces.id

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/28694/commands/89394

SELECT
    1 AS one
FROM
    "organization_users"
WHERE
    "organization_users"."user_id" = 9430722
    AND "organization_users"."organization_id" = 1
    AND "organization_users"."access_level" = 50
LIMIT 1

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/28694/commands/89395

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Marcos Rocha

Merge request reports