app/controllers/runtime/app_bits_upload_controller.rb
require 'presenters/api/job_presenter'
require 'controllers/runtime/mixins/find_process_through_app'
module VCAP::CloudController
class AppBitsUploadController < RestController::ModelController
include FindProcessThroughApp
def self.dependencies
[:app_event_repository]
end
def inject_dependencies(dependencies)
super
@app_event_repository = dependencies.fetch(:app_event_repository)
end
path_base 'apps'
model_class_name :ProcessModel
self.not_found_exception_name = 'AppNotFound'
def check_authentication(operation)
auth = env['HTTP_AUTHORIZATION']
grace_period = config.get(:app_bits_upload_grace_period_in_seconds)
relaxed_token_decoder = VCAP::CloudController::UaaTokenDecoder.new(config.get(:uaa), grace_period_in_seconds: grace_period)
VCAP::CloudController::Security::SecurityContextConfigurer.new(relaxed_token_decoder).configure(auth)
super
end
put "#{path_guid}/bits", :upload
def upload(guid)
process = find_guid_and_validate_access(:upload, guid)
raise CloudController::Errors::ApiError.new_from_details('UnprocessableEntity', 'cannot upload bits to a docker app') if process.docker?
relationships = { app: { data: { guid: process.app_guid } } }
create_message = PackageCreateMessage.new({ type: 'bits', relationships: relationships })
package = PackageCreate.create_without_event(create_message)
unless params['resources']
missing_resources_message = 'missing :resources'
package.fail_upload!(missing_resources_message)
raise CloudController::Errors::ApiError.new_from_details('AppBitsUploadInvalid', missing_resources_message)
end
upload_handler = CloudController::DependencyLocator.instance.upload_handler
upload_message = PackageUploadMessage.new({
bits_path: upload_handler.uploaded_file(request.POST, 'application'),
bits_name: upload_handler.uploaded_filename(request.POST, 'application'),
resources: json_param('resources')
})
uploader = PackageUpload.new
if async?
enqueued_job = uploader.upload_async_without_event(
message: upload_message,
package: package,
config: config
)
result = [HTTP::CREATED, JobPresenter.new(enqueued_job).to_json]
else
uploader.upload_sync_without_event(upload_message, package)
result = [HTTP::CREATED, '{}']
end
record_upload_bits(package)
TelemetryLogger.v2_emit(
'upload-package',
{
'app-id' => process.app_guid,
'user-id' => current_user.guid
}
)
result
end
post "#{path_guid}/copy_bits", :copy_app_bits
def copy_app_bits(dest_app_guid)
json_request = Oj.load(body)
source_process_guid = json_request['source_app_guid']
raise CloudController::Errors::ApiError.new_from_details('AppBitsCopyInvalid', 'missing source_app_guid') unless source_process_guid
src_process = find_guid_and_validate_access(:upload, source_process_guid)
dest_process = find_guid_and_validate_access(:upload, dest_app_guid)
copier = PackageCopy.new
copier.copy_without_event(dest_process.app_guid, src_process.latest_package)
@app_event_repository.record_src_copy_bits(dest_process.app, src_process.app, UserAuditInfo.from_context(SecurityContext))
@app_event_repository.record_dest_copy_bits(dest_process.app, src_process.app, UserAuditInfo.from_context(SecurityContext))
[HTTP::CREATED, JobPresenter.new(copier.enqueued_job).to_json]
end
private
def record_upload_bits(package)
Repositories::PackageEventRepository.record_app_upload_bits(
package,
UserAuditInfo.from_context(SecurityContext)
)
end
def json_param(name)
raw = params[name]
Oj.load(raw)
rescue StandardError
raise CloudController::Errors::ApiError.new_from_details('AppBitsUploadInvalid', "invalid :#{name}")
end
end
end