Beispiel #1
0
    def from_upload(cls, upload, addon, platforms, send_signal=True,
                    source=None, is_beta=False):
        from olympia.addons.models import AddonFeatureCompatibility

        data = utils.parse_addon(upload, addon)
        try:
            license = addon.versions.latest().license_id
        except Version.DoesNotExist:
            license = None
        v = cls.objects.create(
            addon=addon,
            version=data['version'],
            license_id=license,
            source=source
        )
        log.info('New version: %r (%s) from %r' % (v, v.id, upload))

        # Update the add-on e10s compatibility since we're creating a new
        # version that may change that.
        e10s_compatibility = data.get('e10s_compatibility')
        if e10s_compatibility is not None:
            feature_compatibility = (
                AddonFeatureCompatibility.objects.get_or_create(addon=addon)[0]
            )
            feature_compatibility.update(e10s=e10s_compatibility)

        AV = ApplicationsVersions
        for app in data.get('apps', []):
            AV(version=v, min=app.min, max=app.max,
               application=app.id).save()
        if addon.type == amo.ADDON_SEARCH:
            # Search extensions are always for all platforms.
            platforms = [amo.PLATFORM_ALL.id]
        else:
            platforms = cls._make_safe_platform_files(platforms)

        for platform in platforms:
            File.from_upload(upload, v, platform, parse_data=data,
                             is_beta=is_beta)

        v.disable_old_files()
        # After the upload has been copied to all platforms, remove the upload.
        storage.delete(upload.path)
        if send_signal:
            version_uploaded.send(sender=v)

        # Track the time it took from first upload through validation
        # (and whatever else) until a version was created.
        upload_start = utc_millesecs_from_epoch(upload.created)
        now = datetime.datetime.now()
        now_ts = utc_millesecs_from_epoch(now)
        upload_time = now_ts - upload_start

        log.info('Time for version {version} creation from upload: {delta}; '
                 'created={created}; now={now}'
                 .format(delta=upload_time, version=v,
                         created=upload.created, now=now))
        statsd.timing('devhub.version_created_from_upload', upload_time)

        return v
Beispiel #2
0
 def test_version_is_not_allowed_upload_full(self):
     version = Version.objects.get(pk=81551)
     version.files.all().delete()
     for platform in [amo.PLATFORM_LINUX.id,
                      amo.PLATFORM_WIN.id,
                      amo.PLATFORM_MAC.id]:
         file = File(platform=platform, version=version)
         file.save()
     # The transform don't know bout my new files.
     version = Version.objects.get(pk=81551)
     assert not version.is_allowed_upload()
    def _extra_version_and_file(self, status):
        version = Version.objects.get(id=81551)

        version_two = Version(addon=self.addon,
                              license=version.license,
                              version='1.2.3')
        version_two.save()

        file_two = File(status=status, version=version_two)
        file_two.save()
        return version_two, file_two
Beispiel #4
0
    def create_file(self, **kwargs):
        addon = Addon()
        addon.save()
        ver = Version(version='0.1')
        ver.addon = addon
        ver.save()

        f = File(**kwargs)
        f.version = ver
        f.save()

        return f
Beispiel #5
0
    def from_upload(cls, upload, addon, platforms, send_signal=True,
                    source=None, is_beta=False):
        data = utils.parse_addon(upload, addon)
        try:
            license = addon.versions.latest().license_id
        except Version.DoesNotExist:
            license = None
        max_len = cls._meta.get_field_by_name('_developer_name')[0].max_length
        developer = data.get('developer_name', '')[:max_len]
        v = cls.objects.create(
            addon=addon,
            version=data['version'],
            license_id=license,
            _developer_name=developer,
            source=source
        )
        log.info('New version: %r (%s) from %r' % (v, v.id, upload))

        AV = ApplicationsVersions
        for app in data.get('apps', []):
            AV(version=v, min=app.min, max=app.max,
               application=app.id).save()
        if addon.type == amo.ADDON_SEARCH:
            # Search extensions are always for all platforms.
            platforms = [amo.PLATFORM_ALL.id]
        else:
            platforms = cls._make_safe_platform_files(platforms)

        for platform in platforms:
            File.from_upload(upload, v, platform, parse_data=data,
                             is_beta=is_beta)

        v.disable_old_files()
        # After the upload has been copied to all platforms, remove the upload.
        storage.delete(upload.path)
        if send_signal:
            version_uploaded.send(sender=v)

        # Track the time it took from first upload through validation
        # (and whatever else) until a version was created.
        upload_start = utc_millesecs_from_epoch(upload.created)
        now = datetime.datetime.now()
        now_ts = utc_millesecs_from_epoch(now)
        upload_time = now_ts - upload_start

        log.info('Time for version {version} creation from upload: {delta}; '
                 'created={created}; now={now}'
                 .format(delta=upload_time, version=v,
                         created=upload.created, now=now))
        statsd.timing('devhub.version_created_from_upload', upload_time)

        return v
