summaryrefslogtreecommitdiff
path: root/lib/api/debian_project_packages.rb
blob: 353f64b8dd1ff43016c91bcf7f991bcb0d7320cf (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
# frozen_string_literal: true

module API
  class DebianProjectPackages < ::API::Base
    PACKAGE_FILE_REQUIREMENTS = {
      id: API::NO_SLASH_URL_PART_REGEX,
      distribution: ::Packages::Debian::DISTRIBUTION_REGEX,
      letter: ::Packages::Debian::LETTER_REGEX,
      package_name: API::NO_SLASH_URL_PART_REGEX,
      package_version: API::NO_SLASH_URL_PART_REGEX,
      file_name: API::NO_SLASH_URL_PART_REGEX
    }.freeze
    FILE_NAME_REQUIREMENTS = {
      file_name: API::NO_SLASH_URL_PART_REGEX
    }.freeze

    before do
      not_found! if Gitlab::FIPS.enabled?
    end

    resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
      helpers do
        def project_or_group
          user_project(action: :read_package)
        end
      end

      after_validation do
        require_packages_enabled!

        not_found! unless ::Feature.enabled?(:debian_packages, project_or_group)

        authorize_read_package!(project_or_group)
      end

      params do
        requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
      end

      namespace ':id/packages/debian' do
        include ::API::Concerns::Packages::DebianPackageEndpoints

        # GET projects/:id/packages/debian/pool/:distribution/:letter/:package_name/:package_version/:file_name
        params do
          use :shared_package_file_params
        end

        desc 'Download Debian package' do
          detail 'This feature was introduced in GitLab 14.2'
          success code: 200
          failure [
            { code: 401, message: 'Unauthorized' },
            { code: 403, message: 'Forbidden' },
            { code: 404, message: 'Not Found' }
          ]
          tags %w[debian_packages]
        end

        route_setting :authentication, authenticate_non_public: true
        get 'pool/:distribution/:letter/:package_name/:package_version/:file_name', requirements: PACKAGE_FILE_REQUIREMENTS do
          present_distribution_package_file!(project_or_group)
        end

        params do
          requires :file_name, type: String, desc: 'The file name', documentation: { example: 'example_1.0.0~alpha2_amd64.deb' }
        end

        namespace ':file_name', requirements: FILE_NAME_REQUIREMENTS do
          format :txt
          content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE

          desc 'Upload Debian package' do
            detail 'This feature was introduced in GitLab 14.0'
            success code: 201
            failure [
              { code: 400, message: 'Bad Request' },
              { code: 401, message: 'Unauthorized' },
              { code: 403, message: 'Forbidden' },
              { code: 404, message: 'Not Found' }
            ]
            tags %w[debian_packages]
          end

          # PUT {projects|groups}/:id/packages/debian/:file_name
          params do
            requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' }
          end

          route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
          put do
            authorize_upload!(authorized_user_project)
            bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size)

            file_params = {
              file: params['file'],
              file_name: params['file_name'],
              file_sha1: params['file.sha1'],
              file_md5: params['file.md5']
            }

            package = ::Packages::Debian::FindOrCreateIncomingService.new(authorized_user_project, current_user).execute

            ::Packages::Debian::CreatePackageFileService.new(package: package, current_user: current_user, params: file_params).execute

            created!
          rescue ObjectStorage::RemoteStoreError => e
            Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: authorized_user_project.id })

            forbidden!
          end

          # PUT {projects|groups}/:id/packages/debian/:file_name/authorize
          desc 'Authorize Debian package upload' do
            detail 'This feature was introduced in GitLab 13.5'
            success code: 200
            failure [
              { code: 401, message: 'Unauthorized' },
              { code: 403, message: 'Forbidden' },
              { code: 404, message: 'Not Found' }
            ]
            tags %w[debian_packages]
          end
          route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
          put 'authorize' do
            authorize_workhorse!(
              subject: authorized_user_project,
              maximum_size: authorized_user_project.actual_limits.debian_max_file_size
            )
          end
        end
      end
    end
  end
end