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