Beispiel #6
0
 def test_version_is_not_allowed_upload_after_review(self):
     version = Version.objects.get(pk=81551)
     version.files.all().delete()
     for platform in [amo.PLATFORM_LINUX.id,
                      amo.PLATFORM_WIN.id,
                      amo.PLATFORM_BSD.id]:
         file = File(platform=platform, version=version)
         file.save()
     version = Version.objects.get(pk=81551)
     assert version.is_allowed_upload()
     version.files.all()[0].update(status=amo.STATUS_PUBLIC)
     # The review has started so no more uploads now.
     version = Version.objects.get(pk=81551)
     assert not version.is_allowed_upload()
 def fake_file_object(self, obj, data):
     file_ = File(
         id=data['id'], created=self.handle_date(data['created']),
         hash=data['hash'], filename=data['filename'],
         is_webextension=data.get('is_webextension'),
         is_mozilla_signed_extension=data.get(
             'is_mozilla_signed_extension'),
         is_restart_required=data.get('is_restart_required', False),
         platform=data['platform'], size=data['size'],
         status=data['status'],
         strict_compatibility=data.get('strict_compatibility', False),
         version=obj)
     file_.webext_permissions_list = data.get('webext_permissions_list', [])
     return file_
Beispiel #8
0
 def test_trusted_lite_to_lite(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_LITE, trusted=True)
     assert self.addon.status == amo.STATUS_LITE
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     assert f.status == amo.STATUS_LITE
Beispiel #9
0
 def test_trusted_public_to_public(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC, trusted=True)
     eq_(self.addon.status, amo.STATUS_PUBLIC)
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     eq_(f.status, amo.STATUS_PUBLIC)
Beispiel #10
0
    def test_extract(self):
        upload = self.get_upload('webextension_no_id.xpi')
        parsed_data = parse_addon(upload, user=mock.Mock())
        # Remove the permissions from the parsed data so they aren't added.
        pdata_permissions = parsed_data.pop('permissions')
        pdata_cscript = parsed_data.pop('content_scripts')
        file_ = File.from_upload(upload, self.version, self.platform,
                                 parsed_data=parsed_data)
        assert WebextPermission.objects.count() == 0
        assert file_.webext_permissions_list == []

        call_command('extract_permissions')

        file_ = File.objects.get(id=file_.id)
        assert WebextPermission.objects.get(file=file_)
        permissions_list = file_.webext_permissions_list
        assert len(permissions_list) == 8
        assert permissions_list == [
            # first 5 are 'permissions'
            u'http://*/*', u'https://*/*', 'bookmarks', 'made up permission',
            'https://google.com/',
            # last 3 are 'content_scripts' matches we treat the same
            '*://*.mozilla.org/*', '*://*.mozilla.com/*',
            'https://*.mozillians.org/*']
        assert permissions_list[0:5] == pdata_permissions
        assert permissions_list[5:8] == [x for y in [
            cs['matches'] for cs in pdata_cscript] for x in y]
Beispiel #11
0
 def test_public_to_unreviewed(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC)
     assert self.addon.status == amo.STATUS_PUBLIC
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     assert f.status == amo.STATUS_AWAITING_REVIEW
Beispiel #12
0
 def test_search_extension(self):
     upload = self.upload('search.xml')
     data = parse_addon(upload.path)
     file_ = File.from_upload(upload, self.version, self.platform,
                              parsed_data=data)
     assert file_.filename.endswith('.xml')
     assert file_.no_restart
