Ejemplo n.º 1
0
    def test_personas_grid_sorting(self):
        """Ensure we hit a grid page if there is a sorting."""
        category = Category(
            type=amo.ADDON_PERSONA, slug='abc', application=amo.FIREFOX.id)
        category.save()
        category_url = reverse('browse.personas', args=[category.slug])
        response = self.client.get(category_url + '?sort=created')
        self.assertTemplateUsed(response, self.grid_template)

        # Whatever the `category.count` is.
        category.update(count=MIN_COUNT_FOR_LANDING + 1)
        response = self.client.get(category_url + '?sort=created')
        self.assertTemplateUsed(response, self.grid_template)
Ejemplo n.º 2
0
def add_static_theme_from_lwt(lwt):
    # 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)
    # 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)

    # Logging
    activity.log_create(
        amo.LOG.CREATE_STATICTHEME_FROM_PERSONA, addon, user=author)
    log.debug('New static theme %r created from %r' % (addon, lwt))

    # 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.update(status=amo.STATUS_PUBLIC)

    return addon
Ejemplo n.º 3
0
    def test_personas_landing(self):
        """
        Show landing page if there are greater than
        MIN_COUNT_FOR_LANDING popular Personas.
        """
        self.create_personas(MIN_COUNT_FOR_LANDING,
                             persona_extras={'popularity': 100})
        base = Addon.objects.public().filter(type=amo.ADDON_PERSONA)
        assert base.count() == MIN_COUNT_FOR_LANDING + 2
        response = self.client.get(self.landing_url)
        self.assertTemplateUsed(response, self.landing_template)

        # Whatever the `category.count` is.
        category = Category(
            type=amo.ADDON_PERSONA, slug='abc',
            count=MIN_COUNT_FOR_LANDING + 1, application=amo.FIREFOX.id)
        category.save()
        response = self.client.get(self.landing_url)
        self.assertTemplateUsed(response, self.landing_template)
Ejemplo n.º 4
0
    def test_personas_landing(self):
        """
        Show landing page if there are greater than
        MIN_COUNT_FOR_LANDING popular Personas.
        """
        self.create_personas(MIN_COUNT_FOR_LANDING,
                             persona_extras={'popularity': 100})
        base = Addon.objects.public().filter(type=amo.ADDON_PERSONA)
        assert base.count() == MIN_COUNT_FOR_LANDING + 2
        r = self.client.get(self.landing_url)
        self.assertTemplateUsed(r, self.landing_template)

        # Whatever the `category.count` is.
        category = Category(
            type=amo.ADDON_PERSONA, slug='abc',
            count=MIN_COUNT_FOR_LANDING + 1, application=amo.FIREFOX.id)
        category.save()
        response = self.client.get(self.landing_url)
        self.assertTemplateUsed(response, self.landing_template)
Ejemplo n.º 5
0
    def test_themes_category(self):
        static_category = (
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_PERSONA]['fashion'])
        category = Category.from_static_category(static_category, True)

        self.theme = amo.tests.addon_factory(
            type=amo.ADDON_PERSONA, users=[self.user], category=category)

        res = self.client.get(
            self.user.get_themes_url_path(args=[category.slug]))
        self._test_good(res)
Ejemplo n.º 6
0
    def test_themes_category(self):
        static_category = (
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_PERSONA]['fashion'])
        category = Category.from_static_category(static_category, True)

        self.theme = amo.tests.addon_factory(
            type=amo.ADDON_PERSONA, users=[self.user], category=category)

        res = self.client.get(
            self.user.get_themes_url_path(args=[category.slug]))
        self._test_good(res)
Ejemplo n.º 7
0
    def setUp(self):
        super(TestCategoriesFeed, self).setUp()
        self.feed = feeds.CategoriesRss()
        self.u = u'Ελληνικά'
        self.wut = Translation(localized_string=self.u, locale='el')

        self.feed.request = mock.Mock()
        self.feed.request.APP.pretty = self.u

        self.category = Category(db_name=self.u)

        self.addon = Addon(name=self.u, id=2, type=1, slug='xx')
        self.addon._current_version = Version(version='v%s' % self.u)
Ejemplo n.º 8
0
def add_static_theme_from_lwt(lwt):
    # 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)
    # 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)

    # Logging
    activity.log_create(
        amo.LOG.CREATE_STATICTHEME_FROM_PERSONA, addon, user=author)
    log.debug('New static theme %r created from %r' % (addon, lwt))

    # And finally update the statuses
    version.all_files[0].update(status=amo.STATUS_PUBLIC)
    addon.update(status=amo.STATUS_PUBLIC)

    return addon
Ejemplo n.º 9
0
    def test_personas_grid_sorting(self):
        """Ensure we hit a grid page if there is a sorting."""
        category = Category(
            type=amo.ADDON_PERSONA, slug='abc', application=amo.FIREFOX.id)
        category.save()
        category_url = reverse('browse.personas', args=[category.slug])
        r = self.client.get(category_url + '?sort=created')
        self.assertTemplateUsed(r, self.grid_template)

        # Whatever the `category.count` is.
        category.update(count=MIN_COUNT_FOR_LANDING + 1)
        r = self.client.get(category_url + '?sort=created')
        self.assertTemplateUsed(r, self.grid_template)
