Example #1
0
class FeedItemSerializer(URLSerializerMixin, serializers.ModelSerializer):
    """
    A serializer for the FeedItem class, which wraps all items that live on the
    feed.
    """
    carrier = SlugChoiceField(required=False,
                              choices_dict=mkt.carriers.CARRIER_MAP)
    region = SlugChoiceField(required=False,
                             choices_dict=mkt.regions.REGION_LOOKUP)
    category = SlugModelChoiceField(
        required=False,
        queryset=Category.objects.filter(type=amo.ADDON_WEBAPP))
    item_type = serializers.SerializerMethodField('get_item_type')

    # Types of objects that are allowed to be a feed item.
    app = SplitField(relations.PrimaryKeyRelatedField(required=False),
                     FeedAppSerializer())
    brand = SplitField(relations.PrimaryKeyRelatedField(required=False),
                       FeedBrandSerializer())

    class Meta:
        fields = ('app', 'brand', 'carrier', 'category', 'id', 'item_type',
                  'region', 'url')
        item_types = (
            'app',
            'brand',
        )
        model = FeedItem
        url_basename = 'feeditems'

    def validate(self, attrs):
        """
        Ensure that at least one object type is specified.
        """
        item_changed = any(k for k in self.Meta.item_types
                           if k in attrs.keys())
        num_defined = sum(1 for item in self.Meta.item_types
                          if attrs.get(item))
        if item_changed and num_defined != 1:
            message = ('A valid value for exactly one of the following '
                       'parameters must be defined: %s' %
                       ','.join(self.Meta.item_types))
            raise serializers.ValidationError(message)
        return attrs

    def get_item_type(self, obj):
        for item_type in self.Meta.item_types:
            if getattr(obj, item_type):
                return item_type
        return
Example #2
0
class WebsiteAbuseSerializer(BaseAbuseSerializer):
    website = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=Website.objects),
        WebsiteSerializer())

    class Meta(BaseAbuseSerializer.Meta):
        fields = BaseAbuseSerializer.Meta.fields + ('website',)
Example #3
0
class UserAbuseSerializer(BaseAbuseSerializer):
    user = SplitField(
        serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects),
        UserSerializer())

    class Meta(BaseAbuseSerializer.Meta):
        fields = BaseAbuseSerializer.Meta.fields + ('user',)
Example #4
0
class FeedAppSerializer(URLSerializerMixin, serializers.ModelSerializer):
    app = SplitField(relations.PrimaryKeyRelatedField(required=True),
                     AppSerializer())
    description = TranslationSerializerField(required=False)
    preview = SplitField(relations.PrimaryKeyRelatedField(required=False),
                         PreviewSerializer())
    pullquote_attribution = TranslationSerializerField(required=False)
    pullquote_rating = serializers.IntegerField(required=False)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'description', 'id', 'preview',
                  'pullquote_attribution', 'pullquote_rating',
                  'pullquote_text', 'url')
        model = FeedApp
        url_basename = 'feedapp'
Example #5
0
class AppAbuseSerializer(BaseAbuseSerializer):
    app = SplitField(
        SlugOrPrimaryKeyRelatedField(source='addon', slug_field='app_slug',
                                     queryset=Webapp.objects.all()),
        SimpleAppSerializer(source='addon'))

    class Meta(BaseAbuseSerializer.Meta):
        fields = BaseAbuseSerializer.Meta.fields + ('app',)
Example #6
0
class ExtensionAbuseSerializer(BaseAbuseSerializer):
    extension = SplitField(
        SlugOrPrimaryKeyRelatedField(
            source='extension', slug_field='slug',
            queryset=Extension.objects.without_deleted().public()),
        ExtensionSerializer())

    class Meta(BaseAbuseSerializer.Meta):
        fields = BaseAbuseSerializer.Meta.fields + ('extension',)
