summaryrefslogtreecommitdiff
path: root/lib/api/project_export.rb
blob: e4e950fb603cd0f89d0074ace9b8b22e7e5ea2bc (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
172
173
174
175
176
177
178
179
180
181
182
183
184
# frozen_string_literal: true

module API
  class ProjectExport < ::API::Base
    feature_category :importers
    urgency :low

    before do
      not_found! unless Gitlab::CurrentSettings.project_export_enabled?
      authorize_admin_project
    end

    params do
      requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
    end
    resource :projects, requirements: { id: %r{[^/]+} } do
      desc 'Get export status' do
        detail 'This feature was introduced in GitLab 10.6.'
        success code: 200, model: Entities::ProjectExportStatus
        failure [
          { code: 401, message: 'Unauthorized' },
          { code: 403, message: 'Forbidden' },
          { code: 404, message: 'Not found' },
          { code: 503, message: 'Service unavailable' }
        ]
        tags ['project_export']
      end
      get ':id/export' do
        present user_project, with: Entities::ProjectExportStatus
      end

      desc 'Download export' do
        detail 'This feature was introduced in GitLab 10.6.'
        success code: 200
        failure [
          { code: 401, message: 'Unauthorized' },
          { code: 403, message: 'Forbidden' },
          { code: 404, message: 'Not found' },
          { code: 503, message: 'Service unavailable' }
        ]
        tags ['project_export']
        produces %w[application/octet-stream application/json]
      end
      get ':id/export/download' do
        check_rate_limit! :project_download_export, scope: [current_user, user_project.namespace]

        if user_project.export_file_exists?
          if user_project.export_archive_exists?
            present_carrierwave_file!(user_project.export_file)
          else
            render_api_error!('The project export file is not available yet', 404)
          end
        else
          render_api_error!('404 Not found or has expired', 404)
        end
      end

      desc 'Start export' do
        detail 'This feature was introduced in GitLab 10.6.'
        success code: 202
        failure [
          { code: 400, message: 'Bad request' },
          { code: 401, message: 'Unauthorized' },
          { code: 403, message: 'Forbidden' },
          { code: 404, message: 'Not found' },
          { code: 429, message: 'Too many requests' },
          { code: 503, message: 'Service unavailable' }
        ]
        tags ['project_export']
      end
      params do
        optional :description, type: String, desc: 'Override the project description'
        optional :upload, type: Hash do
          optional :url, type: String, desc: 'The URL to upload the project'
          optional :http_method, type: String, default: 'PUT', values: %w[PUT POST],
                                 desc: 'HTTP method to upload the exported project'
        end
      end
      post ':id/export' do
        check_rate_limit! :project_export, scope: current_user

        user_project.remove_exports

        project_export_params = declared_params(include_missing: false)
        after_export_params = project_export_params.delete(:upload) || {}

        export_strategy = if after_export_params[:url].present?
                            params = after_export_params.slice(:url, :http_method).symbolize_keys

                            Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy.new(**params)
                          end

        if export_strategy&.invalid?
          render_validation_error!(export_strategy)
        else
          begin
            user_project.add_export_job(current_user: current_user,
                                        after_export_strategy: export_strategy,
                                        params: project_export_params)
          rescue Project::ExportLimitExceeded => e
            render_api_error!(e.message, 400)
          end
        end

        accepted!
      end

      resource do
        before do
          not_found! unless ::Feature.enabled?(:bulk_import)
        end

        desc 'Start relations export' do
          detail 'This feature was introduced in GitLab 14.4'
          success code: 202
          failure [
            { code: 400, message: 'Bad request' },
            { code: 401, message: 'Unauthorized' },
            { code: 403, message: 'Forbidden' },
            { code: 404, message: 'Not found' },
            { code: 503, message: 'Service unavailable' }
          ]
          tags ['project_export']
        end
        post ':id/export_relations' do
          response = ::BulkImports::ExportService.new(portable: user_project, user: current_user).execute

          if response.success?
            accepted!
          else
            render_api_error!('Project relations export could not be started.', 500)
          end
        end

        desc 'Download relations export' do
          detail 'This feature was introduced in GitLab 14.4'
          success code: 200
          failure [
            { code: 400, message: 'Bad request' },
            { code: 401, message: 'Unauthorized' },
            { code: 403, message: 'Forbidden' },
            { code: 404, message: 'Not found' },
            { code: 500, message: 'Internal Server Error' },
            { code: 503, message: 'Service unavailable' }
          ]
          tags ['project_export']
          produces %w[application/octet-stream application/json]
        end
        params do
          requires :relation,
                   type: String,
                   project_portable: true,
                   desc: 'Project relation name'
        end
        get ':id/export_relations/download' do
          export = user_project.bulk_import_exports.find_by_relation(params[:relation])
          file = export&.upload&.export_file

          if file
            present_carrierwave_file!(file)
          else
            render_api_error!('404 Not found', 404)
          end
        end

        desc 'Relations export status' do
          detail 'This feature was introduced in GitLab 14.4'
          is_array true
          success code: 200, model: Entities::BulkImports::ExportStatus
          failure [
            { code: 401, message: 'Unauthorized' },
            { code: 403, message: 'Forbidden' },
            { code: 404, message: 'Not found' },
            { code: 503, message: 'Service unavailable' }
          ]
          tags ['project_export']
        end
        get ':id/export_relations/status' do
          present user_project.bulk_import_exports, with: Entities::BulkImports::ExportStatus
        end
      end
    end
  end
end