Ejemplo n.º 10
0
    def _handle_addon(self, addon_data):
        version = addon_data['current_version']
        files = version['files'] or []

        file_kw = {}

        try:
            file_kw = {
                'hash': files[0]['hash'],
                'status': amo.STATUS_CHOICES_API_LOOKUP[files[0]['status']],
                'platform': amo.PLATFORM_DICT[files[0]['platform']].id,
                'size': files[0]['size'],
                'is_webextension': files[0]['is_webextension'],
                'is_mozilla_signed_extension': (
                    files[0]['is_mozilla_signed_extension']),
                'strict_compatibility': (
                    version['is_strict_compatibility_enabled'])
            }
        except (KeyError, IndexError):
            file_kw = {}

        # TODO:
        # * license
        # * ratings
        # * previews
        # * android compat & category data

        if Addon.objects.filter(slug=addon_data['slug']).exists():
            print('Skipping %s (slug already exists)' % addon_data['slug'])
            return

        if addon_data['guid'] and Addon.objects.filter(
                guid=addon_data['guid']).exists():
            print('Skipping %s (guid already exists)' % addon_data['guid'])
            return

        users = []

        for user in addon_data['authors']:
            try:
                users.append(UserProfile.objects.get(username=user['name']))
            except UserProfile.DoesNotExist:
                email = '*****@*****.**' % str(uuid.uuid4().hex)
                users.append(user_factory(username=user['name'], email=email))

        addon_type = amo.ADDON_SEARCH_SLUGS[addon_data['type']]

        if 'firefox' in addon_data['categories']:
            category = addon_data['categories']['firefox'][0]
        else:
            category = None

        if category not in CATEGORIES[amo.FIREFOX.id][addon_type]:
            category = None
            print('Category %s' % category, 'not found')
        else:
            category = Category.from_static_category(
                CATEGORIES[amo.FIREFOX.id][addon_type][category],
                True)

        print('Creating add-on %s' % addon_data['slug'])

        compatibility = version['compatibility']

        if compatibility and 'firefox' in compatibility:
            version_kw = {
                'min_app_version': version['compatibility']['firefox']['min'],
                'max_app_version': version['compatibility']['firefox']['max'],
            }
        else:
            version_kw = {}

        with atomic():
            addon_factory(
                users=users,
                average_daily_users=addon_data['average_daily_users'],
                category=category,
                type=addon_type,
                guid=addon_data['guid'],
                slug=addon_data['slug'],
                name=addon_data['name'],
                summary=addon_data['summary'],
                description=addon_data['description'],
                file_kw=file_kw,
                version_kw=version_kw,
                weekly_downloads=addon_data.get('weekly_downloads', 0),
                default_locale=addon_data['default_locale'],
                tags=addon_data['tags'],
            )
Ejemplo n.º 11
0
def addon_factory(status=amo.STATUS_PUBLIC,
                  version_kw=None,
                  file_kw=None,
                  **kw):
    version_kw = version_kw or {}

    # Disconnect signals until the last save.
    post_save.disconnect(addon_update_search_index,
                         sender=Addon,
                         dispatch_uid='addons.search.index')

    type_ = kw.pop('type', amo.ADDON_EXTENSION)
    popularity = kw.pop('popularity', None)
    persona_id = kw.pop('persona_id', None)
    tags = kw.pop('tags', [])
    users = kw.pop('users', [])
    when = _get_created(kw.pop('created', None))
    category = kw.pop('category', None)

    # Keep as much unique data as possible in the uuid: '-' aren't important.
    name = kw.pop('name', u'Addôn %s' % unicode(uuid.uuid4()).replace('-', ''))

    kwargs = {
        # Set artificially the status to STATUS_PUBLIC for now, the real
        # status will be set a few lines below, after the update_version()
        # call. This prevents issues when calling addon_factory with
        # STATUS_DELETED.
        'status': amo.STATUS_PUBLIC,
        'name': name,
        'slug': name.replace(' ', '-').lower()[:30],
        'average_daily_users': popularity or random.randint(200, 2000),
        'weekly_downloads': popularity or random.randint(200, 2000),
        'created': when,
        'last_updated': when,
    }
    if type_ != amo.ADDON_PERSONA:
        # Personas don't have a summary.
        kwargs['summary'] = u'Summary for %s' % name
    kwargs.update(kw)

    # Save 1.
    if type_ == amo.ADDON_PERSONA:
        # Personas need to start life as an extension for versioning.
        addon = Addon.objects.create(type=amo.ADDON_EXTENSION, **kwargs)
    else:
        addon = Addon.objects.create(type=type_, **kwargs)

    # Save 2.
    version = version_factory(file_kw, addon=addon, **version_kw)
    addon.update_version()
    addon.status = status
    if type_ == amo.ADDON_PERSONA:
        addon.type = type_
        persona_id = persona_id if persona_id is not None else addon.id

        # Save 3.
        Persona.objects.create(addon=addon,
                               popularity=addon.weekly_downloads,
                               persona_id=persona_id)

    for tag in tags:
        Tag(tag_text=tag).save_tag(addon)

    for user in users:
        addon.addonuser_set.create(user=user)

    application = version_kw.get('application', amo.FIREFOX.id)
    if not category:
        static_category = random.choice(
            CATEGORIES[application][type_].values())
        category = Category.from_static_category(static_category, True)
    AddonCategory.objects.create(addon=addon, category=category)

    # Put signals back.
    post_save.connect(addon_update_search_index,
                      sender=Addon,
                      dispatch_uid='addons.search.index')

    # Save 4.
    addon.save()

    if 'nomination' in version_kw:
        # If a nomination date was set on the version, then it might have been
        # erased at post_save by addons.models.watch_status()
        version.save()

    return addon