Example #7
0
class AppAbuseSerializer(BaseAbuseSerializer):
    app = SplitField(
        SlugOrPrimaryKeyRelatedField(source='addon',
                                     slug_field='app_slug',
                                     queryset=Webapp.objects.all()),
        SimpleAppSerializer(source='addon'))

    class Meta:
        model = AbuseReport
        fields = ('text', 'ip_address', 'reporter', 'app')
Example #8
0
class BaseAbuseSerializer(serializers.ModelSerializer):
    text = serializers.CharField(source='message')
    ip_address = serializers.CharField(required=False)
    reporter = SplitField(serializers.PrimaryKeyRelatedField(required=False),
                          UserSerializer())

    def save(self, force_insert=False):
        serializers.ModelSerializer.save(self)
        del self.data['ip_address']
        return self.object
Example #9
0
class FeedAppSerializer(URLSerializerMixin, serializers.ModelSerializer):
    """Thin wrappers around apps w/ metadata related to its feature in feed."""
    app = SplitField(relations.PrimaryKeyRelatedField(required=True),
                     AppSerializer())
    description = TranslationSerializerField(required=False)
    image = CollectionImageField(source='*',
                                 view_name='feed-app-image-detail',
                                 format='png')
    preview = SplitField(relations.PrimaryKeyRelatedField(required=False),
                         PreviewSerializer())
    pullquote_attribution = TranslationSerializerField(required=False)
    pullquote_rating = serializers.IntegerField(required=False)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'background_color', 'description', 'feedapp_type',
                  'id', 'image', 'preview', 'pullquote_attribution',
                  'pullquote_rating', 'pullquote_text', 'slug', 'url')
        model = FeedApp
        url_basename = 'feedapps'
Example #10
0
class FeedAppSerializer(ValidateSlugMixin, URLSerializerMixin,
                        serializers.ModelSerializer):
    """
     A serializer for the FeedApp class, which highlights a single app and some
    additional metadata (e.g. a review or a screenshot).
    """
    app = SplitField(
        relations.PrimaryKeyRelatedField(required=True,
                                         queryset=Webapp.objects),
        AppSerializer())
    background_image = FeedImageField(allow_null=True)
    description = TranslationSerializerField(required=False)
    preview = SplitField(
        relations.PrimaryKeyRelatedField(required=False,
                                         queryset=Preview.objects),
        FeedPreviewESSerializer())
    pullquote_rating = serializers.IntegerField(required=False,
                                                max_value=5,
                                                min_value=1)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'background_color', 'background_image', 'color',
                  'created', 'description', 'id', 'preview',
                  'pullquote_attribution', 'pullquote_rating',
                  'pullquote_text', 'slug', 'type', 'url')
        model = FeedApp
        url_basename = 'feedapps'

    def validate(self, attrs):
        """
        Require `pullquote_text` if `pullquote_rating` or
        `pullquote_attribution` are set.
        """
        if (not attrs.get('pullquote_text')
                and (attrs.get('pullquote_rating')
                     or attrs.get('pullquote_attribution'))):
            raise ValidationError('Pullquote text required if rating or '
                                  'attribution is defined.')
        return attrs
Example #11
0
class FeedAppSerializer(URLSerializerMixin, serializers.ModelSerializer):
    """
    A serializer for the FeedApp class, which highlights a single app and some
    additional metadata (e.g. a review or a screenshot).
    """
    app = SplitField(relations.PrimaryKeyRelatedField(required=True),
                     AppSerializer())
    description = TranslationSerializerField(required=False)
    background_image = CollectionImageField(
        source='*', view_name='api-v2:feed-app-image-detail', format='png')
    preview = SplitField(relations.PrimaryKeyRelatedField(required=False),
                         PreviewSerializer())
    pullquote_rating = serializers.IntegerField(required=False)
    pullquote_text = TranslationSerializerField(required=False)

    class Meta:
        fields = ('app', 'background_color', 'created', 'description',
                  'feedapp_type', 'id', 'background_image', 'preview',
                  'pullquote_attribution', 'pullquote_rating',
                  'pullquote_text', 'slug', 'url')
        model = FeedApp
        url_basename = 'feedapps'
