def test_app_has_bad_regions(self, mock_stdout):
        app = Webapp.objects.get(id=337141)
        app.update(premium_type=amo.ADDON_PREMIUM)
        price = Price.objects.get(id=1)
        AddonPremium.objects.create(addon=app, price=price)
        call_command('check_paid_app_regions', app.app_slug)
        # From the fixture poland is the only ok region
        # for the price.
        stdout_val = mock_stdout.getvalue()
        assert 'Poland *' not in stdout_val
        assert '* Inappropriate region' in stdout_val

        for region_id in ALL_REGION_IDS:
            region_id = int(region_id)
            if region_id in (PL.id, US.id):
                continue
            region_name = unicode(REGIONS_CHOICES_ID_DICT.get(region_id).name)
            ok_('%s *' % region_name in stdout_val,
                '%s not present' % region_name)
    def test_app_has_bad_regions(self, mock_stdout):
        app = Webapp.objects.get(id=337141)
        app.update(premium_type=amo.ADDON_PREMIUM)
        price = Price.objects.get(id=1)
        AddonPremium.objects.create(addon=app, price=price)
        call_command('check_paid_app_regions', app.app_slug)
        # From the fixture poland is the only ok region
        # for the price.
        stdout_val = mock_stdout.getvalue()
        assert 'Poland *' not in stdout_val
        assert '* Inappropriate region' in stdout_val

        for region_id in ALL_REGION_IDS:
            region_id = int(region_id)
            if region_id in (PL.id, US.id):
                continue
            region_name = unicode(REGIONS_CHOICES_ID_DICT.get(
                                  region_id).name)
            ok_('%s *' % region_name in stdout_val,
                '%s not present' % region_name)
Beispiel #3
0
def es_app_to_dict(obj, region=None, profile=None, request=None):
    """
    Return app data as dict for API where `app` is the elasticsearch result.
    """
    # Circular import.
    from mkt.developers.models import AddonPaymentAccount
    from mkt.webapps.models import Installed, Webapp

    translation_fields = ('banner_message', 'description', 'homepage', 'name',
                          'release_notes', 'support_email', 'support_url')
    lang = None
    if request and request.method == 'GET' and 'lang' in request.GET:
        lang = request.GET.get('lang', '').lower()

    src = obj._source
    # The following doesn't perform a database query, but gives us useful
    # methods like `get_detail_url`. If you use `obj` make sure the calls
    # don't query the database.
    is_packaged = src.get('app_type') != amo.ADDON_WEBAPP_HOSTED
    app = Webapp(app_slug=obj.app_slug, is_packaged=is_packaged)

    attrs = ('created', 'current_version', 'default_locale', 'is_offline',
             'manifest_url', 'previews', 'reviewed', 'ratings', 'status',
             'weekly_downloads')
    data = dict((a, getattr(obj, a, None)) for a in attrs)

    # Flatten the localized fields from {'lang': ..., 'string': ...}
    # to {lang: string}.
    for field in translation_fields:
        src_field = '%s_translations' % field
        value_field = src.get(src_field)
        src[src_field] = dict((v.get('lang', ''), v.get('string', ''))
                              for v in value_field) if value_field else {}
        data[field] = get_translations(src, src_field, obj.default_locale,
                                       lang)

    if getattr(obj, 'content_ratings', None):
        for region_key in obj.content_ratings:
            obj.content_ratings[region_key] = dehydrate_content_rating(
                obj.content_ratings[region_key], region_key)

    data.update({
        'absolute_url': absolutify(app.get_detail_url()),
        'app_type': app.app_type,
        'author': src.get('author', ''),
        'banner_regions': src.get('banner_regions', []),
        'categories': [c for c in obj.category],
        'content_ratings': {
            'ratings': getattr(obj, 'content_ratings', {}),
            'descriptors': dehydrate_descriptors(
                getattr(obj, 'content_descriptors', {})),
            'interactive_elements': dehydrate_interactives(
                getattr(obj, 'interactive_elements', [])),
        },
        'device_types': [DEVICE_TYPES[d].api_name for d in src.get('device')],
        'icons': dict((i['size'], i['url']) for i in src.get('icons')),
        'id': str(obj._id),
        'is_packaged': is_packaged,
        'payment_required': False,
        'premium_type': amo.ADDON_PREMIUM_API[src.get('premium_type')],
        'privacy_policy': reverse('app-privacy-policy-detail',
                                  kwargs={'pk': obj._id}),
        'public_stats': obj.has_public_stats,
        'supported_locales': src.get('supported_locales', ''),
        'slug': obj.app_slug,
        # TODO: Remove the type check once this code rolls out and our indexes
        # aren't between mapping changes.
        'versions': dict((v.get('version'), v.get('resource_uri')) for v in
                         src.get('versions') if type(v) == dict),
    })

    if not data['public_stats']:
        data['weekly_downloads'] = None
    def serialize_region(o):
        d = {}
        for field in ('name', 'slug', 'mcc', 'adolescent'):
            d[field] = getattr(o, field, None)
        return d
    data['regions'] = [serialize_region(REGIONS_CHOICES_ID_DICT.get(k))
                       for k in app.get_region_ids(
                               worldwide=True,
                               excluded=obj.region_exclusions)]

    if src.get('premium_type') in amo.ADDON_PREMIUMS:
        acct = list(AddonPaymentAccount.objects.filter(addon=app))
        if acct and acct.payment_account:
            data['payment_account'] = reverse(
                'payment-account-detail',
                kwargs={'pk': acct.payment_account.pk})
    else:
        data['payment_account'] = None

    data['upsell'] = False
    if hasattr(obj, 'upsell'):
        exclusions = obj.upsell.get('region_exclusions')
        if exclusions is not None and region not in exclusions:
            data['upsell'] = obj.upsell
            data['upsell']['resource_uri'] = reverse(
                'app-detail',
                kwargs={'pk': obj.upsell['id']})

    data['price'] = data['price_locale'] = None
    try:
        price_tier = src.get('price_tier')
        if price_tier:
            price = Price.objects.get(name=price_tier)
            price_currency = price.get_price_currency(region=region)
            if price_currency and price_currency.paid:
                data['price'] = price.get_price(region=region)
                data['price_locale'] = price.get_price_locale(
                    region=region)
            data['payment_required'] = bool(price.price)
    except Price.DoesNotExist:
        log.warning('Issue with price tier on app: {0}'.format(obj._id))
        data['payment_required'] = True

    # TODO: Let's get rid of these from the API to avoid db hits.
    if profile and isinstance(profile, UserProfile):
        data['user'] = {
            'developed': AddonUser.objects.filter(
                addon=obj.id, user=profile,
                role=amo.AUTHOR_ROLE_OWNER).exists(),
            'installed': Installed.objects.filter(
                user=profile, addon_id=obj.id).exists(),
            'purchased': obj.id in profile.purchase_ids(),
        }

    return data
 def _region_obj(self, id_):
     return REGIONS_CHOICES_ID_DICT.get(id_)
