2018-12-05 23:21:45 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
# This concern assumes:
|
2021-01-29 00:20:46 +05:30
|
|
|
# - a `#container` accessor
|
2017-08-17 22:00:37 +05:30
|
|
|
# - a `#project` accessor
|
|
|
|
# - a `#user` accessor
|
2021-10-27 15:23:28 +05:30
|
|
|
# - a `#deploy_token` accessor
|
2017-08-17 22:00:37 +05:30
|
|
|
# - a `#authentication_result` accessor
|
|
|
|
# - a `#can?(object, action, subject)` method
|
|
|
|
# - a `#ci?` method
|
|
|
|
# - a `#download_request?` method
|
|
|
|
# - a `#upload_request?` method
|
|
|
|
# - a `#has_authentication_ability?(ability)` method
|
|
|
|
module LfsRequest
|
|
|
|
extend ActiveSupport::Concern
|
2021-01-29 00:20:46 +05:30
|
|
|
include Gitlab::Utils::StrongMemoize
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2019-12-04 20:38:33 +05:30
|
|
|
CONTENT_TYPE = 'application/vnd.git-lfs+json'
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
included do
|
|
|
|
before_action :require_lfs_enabled!
|
|
|
|
before_action :lfs_check_access!
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
2016-11-24 13:41:30 +05:30
|
|
|
|
2016-09-13 17:45:13 +05:30
|
|
|
def require_lfs_enabled!
|
|
|
|
return if Gitlab.config.lfs.enabled
|
|
|
|
|
|
|
|
render(
|
|
|
|
json: {
|
2019-07-07 11:18:12 +05:30
|
|
|
message: _('Git LFS is not enabled on this GitLab server, contact your admin.'),
|
2017-09-10 17:25:29 +05:30
|
|
|
documentation_url: help_url
|
2016-09-13 17:45:13 +05:30
|
|
|
},
|
2021-01-29 00:20:46 +05:30
|
|
|
content_type: CONTENT_TYPE,
|
2018-11-18 11:00:15 +05:30
|
|
|
status: :not_implemented
|
2016-09-13 17:45:13 +05:30
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def lfs_check_access!
|
2021-01-29 00:20:46 +05:30
|
|
|
return render_lfs_not_found unless container&.lfs_enabled?
|
2016-09-13 17:45:13 +05:30
|
|
|
return if download_request? && lfs_download_access?
|
|
|
|
return if upload_request? && lfs_upload_access?
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
# Only return a 403 response if the user has download access permission,
|
|
|
|
# otherwise return a 404 to avoid exposing the existence of the container.
|
|
|
|
if lfs_download_access?
|
2017-08-17 22:00:37 +05:30
|
|
|
lfs_forbidden!
|
2016-09-13 17:45:13 +05:30
|
|
|
else
|
|
|
|
render_lfs_not_found
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
def lfs_forbidden!
|
|
|
|
render_lfs_forbidden
|
2016-09-13 17:45:13 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def render_lfs_forbidden
|
|
|
|
render(
|
|
|
|
json: {
|
2019-07-07 11:18:12 +05:30
|
|
|
message: _('Access forbidden. Check your access level.'),
|
2017-09-10 17:25:29 +05:30
|
|
|
documentation_url: help_url
|
2016-09-13 17:45:13 +05:30
|
|
|
},
|
2018-03-17 18:26:18 +05:30
|
|
|
content_type: CONTENT_TYPE,
|
2019-12-26 22:10:19 +05:30
|
|
|
status: :forbidden
|
2016-09-13 17:45:13 +05:30
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def render_lfs_not_found
|
|
|
|
render(
|
|
|
|
json: {
|
2019-07-07 11:18:12 +05:30
|
|
|
message: _('Not found.'),
|
2017-09-10 17:25:29 +05:30
|
|
|
documentation_url: help_url
|
2016-09-13 17:45:13 +05:30
|
|
|
},
|
2018-03-17 18:26:18 +05:30
|
|
|
content_type: CONTENT_TYPE,
|
2019-12-26 22:10:19 +05:30
|
|
|
status: :not_found
|
2016-09-13 17:45:13 +05:30
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
def lfs_download_access?
|
2021-01-29 00:20:46 +05:30
|
|
|
strong_memoize(:lfs_download_access) do
|
|
|
|
ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? || deploy_token_can_download_code?
|
|
|
|
end
|
2018-11-18 11:00:15 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def deploy_token_can_download_code?
|
2021-10-27 15:23:28 +05:30
|
|
|
deploy_token.present? &&
|
2018-11-18 11:00:15 +05:30
|
|
|
deploy_token.project == project &&
|
|
|
|
deploy_token.active? &&
|
|
|
|
deploy_token.read_repository?
|
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
def lfs_upload_access?
|
2021-01-29 00:20:46 +05:30
|
|
|
strong_memoize(:lfs_upload_access) do
|
|
|
|
next false unless has_authentication_ability?(:push_code)
|
|
|
|
next false if limit_exceeded?
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
lfs_deploy_token? || can?(user, :push_code, project) || can?(deploy_token, :push_code, project)
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def lfs_deploy_token?
|
|
|
|
authentication_result.lfs_deploy_token?(project)
|
|
|
|
end
|
|
|
|
|
|
|
|
def user_can_download_code?
|
2021-10-27 15:23:28 +05:30
|
|
|
has_authentication_ability?(:download_code) && can?(user, :download_code, project)
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def build_can_download_code?
|
|
|
|
has_authentication_ability?(:build_download_code) && can?(user, :build_download_code, project)
|
|
|
|
end
|
|
|
|
|
|
|
|
def objects
|
|
|
|
@objects ||= (params[:objects] || []).to_a
|
|
|
|
end
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
def objects_oids
|
|
|
|
objects.map { |o| o['oid'].to_s }
|
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
def has_authentication_ability?(capability)
|
|
|
|
(authentication_abilities || []).include?(capability)
|
|
|
|
end
|
2019-02-15 15:39:39 +05:30
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
# Overridden in EE
|
2019-02-15 15:39:39 +05:30
|
|
|
def limit_exceeded?
|
|
|
|
false
|
|
|
|
end
|
2016-09-13 17:45:13 +05:30
|
|
|
end
|
2019-12-04 20:38:33 +05:30
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
LfsRequest.prepend_mod_with('LfsRequest')
|