Example #12
0
class BaseAbuseSerializer(PotatoCaptchaSerializer,
                          serializers.ModelSerializer):
    text = serializers.CharField(source='message')
    reporter = SplitField(serializers.PrimaryKeyRelatedField(required=False),
                          UserSerializer())

    class Meta:
        model = AbuseReport
        fields = ('text', 'reporter')

    def validate(self, attrs):
        request = self.context['request']
        if request.user.is_authenticated():
            attrs['reporter'] = request.user
        else:
            attrs['reporter'] = None
        attrs['ip_address'] = request.META.get('REMOTE_ADDR', '')
        return super(BaseAbuseSerializer, self).validate(attrs)
Example #13
0
class FeedItemSerializer(URLSerializerMixin, serializers.ModelSerializer):
    """
    A serializer for the FeedItem class, which wraps all items that live on the
    feed.
    """
    carrier = SlugChoiceField(required=False,
        choices_dict=mkt.carriers.CARRIER_MAP)
    region = SlugChoiceField(required=False,
        choices_dict=mkt.regions.REGION_LOOKUP)
    category = UnicodeChoiceField(required=False, choices=CATEGORY_CHOICES)
    item_type = serializers.SerializerMethodField('get_item_type')

    # Types of objects that are allowed to be a feed item.
    app = SplitField(relations.PrimaryKeyRelatedField(required=False),
                     FeedAppSerializer())
    brand = SplitField(relations.PrimaryKeyRelatedField(required=False),
                       FeedBrandSerializer())
    collection = SplitField(relations.PrimaryKeyRelatedField(required=False),
                            FeedCollectionSerializer())
    shelf = SplitField(relations.PrimaryKeyRelatedField(required=False),
                       FeedShelfSerializer())

    class Meta:
        fields = ('app', 'brand', 'carrier', 'category', 'collection', 'id',
                  'item_type', 'region', 'shelf', 'url')
        item_types = ('app', 'brand', 'collection', 'shelf',)
        model = FeedItem
        url_basename = 'feeditems'

    def validate(self, attrs):
        """
        Ensure that at least one object type is specified.
        """
        item_changed = any(k for k in self.Meta.item_types
                           if k in attrs.keys())
        num_defined = sum(1 for item in self.Meta.item_types
                          if attrs.get(item))
        if item_changed and num_defined != 1:
            message = ('A valid value for exactly one of the following '
                       'parameters must be defined: %s' % ','.join(
                        self.Meta.item_types))
            raise serializers.ValidationError(message)
        return attrs

    def get_item_type(self, obj):
        for item_type in self.Meta.item_types:
            if getattr(obj, item_type):
                return item_type
        return

    def validate_shelf(self, attrs, source):
        """
        If `shelf` is defined, validate that the FeedItem's `carrier` and
        `region` match the `carrier` and `region on `shelf`.
        """
        shelf_id = attrs.get(source)
        if shelf_id:
            shelf = FeedShelf.objects.get(pk=shelf_id)

            carrier = CARRIER_CHOICE_DICT[shelf.carrier]
            if attrs.get('carrier') != carrier.slug:
                raise serializers.ValidationError(
                    'Feed item carrier does not match operator shelf carrier.')

            region = REGIONS_CHOICES_ID_DICT[shelf.region]
            if attrs.get('region') != region.slug:
                raise serializers.ValidationError(
                    'Feed item region does not match operator shelf region.')

        return attrs
Example #14
0
class UserAbuseSerializer(BaseAbuseSerializer):
    user = SplitField(serializers.PrimaryKeyRelatedField(), UserSerializer())

    class Meta(BaseAbuseSerializer.Meta):
        fields = BaseAbuseSerializer.Meta.fields + ('user',)
Example #15
0
class UserAbuseSerializer(BaseAbuseSerializer):
    user = SplitField(serializers.PrimaryKeyRelatedField(), UserSerializer())

    class Meta:
        model = AbuseReport
        fields = ('text', 'ip_address', 'reporter', 'user')