Ejemplo n.º 12
0
def addon_factory(status=amo.STATUS_APPROVED,
                  version_kw=None,
                  file_kw=None,
                  **kw):
    version_kw = version_kw or {}

    # Disconnect signals until the last save.
    post_save.disconnect(addon_update_search_index,
                         sender=Addon,
                         dispatch_uid='addons.search.index')

    type_ = kw.pop('type', amo.ADDON_EXTENSION)
    popularity = kw.pop('popularity', None)
    tags = kw.pop('tags', [])
    users = kw.pop('users', [])
    when = _get_created(kw.pop('created', None))
    category = kw.pop('category', None)
    default_locale = kw.get('default_locale', settings.LANGUAGE_CODE)

    # Keep as much unique data as possible in the uuid: '-' aren't important.
    name = kw.pop('name', u'Addôn %s' % str(uuid.uuid4()).replace('-', ''))
    slug = kw.pop('slug', None)
    if slug is None:
        slug = name.replace(' ', '-').lower()[:30]

    should_be_recommended = kw.pop('recommended', False)

    kwargs = {
        # Set artificially the status to STATUS_APPROVED for now, the real
        # status will be set a few lines below, after the update_version()
        # call. This prevents issues when calling addon_factory with
        # STATUS_DELETED.
        'status': amo.STATUS_APPROVED,
        'default_locale': default_locale,
        'name': name,
        'slug': slug,
        'average_daily_users': popularity or random.randint(200, 2000),
        'weekly_downloads': popularity or random.randint(200, 2000),
        'created': when,
        'last_updated': when,
    }
    if 'summary' not in kw:
        # Assign a dummy summary if none was specified in keyword args.
        kwargs['summary'] = u'Summary for %s' % name
    if type_ not in [amo.ADDON_SEARCH]:
        # Search engines don't need guids
        kwargs['guid'] = kw.pop('guid', '{%s}' % str(uuid.uuid4()))
    kwargs.update(kw)

    # Save 1.
    with translation.override(default_locale):
        addon = Addon.objects.create(type=type_, **kwargs)

    # Save 2.
    if should_be_recommended:
        version_kw['recommendation_approved'] = True
    version = version_factory(file_kw, addon=addon, **version_kw)

    addon.update_version()
    addon.status = status

    for tag in tags:
        Tag(tag_text=tag).save_tag(addon)

    for user in users:
        addon.addonuser_set.create(user=user)

    application = version_kw.get('application', amo.FIREFOX.id)
    if not category:
        static_category = random.choice(
            list(CATEGORIES[application][addon.type].values()))
        category = Category.from_static_category(static_category, True)
    AddonCategory.objects.create(addon=addon, category=category)

    if should_be_recommended:
        DiscoveryItem.objects.create(addon=addon, recommendable=True)

    # Put signals back.
    post_save.connect(addon_update_search_index,
                      sender=Addon,
                      dispatch_uid='addons.search.index')

    # Save 4.
    addon.save()
    if addon.guid:
        AddonGUID.objects.create(addon=addon, guid=addon.guid)

    # Potentially update is_public on authors
    [user.update_is_public() for user in users]

    if 'nomination' in version_kw:
        # If a nomination date was set on the version, then it might have been
        # erased at post_save by addons.models.watch_status()
        version.save()

    return addon
Ejemplo n.º 13
0
def addon_factory(status=amo.STATUS_PUBLIC,
                  version_kw=None,
                  file_kw=None,
                  **kw):
    version_kw = version_kw or {}

    # Disconnect signals until the last save.
    post_save.disconnect(addon_update_search_index,
                         sender=Addon,
                         dispatch_uid='addons.search.index')

    type_ = kw.pop('type', amo.ADDON_EXTENSION)
    popularity = kw.pop('popularity', None)
    persona_id = kw.pop('persona_id', None)
    tags = kw.pop('tags', [])
    users = kw.pop('users', [])
    when = _get_created(kw.pop('created', None))
    category = kw.pop('category', None)
    default_locale = kw.get('default_locale', settings.LANGUAGE_CODE)

    # Keep as much unique data as possible in the uuid: '-' aren't important.
    name = kw.pop('name',
                  u'Addôn %s' % six.text_type(uuid.uuid4()).replace('-', ''))
    slug = kw.pop('slug', None)
    if slug is None:
        slug = name.replace(' ', '-').lower()[:30]

    kwargs = {
        # Set artificially the status to STATUS_PUBLIC for now, the real
        # status will be set a few lines below, after the update_version()
        # call. This prevents issues when calling addon_factory with
        # STATUS_DELETED.
        'status': amo.STATUS_PUBLIC,
        'default_locale': default_locale,
        'name': name,
        'slug': slug,
        'average_daily_users': popularity or random.randint(200, 2000),
        'weekly_downloads': popularity or random.randint(200, 2000),
        'created': when,
        'last_updated': when,
    }
    if type_ != amo.ADDON_PERSONA and 'summary' not in kw:
        # Assign a dummy summary if none was specified in keyword args, unless
        # we're creating a Persona since they don't have summaries.
        kwargs['summary'] = u'Summary for %s' % name
    if type_ not in [amo.ADDON_PERSONA, amo.ADDON_SEARCH]:
        # Personas and search engines don't need guids
        kwargs['guid'] = kw.pop('guid', '{%s}' % six.text_type(uuid.uuid4()))
    kwargs.update(kw)

    # Save 1.
    with translation.override(default_locale):
        addon = Addon.objects.create(type=type_, **kwargs)

    # Save 2.
    version = version_factory(file_kw, addon=addon, **version_kw)
    if addon.type == amo.ADDON_PERSONA:
        addon._current_version = version
        persona_id = persona_id if persona_id is not None else addon.id

        # Save 3.
        Persona.objects.create(addon=addon,
                               popularity=addon.average_daily_users,
                               persona_id=persona_id)

    addon.update_version()
    addon.status = status

    for tag in tags:
        Tag(tag_text=tag).save_tag(addon)

    for user in users:
        addon.addonuser_set.create(user=user)

    application = version_kw.get('application', amo.FIREFOX.id)
    if not category:
        static_category = random.choice(
            list(CATEGORIES[application][addon.type].values()))
        category = Category.from_static_category(static_category, True)
    AddonCategory.objects.create(addon=addon, category=category)

    # Put signals back.
    post_save.connect(addon_update_search_index,
                      sender=Addon,
                      dispatch_uid='addons.search.index')

    # Save 4.
    addon.save()

    if addon.type == amo.ADDON_PERSONA:
        # Personas only have one version and signals.version_changed is never
        # fired for them - instead it gets updated through a cron (!). We do
        # need to get it right in some tests like the ui tests, so we call the
        # task ourselves.
        version_changed(addon.pk)

    # Potentially update is_public on authors
    [user.update_is_public() for user in users]

    if 'nomination' in version_kw:
        # If a nomination date was set on the version, then it might have been
        # erased at post_save by addons.models.watch_status()
        version.save()

    return addon
