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
|
# frozen_string_literal: true
module API
module Helpers
module PackagesHelpers
extend ::Gitlab::Utils::Override
include ::Gitlab::Utils::StrongMemoize
MAX_PACKAGE_FILE_SIZE = 50.megabytes.freeze
def require_packages_enabled!
not_found! unless ::Gitlab.config.packages.enabled
end
def require_dependency_proxy_enabled!
not_found! unless ::Gitlab.config.dependency_proxy.enabled
end
def authorize_admin_package!(subject = user_project)
authorize!(:admin_package, subject)
end
def authorize_read_package!(subject = user_project)
authorize!(:read_package, subject.try(:packages_policy_subject) || subject)
end
def authorize_create_package!(subject = user_project)
authorize!(:create_package, subject)
end
def authorize_destroy_package!(subject = user_project)
authorize!(:destroy_package, subject)
end
def authorize_packages_access!(subject = user_project, required_permission = :read_package)
require_packages_enabled!
case required_permission
when :read_package
authorize_read_package!(subject)
when :read_package_within_public_registries
authorize!(required_permission, subject.packages_policy_subject)
when :read_group
authorize!(required_permission, subject)
else
forbidden!
end
end
def authorize_workhorse!(
subject: user_project,
has_length: true,
maximum_size: MAX_PACKAGE_FILE_SIZE,
use_final_store_path: false)
authorize_upload!(subject)
status 200
content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
params = { has_length: has_length, use_final_store_path: use_final_store_path }
params[:maximum_size] = maximum_size unless has_length
params[:final_store_path_root_id] = subject.id if use_final_store_path
::Packages::PackageFileUploader.workhorse_authorize(**params)
end
def authorize_upload!(subject = user_project)
authorize_create_package!(subject)
require_gitlab_workhorse!
end
override :user_project
def user_project(action: :read_project)
case action
when :read_project
super()
when :read_package
user_project_with_read_package
else
raise ArgumentError, "unexpected action: #{action}"
end
end
# This function is similar to the `find_project!` function, but it considers the `read_package` ability.
def user_project_with_read_package
project = find_project(params[:id])
return forbidden! unless authorized_project_scope?(project)
return project if can?(current_user, :read_package, project&.packages_policy_subject)
# guest users can have :read_project but not :read_package
return forbidden! if can?(current_user, :read_project, project)
return unauthorized! if authenticate_non_public?
not_found!('Project')
end
strong_memoize_attr :user_project_with_read_package
def track_package_event(action, scope, **args)
service = ::Packages::CreateEventService.new(
args[:project],
current_user,
namespace: args[:namespace],
event_name: action,
scope: scope
)
service.execute
category = args.delete(:category) || self.options[:for].name
args[:user] = current_user if current_user
event_name = "i_package_#{scope}_user"
::Gitlab::Tracking.event(
category,
action.to_s,
property: event_name,
label: 'redis_hll_counters.user_packages.user_packages_total_unique_counts_monthly',
context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event_name).to_context],
**args
)
if action.to_s == 'push_package' && service.originator_type == :deploy_token
track_snowplow_event(
'push_package_by_deploy_token',
'package_pushed_using_deploy_token',
category,
args
)
elsif action.to_s == 'pull_package' && service.originator_type == :guest
track_snowplow_event(
'pull_package_by_guest',
'package_pulled_by_guest',
category,
args
)
end
end
def present_package_file!(package_file, supports_direct_download: true, content_disposition: nil)
package_file.package.touch_last_downloaded_at
present_carrierwave_file!(
package_file.file,
supports_direct_download: supports_direct_download,
content_disposition: content_disposition
)
end
private
def track_snowplow_event(action_name, snowplow_event_name, category, args)
event_name = "i_package_#{action_name}"
key_path = "counts.package_events_i_package_#{action_name}"
context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis, event: snowplow_event_name).to_context
Gitlab::Tracking.event(
category,
action_name,
property: event_name,
label: key_path,
context: [context],
**args
)
end
end
end
end
|