Example #16
0
class PotatoSerializer(Serializer):
    spud = SplitField(CharField(), SpudSerializer())
Example #17
0
class RatingSerializer(serializers.ModelSerializer):
    app = SplitField(
        SlugOrPrimaryKeyRelatedField(slug_field='app_slug',
                                     queryset=Webapp.objects.all(),
                                     source='addon'),
        serializers.HyperlinkedRelatedField(view_name='app-detail',
                                            read_only=True, source='addon'))
    body = serializers.CharField()
    user = UserSerializer(read_only=True)
    report_spam = serializers.SerializerMethodField('get_report_spam_link')
    resource_uri = serializers.HyperlinkedIdentityField(
        view_name='ratings-detail')
    is_author = serializers.SerializerMethodField('get_is_author')
    has_flagged = serializers.SerializerMethodField('get_has_flagged')
    version = SimpleVersionSerializer(read_only=True)
    lang = serializers.SerializerMethodField('get_lang')

    class Meta:
        model = Review
        fields = ('app', 'body', 'created', 'has_flagged', 'is_author', 'lang',
                  'modified', 'rating', 'report_spam', 'resource_uri', 'user',
                  'version')

    def __init__(self, *args, **kwargs):
        super(RatingSerializer, self).__init__(*args, **kwargs)
        if 'request' in self.context:
            self.request = self.context['request']
        else:
            self.request = None

        if 'view' in self.context and hasattr(self.context['view'], 'app'):
            self.app = self.context['view'].app

        if not self.request or not self.request.user.is_authenticated():
            self.fields.pop('is_author')
            self.fields.pop('has_flagged')

        if self.request and self.request.method in ('PUT', 'PATCH'):
            # Don't let users modify 'app' field at edit time
            self.fields['app'].read_only = True

    def to_native(self, obj):
        # When we have an `app` set on the serializer, we know it's because the
        # view was filtering on this app, so we can safely overwrite the
        # `addon` property on the instance with it, saving some costly queries.
        app = getattr(self, 'app', None)
        if app is not None:
            obj.addon = app
        return super(RatingSerializer, self).to_native(obj)

    def get_report_spam_link(self, obj):
        return reverse('ratings-flag', kwargs={'pk': obj.pk})

    def get_is_author(self, obj):
        return obj.user.pk == self.request.user.pk

    def get_has_flagged(self, obj):
        return (not self.get_is_author(obj) and
                obj.reviewflag_set.filter(user=self.request.user).exists())

    def get_lang(self, obj):
        if obj.pk is None:
            return self.request.LANG
        else:
            return obj.lang

    def validate(self, attrs):
        if not getattr(self, 'object'):
            # If we are creating a rating, then we need to do various checks on
            # the app. Because these checks need the version as well, we have
            # to do them here and not in validate_app().

            # Assign user and ip_address. It won't change once the review is
            # created.
            user = self.request.user
            attrs['user'] = user
            attrs['ip_address'] = self.request.META.get('REMOTE_ADDR', '')
            guessed_lang = guess_language(attrs['body'])
            if guessed_lang is None:
                attrs['lang'] = user.lang
            else:
                attrs['lang'] = guessed_lang

            # If the app is packaged, add in the current version.
            if attrs['addon'].is_packaged:
                attrs['version'] = attrs['addon'].current_version

            # Return 409 if the user has already reviewed this app.
            app = attrs['addon']
            qs = self.context['view'].queryset.filter(addon=app, user=user)
            if app.is_packaged:
                qs = qs.filter(version=attrs['version'])
            if qs.exists():
                raise Conflict('You have already reviewed this app.')

            # Return 403 is the app is not public.
            if not app.is_public():
                raise PermissionDenied('The app requested is not public.')

            # Return 403 if the user is attempting to review their own app.
            if app.has_author(user):
                raise PermissionDenied('You may not review your own app.')

            # Return 403 if not a free app and the user hasn't purchased it.
            if app.is_premium() and not app.is_purchased(user):
                raise PermissionDenied("You may not review paid apps you "
                                       "haven't purchased.")

            # Return 403 if the app is not available in the current region.
            current_region = get_region()
            if not app.listed_in(region=current_region):
                raise PermissionDenied('App not available in region "%s".' %
                                       current_region.slug)

        return attrs

    def validate_app(self, attrs, source):
        # Don't allow users to change the app on an existing rating.
        if getattr(self, 'object'):
            attrs[source] = self.object.addon
        return attrs

    def validate_rating(self, attrs, source):
        # Don't allow user to submit rating outside the range
        valid_ratings = [1, 2, 3, 4, 5]

        # ensure rating key is present
        if source not in attrs:
            raise serializers.ValidationError("Rating key is required")

        value = attrs[source]
        rating = int(value) if value else value

        # ensure rating is in desired range
        if rating not in valid_ratings:
            raise serializers.ValidationError("Rating must be between 1-5")

        return attrs