Ejemplo n.º 14
0
def addon_factory(
        status=amo.STATUS_PUBLIC, version_kw=None, file_kw=None, **kw):
    version_kw = version_kw or {}

    # Disconnect signals until the last save.
    post_save.disconnect(addon_update_search_index, sender=Addon,
                         dispatch_uid='addons.search.index')

    type_ = kw.pop('type', amo.ADDON_EXTENSION)
    popularity = kw.pop('popularity', None)
    persona_id = kw.pop('persona_id', None)
    tags = kw.pop('tags', [])
    users = kw.pop('users', [])
    when = _get_created(kw.pop('created', None))
    category = kw.pop('category', None)
    default_locale = kw.get('default_locale', settings.LANGUAGE_CODE)

    # Keep as much unique data as possible in the uuid: '-' aren't important.
    name = kw.pop('name', u'Addôn %s' % unicode(uuid.uuid4()).replace('-', ''))
    slug = kw.pop('slug', None)
    if slug is None:
        slug = name.replace(' ', '-').lower()[:30]

    kwargs = {
        # Set artificially the status to STATUS_PUBLIC for now, the real
        # status will be set a few lines below, after the update_version()
        # call. This prevents issues when calling addon_factory with
        # STATUS_DELETED.
        'status': amo.STATUS_PUBLIC,
        'default_locale': default_locale,
        'name': name,
        'slug': slug,
        'average_daily_users': popularity or random.randint(200, 2000),
        'weekly_downloads': popularity or random.randint(200, 2000),
        'created': when,
        'last_updated': when,
    }
    if type_ != amo.ADDON_PERSONA:
        # Personas don't have a summary.
        kwargs['summary'] = u'Summary for %s' % name
    if type_ not in [amo.ADDON_PERSONA, amo.ADDON_SEARCH]:
        # Personas and search engines don't need guids
        kwargs['guid'] = kw.pop('guid', '{%s}' % unicode(uuid.uuid4()))
    kwargs.update(kw)

    # Save 1.
    with translation.override(default_locale):
        addon = Addon.objects.create(type=type_, **kwargs)

    # Save 2.
    version = version_factory(file_kw, addon=addon, **version_kw)
    if addon.type == amo.ADDON_PERSONA:
        addon._current_version = version
        persona_id = persona_id if persona_id is not None else addon.id

        # Save 3.
        Persona.objects.create(
            addon=addon, popularity=addon.average_daily_users,
            persona_id=persona_id)

    addon.update_version()
    addon.status = status

    for tag in tags:
        Tag(tag_text=tag).save_tag(addon)

    for user in users:
        addon.addonuser_set.create(user=user)

    application = version_kw.get('application', amo.FIREFOX.id)
    if not category:
        static_category = random.choice(
            CATEGORIES[application][addon.type].values())
        category = Category.from_static_category(static_category, True)
    AddonCategory.objects.create(addon=addon, category=category)

    # Put signals back.
    post_save.connect(addon_update_search_index, sender=Addon,
                      dispatch_uid='addons.search.index')

    # Save 4.
    addon.save()

    if addon.type == amo.ADDON_PERSONA:
        # Personas only have one version and signals.version_changed is never
        # fired for them - instead it gets updated through a cron (!). We do
        # need to get it right in some tests like the ui tests, so we call the
        # task ourselves.
        version_changed(addon.pk)

    # Potentially update is_public on authors
    [user.update_is_public() for user in users]

    if 'nomination' in version_kw:
        # If a nomination date was set on the version, then it might have been
        # erased at post_save by addons.models.watch_status()
        version.save()

    return addon
Ejemplo n.º 15
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()]

    # Logging
    activity.log_create(amo.LOG.CREATE_STATICTHEME_FROM_PERSONA,
                        addon,
                        user=author)
    log.debug('New static theme %r created from %r' % (addon, lwt))

    # 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

    addon.update(**addon_updates)
    return addon
