Welcome to mirror list, hosted at ThFree Co, Russian Federation.

group.rb « models « user_mentions « background_migration « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bc04172b9a232769fa62387e9b74cdea839c6f95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# frozen_string_literal: true

module Gitlab
  module BackgroundMigration
    module UserMentions
      module Models
        # isolated Group model
        class Group < ::Gitlab::BackgroundMigration::UserMentions::Models::Namespace
          self.store_full_sti_class = false
          has_one :saml_provider

          def self.declarative_policy_class
            "GroupPolicy"
          end

          def max_member_access_for_user(user)
            return GroupMember::NO_ACCESS unless user

            return GroupMember::OWNER if user.admin?

            max_member_access = members_with_parents.where(user_id: user)
                                  .reorder(access_level: :desc)
                                  .first
                                  &.access_level

            max_member_access || GroupMember::NO_ACCESS
          end

          def members_with_parents
            # Avoids an unnecessary SELECT when the group has no parents
            source_ids =
              if has_parent?
                self_and_ancestors.reorder(nil).select(:id)
              else
                id
              end

            group_hierarchy_members = GroupMember.active_without_invites_and_requests
                                        .where(source_id: source_ids)

            GroupMember.from_union([group_hierarchy_members,
                                    members_from_self_and_ancestor_group_shares])
          end

          # rubocop: disable Metrics/AbcSize
          def members_from_self_and_ancestor_group_shares
            group_group_link_table = GroupGroupLink.arel_table
            group_member_table = GroupMember.arel_table

            source_ids =
              if has_parent?
                self_and_ancestors.reorder(nil).select(:id)
              else
                id
              end

            group_group_links_query = GroupGroupLink.where(shared_group_id: source_ids)
            cte = Gitlab::SQL::CTE.new(:group_group_links_cte, group_group_links_query)
            cte_alias = cte.table.alias(GroupGroupLink.table_name)

            # Instead of members.access_level, we need to maximize that access_level at
            # the respective group_group_links.group_access.
            member_columns = GroupMember.attribute_names.map do |column_name|
              if column_name == 'access_level'
                smallest_value_arel([cte_alias[:group_access], group_member_table[:access_level]],
                                    'access_level')
              else
                group_member_table[column_name]
              end
            end

            GroupMember
              .with(cte.to_arel)
              .select(*member_columns)
              .from([group_member_table, cte.alias_to(group_group_link_table)])
              .where(group_member_table[:requested_at].eq(nil))
              .where(group_member_table[:source_id].eq(group_group_link_table[:shared_with_group_id]))
              .where(group_member_table[:source_type].eq('Namespace'))
          end
          # rubocop: enable Metrics/AbcSize

          def smallest_value_arel(args, column_alias)
            Arel::Nodes::As.new(
              Arel::Nodes::NamedFunction.new('LEAST', args),
              Arel::Nodes::SqlLiteral.new(column_alias))
          end
        end
      end
    end
  end
end