Beispiel #13
0
 def test_public_to_unreviewed(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC)
     eq_(self.addon.status, amo.STATUS_PUBLIC)
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     eq_(f.status, amo.STATUS_UNREVIEWED)
Beispiel #14
0
 def test_lite_to_unreviewed(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_LITE)
     assert self.addon.status == amo.STATUS_LITE
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     assert f.status == amo.STATUS_UNREVIEWED
Beispiel #15
0
 def test_beta_version_non_public(self):
     # Only public add-ons can get beta versions.
     upload = self.upload('beta-extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_LITE)
     assert self.addon.status == amo.STATUS_LITE
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     assert f.status == amo.STATUS_UNREVIEWED
Beispiel #16
0
 def test_mozilla_signed_extension(self):
     upload = self.upload('webextension_signed_already')
     file_ = File.from_upload(
         upload,
         self.version,
         parsed_data={'is_mozilla_signed_extension': True},
     )
     assert file_.is_mozilla_signed_extension
Beispiel #17
0
 def test_not_mozilla_signed_extension(self):
     upload = self.upload('webextension.xpi')
     file_ = File.from_upload(
         upload,
         self.version,
         parsed_data={'is_mozilla_signed_extension': False},
     )
     assert not file_.is_mozilla_signed_extension
Beispiel #18
0
 def test_webextension(self):
     self.create_switch('webextensions')
     upload = self.upload('webextension')
     file_ = File.from_upload(upload,
                              self.version,
                              self.platform,
                              parse_data={'is_webextension': True})
     assert file_.is_webextension
Beispiel #19
0
 def test_file_is_copied_to_current_path_at_upload(self):
     upload = self.upload('webextension')
     file_ = File.from_upload(upload,
                              self.version,
                              parsed_data={'is_webextension': True})
     assert os.path.exists(file_.file_path)
     assert not os.path.exists(file_.guarded_file_path)
     assert os.path.exists(file_.current_file_path)
Beispiel #20
0
 def test_optional_permissions(self):
     upload = self.upload('webextension_no_id.xpi')
     parsed_data = parse_addon(upload, user=user_factory())
     assert len(parsed_data['optional_permissions']) == 2
     file_ = File.from_upload(upload, self.version, parsed_data=parsed_data)
     permissions_list = file_.optional_permissions
     assert len(permissions_list) == 2
     assert permissions_list == parsed_data['optional_permissions']
Beispiel #21
0
 def test_beta_version_non_public(self):
     # Only public add-ons can get beta versions.
     upload = self.upload('beta-extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_LITE)
     eq_(self.addon.status, amo.STATUS_LITE)
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     eq_(f.status, amo.STATUS_UNREVIEWED)
Beispiel #22
0
 def test_public_to_beta(self):
     upload = self.upload('beta-extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC)
     assert self.addon.status == amo.STATUS_PUBLIC
     f = File.from_upload(upload, self.version, self.platform, is_beta=True,
                          parse_data=d)
     assert f.status == amo.STATUS_BETA
Beispiel #23
0
 def test_public_to_beta(self):
     upload = self.upload('beta-extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC)
     assert self.addon.status == amo.STATUS_PUBLIC
     f = File.from_upload(upload, self.version, self.platform, is_beta=True,
                          parse_data=d)
     assert f.status == amo.STATUS_BETA
Beispiel #24
0
 def test_file_validation(self):
     upload = self.upload('jetpack')
     file = File.from_upload(upload, self.version, self.platform)
     fv = FileValidation.objects.get(file=file)
     eq_(json.loads(fv.validation), json.loads(upload.validation))
     eq_(fv.valid, True)
     eq_(fv.errors, 0)
     eq_(fv.warnings, 1)
     eq_(fv.notices, 2)
Beispiel #25
0
 def test_litenominated_to_unreviewed(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     with mock.patch('olympia.addons.models.Addon.update_status'):
         # mock update_status because it doesn't like Addons without files.
         self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
     assert self.addon.status == amo.STATUS_LITE_AND_NOMINATED
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     assert f.status == amo.STATUS_UNREVIEWED
 def test_search_extension(self):
     upload = self.upload('search.xml')
     data = parse_addon(upload.path)
     file_ = File.from_upload(upload,
                              self.version,
                              self.platform,
                              parsed_data=data)
     assert file_.filename.endswith('.xml')
     assert file_.no_restart
Beispiel #27
0
 def test_file_validation(self):
     upload = self.upload('jetpack')
     file = File.from_upload(upload, self.version, self.platform)
     fv = FileValidation.objects.get(file=file)
     assert json.loads(fv.validation) == json.loads(upload.validation)
     assert fv.valid
     assert fv.errors == 0
     assert fv.warnings == 1
     assert fv.notices == 2
Beispiel #28
0
 def fake_file_object(self, obj, data):
     file_ = File(id=data['id'],
                  created=self.handle_date(data['created']),
                  hash=data['hash'],
                  filename=data['filename'],
                  is_webextension=data.get('is_webextension'),
                  is_mozilla_signed_extension=data.get(
                      'is_mozilla_signed_extension'),
                  is_restart_required=data.get('is_restart_required',
                                               False),
                  platform=data['platform'],
                  size=data['size'],
                  status=data['status'],
                  strict_compatibility=data.get('strict_compatibility',
                                                False),
                  version=obj)
     file_.webext_permissions_list = data.get('webext_permissions_list', [])
     return file_
Beispiel #29
0
 def test_file_validation(self):
     upload = self.upload('webextension.xpi')
     file = File.from_upload(upload, self.version, parsed_data={})
     fv = FileValidation.objects.get(file=file)
     assert json.loads(fv.validation) == json.loads(upload.validation)
     assert fv.valid
     assert fv.errors == 0
     assert fv.warnings == 1
     assert fv.notices == 2
Beispiel #30
0
 def test_file_validation(self):
     upload = self.upload('jetpack')
     file = File.from_upload(upload, self.version, self.platform)
     fv = FileValidation.objects.get(file=file)
     assert json.loads(fv.validation) == json.loads(upload.validation)
     assert fv.valid
     assert fv.errors == 0
     assert fv.warnings == 1
     assert fv.notices == 2
Beispiel #31
0
 def test_file_validation(self):
     upload = self.upload('jetpack')
     file = File.from_upload(upload, self.version, self.platform)
     fv = FileValidation.objects.get(file=file)
     eq_(json.loads(fv.validation), json.loads(upload.validation))
     eq_(fv.valid, True)
     eq_(fv.errors, 0)
     eq_(fv.warnings, 1)
     eq_(fv.notices, 2)
Beispiel #32
0
 def test_litenominated_to_unreviewed(self):
     upload = self.upload('extension')
     d = parse_addon(upload.path)
     with mock.patch('olympia.addons.models.Addon.update_status'):
         # mock update_status because it doesn't like Addons without files.
         self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
     assert self.addon.status == amo.STATUS_LITE_AND_NOMINATED
     f = File.from_upload(upload, self.version, self.platform, parse_data=d)
     assert f.status == amo.STATUS_UNREVIEWED
Beispiel #33
0
 def fake_file_object(self, obj, data):
     file_ = File(
         id=data['id'],
         created=self.handle_date(data['created']),
         hash=data['hash'],
         filename=data['filename'],
         is_webextension=True,
         is_mozilla_signed_extension=data.get('is_mozilla_signed_extension'),
         size=data['size'],
         status=data['status'],
         strict_compatibility=data.get('strict_compatibility', False),
         version=obj,
     )
     file_.permissions = data.get(
         'permissions', data.get('webext_permissions_list', [])
     )
     file_.optional_permissions = data.get('optional_permissions', [])
     return file_
Beispiel #34
0
 def test_file_is_copied_to_current_path_at_upload_if_disabled(self):
     self.addon.update(disabled_by_user=True)
     upload = self.upload('webextension')
     file_ = File.from_upload(
         upload, self.version, parsed_data={'is_webextension': True}
     )
     assert not os.path.exists(file_.file_path)
     assert os.path.exists(file_.guarded_file_path)
     assert os.path.exists(file_.current_file_path)
Beispiel #35
0
    def _save_file(self, version):
        data = self.cleaned_data
        xpi = data['xpi']
        hash = hashlib.sha256()

        f = File(version=version,
                 platform=amo.PLATFORM_DICT[data['platform']].id,
                 size=xpi.size)

        filename = f.generate_filename()
        path = os.path.join(user_media_path('addons'), str(version.addon.id))
        with storage.open(os.path.join(path, filename), 'wb') as destination:
            for chunk in xpi.chunks():
                hash.update(chunk)
                destination.write(chunk)

        f.hash = 'sha256:%s' % hash.hexdigest()
        f.save()
        return f
 def test_public_to_unreviewed(self):
     upload = self.upload('extension')
     data = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC)
     assert self.addon.status == amo.STATUS_PUBLIC
     file_ = File.from_upload(upload,
                              self.version,
                              self.platform,
                              parsed_data=data)
     assert file_.status == amo.STATUS_AWAITING_REVIEW
Beispiel #37
0
    def test_is_ready_for_auto_approval(self):
        addon = Addon.objects.get(id=3615)
        version = addon.current_version
        assert not version.is_ready_for_auto_approval

        version.all_files = [
            File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=False)]
        assert not version.is_ready_for_auto_approval

        version.all_files = [
            File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=True)]
        version.channel = amo.RELEASE_CHANNEL_UNLISTED
        assert not version.is_ready_for_auto_approval

        version.channel = amo.RELEASE_CHANNEL_LISTED
        assert version.is_ready_for_auto_approval

        addon.type = amo.ADDON_THEME
        assert not version.is_ready_for_auto_approval
Beispiel #38
0
 def test_webextension_crx(self):
     """Test to ensure we accept CRX uploads, but convert them into XPI
     files ASAP to keep things simple.
     """
     upload = self.upload('webextension.crx')
     file_ = File.from_upload(upload, self.version, self.platform,
                              parse_data={'is_webextension': True})
     assert file_.filename.endswith('.xpi')
     assert file_.is_webextension
     storage.delete(upload.path)
Beispiel #39
0
 def test_webextension_crx_large(self):
     """Test to ensure we accept large CRX uploads, because of how we
     write them to storage.
     """
     upload = self.upload('https-everywhere.crx')
     file_ = File.from_upload(upload, self.version, self.platform,
                              parse_data={'is_webextension': True})
     assert file_.filename.endswith('.xpi')
     assert file_.is_webextension
     storage.delete(upload.path)
Beispiel #40
0
 def test_webextension_crx(self):
     """Test to ensure we accept CRX uploads, but convert them into XPI
     files ASAP to keep things simple.
     """
     upload = self.upload('webextension.crx')
     file_ = File.from_upload(upload, self.version, self.platform,
                              parsed_data={'is_webextension': True})
     assert file_.filename.endswith('.xpi')
     assert file_.is_webextension
     storage.delete(upload.path)
Beispiel #41
0
 def test_webextension_crx_large(self):
     """Test to ensure we accept large CRX uploads, because of how we
     write them to storage.
     """
     upload = self.upload('https-everywhere.crx')
     file_ = File.from_upload(upload, self.version, self.platform,
                              parsed_data={'is_webextension': True})
     assert file_.filename.endswith('.xpi')
     assert file_.is_webextension
     storage.delete(upload.path)
Beispiel #42
0
    def test_is_ready_for_auto_approval_addon_status(self):
        addon = Addon.objects.get(id=3615)
        addon.status = amo.STATUS_NOMINATED
        version = addon.current_version
        version.all_files = [
            File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=True)]
        assert version.is_ready_for_auto_approval

        addon.status = amo.STATUS_DISABLED
        assert not version.is_ready_for_auto_approval
Beispiel #43
0
    def test_generate_hash(self):
        file_ = File()
        file_.version = Version.objects.get(pk=81551)
        filename = self.xpi_path('https-everywhere.xpi')
        assert file_.generate_hash(filename).startswith('sha256:95bd414295acda29c4')

        file_ = File.objects.get(pk=67442)
        with storage.open(file_.file_path, 'wb') as fp:
            fp.write(b'some data\n')
        with storage.open(file_.guarded_file_path, 'wb') as fp:
            fp.write(b'some data guarded\n')
        assert file_.generate_hash().startswith('sha256:5aa03f96c77536579166f')
        file_.status = amo.STATUS_DISABLED
        assert file_.generate_hash().startswith('sha256:6524f7791a35ef4dd4c6f')
        file_.status = amo.STATUS_APPROVED
        assert file_.generate_hash().startswith('sha256:5aa03f96c77536579166f')
Beispiel #44
0
 def get_file(self, platform):
     file = File()  # Real object and not a mock to get the true methods.
     file.version = self.version
     file.pk = 666
     file.platform = platform
     file.status = amo.STATUS_PUBLIC
     file.strict_compatibility = False
     file.binary_components = False
     return file
Beispiel #45
0
 def test_trusted_public_to_beta(self):
     upload = self.upload('beta-extension')
     d = parse_addon(upload.path)
     self.addon.update(status=amo.STATUS_PUBLIC, trusted=True)
     eq_(self.addon.status, amo.STATUS_PUBLIC)
     f = File.from_upload(upload,
                          self.version,
                          self.platform,
                          is_beta=True,
                          parse_data=d)
     eq_(f.status, amo.STATUS_BETA)
Beispiel #46
0
    def test_file_for_platform(self):
        """If client passes a platform, make sure we get the right file."""
        version = Version.objects.get(pk=self.version_1_2_2)
        file_one = version.files.all()[0]
        file_one.platform = amo.PLATFORM_LINUX.id
        file_one.save()

        file_two = File(version=version, filename='foo', hash='bar',
                        platform=amo.PLATFORM_WIN.id,
                        status=amo.STATUS_PUBLIC)
        file_two.save()
        version, file = self.get_update_instance(
            '1.2', self.version_int, self.app, amo.PLATFORM_LINUX)
        assert version == self.version_1_2_2
        assert file == file_one.pk

        version, file = self.get_update_instance(
            '1.2', self.version_int, self.app, amo.PLATFORM_WIN)
        assert version == self.version_1_2_2
        assert file == file_two.pk
Beispiel #47
0
    def test_file_for_platform(self):
        """If client passes a platform, make sure we get the right file."""
        version = Version.objects.get(pk=self.version_1_2_2)
        file_one = version.files.all()[0]
        file_one.platform = amo.PLATFORM_LINUX.id
        file_one.save()

        file_two = File(version=version, filename='foo', hash='bar',
                        platform=amo.PLATFORM_WIN.id,
                        status=amo.STATUS_PUBLIC)
        file_two.save()
        version, file = self.get('1.2', self.version_int,
                                 self.app, amo.PLATFORM_LINUX)
        assert version == self.version_1_2_2
        assert file == file_one.pk

        version, file = self.get('1.2', self.version_int,
                                 self.app, amo.PLATFORM_WIN)
        assert version == self.version_1_2_2
        assert file == file_two.pk
Beispiel #48
0
 def test_permissions(self):
     upload = self.upload('webextension_no_id.xpi')
     parsed_data = parse_addon(upload)
     # 5 total permissions.
     assert len(parsed_data['permissions']) == 5
     file_ = File.from_upload(upload, self.version, self.platform,
                              parsed_data=parsed_data)
     permissions_list = file_.webext_permissions_list
     assert len(permissions_list) == 5
     assert permissions_list == [u'http://*/*', u'https://*/*', 'bookmarks',
                                 'made up permission', 'https://google.com/'
                                 ]
Beispiel #49
0
 def test_dont_send_both_bytes_and_str_to_copy_stored_file(
         self, copy_stored_file_mock):
     upload = self.upload('wébextension.xpi')
     self.version.addon.name = 'jéts!'
     file_ = File.from_upload(upload, self.version, parsed_data={})
     assert file_.filename == 'jets-0.1.xpi'
     expected_path_orig = force_str(upload.path)
     expected_path_dest = force_str(file_.current_file_path)
     assert copy_stored_file_mock.call_count == 1
     assert copy_stored_file_mock.call_args_list[0][0] == (
         expected_path_orig,
         expected_path_dest,
     )
Beispiel #50
0
 def test_version_is_not_allowed_upload(self):
     version = Version.objects.get(pk=81551)
     version.files.all().delete()
     for platform in [
             amo.PLATFORM_LINUX.id, amo.PLATFORM_WIN.id, amo.PLATFORM_BSD.id
     ]:
         file = File(platform=platform, version=version)
         file.save()
     version = Version.objects.get(pk=81551)
     assert version.is_allowed_upload()
     file = File(platform=amo.PLATFORM_MAC.id, version=version)
     file.save()
     # The transform don't know bout my new files.
     version = Version.objects.no_cache().get(pk=81551)
     assert not version.is_allowed_upload()
Beispiel #51
0
    def fake_object(self, data):
        """Create a fake instance of Addon and related models from ES data."""
        obj = Addon(id=data['id'], slug=data['slug'], is_listed=True)

        data_version = data.get('current_version')
        if data_version:
            obj._current_version = Version(addon=obj,
                                           id=data_version['id'],
                                           reviewed=self.handle_date(
                                               data_version['reviewed']),
                                           version=data_version['version'])
            data_files = data_version.get('files', [])
            obj._current_version.all_files = [
                File(id=file_['id'],
                     created=self.handle_date(file_['created']),
                     hash=file_['hash'],
                     filename=file_['filename'],
                     platform=file_['platform'],
                     size=file_['size'],
                     status=file_['status'],
                     version=obj._current_version) for file_ in data_files
            ]

            # In ES we store integers for the appversion info, we need to
            # convert it back to strings.
            compatible_apps = {}
            for app_id, compat_dict in data['appversion'].items():
                app_name = APPS_ALL[int(app_id)]
                compatible_apps[app_name] = ApplicationsVersions(
                    min=AppVersion(version=compat_dict.get('min_human', '')),
                    max=AppVersion(version=compat_dict.get('max_human', '')))

            obj._current_version.compatible_apps = compatible_apps

        # Attach base attributes that have the same name/format in ES and in
        # the model.
        self._attach_fields(
            obj, data,
            ('average_daily_users', 'bayesian_rating', 'created',
             'default_locale', 'guid', 'hotness', 'is_listed', 'last_updated',
             'public_stats', 'slug', 'status', 'type', 'weekly_downloads'))

        # Attach attributes that do not have the same name/format in ES.
        obj.tag_list = data['tags']
        obj.disabled_by_user = data['is_disabled']  # Not accurate, but enough.

        # Attach translations (they require special treatment).
        self._attach_translations(obj, data, self.translated_fields)

        return obj
Beispiel #52
0
    def test_force_extract(self):
        upload = self.get_upload('webextension_no_id.xpi')
        parsed_data = parse_addon(upload, user=mock.Mock())
        # change the permissions so we can tell they've been re-parsed.
        parsed_data['permissions'].pop()
        file_ = File.from_upload(upload, self.version, self.platform,
                                 parsed_data=parsed_data)
        assert WebextPermission.objects.count() == 1
        assert len(file_.webext_permissions_list) == 7

        call_command('extract_permissions', force=True)

        file_ = File.objects.get(id=file_.id)
        assert WebextPermission.objects.get(file=file_)
        assert len(file_.webext_permissions_list) == 8
    def test_force_extract(self):
        upload = self.get_upload('webextension_no_id.xpi')
        parsed_data = parse_addon(upload)
        # change the permissions so we can tell they've been re-parsed.
        parsed_data['permissions'].pop()
        file_ = File.from_upload(upload, self.version, self.platform,
                                 parsed_data=parsed_data)
        assert WebextPermission.objects.count() == 1
        assert len(file_.webext_permissions) == 2

        call_command('extract_permissions', force=True)

        file_ = File.objects.no_cache().get(id=file_.id)
        assert WebextPermission.objects.get(file=file_)
        permissions = file_.webext_permissions
        assert len(permissions) == 3
Beispiel #54
0
    def test_extract(self):
        upload = self.get_upload('webextension_no_id.xpi')
        parsed_data = parse_addon(upload, user=mock.Mock())

        # Remove the optional permissions from the parsed data so they aren't
        # added.
        pdata_optional_permissions = parsed_data.pop('optional_permissions')
        file_ = File.from_upload(upload, self.version, self.platform,
                                 parsed_data=parsed_data)
        assert file_.optional_permissions == []

        call_command('extract_optional_permissions')

        file_ = File.objects.get(id=file_.id)
        optional_permissions = file_.optional_permissions
        assert len(optional_permissions) == 2
        assert optional_permissions == pdata_optional_permissions
Beispiel #55
0
    def test_is_ready_for_auto_approval_addon_status(self):
        addon = Addon.objects.get(id=3615)
        addon.status = amo.STATUS_NOMINATED
        version = addon.current_version
        version.all_files = [
            File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=True)
        ]
        assert not version.is_ready_for_auto_approval

        with override_switch('post-review', active=True):
            # When the post-review switch is active, we also accept add-ons
            # with NOMINATED status.
            assert version.is_ready_for_auto_approval

            addon.status = amo.STATUS_NOMINATED
            assert version.is_ready_for_auto_approval

            addon.status = amo.STATUS_DISABLED
            assert not version.is_ready_for_auto_approval
    def test_extract(self):
        upload = self.get_upload('webextension_no_id.xpi')
        parsed_data = parse_addon(upload)
        # Delete the permissions from the parsed data so they aren't added.
        del parsed_data['permissions']
        file_ = File.from_upload(upload, self.version, self.platform,
                                 parsed_data=parsed_data)
        assert WebextPermission.objects.count() == 0
        assert file_.webext_permissions == {}

        call_command('extract_permissions')

        file_ = File.objects.no_cache().get(id=file_.id)
        assert WebextPermission.objects.get(file=file_)
        permissions = file_.webext_permissions
        assert len(permissions) == 3
        assert permissions['alarms']
        assert permissions[u'http://*/*']
        assert permissions[u'https://*/*']
