Пример #1
0
def version_list(request, addon, beta=False):
    qs = _version_list_qs(addon, beta=beta)
    versions = amo.utils.paginate(request, qs, PER_PAGE)
    versions.object_list = list(versions.object_list)
    Version.transformer(versions.object_list)
    return render(request, 'versions/version_list.html', {
        'addon': addon, 'beta': beta, 'versions': versions})
Пример #2
0
 def test_status_beta(self):
     # Check that the add-on + files are in the public status.
     assert self.addon.status == amo.STATUS_PUBLIC
     assert File.objects.filter(version=self.current)[0].status == (
         amo.STATUS_PUBLIC)
     # Create a new under review version with a pending file.
     upload = self.get_upload('extension-0.2.xpi')
     new_version = Version.from_upload(upload, self.addon, [self.platform],
                                       amo.RELEASE_CHANNEL_LISTED)
     new_version.files.all()[0].update(status=amo.STATUS_PENDING)
     # Create a beta version.
     upload = self.get_upload('extension-0.2b1.xpi')
     beta_version = Version.from_upload(upload, self.addon, [self.platform],
                                        amo.RELEASE_CHANNEL_LISTED,
                                        is_beta=True)
     # Check that it doesn't modify the public status.
     assert self.addon.status == amo.STATUS_PUBLIC
     assert File.objects.filter(version=self.current)[0].status == (
         amo.STATUS_PUBLIC)
     # Check that the file created with the beta version is in beta status.
     assert File.objects.filter(version=beta_version)[0].status == (
         amo.STATUS_BETA)
     # Check that the previously uploaded version is still pending.
     assert File.objects.filter(version=new_version)[0].status == (
         amo.STATUS_PENDING)
Пример #3
0
    def fake_version_object(self, obj, data, channel):
        if data:
            version = Version(
                addon=obj, id=data['id'],
                reviewed=self.handle_date(data['reviewed']),
                version=data['version'], channel=channel)
            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=version)
                for file_ in data.get('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.get('compatible_apps', {}).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', '')))
            version.compatible_apps = compatible_apps
        else:
            version = None
        return version
Пример #4
0
 def test_status(self):
     self.current.files.all().update(status=amo.STATUS_AWAITING_REVIEW)
     Version.from_upload(self.upload, self.addon, [self.platform],
                         amo.RELEASE_CHANNEL_LISTED,
                         parsed_data=self.dummy_parsed_data)
     assert File.objects.filter(version=self.current)[0].status == (
         amo.STATUS_DISABLED)
Пример #5
0
def version_list(request, addon, template, beta=False):
    status_list = (amo.STATUS_BETA,) if beta else amo.VALID_STATUSES
    qs = addon.versions.filter(files__status__in=status_list).distinct().order_by("-created")
    versions = amo.utils.paginate(request, qs, PER_PAGE)
    versions.object_list = list(versions.object_list)
    Version.transformer(versions.object_list)
    return render(request, template, {"addon": addon, "beta": beta, "versions": versions})
Пример #6
0
def version_list(request, addon, template, beta=False):
    status_list = (amo.STATUS_BETA,) if beta else amo.VALID_FILE_STATUSES
    qs = (addon.versions.filter(files__status__in=status_list)
          .distinct().order_by('-created'))
    versions = amo.utils.paginate(request, qs, PER_PAGE)
    versions.object_list = list(versions.object_list)
    Version.transformer(versions.object_list)
    return render(request, template, {'addon': addon, 'beta': beta,
                                      'versions': versions})
Пример #7
0
 def create_version(self, license=None):
     data = self.cleaned_data
     v = Version(addon=self.addon, license=license,
                 version=data['version'],
                 releasenotes=data['release_notes'])
     v.save()
     amo.log(amo.LOG.ADD_VERSION, v.addon, v)
     self._save_apps(v)
     self._save_file(v)
     return v
Пример #8
0
def test_version_status():
    addon = Addon()
    version = Version()
    version.all_files = [File(status=amo.STATUS_PUBLIC),
                         File(status=amo.STATUS_AWAITING_REVIEW)]
    assert u'Approved,Awaiting Review' == (
        jinja_helpers.version_status(addon, version))

    version.all_files = [File(status=amo.STATUS_AWAITING_REVIEW)]
    assert u'Awaiting Review' == jinja_helpers.version_status(addon, version)
