class UserProfileSerializer(PublicUserProfileSerializer):
    display_name = serializers.CharField(
        min_length=2,
        max_length=50,
        validators=[OneOrMorePrintableCharacterAPIValidator()])
    picture_upload = serializers.ImageField(use_url=True, write_only=True)
    permissions = serializers.SerializerMethodField()
    fxa_edit_email_url = serializers.SerializerMethodField()
    reviewer_name = serializers.CharField(
        min_length=2,
        max_length=50,
        allow_blank=True,
        validators=[OneOrMorePrintableCharacterAPIValidator()])

    class Meta(PublicUserProfileSerializer.Meta):
        fields = PublicUserProfileSerializer.Meta.fields + (
            'deleted', 'display_name', 'email', 'fxa_edit_email_url',
            'last_login', 'last_login_ip', 'permissions', 'picture_upload',
            'read_dev_agreement', 'reviewer_name', 'username')
        writeable_fields = (
            'biography',
            'display_name',
            'homepage',
            'location',
            'occupation',
            'picture_upload',
            'reviewer_name',
        )
        read_only_fields = tuple(set(fields) - set(writeable_fields))

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if (not self.instance
                or not acl.is_user_any_kind_of_reviewer(self.instance)):
            self.fields.pop('reviewer_name', None)

    def get_fxa_edit_email_url(self, user):
        base_url = '{}/settings'.format(
            settings.FXA_CONFIG['default']['content_host'])
        return urlparams(base_url,
                         uid=user.fxa_id,
                         email=user.email,
                         entrypoint='addons')

    def validate_biography(self, value):
        if has_links(clean_nl(str(value))):
            # There's some links, we don't want them.
            raise serializers.ValidationError(
                ugettext(u'No links are allowed.'))
        return value

    def validate_display_name(self, value):
        if DeniedName.blocked(value):
            raise serializers.ValidationError(
                ugettext(u'This display name cannot be used.'))
        return value

    def validate_reviewer_name(self, value):
        if DeniedName.blocked(value):
            raise serializers.ValidationError(
                ugettext(u'This reviewer name cannot be used.'))
        return value

    def validate_homepage(self, value):
        if settings.DOMAIN.lower() in value.lower():
            raise serializers.ValidationError(
                ugettext(u'The homepage field can only be used to link to '
                         u'external websites.'))
        return value

    def validate_picture_upload(self, value):
        image_check = ImageCheck(value)

        if (value.content_type not in amo.IMG_TYPES
                or not image_check.is_image()):
            raise serializers.ValidationError(
                ugettext(u'Images must be either PNG or JPG.'))

        if image_check.is_animated():
            raise serializers.ValidationError(
                ugettext(u'Images cannot be animated.'))

        if value.size > settings.MAX_PHOTO_UPLOAD_SIZE:
            raise serializers.ValidationError(
                ugettext(u'Please use images smaller than %dMB.' %
                         (settings.MAX_PHOTO_UPLOAD_SIZE / 1024 / 1024)))
        return value

    def update(self, instance, validated_data):
        instance = super(UserProfileSerializer,
                         self).update(instance, validated_data)

        photo = validated_data.get('picture_upload')
        if photo:
            tmp_destination = instance.picture_path_original

            with default_storage.open(tmp_destination, 'wb') as temp_file:
                for chunk in photo.chunks():
                    temp_file.write(chunk)
            instance.update(picture_type=photo.content_type)
            resize_photo.delay(
                tmp_destination,
                instance.picture_path,
                set_modified_on=instance.serializable_reference())
        return instance

    def to_representation(self, obj):
        data = super(UserProfileSerializer, self).to_representation(obj)
        request = self.context.get('request', None)

        if request and is_gate_active(request,
                                      'del-accounts-fxa-edit-email-url'):
            data.pop('fxa_edit_email_url', None)
        return data
Exemple #2
0
class UserProfileSerializer(PublicUserProfileSerializer):
    display_name = serializers.CharField(
        min_length=2,
        max_length=50,
        validators=[OneOrMorePrintableCharacterAPIValidator()],
    )
    picture_upload = serializers.ImageField(use_url=True, write_only=True)
    permissions = serializers.SerializerMethodField()
    fxa_edit_email_url = serializers.SerializerMethodField()
    # Just Need to specify any field for the source - '*' is the entire obj.
    site_status = SiteStatusSerializer(source='*')

    class Meta(PublicUserProfileSerializer.Meta):
        fields = PublicUserProfileSerializer.Meta.fields + (
            'deleted',
            'display_name',
            'email',
            'fxa_edit_email_url',
            'last_login',
            'last_login_ip',
            'permissions',
            'picture_upload',
            'read_dev_agreement',
            'site_status',
            'username',
        )
        writeable_fields = (
            'biography',
            'display_name',
            'homepage',
            'location',
            'occupation',
            'picture_upload',
        )
        read_only_fields = tuple(set(fields) - set(writeable_fields))

    def get_fxa_edit_email_url(self, user):
        base_url = f'{settings.FXA_CONTENT_HOST}/settings'
        return urlparams(
            base_url, uid=user.fxa_id, email=user.email, entrypoint='addons'
        )

    def validate_biography(self, value):
        if has_links(clean_nl(str(value))):
            # There's some links, we don't want them.
            raise serializers.ValidationError(gettext('No links are allowed.'))
        return value

    def validate_display_name(self, value):
        if DeniedName.blocked(value):
            raise serializers.ValidationError(
                gettext('This display name cannot be used.')
            )
        return value

    def validate_homepage(self, value):
        if settings.DOMAIN.lower() in value.lower():
            raise serializers.ValidationError(
                gettext(
                    'The homepage field can only be used to link to '
                    'external websites.'
                )
            )
        return value

    def validate_picture_upload(self, value):
        image_check = ImageCheck(value)

        if value.content_type not in amo.IMG_TYPES or not image_check.is_image():
            raise serializers.ValidationError(
                gettext('Images must be either PNG or JPG.')
            )

        if image_check.is_animated():
            raise serializers.ValidationError(gettext('Images cannot be animated.'))

        if value.size > settings.MAX_PHOTO_UPLOAD_SIZE:
            raise serializers.ValidationError(
                gettext(
                    'Please use images smaller than %dMB.'
                    % (settings.MAX_PHOTO_UPLOAD_SIZE / 1024 / 1024)
                )
            )
        return value

    def update(self, instance, validated_data):
        instance = super().update(instance, validated_data)

        photo = validated_data.get('picture_upload')
        if photo:
            original = instance.picture_path_original

            storage = SafeStorage(user_media='userpics')
            with storage.open(original, 'wb') as original_file:
                for chunk in photo.chunks():
                    original_file.write(chunk)
            instance.update(picture_type=photo.content_type)
            resize_photo.delay(
                original,
                instance.picture_path,
                set_modified_on=instance.serializable_reference(),
            )
        return instance

    def to_representation(self, obj):
        data = super().to_representation(obj)
        request = self.context.get('request', None)

        if request and is_gate_active(request, 'del-accounts-fxa-edit-email-url'):
            data.pop('fxa_edit_email_url', None)
        return data