Beispiel #57
0
    def test_extract(self):
        upload = self.get_upload('webextension_no_id.xpi')
        parsed_data = parse_addon(upload)
        # Delete the permissions from the parsed data so they aren't added.
        del parsed_data['permissions']
        file_ = File.from_upload(upload, self.version, self.platform,
                                 parsed_data=parsed_data)
        assert WebextPermission.objects.count() == 0
        assert file_.webext_permissions_list == []

        call_command('extract_permissions')

        file_ = File.objects.no_cache().get(id=file_.id)
        assert WebextPermission.objects.get(file=file_)
        permissions_list = file_.webext_permissions_list
        assert len(permissions_list) == 5
        assert permissions_list == [u'http://*/*', u'https://*/*', 'bookmarks',
                                    'made up permission', 'https://google.com/'
                                    ]
Beispiel #58
0
 def test_validator_sets_require_chrome(self):
     validation = json.dumps({
         "errors": 0,
         "success": True,
         "warnings": 0,
         "notices": 0,
         "message_tree": {},
         "messages": [],
         "metadata": {
             "version": "1.0",
             "name": "gK0Bes Bot",
             "id": "gkobes@gkobes",
             "requires_chrome": True
         }
     })
     upload = self.get_upload(filename='extension.xpi',
                              validation=validation)
     version = Version.objects.filter(addon__pk=3615)[0]
     file_ = File.from_upload(upload, version, amo.PLATFORM_LINUX.id)
     assert file_.requires_chrome
