diff options
Diffstat (limited to 'lib/gitlab/background_migration/user_mentions/models/group.rb')
-rw-r--r-- | lib/gitlab/background_migration/user_mentions/models/group.rb | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/gitlab/background_migration/user_mentions/models/group.rb b/lib/gitlab/background_migration/user_mentions/models/group.rb new file mode 100644 index 00000000000..bc04172b9a2 --- /dev/null +++ b/lib/gitlab/background_migration/user_mentions/models/group.rb @@ -0,0 +1,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 |