Beispiel #5
0
def es_app_to_dict(obj, profile=None, request=None):
    """
    Return app data as dict for API where `app` is the elasticsearch result.
    """
    # Circular import.
    from mkt.developers.models import AddonPaymentAccount
    from mkt.webapps.models import Installed, Webapp

    translation_fields = ('banner_message', 'description', 'homepage', 'name',
                          'release_notes', 'support_email', 'support_url')
    lang = None
    if request and request.method == 'GET' and 'lang' in request.GET:
        lang = request.GET.get('lang', '').lower()

    region_slug = None
    region_id = None
    if request and request.method == 'GET' and 'region' in request.GET:
        region_slug = request.GET.get('region', '').lower()
    if region_slug not in REGIONS_DICT:
        region_slug = get_region()
    region_id = REGIONS_DICT[region_slug].id

    src = obj._source
    is_packaged = src.get('app_type') != amo.ADDON_WEBAPP_HOSTED
    # The following doesn't perform a database query, but gives us useful
    # methods like `get_detail_url` and `get_icon_url`. If you use `app` make
    # sure the calls don't query the database.
    app = Webapp(id=obj._id, app_slug=obj.app_slug, is_packaged=is_packaged,
                 type=amo.ADDON_WEBAPP, icon_type='image/png',
                 modified=getattr(obj, 'modified', None))

    attrs = ('created', 'current_version', 'default_locale', 'is_offline',
             'manifest_url', 'reviewed', 'ratings', 'status',
             'weekly_downloads')
    data = dict((a, getattr(obj, a, None)) for a in attrs)

    # Flatten the localized fields from {'lang': ..., 'string': ...}
    # to {lang: string}.
    for field in translation_fields:
        src_field = '%s_translations' % field
        value_field = src.get(src_field)
        src[src_field] = dict((v.get('lang', ''), v.get('string', ''))
                              for v in value_field) if value_field else {}
        data[field] = get_translations(src, src_field, obj.default_locale,
                                       lang)

    # Generate urls for previews and icons before the data.update() call below
    # adds them to the result.
    previews = getattr(obj, 'previews', [])
    for preview in previews:
        if 'image_url' and 'thumbnail_url' in preview:
            # Old-style index, the full URL is already present, nothing to do.
            # TODO: remove this check once we have re-indexed everything.
            continue
        else:
            # New-style index, we need to build the URLs from the data we have.
            p = Preview(id=preview.pop('id'), modified=preview.pop('modified'),
                        filetype=preview['filetype'])
            preview['image_url'] = p.image_url
            preview['thumbnail_url'] = p.thumbnail_url
    icons = getattr(obj, 'icons', [])
    for icon in icons:
        if 'url' in icon:
            # Old-style index, the full URL is already present, nothing to do.
            # TODO: remove this check once we have re-indexed everything.
            continue
        else:
            # New-style index, we need to build the URLs from the data we have.
            icon['url'] = app.get_icon_url(icon['size'])

    data.update({
        'absolute_url': absolutify(app.get_detail_url()),
        'app_type': 'packaged' if is_packaged else 'hosted',
        'author': src.get('author', ''),
        'banner_regions': src.get('banner_regions', []),
        'categories': [c for c in obj.category],
        'content_ratings': filter_content_ratings_by_region({
            'ratings': dehydrate_content_ratings(
                getattr(obj, 'content_ratings', {})),
            'descriptors': dehydrate_descriptors(
                getattr(obj, 'content_descriptors', {})),
            'interactive_elements': dehydrate_interactives(
                getattr(obj, 'interactive_elements', [])),
            'regions': mkt.regions.REGION_TO_RATINGS_BODY()
        }, region=region_slug),
        'device_types': [DEVICE_TYPES[d].api_name for d in src.get('device')],
        'icons': dict((i['size'], i['url']) for i in src.get('icons')),
        'id': long(obj._id),
        'is_packaged': is_packaged,
        'payment_required': False,
        'premium_type': amo.ADDON_PREMIUM_API[src.get('premium_type')],
        'previews': previews,
        'privacy_policy': reverse('app-privacy-policy-detail',
                                  kwargs={'pk': obj._id}),
        'public_stats': obj.has_public_stats,
        'supported_locales': src.get('supported_locales', ''),
        'slug': obj.app_slug,
        'versions': dict((v.get('version'), v.get('resource_uri')) for v in
                         src.get('versions')),
    })

    if not data['public_stats']:
        data['weekly_downloads'] = None

    def serialize_region(o):
        d = {}
        for field in ('name', 'slug', 'mcc', 'adolescent'):
            d[field] = getattr(o, field, None)
        return d

    data['regions'] = [serialize_region(REGIONS_CHOICES_ID_DICT.get(k))
                       for k in app.get_region_ids(
                           worldwide=True, excluded=obj.region_exclusions)]

    data['payment_account'] = None
    if src.get('premium_type') in amo.ADDON_PREMIUMS:
        try:
            acct = AddonPaymentAccount.objects.get(addon_id=src.get('id'))
            if acct.payment_account:
                data['payment_account'] = reverse(
                    'payment-account-detail',
                    kwargs={'pk': acct.payment_account.pk})
        except AddonPaymentAccount.DoesNotExist:
            pass  # Developer hasn't set up a payment account yet.

    data['upsell'] = False
    if hasattr(obj, 'upsell'):
        exclusions = obj.upsell.get('region_exclusions')
        if exclusions is not None and region_slug not in exclusions:
            data['upsell'] = obj.upsell
            data['upsell']['resource_uri'] = reverse(
                'app-detail',
                kwargs={'pk': obj.upsell['id']})

    data['price'] = data['price_locale'] = None
    try:
        price_tier = src.get('price_tier')
        if price_tier:
            price = Price.objects.get(name=price_tier)
            price_currency = price.get_price_currency(region=region_id)
            if price_currency and price_currency.paid:
                data['price'] = price.get_price(region=region_id)
                data['price_locale'] = price.get_price_locale(
                    region=region_id)
            data['payment_required'] = bool(price.price)
    except Price.DoesNotExist:
        log.warning('Issue with price tier on app: {0}'.format(obj._id))
        data['payment_required'] = True

    # TODO: Let's get rid of these from the API to avoid db hits.
    if profile and isinstance(profile, UserProfile):
        data['user'] = {
            'developed': AddonUser.objects.filter(
                addon=obj.id, user=profile,
                role=amo.AUTHOR_ROLE_OWNER).exists(),
            'installed': Installed.objects.filter(
                user=profile, addon_id=obj.id).exists(),
            'purchased': obj.id in profile.purchase_ids(),
        }

    return data