Beispiel #59
0
 def test_validator_sets_binary_via_content(self):
     validation = json.dumps({
         "errors": 0,
         "success": True,
         "warnings": 0,
         "notices": 0,
         "message_tree": {},
         "messages": [],
         "metadata": {
             "contains_binary_content": True,
             "version": "1.0",
             "name": "gK0Bes Bot",
             "id": "gkobes@gkobes",
         }
     })
     upload = self.get_upload(filename='extension.xpi',
                              validation=validation)
     version = Version.objects.filter(addon__pk=3615)[0]
     file_ = File.from_upload(upload, version, amo.PLATFORM_LINUX.id)
     eq_(file_.binary, True)
Beispiel #60
0
    def from_upload(cls, upload, addon, platforms, channel, send_signal=True,
                    source=None, is_beta=False):
        from olympia.addons.models import AddonFeatureCompatibility

        data = utils.parse_addon(upload, addon)
        try:
            license = addon.versions.latest().license_id
        except Version.DoesNotExist:
            license = None
        version = cls.objects.create(
            addon=addon,
            version=data['version'],
            license_id=license,
            source=source,
            channel=channel,
        )
        log.info(
            'New version: %r (%s) from %r' % (version, version.id, upload))

        # Update the add-on e10s compatibility since we're creating a new
        # version that may change that.
        e10s_compatibility = data.get('e10s_compatibility')
        if e10s_compatibility is not None:
            feature_compatibility = (
                AddonFeatureCompatibility.objects.get_or_create(addon=addon)[0]
            )
            feature_compatibility.update(e10s=e10s_compatibility)

        compatible_apps = {}
        for app in data.get('apps', []):
            compatible_apps[app.appdata] = ApplicationsVersions(
                version=version, min=app.min, max=app.max, application=app.id)
            compatible_apps[app.appdata].save()

        # See #2828: sometimes when we generate the filename(s) below, in
        # File.from_upload(), cache-machine is confused and has trouble
        # fetching the ApplicationsVersions that were just created. To work
        # around this we pre-generate version.compatible_apps and avoid the
        # queries completely.
        version.compatible_apps = compatible_apps

        if addon.type == amo.ADDON_SEARCH:
            # Search extensions are always for all platforms.
            platforms = [amo.PLATFORM_ALL.id]
        else:
            platforms = cls._make_safe_platform_files(platforms)

        for platform in platforms:
            File.from_upload(upload, version, platform, parse_data=data,
                             is_beta=is_beta)

        version.disable_old_files()
        # After the upload has been copied to all platforms, remove the upload.
        storage.delete(upload.path)
        if send_signal:
            version_uploaded.send(sender=version)

        # Track the time it took from first upload through validation
        # (and whatever else) until a version was created.
        upload_start = utc_millesecs_from_epoch(upload.created)
        now = datetime.datetime.now()
        now_ts = utc_millesecs_from_epoch(now)
        upload_time = now_ts - upload_start

        log.info('Time for version {version} creation from upload: {delta}; '
                 'created={created}; now={now}'
                 .format(delta=upload_time, version=version,
                         created=upload.created, now=now))
        statsd.timing('devhub.version_created_from_upload', upload_time)

        return version