Ejemplo n.º 16
0
    def test_basic(self):
        cat1 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['bookmarks'])
        cat1.save()
        license = License.objects.create(
            name={
                'en-US': u'My License',
                'fr': u'Mä Licence',
            },
            text={
                'en-US': u'Lorem ipsum dolor sit amet, has nemore patrioqué',
            },
            url='http://license.example.com/'

        )
        self.addon = addon_factory(
            average_daily_users=4242,
            average_rating=4.21,
            bayesian_rating=4.22,
            category=cat1,
            contributions=u'https://paypal.me/foobar/',
            description=u'My Addôn description',
            developer_comments=u'Dévelopers Addôn comments',
            file_kw={
                'hash': 'fakehash',
                'is_restart_required': False,
                'is_webextension': True,
                'platform': amo.PLATFORM_WIN.id,
                'size': 42,
            },
            guid=generate_addon_guid(),
            homepage=u'https://www.example.org/',
            icon_type='image/png',
            name=u'My Addôn',
            public_stats=True,
            slug='my-addon',
            summary=u'My Addôn summary',
            support_email=u'*****@*****.**',
            support_url=u'https://support.example.org/support/my-addon/',
            tags=['some_tag', 'some_other_tag'],
            total_ratings=666,
            text_ratings_count=555,
            version_kw={
                'license': license,
                'releasenotes': {
                    'en-US': u'Release notes in english',
                    'fr': u'Notes de version en français',
                },
            },
            weekly_downloads=2147483647,
        )
        AddonUser.objects.create(user=user_factory(username='******'),
                                 addon=self.addon, listed=False)
        second_author = user_factory(
            username='******', display_name=u'Secönd Author')
        first_author = user_factory(
            username='******', display_name=u'First Authôr')
        AddonUser.objects.create(
            user=second_author, addon=self.addon, position=2)
        AddonUser.objects.create(
            user=first_author, addon=self.addon, position=1)
        second_preview = Preview.objects.create(
            addon=self.addon, position=2,
            caption={'en-US': u'My câption', 'fr': u'Mön tîtré'},
            sizes={'thumbnail': [199, 99], 'image': [567, 780]})
        first_preview = Preview.objects.create(addon=self.addon, position=1)

        av_min = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='2.0.99')[0]
        av_max = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='3.0.99')[0]
        ApplicationsVersions.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version=self.addon.current_version,
            min=av_min, max=av_max)
        # Reset current_version.compatible_apps now that we've added an app.
        del self.addon.current_version._compatible_apps

        cat2 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['alerts-updates'])
        cat2.save()
        AddonCategory.objects.create(addon=self.addon, category=cat2)
        cat3 = Category.from_static_category(
            CATEGORIES[amo.THUNDERBIRD.id][amo.ADDON_EXTENSION]['calendar'])
        cat3.save()
        AddonCategory.objects.create(addon=self.addon, category=cat3)

        result = self.serialize()

        assert result['id'] == self.addon.pk

        assert result['average_daily_users'] == self.addon.average_daily_users
        assert result['categories'] == {
            'firefox': ['alerts-updates', 'bookmarks'],
            'thunderbird': ['calendar']}

        assert result['current_beta_version'] is None

        # In this serializer latest_unlisted_version is omitted.
        assert 'latest_unlisted_version' not in result

        assert result['current_version']
        self._test_version(
            self.addon.current_version, result['current_version'])
        assert result['current_version']['url'] == absolutify(
            reverse('addons.versions',
                    args=[self.addon.slug, self.addon.current_version.version])
        )
        self._test_version_license_and_release_notes(
            self.addon.current_version, result['current_version'])

        assert result['authors']
        assert len(result['authors']) == 2
        self._test_author(first_author, result['authors'][0])
        self._test_author(second_author, result['authors'][1])

        assert result['contributions_url'] == self.addon.contributions
        assert result['edit_url'] == absolutify(self.addon.get_dev_url())
        assert result['default_locale'] == self.addon.default_locale
        assert result['description'] == {'en-US': self.addon.description}
        assert result['developer_comments'] == {
            'en-US': self.addon.developer_comments}
        assert result['guid'] == self.addon.guid
        assert result['has_eula'] is False
        assert result['has_privacy_policy'] is False
        assert result['homepage'] == {
            'en-US': get_outgoing_url(unicode(self.addon.homepage))
        }
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))
        assert result['is_disabled'] == self.addon.is_disabled
        assert result['is_experimental'] == self.addon.is_experimental is False
        assert result['is_featured'] == self.addon.is_featured() is False
        assert result['is_source_public'] == self.addon.view_source
        assert result['last_updated'] == (
            self.addon.last_updated.replace(microsecond=0).isoformat() + 'Z')
        assert result['name'] == {'en-US': self.addon.name}
        assert result['previews']
        assert len(result['previews']) == 2

        result_preview = result['previews'][0]
        assert result_preview['id'] == first_preview.pk
        assert result_preview['caption'] is None
        assert result_preview['image_url'] == absolutify(
            first_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            first_preview.thumbnail_url)
        assert result_preview['image_size'] == first_preview.image_size
        assert result_preview['thumbnail_size'] == first_preview.thumbnail_size

        result_preview = result['previews'][1]
        assert result_preview['id'] == second_preview.pk
        assert result_preview['caption'] == {
            'en-US': u'My câption',
            'fr': u'Mön tîtré'
        }
        assert result_preview['image_url'] == absolutify(
            second_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            second_preview.thumbnail_url)
        assert (result_preview['image_size'] == second_preview.image_size ==
                [567, 780])
        assert (result_preview['thumbnail_size'] ==
                second_preview.thumbnail_size == [199, 99])

        assert result['ratings'] == {
            'average': self.addon.average_rating,
            'bayesian_average': self.addon.bayesian_rating,
            'count': self.addon.total_ratings,
            'text_count': self.addon.text_ratings_count,
        }
        assert result['public_stats'] == self.addon.public_stats
        assert result['requires_payment'] == self.addon.requires_payment
        assert result['review_url'] == absolutify(
            reverse('reviewers.review', args=[self.addon.pk]))
        assert result['slug'] == self.addon.slug
        assert result['status'] == 'public'
        assert result['summary'] == {'en-US': self.addon.summary}
        assert result['support_email'] == {'en-US': self.addon.support_email}
        assert result['support_url'] == {
            'en-US': get_outgoing_url(unicode(self.addon.support_url))
        }
        assert 'theme_data' not in result
        assert set(result['tags']) == set(['some_tag', 'some_other_tag'])
        assert result['type'] == 'extension'
        assert result['url'] == absolutify(self.addon.get_url_path())
        assert result['weekly_downloads'] == self.addon.weekly_downloads

        return result
