File: members_helpers.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (155 lines) | stat: -rw-r--r-- 5,364 bytes parent folder | download
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# frozen_string_literal: true

module API
  module Helpers
    module MembersHelpers
      extend Grape::API::Helpers

      params :optional_filter_params_ee do
      end

      params :optional_state_filter_ee do
      end

      params :optional_put_params_ee do
      end

      def find_source(source_type, id)
        public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
      end

      def authorize_read_source_member!(source_type, source)
        authorize! :"read_#{source_type}_member", source
      end

      def authorize_admin_source_member!(source_type, source)
        authorize! :"admin_#{source_type}_member", source
      end

      def authorize_update_source_member!(source_type, member)
        authorize! :"update_#{source_type}_member", member
      end

      def authorize_admin_source!(source_type, source)
        authorize! :"admin_#{source_type}", source
      end

      # rubocop: disable CodeReuse/ActiveRecord
      def retrieve_members(source, params:, deep: false)
        members = deep ? find_all_members(source) : source_members(source).connected_to_user
        members = members.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
        members = members.includes(:user)
        members = members.references(:user).merge(User.search(params[:query], use_minimum_char_limit: false)) if params[:query].present?
        members = members.where(user_id: params[:user_ids]) if params[:user_ids].present?
        members
      end

      def retrieve_member_invitations(source, query = nil)
        members = source_members(source).where.not(invite_token: nil)
        members = members.includes(:user)
        members = members.where(invite_email: query) if query.present?
        members
      end

      def source_members(source)
        return source.namespace_members if source.is_a?(Project)

        source.members
      end
      # rubocop: enable CodeReuse/ActiveRecord

      def find_all_members(source)
        members = source.is_a?(Project) ? find_all_members_for_project(source) : find_all_members_for_group(source)
        members.non_invite.non_request
      end

      def find_all_members_for_project(project)
        include_relations = [:inherited, :direct, :invited_groups, :shared_into_ancestors]
        MembersFinder.new(project, current_user).execute(include_relations: include_relations)
      end

      def find_all_members_for_group(group)
        GroupMembersFinder.new(group, current_user).execute(include_relations: [:inherited, :direct, :shared_from_groups])
      end

      def present_members(members)
        present members, with: Entities::Member, current_user: current_user, show_seat_info: params[:show_seat_info]
      end

      def present_member_invitations(invitations)
        present invitations, with: Entities::Invitation, current_user: current_user
      end

      def present_members_with_invited_private_group_accessibility(members, source)
        ::Members::InvitedPrivateGroupAccessibilityAssigner
          .new(members, source: source, current_user: current_user)
          .execute

        present_members members
      end

      def add_single_member(create_service_params)
        check_existing_membership(create_service_params)

        instance = ::Members::CreateService.new(current_user, create_service_params)
        result = instance.execute

        # This currently can only be reached in EE if group membership is locked
        not_allowed! if instance.membership_locked

        if result[:status] == :error && result[:http_status] == :unauthorized
          raise Gitlab::Access::AccessDeniedError
        end

        # prefer responding with model validations, if present
        member = instance.single_member
        render_validation_error!(member) if member&.invalid?

        present_add_single_member_response(result, member)
      end

      def present_put_membership_response(result)
        updated_member = result[:members].first

        if result[:status] == :success
          present_members updated_member
        else
          render_validation_error!(updated_member)
        end
      end

      def check_existing_membership(create_service_params)
        user_id = User.get_ids_by_ids_or_usernames(create_service_params[:user_id], create_service_params[:username]).first

        not_found!('User') unless user_id
        conflict!('Member already exists') if member_already_exists?(create_service_params[:source], user_id)
      end

      def add_multiple_members?(user_id, username)
        user_id&.include?(',') || username&.include?(',')
      end

      def self.member_access_levels
        Gitlab::Access.all_values
      end

      private

      def member_already_exists?(source, user_id)
        source.members.exists?(user_id: user_id) # rubocop: disable CodeReuse/ActiveRecord
      end

      def present_add_single_member_response(result, member)
        # if errors occurred besides model validations or authorization failures,
        # render those appropriately
        if result[:status] == :error
          render_structured_api_error!(result, :bad_request)
        else
          present_members(member)
        end
      end
    end
  end
end

API::Helpers::MembersHelpers.prepend_mod_with('API::Helpers::MembersHelpers')