in src/olympia/signing/views.py [0:0]
def handle_upload(self, request, addon, version_string, guid=None):
if 'upload' in request.FILES:
filedata = request.FILES['upload']
else:
raise forms.ValidationError(
gettext('Missing "upload" key in multipart file data.'),
status.HTTP_400_BAD_REQUEST,
)
# Parse the file to get and validate package data with the addon.
parsed_data = parse_addon(filedata, addon=addon, user=request.user)
if addon is not None and addon.status == amo.STATUS_DISABLED:
msg = gettext(
'You cannot add versions to an add-on that has status: %s.'
% amo.STATUS_CHOICES_ADDON[amo.STATUS_DISABLED]
)
raise forms.ValidationError(msg, status.HTTP_400_BAD_REQUEST)
version_string = version_string or parsed_data['version']
if version_string and parsed_data['version'] != version_string:
raise forms.ValidationError(
gettext('Version does not match the manifest file.'),
status.HTTP_400_BAD_REQUEST,
)
existing_version = (
addon
and Version.unfiltered.filter(addon=addon, version=version_string).last()
)
if existing_version:
if existing_version.deleted:
msg = gettext('Version {version} was uploaded before and deleted.')
else:
msg = gettext('Version {version} already exists.')
raise forms.ValidationError(
msg.format(version=version_string), status.HTTP_409_CONFLICT
)
package_guid = parsed_data.get('guid', None)
if guid is not None and not addon and not package_guid:
# No guid was present in the package, but one was provided in the
# URL, so we take it instead of generating one ourselves. There is
# an extra validation check for those: guids passed in the URL are
# not allowed to be longer than 64 chars.
if len(guid) > 64:
raise forms.ValidationError(
gettext(
"Please specify your Add-on ID in the manifest if it's "
'longer than 64 characters.'
)
)
parsed_data['guid'] = guid
elif not guid and package_guid:
guid = package_guid
if guid:
# If we did get a guid, regardless of its source, validate it now
# before creating anything.
if not amo.ADDON_GUID_PATTERN.match(guid):
raise forms.ValidationError(
gettext('Invalid Add-on ID in URL or package'),
status.HTTP_400_BAD_REQUEST,
)
# channel will be ignored for new addons.
if addon is None:
channel = amo.CHANNEL_UNLISTED # New is always unlisted.
addon = Addon.initialize_addon_from_upload(
data=parsed_data, upload=filedata, channel=channel, user=request.user
)
created = True
else:
created = False
channel_param = request.POST.get('channel')
channel = amo.CHANNEL_CHOICES_LOOKUP.get(channel_param)
if not channel:
last_version = addon.find_latest_version(None, exclude=())
if last_version:
channel = last_version.channel
else:
channel = amo.CHANNEL_UNLISTED # Treat as new.
if addon.disabled_by_user and channel == amo.CHANNEL_LISTED:
msg = gettext(
'You cannot add listed versions to an add-on set to '
'"Invisible" state.'
)
raise forms.ValidationError(msg, status.HTTP_400_BAD_REQUEST)
will_have_listed = channel == amo.CHANNEL_LISTED
if not addon.has_complete_metadata(has_listed_versions=will_have_listed):
raise forms.ValidationError(
gettext(
'You cannot add a listed version to this add-on '
'via the API due to missing metadata. '
'Please submit via the website'
),
status.HTTP_400_BAD_REQUEST,
)
if channel == amo.CHANNEL_LISTED and (
error_message := validate_version_number_is_gt_latest_signed_listed_version(
addon, version_string
)
):
raise forms.ValidationError(
error_message,
status.HTTP_409_CONFLICT,
)
# Note: The following function call contains a log statement that is
# used by foxsec-pipeline - if refactoring, keep in mind we need to
# trigger the same log statement.
file_upload = devhub_handle_upload(
filedata=filedata,
request=request,
addon=addon,
submit=True,
channel=channel,
source=amo.UPLOAD_SOURCE_SIGNING_API,
)
return file_upload, created