Ejemplo n.º 17
0
def add_static_theme_from_lwt(lwt):
    from olympia.activity.models import AddonLog
    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)
    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 = {}
    # 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)

    # 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=lwt.last_updated,
                     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_updates['last_updated'] = lwt.last_updated

    addon.update(**addon_updates)
    return addon
    def test_basic(self):
        self.addon = addon_factory(
            average_daily_users=4242,
            average_rating=4.21,
            description=u'My Addôn description',
            file_kw={
                'hash': 'fakehash',
                'platform': amo.PLATFORM_WIN.id,
                'size': 42,
            },
            guid=generate_addon_guid(),
            homepage=u'https://www.example.org/',
            icon_type='image/png',
            name=u'My Addôn',
            public_stats=True,
            slug='my-addon',
            summary=u'My Addôn summary',
            support_email=u'*****@*****.**',
            support_url=u'https://support.example.org/support/my-addon/',
            tags=['some_tag', 'some_other_tag'],
            total_reviews=666,
            weekly_downloads=2147483647,
        )
        AddonUser.objects.create(user=user_factory(username='******'),
                                 addon=self.addon, listed=False)
        second_author = user_factory(
            username='******', display_name=u'Secönd Author')
        first_author = user_factory(
            username='******', display_name=u'First Authôr')
        AddonUser.objects.create(
            user=second_author, addon=self.addon, position=2)
        AddonUser.objects.create(
            user=first_author, addon=self.addon, position=1)
        second_preview = Preview.objects.create(
            addon=self.addon, position=2,
            caption={'en-US': u'My câption', 'fr': u'Mön tîtré'})
        first_preview = Preview.objects.create(addon=self.addon, position=1)

        av_min = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='2.0.99')[0]
        av_max = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='3.0.99')[0]
        ApplicationsVersions.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version=self.addon.current_version,
            min=av_min, max=av_max)
        # Reset current_version.compatible_apps now that we've added an app.
        del self.addon.current_version.compatible_apps

        cat1 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['bookmarks'])
        cat1.save()
        AddonCategory.objects.create(addon=self.addon, category=cat1)
        cat2 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['alerts-updates'])
        cat2.save()
        AddonCategory.objects.create(addon=self.addon, category=cat2)
        cat3 = Category.from_static_category(
            CATEGORIES[amo.THUNDERBIRD.id][amo.ADDON_EXTENSION]['calendar'])
        cat3.save()
        AddonCategory.objects.create(addon=self.addon, category=cat3)

        result = self.serialize()

        assert result['id'] == self.addon.pk

        assert result['average_daily_users'] == self.addon.average_daily_users
        assert result['categories'] == {
            'firefox': ['alerts-updates', 'bookmarks'],
            'thunderbird': ['calendar']}

        assert result['current_beta_version'] is None

        assert result['current_version']
        self._test_version(
            self.addon.current_version, result['current_version'])

        assert result['authors']
        assert len(result['authors']) == 2
        assert result['authors'][0] == {
            'name': first_author.name,
            'url': absolutify(first_author.get_url_path())}
        assert result['authors'][1] == {
            'name': second_author.name,
            'url': absolutify(second_author.get_url_path())}

        assert result['edit_url'] == absolutify(self.addon.get_dev_url())
        assert result['default_locale'] == self.addon.default_locale
        assert result['description'] == {'en-US': self.addon.description}
        assert result['guid'] == self.addon.guid
        assert result['has_eula'] is False
        assert result['has_privacy_policy'] is False
        assert result['homepage'] == {'en-US': self.addon.homepage}
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))
        assert result['is_disabled'] == self.addon.is_disabled
        assert result['is_experimental'] == self.addon.is_experimental is False
        assert result['is_listed'] == self.addon.is_listed
        assert result['is_source_public'] == self.addon.view_source
        assert result['name'] == {'en-US': self.addon.name}
        assert result['last_updated'] == self.addon.last_updated.isoformat()

        assert result['previews']
        assert len(result['previews']) == 2

        result_preview = result['previews'][0]
        assert result_preview['id'] == first_preview.pk
        assert result_preview['caption'] is None
        assert result_preview['image_url'] == absolutify(
            first_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            first_preview.thumbnail_url)

        result_preview = result['previews'][1]
        assert result_preview['id'] == second_preview.pk
        assert result_preview['caption'] == {
            'en-US': u'My câption',
            'fr': u'Mön tîtré'
        }
        assert result_preview['image_url'] == absolutify(
            second_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            second_preview.thumbnail_url)

        assert result['ratings'] == {
            'average': self.addon.average_rating,
            'count': self.addon.total_reviews,
        }
        assert result['public_stats'] == self.addon.public_stats
        assert result['review_url'] == absolutify(
            reverse('editors.review', args=[self.addon.pk]))
        assert result['slug'] == self.addon.slug
        assert result['status'] == 'public'
        assert result['summary'] == {'en-US': self.addon.summary}
        assert result['support_email'] == {'en-US': self.addon.support_email}
        assert result['support_url'] == {'en-US': self.addon.support_url}
        assert 'theme_data' not in result
        assert set(result['tags']) == set(['some_tag', 'some_other_tag'])
        assert result['type'] == 'extension'
        assert result['url'] == absolutify(self.addon.get_url_path())
        assert result['weekly_downloads'] == self.addon.weekly_downloads

        return result
Ejemplo n.º 19
0
            if addon.default_locale.lower() == lang.lower():
                addon.target_locale = addon.default_locale

            addon.save()

            log.info(
                '[@None] Created new "{0}" language pack, version {1}'.format(
                    xpi, data['version']))

        # Set the category
        for app in version.compatible_apps:
            static_category = (CATEGORIES.get(app.id,
                                              []).get(amo.ADDON_LPAPP,
                                                      []).get('general'))
            if static_category:
                category = Category.from_static_category(static_category, True)
                AddonCategory.objects.get_or_create(addon=addon,
                                                    category=category)

        # Add a license if there isn't one already
        if not version.license:
            license = License.objects.builtins().get(builtin=1)
            version.update(license=license)

        file_ = version.files.get()
        if not is_beta:
            # Not `version.files.update`, because we need to trigger save
            # hooks.
            file_.update(status=amo.STATUS_PUBLIC)
        sign_file(file_)