Example #18
0
class RatingSerializer(serializers.ModelSerializer):
    app = SplitField(
        SlugOrPrimaryKeyRelatedField(slug_field='app_slug',
                                     queryset=Webapp.objects.all(),
                                     source='addon'),
        serializers.HyperlinkedRelatedField(view_name='app-detail',
                                            read_only=True,
                                            source='addon'))
    body = serializers.CharField()
    user = AccountSerializer(read_only=True)
    report_spam = serializers.SerializerMethodField('get_report_spam_link')
    resource_uri = serializers.HyperlinkedIdentityField(
        view_name='ratings-detail')
    is_author = serializers.SerializerMethodField('get_is_author')
    has_flagged = serializers.SerializerMethodField('get_has_flagged')
    version = SimpleVersionSerializer(read_only=True)

    class Meta:
        model = Review
        fields = ('app', 'body', 'created', 'has_flagged', 'is_author',
                  'modified', 'rating', 'report_spam', 'resource_uri', 'user',
                  'version')

    def __init__(self, *args, **kwargs):
        super(RatingSerializer, self).__init__(*args, **kwargs)
        if 'request' in self.context:
            self.request = self.context['request']
        else:
            self.request = None

        if not self.request or not self.request.amo_user:
            self.fields.pop('is_author')
            self.fields.pop('has_flagged')

        if self.request and self.request.method in ('PUT', 'PATCH'):
            # Don't let users modify 'app' field at edit time
            self.fields['app'].read_only = True

    def get_report_spam_link(self, obj):
        return reverse('ratings-flag', kwargs={'pk': obj.pk})

    def get_is_author(self, obj):
        return obj.user.pk == self.request.amo_user.pk

    def get_has_flagged(self, obj):
        return (not self.get_is_author(obj) and
                obj.reviewflag_set.filter(user=self.request.amo_user).exists())

    def validate(self, attrs):
        if not getattr(self, 'object'):
            # If we are creating a rating, then we need to do various checks on
            # the app. Because these checks need the version as well, we have
            # to do them here and not in validate_app().

            # Assign user and ip_address. It won't change once the review is
            # created.
            attrs['user'] = self.request.amo_user
            attrs['ip_address'] = self.request.META.get('REMOTE_ADDR', '')

            # If the app is packaged, add in the current version.
            if attrs['addon'].is_packaged:
                attrs['version'] = attrs['addon'].current_version

            # Return 409 if the user has already reviewed this app.
            app = attrs['addon']
            amo_user = self.request.amo_user
            qs = self.context['view'].queryset.filter(addon=app, user=amo_user)
            if app.is_packaged:
                qs = qs.filter(version=attrs['version'])
            if qs.exists():
                raise Conflict('You have already reviewed this app.')

            # Return 403 is the app is not public.
            if not app.is_public():
                raise PermissionDenied('The app requested is not public.')

            # Return 403 if the user is attempting to review their own app.
            if app.has_author(amo_user):
                raise PermissionDenied('You may not review your own app.')

            # Return 403 if not a free app and the user hasn't purchased it.
            if app.is_premium() and not app.is_purchased(amo_user):
                raise PermissionDenied("You may not review paid apps you "
                                       "haven't purchased.")

            # Return 403 if the app is not available in the current region.
            current_region = get_region()
            if not app.listed_in(region=current_region):
                raise PermissionDenied('App not available in region "%s".' %
                                       current_region.slug)

        return attrs

    def validate_app(self, attrs, source):
        # Don't allow users to change the app on an existing rating.
        if getattr(self, 'object'):
            attrs[source] = self.object.addon
        return attrs
