summaryrefslogtreecommitdiff
path: root/lib/api/groups.rb
blob: 605769edddee5ec39224a79a4541ea01d9e90934 (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
module API
  class Groups < Grape::API
    include PaginationParams

    before { authenticate! }

    helpers do
      params :optional_params do
        optional :description, type: String, desc: 'The description of the group'
        optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the group'
        optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
        optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
      end

      params :statistics_params do
        optional :statistics, type: Boolean, default: false, desc: 'Include project statistics'
      end

      def present_groups(groups, options = {})
        options = options.reverse_merge(
          with: Entities::Group,
          current_user: current_user,
        )

        groups = groups.with_statistics if options[:statistics]
        present paginate(groups), options
      end
    end

    resource :groups do
      desc 'Get a groups list' do
        success Entities::Group
      end
      params do
        use :statistics_params
        optional :skip_groups, type: Array[Integer], desc: 'Array of group ids to exclude from list'
        optional :all_available, type: Boolean, desc: 'Show all group that you have access to'
        optional :search, type: String, desc: 'Search for a specific group'
        optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user'
        optional :order_by, type: String, values: %w[name path], default: 'name', desc: 'Order by name or path'
        optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
        use :pagination
      end
      get do
        groups = if params[:owned]
                   current_user.owned_groups
                 elsif current_user.admin
                   Group.all
                 elsif params[:all_available]
                   GroupsFinder.new.execute(current_user)
                 else
                   current_user.groups
                 end

        groups = groups.search(params[:search]) if params[:search].present?
        groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
        groups = groups.reorder(params[:order_by] => params[:sort])

        present_groups groups, statistics: params[:statistics] && current_user.is_admin?
      end

      desc 'Create a group. Available only for users who can create groups.' do
        success Entities::Group
      end
      params do
        requires :name, type: String, desc: 'The name of the group'
        requires :path, type: String, desc: 'The path of the group'
        optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group'
        use :optional_params
      end
      post do
        authorize! :create_group

        group = ::Groups::CreateService.new(current_user, declared_params(include_missing: false)).execute

        if group.persisted?
          present group, with: Entities::Group, current_user: current_user
        else
          render_api_error!("Failed to save group #{group.errors.messages}", 400)
        end
      end
    end

    params do
      requires :id, type: String, desc: 'The ID of a group'
    end
    resource :groups, requirements: { id: %r{[^/]+} } do
      desc 'Update a group. Available only for users who can administrate groups.' do
        success Entities::Group
      end
      params do
        optional :name, type: String, desc: 'The name of the group'
        optional :path, type: String, desc: 'The path of the group'
        use :optional_params
        at_least_one_of :name, :path, :description, :visibility,
                        :lfs_enabled, :request_access_enabled
      end
      put ':id' do
        group = find_group!(params[:id])
        authorize! :admin_group, group

        if ::Groups::UpdateService.new(group, current_user, declared_params(include_missing: false)).execute
          present group, with: Entities::GroupDetail, current_user: current_user
        else
          render_validation_error!(group)
        end
      end

      desc 'Get a single group, with containing projects.' do
        success Entities::GroupDetail
      end
      get ":id" do
        group = find_group!(params[:id])
        present group, with: Entities::GroupDetail, current_user: current_user
      end

      desc 'Remove a group.'
      delete ":id" do
        group = find_group!(params[:id])
        authorize! :admin_group, group
        ::Groups::DestroyService.new(group, current_user).execute
      end

      desc 'Get a list of projects in this group.' do
        success Entities::Project
      end
      params do
        optional :archived, type: Boolean, default: false, desc: 'Limit by archived status'
        optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values,
                              desc: 'Limit by visibility'
        optional :search, type: String, desc: 'Return list of authorized projects matching the search criteria'
        optional :order_by, type: String, values: %w[id name path created_at updated_at last_activity_at],
                            default: 'created_at', desc: 'Return projects ordered by field'
        optional :sort, type: String, values: %w[asc desc], default: 'desc',
                        desc: 'Return projects sorted in ascending and descending order'
        optional :simple, type: Boolean, default: false,
                          desc: 'Return only the ID, URL, name, and path of each project'
        optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user'
        optional :starred, type: Boolean, default: false, desc: 'Limit by starred status'

        use :pagination
      end
      get ":id/projects" do
        group = find_group!(params[:id])
        projects = GroupProjectsFinder.new(group: group, current_user: current_user).execute
        projects = filter_projects(projects)
        entity = params[:simple] ? Entities::BasicProjectDetails : Entities::Project
        present paginate(projects), with: entity, current_user: current_user
      end

      desc 'Transfer a project to the group namespace. Available only for admin.' do
        success Entities::GroupDetail
      end
      params do
        requires :project_id, type: String, desc: 'The ID or path of the project'
      end
      post ":id/projects/:project_id", requirements: { project_id: /.+/ } do
        authenticated_as_admin!
        group = find_group!(params[:id])
        project = find_project!(params[:project_id])
        result = ::Projects::TransferService.new(project, current_user).execute(group)

        if result
          present group, with: Entities::GroupDetail, current_user: current_user
        else
          render_api_error!("Failed to transfer project #{project.errors.messages}", 400)
        end
      end
    end
  end
end