Пример #9
0
def test_version_status():
    addon = Addon()
    version = Version()
    version.all_files = [File(status=amo.STATUS_PUBLIC),
                         File(status=amo.STATUS_UNREVIEWED)]
    assert u'Fully Reviewed,Awaiting Review' == (
        helpers.version_status(addon, version))

    version.all_files = [File(status=amo.STATUS_UNREVIEWED)]
    assert u'Awaiting Review' == helpers.version_status(addon, version)
    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
Пример #11
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
Пример #12
0
 def test_version_number(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(
         self.upload, self.addon, [self.selected_app],
         amo.RELEASE_CHANNEL_LISTED,
         parsed_data=parsed_data)
     assert version.version == self.now
Пример #13
0
 def test_file_not_multi_package(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED,
                                   parsed_data=parsed_data)
     files = version.all_files
     assert not files[0].is_multi_package
Пример #14
0
 def test_file_name(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED,
                                   parsed_data=parsed_data)
     files = version.all_files
     assert files[0].filename == u'delicious_bookmarks-0.1-fx-mac.xpi'
Пример #15
0
def create_version_for_upload(addon, upload):
    fileupload_exists = addon.fileupload_set.filter(
        created__gt=upload.created, version=upload.version).exists()
    version_exists = Version.unfiltered.filter(
        addon=addon, version=upload.version).exists()
    if (fileupload_exists or version_exists):
        log.info('Skipping Version creation for {upload_uuid} that would '
                 ' cause duplicate version'.format(upload_uuid=upload.uuid))
    else:
        # Import loop.
        from olympia.devhub.views import auto_sign_version

        log.info('Creating version for {upload_uuid} that passed '
                 'validation'.format(upload_uuid=upload.uuid))
        beta = (addon.is_listed and
                bool(upload.version) and is_beta(upload.version))
        version = Version.from_upload(
            upload, addon, [amo.PLATFORM_ALL.id], is_beta=beta)
        # The add-on's status will be STATUS_NULL when its first version is
        # created because the version has no files when it gets added and it
        # gets flagged as invalid. We need to manually set the status.
        #
        # Note: this assumes the developer wants a full review. This makes
        # sense for now because this function is only called from
        # submit_file(), which is itself only called from the signing API,
        # which only supports unlisted add-ons, and unlisted add-ons are
        # supposed to automatically be set as fully reviewed once signed.
        if addon.status == amo.STATUS_NULL:
            addon.update(status=amo.STATUS_NOMINATED)
        auto_sign_version(version, is_beta=version.is_beta)
Пример #16
0
def create_version_for_upload(addon, upload):
    fileupload_exists = addon.fileupload_set.filter(
        created__gt=upload.created, version=upload.version).exists()
    version_exists = Version.unfiltered.filter(
        addon=addon, version=upload.version).exists()
    if (fileupload_exists or version_exists):
        log.info('Skipping Version creation for {upload_uuid} that would '
                 ' cause duplicate version'.format(upload_uuid=upload.uuid))
    else:
        # Import loop.
        from olympia.devhub.views import auto_sign_version

        log.info('Creating version for {upload_uuid} that passed '
                 'validation'.format(upload_uuid=upload.uuid))
        beta = bool(upload.version) and is_beta(upload.version)
        version = Version.from_upload(
            upload, addon, [amo.PLATFORM_ALL.id], is_beta=beta)
        # The add-on's status will be STATUS_NULL when its first version is
        # created because the version has no files when it gets added and it
        # gets flagged as invalid. We need to manually set the status.
        # TODO: Handle sideload add-ons. This assumes the user wants a prelim
        # review since listed and sideload aren't supported for creation yet.
        if addon.status == amo.STATUS_NULL:
            addon.update(status=amo.STATUS_LITE)
        auto_sign_version(version, is_beta=version.is_beta)
Пример #17
0
 def test_android_creates_platform_files(self):
     version = Version.from_upload(self.upload, self.addon,
                                   [amo.PLATFORM_ANDROID.id],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert sorted(amo.PLATFORMS[f.platform].shortname for f in files) == (
         ['android'])
Пример #18
0
 def test_carry_over_license_no_version(self):
     self.addon.versions.all().delete()
     version = Version.from_upload(
         self.upload, self.addon, [self.selected_app],
         amo.RELEASE_CHANNEL_LISTED,
         parsed_data=self.dummy_parsed_data)
     assert version.license_id is None
Пример #19
0
 def test_app_versions(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     assert amo.FIREFOX in version.compatible_apps
     app = version.compatible_apps[amo.FIREFOX]
     assert app.min.version == '3.0'
     assert app.max.version == '3.6.*'
Пример #20
0
def create_version_for_upload(addon, upload, channel):
    """Note this function is only used for API uploads."""
    fileupload_exists = addon.fileupload_set.filter(
        created__gt=upload.created, version=upload.version).exists()
    version_exists = Version.unfiltered.filter(
        addon=addon, version=upload.version).exists()
    if (fileupload_exists or version_exists):
        log.info('Skipping Version creation for {upload_uuid} that would '
                 ' cause duplicate version'.format(upload_uuid=upload.uuid))
    else:
        # Import loop.
        from olympia.devhub.utils import add_dynamic_theme_tag
        from olympia.devhub.views import auto_sign_version

        log.info('Creating version for {upload_uuid} that passed '
                 'validation'.format(upload_uuid=upload.uuid))
        # Note: if we somehow managed to get here with an invalid add-on,
        # parse_addon() will raise ValidationError and the task will fail
        # loudly in sentry.
        parsed_data = parse_addon(upload, addon, user=upload.user)
        version = Version.from_upload(
            upload, addon, [x[0] for x in amo.APPS_CHOICES],
            channel,
            parsed_data=parsed_data)
        # The add-on's status will be STATUS_NULL when its first version is
        # created because the version has no files when it gets added and it
        # gets flagged as invalid. We need to manually set the status.
        if (addon.status == amo.STATUS_NULL and
                channel == amo.RELEASE_CHANNEL_LISTED):
            addon.update(status=amo.STATUS_NOMINATED)
        auto_sign_version(version)
        add_dynamic_theme_tag(version)
Пример #21
0
def create_version_for_upload(addon, upload, channel):
    """Note this function is only used for API uploads."""
    fileupload_exists = addon.fileupload_set.filter(
        created__gt=upload.created, version=upload.version).exists()
    version_exists = Version.unfiltered.filter(
        addon=addon, version=upload.version).exists()
    if (fileupload_exists or version_exists):
        log.info('Skipping Version creation for {upload_uuid} that would '
                 ' cause duplicate version'.format(upload_uuid=upload.uuid))
    else:
        # Import loop.
        from olympia.devhub.views import auto_sign_version

        log.info('Creating version for {upload_uuid} that passed '
                 'validation'.format(upload_uuid=upload.uuid))
        beta = bool(upload.version) and is_beta(upload.version)
        version = Version.from_upload(
            upload, addon, [amo.PLATFORM_ALL.id], channel,
            is_beta=beta)
        # The add-on's status will be STATUS_NULL when its first version is
        # created because the version has no files when it gets added and it
        # gets flagged as invalid. We need to manually set the status.
        if (addon.status == amo.STATUS_NULL and
                channel == amo.RELEASE_CHANNEL_LISTED):
            addon.update(status=amo.STATUS_NOMINATED)
        auto_sign_version(version, is_beta=version.is_beta)
Пример #22
0
def migrate_legacy_dictionary_to_webextension(addon):
    """Migrate a single legacy dictionary to webextension format, creating a
    new package from the current_version, faking an upload to create a new
    Version instance."""
    user = UserProfile.objects.get(pk=settings.TASK_USER_ID)
    now = datetime.now()

    # Wrap zip in FileUpload for Version.from_upload() to consume.
    upload = FileUpload.objects.create(
        user=user, valid=True)
    destination = os.path.join(
        user_media_path('addons'), 'temp', uuid.uuid4().hex + '.xpi')
    target_language = build_webext_dictionary_from_legacy(addon, destination)
    if not addon.target_locale:
        addon.update(target_locale=target_language)

    upload.update(path=destination)

    parsed_data = parse_addon(upload, addon=addon, user=user)
    # Create version.
    # WebExtension dictionaries are only compatible with Firefox Desktop
    # Firefox for Android uses the OS spellchecking.
    version = Version.from_upload(
        upload, addon, selected_apps=[amo.FIREFOX.id],
        channel=amo.RELEASE_CHANNEL_LISTED, parsed_data=parsed_data)
    activity.log_create(amo.LOG.ADD_VERSION, version, addon, user=user)

    # Sign the file, and set it to public. That should automatically set
    # current_version to the version we created.
    file_ = version.all_files[0]
    sign_file(file_)
    file_.update(datestatuschanged=now, reviewed=now, status=amo.STATUS_PUBLIC)
Пример #23
0
 def test_mozilla_signed_extension(self):
     self.dummy_parsed_data['is_mozilla_signed_extension'] = True
     version = Version.from_upload(
         self.upload, self.addon, [self.selected_app],
         amo.RELEASE_CHANNEL_LISTED, parsed_data=self.dummy_parsed_data)
     assert version.is_mozilla_signed
     assert version.approval_notes == (u'This version has been signed with '
                                       u'Mozilla internal certificate.')
Пример #24
0
 def test_file_platform_is_always_all(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED,
                                   parsed_data=parsed_data)
     files = version.all_files
     assert len(files) == 1
     assert files[0].platform == amo.PLATFORM_ALL.id
Пример #25
0
 def test_new_version_is_10s_compatible_no_feature_compat_previously(self):
     assert not self.addon.feature_compatibility.pk
     self.upload = self.get_upload('multiprocess_compatible_extension.xpi')
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     assert version.pk
     assert self.addon.feature_compatibility.pk
     assert self.addon.feature_compatibility.e10s == amo.E10S_COMPATIBLE
Пример #26
0
 def test_app_versions(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED,
                                   parsed_data=parsed_data)
     assert amo.FIREFOX in version.compatible_apps
     app = version.compatible_apps[amo.FIREFOX]
     assert app.min.version == '3.0'
     assert app.max.version == '3.6.*'
Пример #27
0
 def test_new_version_while_public(
         self, generate_static_theme_preview_mock):
     self.addon = addon_factory(type=amo.ADDON_STATICTHEME)
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(
         self.upload, self.addon, [], amo.RELEASE_CHANNEL_LISTED,
         parsed_data=parsed_data)
     assert len(version.all_files) == 1
     assert generate_static_theme_preview_mock.call_count == 1
Пример #28
0
 def test_file_name(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(
         self.upload, self.addon, [self.selected_app],
         amo.RELEASE_CHANNEL_LISTED,
         parsed_data=parsed_data)
     files = version.all_files
     assert files[0].filename == (
         u'delicious_bookmarks-%s.xml' % self.now)
Пример #29
0
    def test_version_log_transformer(self):
        addon = Addon.objects.get()
        version = addon.latest_version
        amo.log(amo.LOG.REJECT_VERSION, addon, version,
                user=self.request.user)

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

        amo.log(amo.LOG.REJECT_VERSION, addon, version_two,
                user=self.request.user)

        versions = (Version.objects.filter(addon=addon).order_by('-created')
                                   .transform(Version.transformer_activity))

        eq_(len(versions[0].all_activity), 1)
        eq_(len(versions[1].all_activity), 1)
Пример #30
0
    def test_track_upload_time(self):
        # Set created time back (just for sanity) otherwise the delta
        # would be in the microsecond range.
        self.upload.update(created=datetime.now() - timedelta(days=1))

        mock_timing_path = 'olympia.versions.models.statsd.timing'
        with mock.patch(mock_timing_path) as mock_timing:
            Version.from_upload(self.upload, self.addon, [self.platform],
                                amo.RELEASE_CHANNEL_LISTED)

            upload_start = utc_millesecs_from_epoch(self.upload.created)
            now = utc_millesecs_from_epoch()
            rough_delta = now - upload_start
            actual_delta = mock_timing.call_args[0][1]

            fuzz = 2000  # 2 seconds
            assert (actual_delta >= (rough_delta - fuzz) and
                    actual_delta <= (rough_delta + fuzz))
Пример #31
0
 def test_file_name(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert files[0].filename == (
         u'delicious_bookmarks-%s.xml' % self.now)
Пример #32
0
 def test_file_not_multi_package(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert not files[0].is_multi_package
Пример #33
0
 def test_version_number(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     assert version.version == self.now
Пример #34
0
        if addon:
            if addon.versions.filter(version=data['version']).exists():
                log.info(
                    '[@None] Version {0} of "{1}" language pack exists'.format(
                        data['version'], xpi))
                return

            if not addon.addonuser_set.filter(user=owner).exists():
                log.info('[@None] Skipping language pack "{0}": '
                         'not owned by {1}'.format(
                             xpi, settings.LANGPACK_OWNER_EMAIL))
                return

            version = Version.from_upload(upload,
                                          addon, [amo.PLATFORM_ALL.id],
                                          is_beta=is_beta)

            log.info(
                '[@None] Updated language pack "{0}" to version {1}'.format(
                    xpi, data['version']))
        else:
            if is_beta:
                log.error('[@None] Not creating beta version {0} for new '
                          '"{1}" language pack'.format(data['version'], xpi))
                return

            if (Addon.objects.filter(
                    name__localized_string=data['name']).exists()):
                data['old_name'] = data['name']
                data['name'] = u'{0} ({1})'.format(
Пример #35
0
 def create_new_version():
     return Version.from_upload(upload,
                                addon, [amo.FIREFOX.id],
                                amo.RELEASE_CHANNEL_LISTED,
                                parsed_data=parsed_data)
Пример #36
0
 def get_url(self, obj):
     # Addon.get_url_path() wants current_version to exist, but that's just
     # a safeguard. We don't care and don't want to fetch the current
     # version field to improve perf, so give it a fake one.
     obj._current_version = Version()
     return absolutify(obj.get_url_path())
Пример #37
0
def add_static_theme_from_lwt(lwt):
    from olympia.activity.models import AddonLog
    # Try to handle LWT with no authors
    author = (lwt.listed_authors or [_get_lwt_default_author()])[0]
    # Wrap zip in FileUpload for Addon/Version from_upload to consume.
    upload = FileUpload.objects.create(
        user=author, valid=True)
    destination = os.path.join(
        user_media_path('addons'), 'temp', uuid.uuid4().hex + '.xpi')
    build_static_theme_xpi_from_lwt(lwt, destination)
    upload.update(path=destination)

    # Create addon + version
    parsed_data = parse_addon(upload, user=author)
    addon = Addon.initialize_addon_from_upload(
        parsed_data, upload, amo.RELEASE_CHANNEL_LISTED, author)
    addon_updates = {}
    # Version.from_upload sorts out platforms for us.
    version = Version.from_upload(
        upload, addon, platforms=None, channel=amo.RELEASE_CHANNEL_LISTED,
        parsed_data=parsed_data)

    # Set category
    static_theme_categories = CATEGORIES.get(amo.FIREFOX.id, []).get(
        amo.ADDON_STATICTHEME, [])
    lwt_category = (lwt.categories.all() or [None])[0]  # lwt only have 1 cat.
    lwt_category_slug = lwt_category.slug if lwt_category else 'other'
    static_category = static_theme_categories.get(
        lwt_category_slug, static_theme_categories.get('other'))
    AddonCategory.objects.create(
        addon=addon,
        category=Category.from_static_category(static_category, True))

    # Set license
    lwt_license = PERSONA_LICENSES_IDS.get(
        lwt.persona.license, LICENSE_COPYRIGHT_AR)  # default to full copyright
    static_license = License.objects.get(builtin=lwt_license.builtin)
    version.update(license=static_license)

    # Set tags
    for addon_tag in AddonTag.objects.filter(addon=lwt):
        AddonTag.objects.create(addon=addon, tag=addon_tag.tag)

    # Steal the ratings (even with soft delete they'll be deleted anyway)
    addon_updates.update(
        average_rating=lwt.average_rating,
        bayesian_rating=lwt.bayesian_rating,
        total_ratings=lwt.total_ratings,
        text_ratings_count=lwt.text_ratings_count)
    Rating.unfiltered.filter(addon=lwt).update(addon=addon, version=version)
    # Modify the activity log entry too.
    rating_activity_log_ids = [
        l.id for l in amo.LOG if getattr(l, 'action_class', '') == 'review']
    addonlog_qs = AddonLog.objects.filter(
        addon=lwt, activity_log__action__in=rating_activity_log_ids)
    [alog.transfer(addon) for alog in addonlog_qs.iterator()]

    # Copy the ADU statistics - the raw(ish) daily UpdateCounts for stats
    # dashboard and future update counts, and copy the summary numbers for now.
    migrate_theme_update_count(lwt, addon)
    addon_updates.update(
        average_daily_users=lwt.persona.popularity or 0,
        hotness=lwt.persona.movers or 0)

    # Logging
    activity.log_create(
        amo.LOG.CREATE_STATICTHEME_FROM_PERSONA, addon, user=author)

    # And finally sign the files (actually just one)
    for file_ in version.all_files:
        sign_file(file_)
        file_.update(
            datestatuschanged=datetime.now(),
            reviewed=datetime.now(),
            status=amo.STATUS_PUBLIC)
    addon_updates['status'] = amo.STATUS_PUBLIC

    # set the modified and creation dates to match the original.
    addon_updates['created'] = lwt.created
    addon_updates['modified'] = lwt.modified

    addon.update(**addon_updates)
    return addon
Пример #38
0
 def _get_version(self, status):
     v = Version()
     v.all_files = [mock.Mock()]
     v.all_files[0].status = status
     return v
Пример #39
0
 def test_carry_over_old_license(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     assert version.license_id == self.addon.current_version.license_id
Пример #40
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)

        # 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', 'icon_type', 'is_listed',
             'last_updated', 'modified', 'public_stats', 'slug', 'status',
             'type', 'weekly_downloads'))

        # Temporary hack to make sure all add-ons have a modified date when
        # serializing, to avoid errors when calling get_icon_url().
        # Remove once all add-ons have been reindexed at least once since the
        # addition of `modified` in the mapping.
        if obj.modified is None:
            obj.modified = obj.created

        # 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.

        # Categories are annoying, skip them for now. We probably need to start
        # declaring them in the code to properly handle translations etc if we
        # want to display them in search results.
        obj.all_categories = []

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

        # Attach related models (also faking them).
        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

        if data['type'] == amo.ADDON_PERSONA:
            persona_data = data.get('persona')
            if persona_data:
                obj.persona = Persona(
                    addon=obj,
                    accentcolor=persona_data['accentcolor'],
                    display_username=persona_data['author'],
                    header=persona_data['header'],
                    footer=persona_data['footer'],
                    persona_id=1 if persona_data['is_new'] else None,
                    textcolor=persona_data['textcolor'])
            else:
                # Sadly, https://code.djangoproject.com/ticket/14368 prevents
                # us from setting obj.persona = None. This is fixed in
                # Django 1.9, but in the meantime, work around it by creating
                # a Persona instance with a custom attribute indicating that
                # it should not be used.
                obj.persona = Persona()
                obj.persona._broken = True

        return obj
Пример #41
0
def add_static_theme_from_lwt(lwt):
    from olympia.activity.models import AddonLog

    timer = StopWatch(
        'addons.tasks.migrate_lwts_to_static_theme.add_from_lwt.')
    timer.start()

    olympia.core.set_user(UserProfile.objects.get(pk=settings.TASK_USER_ID))
    # Try to handle LWT with no authors
    author = (lwt.listed_authors or [_get_lwt_default_author()])[0]
    # Wrap zip in FileUpload for Addon/Version from_upload to consume.
    upload = FileUpload.objects.create(user=author, valid=True)
    filename = uuid.uuid4().hex + '.xpi'
    destination = os.path.join(user_media_path('addons'), 'temp', filename)
    build_static_theme_xpi_from_lwt(lwt, destination)
    upload.update(path=destination, name=filename)
    timer.log_interval('1.build_xpi')

    # Create addon + version
    parsed_data = parse_addon(upload, user=author)
    timer.log_interval('2a.parse_addon')

    addon = Addon.initialize_addon_from_upload(parsed_data, upload,
                                               amo.RELEASE_CHANNEL_LISTED,
                                               author)
    addon_updates = {}
    timer.log_interval('2b.initialize_addon')

    # static themes are only compatible with Firefox at the moment,
    # not Android
    version = Version.from_upload(upload,
                                  addon,
                                  selected_apps=[amo.FIREFOX.id],
                                  channel=amo.RELEASE_CHANNEL_LISTED,
                                  parsed_data=parsed_data)
    timer.log_interval('3.initialize_version')

    # Set category
    lwt_category = (lwt.categories.all() or [None])[0]  # lwt only have 1 cat.
    lwt_category_slug = lwt_category.slug if lwt_category else 'other'
    for app, type_dict in CATEGORIES.items():
        static_theme_categories = type_dict.get(amo.ADDON_STATICTHEME, [])
        static_category = static_theme_categories.get(
            lwt_category_slug, static_theme_categories.get('other'))
        AddonCategory.objects.create(addon=addon,
                                     category=Category.from_static_category(
                                         static_category, True))
    timer.log_interval('4.set_categories')

    # Set license
    lwt_license = PERSONA_LICENSES_IDS.get(
        lwt.persona.license, LICENSE_COPYRIGHT_AR)  # default to full copyright
    static_license = License.objects.get(builtin=lwt_license.builtin)
    version.update(license=static_license)
    timer.log_interval('5.set_license')

    # Set tags
    for addon_tag in AddonTag.objects.filter(addon=lwt):
        AddonTag.objects.create(addon=addon, tag=addon_tag.tag)
    timer.log_interval('6.set_tags')

    # Steal the ratings (even with soft delete they'll be deleted anyway)
    addon_updates.update(average_rating=lwt.average_rating,
                         bayesian_rating=lwt.bayesian_rating,
                         total_ratings=lwt.total_ratings,
                         text_ratings_count=lwt.text_ratings_count)
    Rating.unfiltered.filter(addon=lwt).update(addon=addon, version=version)
    timer.log_interval('7.move_ratings')

    # Replace the lwt in collections
    CollectionAddon.objects.filter(addon=lwt).update(addon=addon)

    # Modify the activity log entry too.
    rating_activity_log_ids = [
        l.id for l in amo.LOG if getattr(l, 'action_class', '') == 'review'
    ]
    addonlog_qs = AddonLog.objects.filter(
        addon=lwt, activity_log__action__in=rating_activity_log_ids)
    [alog.transfer(addon) for alog in addonlog_qs.iterator()]
    timer.log_interval('8.move_activity_logs')

    # Copy the ADU statistics - the raw(ish) daily UpdateCounts for stats
    # dashboard and future update counts, and copy the average_daily_users.
    # hotness will be recalculated by the deliver_hotness() cron in a more
    # reliable way that we could do, so skip it entirely.
    migrate_theme_update_count(lwt, addon)
    addon_updates.update(average_daily_users=lwt.persona.popularity or 0,
                         hotness=0)
    timer.log_interval('9.copy_statistics')

    # Logging
    activity.log_create(amo.LOG.CREATE_STATICTHEME_FROM_PERSONA,
                        addon,
                        user=author)

    # And finally sign the files (actually just one)
    for file_ in version.all_files:
        sign_file(file_)
        file_.update(datestatuschanged=lwt.last_updated,
                     reviewed=datetime.now(),
                     status=amo.STATUS_APPROVED)
    timer.log_interval('10.sign_files')
    addon_updates['status'] = amo.STATUS_APPROVED

    # set the modified and creation dates to match the original.
    addon_updates['created'] = lwt.created
    addon_updates['modified'] = lwt.modified
    addon_updates['last_updated'] = lwt.last_updated

    addon.update(**addon_updates)
    return addon
Пример #42
0
 def _transformer(self, objs):
     Version.transformer_promoted([
         promo.addon._current_version for promo in objs
         if promo.addon._current_version
     ])
Пример #43
0
        owner = UserProfile.objects.get(email=settings.LANGPACK_OWNER_EMAIL)

        if addon:
            if addon.versions.filter(version=data['version']).exists():
                log.info('[@None] Version {0} of "{1}" language pack exists'
                         .format(data['version'], xpi))
                return

            if not addon.addonuser_set.filter(user=owner).exists():
                log.info('[@None] Skipping language pack "{0}": '
                         'not owned by {1}'.format(
                             xpi, settings.LANGPACK_OWNER_EMAIL))
                return

            version = Version.from_upload(upload, addon, [amo.PLATFORM_ALL.id],
                                          amo.RELEASE_CHANNEL_LISTED,
                                          parsed_data=data)

            log.info('[@None] Updated language pack "{0}" to version {1}'
                     .format(xpi, data['version']))
        else:
            if (Addon.objects.filter(name__localized_string=data['name'])
                    .exists()):
                data['old_name'] = data['name']
                data['name'] = u'{0} ({1})'.format(
                    data['old_name'], data['apps'][0].appdata.pretty)

                log.warning(u'[@None] Creating langpack {guid}: Add-on with '
                            u'name {old_name!r} already exists, trying '
                            u'{name!r}.'.format(**data))
Пример #44
0
 def test_carry_over_old_license(self):
     version = Version.from_upload(self.upload,
                                   self.addon, [self.selected_app],
                                   amo.RELEASE_CHANNEL_LISTED,
                                   parsed_data=self.dummy_parsed_data)
     assert version.license_id == self.addon.current_version.license_id
Пример #45
0
 def test_file_platform_is_always_all(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert len(files) == 1
     assert files[0].platform == amo.PLATFORM_ALL.id
Пример #46
0
 def test_carry_over_license_no_version(self):
     self.addon.versions.all().delete()
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     assert version.license_id is None
Пример #47
0
 def test_status(self):
     self.current.files.all().update(status=amo.STATUS_AWAITING_REVIEW)
     Version.from_upload(self.upload, self.addon, [self.platform],
                         amo.RELEASE_CHANNEL_LISTED)
     assert File.objects.filter(version=self.current)[0].status == (
         amo.STATUS_DISABLED)
Пример #48
0
 def test_file_platform(self):
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert len(files) == 1
     assert files[0].platform == self.platform
Пример #49
0
 def test_generate_filename_ja(self):
     f = File()
     f.version = Version(version='0.1.7')
     f.version.compatible_apps = (amo.FIREFOX, )
     f.version.addon = Addon(name=u' フォクすけ  といっしょ')
     assert f.generate_filename() == 'addon-0.1.7-fx.xpi'
Пример #50
0
 def test_file_name_platform_all(self):
     version = Version.from_upload(self.upload, self.addon,
                                   [amo.PLATFORM_ALL.id],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert files[0].filename == u'delicious_bookmarks-0.1-fx.xpi'
Пример #51
0
    def create_version(self, addon=None):
        from olympia.addons.models import Addon
        from olympia.files.models import FileUpload
        from olympia.files.utils import parse_addon
        from olympia.versions.models import Version
        from olympia.versions.utils import get_next_version_number

        version_number = '1.0'

        # If passing an existing add-on, we need to bump the version number
        # to avoid clashes, and also perform a few checks.
        if addon is not None:
            # Obviously we want an add-on with the right type.
            if addon.type != amo.ADDON_SITE_PERMISSION:
                raise ImproperlyConfigured(
                    'SitePermissionVersionCreator was instantiated with non '
                    'site-permission add-on'
                )
            # If the user isn't an author, something is wrong.
            if not addon.authors.filter(pk=self.user.pk).exists():
                raise ImproperlyConfigured(
                    'SitePermissionVersionCreator was instantiated with a '
                    'bogus addon/user'
                )
            # Changing the origins isn't supported at the moment.
            latest_version = addon.find_latest_version(
                exclude=(), channel=amo.RELEASE_CHANNEL_UNLISTED
            )
            previous_origins = sorted(
                latest_version.installorigin_set.all().values_list('origin', flat=True)
            )
            if previous_origins != self.install_origins:
                raise ImproperlyConfigured(
                    'SitePermissionVersionCreator was instantiated with an '
                    'addon that has different origins'
                )

            version_number = get_next_version_number(addon)

        # Create the manifest, with more user-friendly name & description built
        # from install_origins/site_permissions, and then the zipfile with that
        # manifest inside.
        manifest_data = self._create_manifest(version_number)
        file_obj = self._create_zipfile(manifest_data)

        # Parse the zip we just created. The user needs to be the Mozilla User
        # because regular submissions of this type of add-on is forbidden to
        # normal users.
        parsed_data = parse_addon(
            file_obj,
            addon=addon,
            user=get_task_user(),
        )

        with core.override_remote_addr(self.remote_addr):
            if addon is None:
                # Create the Addon instance (without a Version/File at this point).
                addon = Addon.initialize_addon_from_upload(
                    data=parsed_data,
                    upload=file_obj,
                    channel=amo.RELEASE_CHANNEL_UNLISTED,
                    user=self.user,
                )

            # Create the FileUpload that will become the File+Version.
            upload = FileUpload.from_post(
                file_obj,
                filename=file_obj.name,
                size=file_obj.size,
                addon=addon,
                version=version_number,
                channel=amo.RELEASE_CHANNEL_UNLISTED,
                user=self.user,
                source=amo.UPLOAD_SOURCE_GENERATED,
            )

        # And finally create the Version instance from the FileUpload.
        return Version.from_upload(
            upload,
            addon,
            amo.RELEASE_CHANNEL_UNLISTED,
            selected_apps=[x[0] for x in amo.APPS_CHOICES],
            parsed_data=parsed_data,
        )
Пример #52
0
 def test_file_multi_package(self):
     version = Version.from_upload(self.get_upload('multi-package.xpi'),
                                   self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED)
     files = version.all_files
     assert files[0].is_multi_package
Пример #53
0
 def test_version_number(self):
     parsed_data = parse_addon(self.upload, self.addon, user=mock.Mock())
     version = Version.from_upload(self.upload, self.addon, [self.platform],
                                   amo.RELEASE_CHANNEL_LISTED,
                                   parsed_data=parsed_data)
     assert version.version == self.now
Пример #54
0
        if addon:
            if addon.versions.filter(version=data['version']).exists():
                log.info(
                    '[@None] Version {0} of "{1}" language pack exists'.format(
                        data['version'], xpi))
                return

            if not addon.addonuser_set.filter(user=owner).exists():
                log.info('[@None] Skipping language pack "{0}": '
                         'not owned by {1}'.format(
                             xpi, settings.LANGPACK_OWNER_EMAIL))
                return

            version = Version.from_upload(upload,
                                          addon, [amo.PLATFORM_ALL.id],
                                          amo.RELEASE_CHANNEL_LISTED,
                                          is_beta=is_beta)

            log.info(
                '[@None] Updated language pack "{0}" to version {1}'.format(
                    xpi, data['version']))
        else:
            if is_beta:
                log.error('[@None] Not creating beta version {0} for new '
                          '"{1}" language pack'.format(data['version'], xpi))
                return

            if (Addon.objects.filter(
                    name__localized_string=data['name']).exists()):
                data['old_name'] = data['name']
                data['name'] = u'{0} ({1})'.format(