Example #19
0
class RatingSerializer(serializers.ModelSerializer):
    app = SplitField(
        SlugOrPrimaryKeyRelatedField(slug_field='app_slug',
                                     queryset=Webapp.objects.all(),
                                     source='addon'),
        serializers.HyperlinkedRelatedField(view_name='app-detail',
                                            read_only=True,
                                            source='addon'))
    body = serializers.CharField()
    user = AccountSerializer(read_only=True)
    report_spam = serializers.SerializerMethodField('get_report_spam_link')
    resource_uri = serializers.HyperlinkedIdentityField(
        view_name='ratings-detail')
    is_author = serializers.SerializerMethodField('get_is_author')
    has_flagged = serializers.SerializerMethodField('get_has_flagged')
    version = SimpleVersionSerializer(read_only=True)

    class Meta:
        model = Review
        fields = ('app', 'body', 'created', 'has_flagged', 'is_author',
                  'modified', 'rating', 'report_spam', 'resource_uri', 'user',
                  'version')

    def __init__(self, *args, **kwargs):
        super(RatingSerializer, self).__init__(*args, **kwargs)
        if 'request' in self.context:
            self.request = self.context['request']
        else:
            self.request = None

        if not self.request or not self.request.amo_user:
            self.fields.pop('is_author')
            self.fields.pop('has_flagged')

        if self.request.method in ('PUT', 'PATCH'):
            # Don't let users modify 'app' field at edit time
            self.fields['app'].read_only = True

    def get_report_spam_link(self, obj):
        return reverse('ratings-flag', kwargs={'pk': obj.pk})

    def get_is_author(self, obj):
        return obj.user.pk == self.request.amo_user.pk

    def get_has_flagged(self, obj):
        return (not self.get_is_author(obj) and
                obj.reviewflag_set.filter(user=self.request.amo_user).exists())

    @classmethod
    def get_app_from_value(cls, value):
        try:
            app = Webapp.objects.valid().get(id=value)
        except (Webapp.DoesNotExist, ValueError):
            try:
                app = Webapp.objects.valid().get(app_slug=value)
            except Webapp.DoesNotExist:
                raise serializers.ValidationError('Invalid app')
        if not app.listed_in(region=REGIONS_DICT[get_region()]):
            raise serializers.ValidationError(
                'App not available in this region')
        return app

    def validate(self, attrs):
        attrs['user'] = self.request.amo_user
        attrs['ip_address'] = self.request.META.get('REMOTE_ADDR', '')

        if not getattr(self, 'object'):
            if attrs['addon'].is_packaged:
                attrs['version'] = attrs['addon'].current_version

            # Return 409 if the user has already reviewed this app.
            app = attrs['addon']
            amo_user = self.request.amo_user
            qs = self.context['view'].queryset.filter(addon=app, user=amo_user)
            if app.is_packaged:
                qs = qs.filter(version=attrs['version'])

            if qs.exists():
                raise Conflict('You have already reviewed this app.')

            # Return 403 if the user is attempting to review their own app:
            if app.has_author(amo_user):
                raise PermissionDenied('You may not review your own app.')

            # Return 403 if not a free app and the user hasn't purchased it.
            if app.is_premium() and not app.is_purchased(amo_user):
                raise PermissionDenied("You may not review paid apps you "
                                       "haven't purchased.")
        return attrs

    def validate_app(self, attrs, source):
        if not getattr(self, 'object'):
            app = attrs[source]
            attrs[source] = RatingSerializer.get_app_from_value(app.pk)
        else:
            attrs[source] = self.object.addon
        return attrs