def handle_upload(self, request, addon, version_string, guid=None):
        if 'upload' in request.FILES:
            filedata = request.FILES['upload']
        else:
            raise forms.ValidationError(
                ugettext(u'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, user=request.user)

        if addon is not None and addon.status == amo.STATUS_DISABLED:
            msg = ugettext(
                'You cannot add versions to an addon 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(
                ugettext('Version does not match the manifest file.'),
                status.HTTP_400_BAD_REQUEST)

        if (addon is not None
                and addon.versions.filter(version=version_string).exists()):
            latest_version = addon.find_latest_version(None, exclude=())
            msg = ugettext('Version already exists. Latest version is: %s.' %
                           latest_version.version)
            raise forms.ValidationError(msg, status.HTTP_409_CONFLICT)

        package_guid = parsed_data.get('guid', None)

        dont_allow_no_guid = (not addon and not package_guid and
                              not parsed_data.get('is_webextension', False))

        if dont_allow_no_guid:
            raise forms.ValidationError(
                ugettext('Only WebExtensions are allowed to omit the GUID'),
                status.HTTP_400_BAD_REQUEST)

        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. But
            # first, validate it properly.
            if len(guid) > 64:
                raise forms.ValidationError(
                    ugettext(
                        'Please specify your Add-on GUID in the manifest if it\'s '
                        'longer than 64 characters.'))

            if not amo.ADDON_GUID_PATTERN.match(guid):
                raise forms.ValidationError(ugettext('Invalid GUID in URL'),
                                            status.HTTP_400_BAD_REQUEST)
            parsed_data['guid'] = guid

        # channel will be ignored for new addons.
        if addon is None:
            channel = amo.RELEASE_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.RELEASE_CHANNEL_UNLISTED  # Treat as new.

            will_have_listed = channel == amo.RELEASE_CHANNEL_LISTED
            if not addon.has_complete_metadata(
                    has_listed_versions=will_have_listed):
                raise forms.ValidationError(
                    ugettext('You cannot add a listed version to this addon '
                             'via the API due to missing metadata. '
                             'Please submit via the website'),
                    status.HTTP_400_BAD_REQUEST)

        file_upload = devhub_handle_upload(filedata=filedata,
                                           request=request,
                                           addon=addon,
                                           submit=True,
                                           channel=channel)

        return file_upload, created
Exemple #2
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, user=request.user)

        if addon is not None and addon.status == amo.STATUS_DISABLED:
            msg = gettext(
                'You cannot add versions to an addon 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)
        if existing_version:
            latest_version = addon.find_latest_version(None, exclude=())
            msg = gettext('Version already exists. Latest version is: %s.' %
                          latest_version.version)
            raise forms.ValidationError(msg, status.HTTP_409_CONFLICT)

        package_guid = parsed_data.get('guid', None)

        dont_allow_no_guid = (not addon and not package_guid and
                              not parsed_data.get('is_webextension', False))

        if dont_allow_no_guid:
            raise forms.ValidationError(
                gettext(
                    'Only WebExtensions are allowed to omit the Add-on ID'),
                status.HTTP_400_BAD_REQUEST,
            )

        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,
                )

        block_qs = Block.objects.filter(guid=addon.guid if addon else guid)
        if block_qs and block_qs.first().is_version_blocked(version_string):
            msg = gettext(
                'Version {version} matches {block_link} for this add-on. '
                'You can contact {amo_admins} for additional information.')

            raise forms.ValidationError(
                msg.format(
                    version=version_string,
                    block_link=absolutify(
                        reverse('blocklist.block', args=[guid])),
                    amo_admins='*****@*****.**',
                ),
                status.HTTP_400_BAD_REQUEST,
            )

        # channel will be ignored for new addons.
        if addon is None:
            channel = amo.RELEASE_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.RELEASE_CHANNEL_UNLISTED  # Treat as new.

            if addon.disabled_by_user and channel == amo.RELEASE_CHANNEL_LISTED:
                msg = gettext(
                    'You cannot add listed versions to an addon set to '
                    '"Invisible" state.')
                raise forms.ValidationError(msg, status.HTTP_400_BAD_REQUEST)

            will_have_listed = channel == amo.RELEASE_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 addon '
                            'via the API due to missing metadata. '
                            'Please submit via the website'),
                    status.HTTP_400_BAD_REQUEST,
                )

        # 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_API,
        )

        return file_upload, created
Exemple #3
0
    def handle_upload(self, request, addon, version_string, guid=None):
        if 'upload' in request.FILES:
            filedata = request.FILES['upload']
        else:
            raise forms.ValidationError(
                ugettext(u'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, user=request.user)

        if addon is not None and addon.status == amo.STATUS_DISABLED:
            msg = ugettext(
                'You cannot add versions to an addon 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(
                ugettext('Version does not match the manifest file.'),
                status.HTTP_400_BAD_REQUEST)

        if (addon is not None and
                addon.versions.filter(version=version_string).exists()):
            latest_version = addon.find_latest_version(None, exclude=())
            msg = ugettext('Version already exists. Latest version is: %s.'
                           % latest_version.version)
            raise forms.ValidationError(msg, status.HTTP_409_CONFLICT)

        package_guid = parsed_data.get('guid', None)

        dont_allow_no_guid = (
            not addon and not package_guid and
            not parsed_data.get('is_webextension', False))

        if dont_allow_no_guid:
            raise forms.ValidationError(
                ugettext('Only WebExtensions are allowed to omit the GUID'),
                status.HTTP_400_BAD_REQUEST)

        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. But
            # first, validate it properly.
            if len(guid) > 64:
                raise forms.ValidationError(ugettext(
                    'Please specify your Add-on GUID in the manifest if it\'s '
                    'longer than 64 characters.'
                ))

            if not amo.ADDON_GUID_PATTERN.match(guid):
                raise forms.ValidationError(
                    ugettext('Invalid GUID in URL'),
                    status.HTTP_400_BAD_REQUEST)
            parsed_data['guid'] = guid

        # channel will be ignored for new addons.
        if addon is None:
            channel = amo.RELEASE_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.RELEASE_CHANNEL_UNLISTED  # Treat as new.

            will_have_listed = channel == amo.RELEASE_CHANNEL_LISTED
            if not addon.has_complete_metadata(
                    has_listed_versions=will_have_listed):
                raise forms.ValidationError(
                    ugettext('You cannot add a listed version to this addon '
                             'via the API due to missing metadata. '
                             'Please submit via the website'),
                    status.HTTP_400_BAD_REQUEST)

        file_upload = devhub_handle_upload(
            filedata=filedata, request=request, addon=addon, submit=True,
            channel=channel)

        return file_upload, created