Ejemplo n.º 20
0
def addon_factory(status=amo.STATUS_APPROVED,
                  version_kw=None,
                  file_kw=None,
                  **kw):
    version_kw = version_kw or {}

    # Disconnect signals until the last save.
    post_save.disconnect(addon_update_search_index,
                         sender=Addon,
                         dispatch_uid='addons.search.index')
    post_save.disconnect(update_es_for_promoted,
                         sender=PromotedAddon,
                         dispatch_uid='addons.search.index')
    post_save.disconnect(
        update_es_for_promoted_approval,
        sender=PromotedApproval,
        dispatch_uid='addons.search.index',
    )

    type_ = kw.pop('type', amo.ADDON_EXTENSION)
    popularity = kw.pop('popularity', None)
    tags = kw.pop('tags', [])
    users = kw.pop('users', [])
    when = _get_created(kw.pop('created', None))
    category = kw.pop('category', None)
    default_locale = kw.get('default_locale', settings.LANGUAGE_CODE)

    # Keep as much unique data as possible in the uuid: '-' aren't important.
    name = kw.pop('name', 'Addôn %s' % str(uuid.uuid4()).replace('-', ''))
    slug = kw.pop('slug', None)
    if slug is None:
        slug = name.replace(' ', '-').lower()[:30]

    promoted_group = kw.pop('promoted', None)

    kwargs = {
        # Set artificially the status to STATUS_APPROVED for now, the real
        # status will be set a few lines below, after the update_version()
        # call. This prevents issues when calling addon_factory with
        # STATUS_DELETED.
        'status': amo.STATUS_APPROVED,
        'default_locale': default_locale,
        'name': name,
        'slug': slug,
        'average_daily_users': popularity or random.randint(200, 2000),
        'weekly_downloads': popularity or random.randint(200, 2000),
        'created': when,
        'last_updated': when,
    }
    if 'summary' not in kw:
        # Assign a dummy summary if none was specified in keyword args.
        kwargs['summary'] = 'Summary for %s' % name
    kwargs['guid'] = kw.pop('guid', '{%s}' % str(uuid.uuid4()))
    kwargs.update(kw)

    # Save 1.
    with translation.override(default_locale):
        addon = Addon.objects.create(type=type_, **kwargs)

    # Save 2.
    if promoted_group:
        PromotedAddon.objects.create(addon=addon, group_id=promoted_group.id)
        if 'promotion_approved' not in version_kw:
            version_kw['promotion_approved'] = True

    version = version_factory(file_kw, addon=addon, **version_kw)
    addon.update_version()
    # version_changed task will be triggered and will update last_updated in
    # database for this add-on depending on the state of the version / files.
    # We're calling the function it uses to compute the value ourselves and=
    # sticking that into the attribute ourselves so that we already have the
    # correct value in the instance we are going to return.
    # Note: the aim is to have the instance consistent with what will be in the
    # database because of the task, *not* to be consistent with the status of
    # the add-on. Because we force the add-on status without forcing the status
    # of the latest file, the value we end up with might not make sense in some
    # cases.
    addon.last_updated = compute_last_updated(addon)
    addon.status = status

    for tag in tags:
        Tag(tag_text=tag).save_tag(addon)

    for user in users:
        addon.addonuser_set.create(user=user)

    application = version_kw.get('application', amo.FIREFOX.id)
    if not category and addon.type in CATEGORIES[application]:
        static_category = random.choice(
            list(CATEGORIES[application][addon.type].values()))
        category = Category.from_static_category(static_category, True)
    if category:
        AddonCategory.objects.create(addon=addon, category=category)

    # Put signals back.
    post_save.connect(addon_update_search_index,
                      sender=Addon,
                      dispatch_uid='addons.search.index')
    post_save.connect(update_es_for_promoted,
                      sender=PromotedAddon,
                      dispatch_uid='addons.search.index')
    post_save.connect(
        update_es_for_promoted_approval,
        sender=PromotedApproval,
        dispatch_uid='addons.search.index',
    )

    # Save 4.
    addon.save()
    if addon.guid:
        AddonGUID.objects.create(addon=addon, guid=addon.guid)

    # Potentially update is_public on authors
    [user.update_is_public() for user in users]

    if 'nomination' in version_kw:
        # If a nomination date was set on the version, then it might have been
        # erased at post_save by addons.models.watch_status()
        version.save()

    return addon
Ejemplo n.º 21
0
    def test_basic(self):
        cat1 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['bookmarks'])
        cat1.save()
        self.addon = addon_factory(
            average_daily_users=4242,
            average_rating=4.21,
            bayesian_rating=4.22,
            category=cat1,
            description=u'My Addôn description',
            file_kw={
                'hash': 'fakehash',
                'is_restart_required': False,
                'is_webextension': True,
                'platform': amo.PLATFORM_WIN.id,
                'size': 42,
            },
            guid=generate_addon_guid(),
            homepage=u'https://www.example.org/',
            icon_type='image/png',
            name=u'My Addôn',
            public_stats=True,
            slug='my-addon',
            summary=u'My Addôn summary',
            support_email=u'*****@*****.**',
            support_url=u'https://support.example.org/support/my-addon/',
            tags=['some_tag', 'some_other_tag'],
            total_reviews=666,
            weekly_downloads=2147483647,
        )
        AddonUser.objects.create(user=user_factory(username='******'),
                                 addon=self.addon,
                                 listed=False)
        second_author = user_factory(username='******',
                                     display_name=u'Secönd Author')
        first_author = user_factory(username='******',
                                    display_name=u'First Authôr')
        AddonUser.objects.create(user=second_author,
                                 addon=self.addon,
                                 position=2)
        AddonUser.objects.create(user=first_author,
                                 addon=self.addon,
                                 position=1)
        second_preview = Preview.objects.create(addon=self.addon,
                                                position=2,
                                                caption={
                                                    'en-US': u'My câption',
                                                    'fr': u'Mön tîtré'
                                                })
        first_preview = Preview.objects.create(addon=self.addon, position=1)

        av_min = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='2.0.99')[0]
        av_max = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='3.0.99')[0]
        ApplicationsVersions.objects.get_or_create(
            application=amo.THUNDERBIRD.id,
            version=self.addon.current_version,
            min=av_min,
            max=av_max)
        # Reset current_version.compatible_apps now that we've added an app.
        del self.addon.current_version.compatible_apps

        cat2 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['alerts-updates'])
        cat2.save()
        AddonCategory.objects.create(addon=self.addon, category=cat2)
        cat3 = Category.from_static_category(
            CATEGORIES[amo.THUNDERBIRD.id][amo.ADDON_EXTENSION]['calendar'])
        cat3.save()
        AddonCategory.objects.create(addon=self.addon, category=cat3)

        result = self.serialize()

        assert result['id'] == self.addon.pk

        assert result['average_daily_users'] == self.addon.average_daily_users
        assert result['categories'] == {
            'firefox': ['alerts-updates', 'bookmarks'],
            'thunderbird': ['calendar']
        }

        assert result['current_beta_version'] is None

        # In this serializer latest_unlisted_version is omitted.
        assert 'latest_unlisted_version' not in result

        assert result['current_version']
        self._test_version(self.addon.current_version,
                           result['current_version'])
        assert result['current_version']['url'] == absolutify(
            reverse('addons.versions',
                    args=[self.addon.slug,
                          self.addon.current_version.version]))

        assert result['authors']
        assert len(result['authors']) == 2
        self.check_author(first_author, result['authors'][0])
        self.check_author(second_author, result['authors'][1])

        assert result['edit_url'] == absolutify(self.addon.get_dev_url())
        assert result['default_locale'] == self.addon.default_locale
        assert result['description'] == {'en-US': self.addon.description}
        assert result['guid'] == self.addon.guid
        assert result['has_eula'] is False
        assert result['has_privacy_policy'] is False
        assert result['homepage'] == {
            'en-US': get_outgoing_url(unicode(self.addon.homepage))
        }
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))
        assert result['is_disabled'] == self.addon.is_disabled
        assert result['is_experimental'] == self.addon.is_experimental is False
        assert result['is_featured'] == self.addon.is_featured() is False
        assert result['is_source_public'] == self.addon.view_source
        assert result['last_updated'] == (
            self.addon.last_updated.replace(microsecond=0).isoformat() + 'Z')
        assert result['name'] == {'en-US': self.addon.name}
        assert result['previews']
        assert len(result['previews']) == 2

        result_preview = result['previews'][0]
        assert result_preview['id'] == first_preview.pk
        assert result_preview['caption'] is None
        assert result_preview['image_url'] == absolutify(
            first_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            first_preview.thumbnail_url)

        result_preview = result['previews'][1]
        assert result_preview['id'] == second_preview.pk
        assert result_preview['caption'] == {
            'en-US': u'My câption',
            'fr': u'Mön tîtré'
        }
        assert result_preview['image_url'] == absolutify(
            second_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            second_preview.thumbnail_url)

        assert result['ratings'] == {
            'average': self.addon.average_rating,
            'bayesian_average': self.addon.bayesian_rating,
            'count': self.addon.total_reviews,
        }
        assert result['public_stats'] == self.addon.public_stats
        assert result['requires_payment'] == self.addon.requires_payment
        assert result['review_url'] == absolutify(
            reverse('editors.review', args=[self.addon.pk]))
        assert result['slug'] == self.addon.slug
        assert result['status'] == 'public'
        assert result['summary'] == {'en-US': self.addon.summary}
        assert result['support_email'] == {'en-US': self.addon.support_email}
        assert result['support_url'] == {
            'en-US': get_outgoing_url(unicode(self.addon.support_url))
        }
        assert 'theme_data' not in result
        assert set(result['tags']) == set(['some_tag', 'some_other_tag'])
        assert result['type'] == 'extension'
        assert result['url'] == absolutify(self.addon.get_url_path())
        assert result['weekly_downloads'] == self.addon.weekly_downloads

        return result
