summaryrefslogtreecommitdiff
path: root/lib/api/members.rb
blob: 03f45858a3322a4d115ba65fb530ac7e1cda17e1 (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
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
# frozen_string_literal: true

module API
  class Members < Grape::API
    include PaginationParams

    before { authenticate! }

    helpers ::API::Helpers::MembersHelpers

    %w[group project].each do |source_type|
      params do
        requires :id, type: String, desc: "The #{source_type} ID"
      end
      resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
        desc _('Gets a list of group or project members viewable by the authenticated user.') do
          success Entities::Member
        end
        params do
          optional :query, type: String, desc: 'A query string to search for members'
          use :pagination
        end
        # rubocop: disable CodeReuse/ActiveRecord
        get ":id/members" do
          source = find_source(source_type, params[:id])

          members = source.members.where.not(user_id: nil).includes(:user)
          members = members.joins(:user).merge(User.search(params[:query])) if params[:query].present?
          members = paginate(members)

          present members, with: Entities::Member
        end
        # rubocop: enable CodeReuse/ActiveRecord

        desc _('Gets a list of group or project members viewable by the authenticated user, including those who gained membership through ancestor group.') do
          success Entities::Member
        end
        params do
          optional :query, type: String, desc: 'A query string to search for members'
          use :pagination
        end
        # rubocop: disable CodeReuse/ActiveRecord
        get ":id/members/all" do
          source = find_source(source_type, params[:id])

          members = find_all_members(source_type, source)
          members = members.includes(:user).references(:user).merge(User.search(params[:query])) if params[:query].present?
          members = paginate(members)

          present members, with: Entities::Member
        end
        # rubocop: enable CodeReuse/ActiveRecord

        desc _('Gets a member of a group or project.') do
          success Entities::Member
        end
        params do
          requires :user_id, type: Integer, desc: 'The user ID of the member'
        end
        # rubocop: disable CodeReuse/ActiveRecord
        get ":id/members/:user_id" do
          source = find_source(source_type, params[:id])

          members = source.members
          member = members.find_by!(user_id: params[:user_id])

          present member, with: Entities::Member
        end
        # rubocop: enable CodeReuse/ActiveRecord

        desc _('Adds a member to a group or project.') do
          success Entities::Member
        end
        params do
          requires :user_id, type: Integer, desc: 'The user ID of the new member'
          requires :access_level, type: Integer, desc: 'A valid access level (defaults: `30`, developer access level)'
          optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
        end
        # rubocop: disable CodeReuse/ActiveRecord
        post ":id/members" do
          source = find_source(source_type, params[:id])
          authorize_admin_source!(source_type, source)

          member = source.members.find_by(user_id: params[:user_id])
          conflict!('Member already exists') if member

          user = User.find_by_id(params[:user_id])
          not_found!('User') unless user

          member = source.add_user(user, params[:access_level], current_user: current_user, expires_at: params[:expires_at])

          if !member
            not_allowed! # This currently can only be reached in EE
          elsif member.persisted? && member.valid?
            present member, with: Entities::Member
          else
            render_validation_error!(member)
          end
        end
        # rubocop: enable CodeReuse/ActiveRecord

        desc _('Updates a member of a group or project.') do
          success Entities::Member
        end
        params do
          requires :user_id, type: Integer, desc: 'The user ID of the new member'
          requires :access_level, type: Integer, desc: 'A valid access level'
          optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
        end
        # rubocop: disable CodeReuse/ActiveRecord
        put ":id/members/:user_id" do
          source = find_source(source_type, params.delete(:id))
          authorize_admin_source!(source_type, source)

          member = source.members.find_by!(user_id: params[:user_id])
          updated_member =
            ::Members::UpdateService
              .new(current_user, declared_params(include_missing: false))
              .execute(member)

          if updated_member.valid?
            present updated_member, with: Entities::Member
          else
            render_validation_error!(updated_member)
          end
        end
        # rubocop: enable CodeReuse/ActiveRecord

        desc _('Removes a user from a group or project.')
        params do
          requires :user_id, type: Integer, desc: 'The user ID of the member'
        end
        # rubocop: disable CodeReuse/ActiveRecord
        delete ":id/members/:user_id" do
          source = find_source(source_type, params[:id])
          member = source.members.find_by!(user_id: params[:user_id])

          destroy_conditionally!(member) do
            ::Members::DestroyService.new(current_user).execute(member)
          end
        end
        # rubocop: enable CodeReuse/ActiveRecord
      end
    end
  end
end