Ejemplo n.º 22
0
    def _handle_addon(self, addon_data):
        version = addon_data['current_version']
        files = version['files'] or []

        file_kw = {}

        try:
            file_kw = {
                'hash':
                files[0]['hash'],
                'status':
                amo.STATUS_CHOICES_API_LOOKUP[files[0]['status']],
                'platform':
                amo.PLATFORM_DICT[files[0]['platform']].id,
                'size':
                files[0]['size'],
                'is_webextension':
                files[0]['is_webextension'],
                'is_mozilla_signed_extension':
                (files[0]['is_mozilla_signed_extension']),
                'strict_compatibility':
                (version['is_strict_compatibility_enabled']),
            }
        except (KeyError, IndexError):
            file_kw = {}

        # TODO:
        # * license
        # * ratings
        # * previews
        # * android compat & category data

        if Addon.objects.filter(slug=addon_data['slug']).exists():
            print('Skipping %s (slug already exists)' % addon_data['slug'])
            return

        if (addon_data['guid']
                and Addon.objects.filter(guid=addon_data['guid']).exists()):
            print('Skipping %s (guid already exists)' % addon_data['guid'])
            return

        users = []

        for user in addon_data['authors']:
            try:
                users.append(UserProfile.objects.get(username=user['name']))
            except UserProfile.DoesNotExist:
                email = '*****@*****.**' % str(uuid.uuid4().hex)
                users.append(user_factory(username=user['name'], email=email))

        addon_type = amo.ADDON_SEARCH_SLUGS[addon_data['type']]

        if 'firefox' in addon_data['categories']:
            category = addon_data['categories']['firefox'][0]
        else:
            category = None

        if category not in CATEGORIES[amo.FIREFOX.id][addon_type]:
            category = None
            print('Category %s' % category, 'not found')
        else:
            category = Category.from_static_category(
                CATEGORIES[amo.FIREFOX.id][addon_type][category], True)

        print('Creating add-on %s' % addon_data['slug'])

        compatibility = version['compatibility']

        if compatibility and 'firefox' in compatibility:
            version_kw = {
                'min_app_version': version['compatibility']['firefox']['min'],
                'max_app_version': version['compatibility']['firefox']['max'],
            }
        else:
            version_kw = {}

        with atomic():
            addon_factory(
                users=users,
                average_daily_users=addon_data['average_daily_users'],
                category=category,
                type=addon_type,
                guid=addon_data['guid'],
                slug=addon_data['slug'],
                name=addon_data['name'],
                summary=addon_data['summary'],
                description=addon_data['description'],
                file_kw=file_kw,
                version_kw=version_kw,
                weekly_downloads=addon_data.get('weekly_downloads', 0),
                default_locale=addon_data['default_locale'],
                tags=addon_data['tags'],
            )
Ejemplo n.º 23
0
def add_static_theme_from_lwt(lwt):
    from olympia.activity.models import AddonLog
    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)
    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 = {}
    # 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)

    # 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=lwt.last_updated,
            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_updates['last_updated'] = lwt.last_updated

    addon.update(**addon_updates)
    return addon
Ejemplo n.º 24
0
            if addon.default_locale.lower() == lang.lower():
                addon.target_locale = addon.default_locale

            addon.save()

            log.info('[@None] Created new "{0}" language pack, version {1}'
                     .format(xpi, data['version']))

        # Set the category
        for app in version.compatible_apps:
            static_category = (
                CATEGORIES.get(app.id, []).get(amo.ADDON_LPAPP, [])
                .get('general'))
            if static_category:
                category = Category.from_static_category(static_category, True)
                AddonCategory.objects.get_or_create(
                    addon=addon, category=category)

        # Add a license if there isn't one already
        if not version.license:
            license = License.objects.builtins().get(builtin=1)
            version.update(license=license)

        file_ = version.files.get()
        if not is_beta:
            # Not `version.files.update`, because we need to trigger save
            # hooks.
            file_.update(status=amo.STATUS_PUBLIC)
        sign_file(file_, settings.SIGNING_SERVER)