class LocalBadgeInstanceUploadSerializerV1(serializers.Serializer): image = Base64FileField(required=False, write_only=True) url = serializers.URLField(required=False, write_only=True) assertion = serializers.CharField(required=False, write_only=True) recipient_identifier = serializers.CharField(required=False, read_only=True) acceptance = serializers.CharField(default='Accepted') public = serializers.BooleanField(required=False, default=False) include_evidence = serializers.BooleanField(required=False, default=False) narrative = MarkdownCharField(required=False, read_only=True) extensions = serializers.DictField(source='extension_items', read_only=True) def to_representation(self, obj): """ If the APIView initialized the serializer with the extra context variable 'format' from a query param in the GET request with the value "plain", make the `json` field for this instance read_only. """ if self.context.get('format', 'v1') == 'plain': self.fields.json = serializers.DictField(read_only=True) representation = super(LocalBadgeInstanceUploadSerializerV1, self).to_representation(obj) representation['id'] = obj.entity_id representation['json'] = V1BadgeInstanceSerializer( obj, context=self.context).data representation['imagePreview'] = { "type": "image", "id": "{}{}?type=png".format( OriginSetting.HTTP, reverse('badgeclass_image', kwargs={'entity_id': obj.cached_badgeclass.entity_id})) } if obj.cached_issuer.image: representation['issuerImagePreview'] = { "type": "image", "id": "{}{}?type=png".format( OriginSetting.HTTP, reverse('issuer_image', kwargs={'entity_id': obj.cached_issuer.entity_id})) } if obj.image: representation['image'] = obj.image_url() representation['shareUrl'] = obj.share_url return representation def validate(self, data): """ Ensure only one assertion input field given. """ fields_present = [ 'image' in data, 'url' in data, 'assertion' in data and data.get('assertion') ] if (fields_present.count(True) > 1): raise serializers.ValidationError( "Only one instance input field allowed.") return data def create(self, validated_data): owner = validated_data.get('created_by') try: instance, created = BadgeCheckHelper.get_or_create_assertion( url=validated_data.get('url', None), imagefile=validated_data.get('image', None), assertion=validated_data.get('assertion', None), created_by=owner, ) if not created: if instance.acceptance == BadgeInstance.ACCEPTANCE_ACCEPTED: raise RestframeworkValidationError([{ 'name': "DUPLICATE_BADGE", 'description': "You already have this badge in your backpack" }]) instance.acceptance = BadgeInstance.ACCEPTANCE_ACCEPTED instance.save() owner.publish() # update BadgeUser.cached_badgeinstances() except DjangoValidationError as e: raise RestframeworkValidationError(e.args[0]) return instance def update(self, instance, validated_data): """ Updating acceptance status (to 'Accepted') is permitted as well as changing public status. """ # Only locally issued badges will ever have an acceptance status other than 'Accepted' if instance.acceptance in [ 'Unaccepted', 'Rejected' ] and validated_data.get('acceptance') == 'Accepted': instance.acceptance = 'Accepted' instance.save() public = validated_data.get('public', None) if public is not None: instance.public = public instance.include_evidence = validated_data.get( 'include_evidence', False) instance.save() return instance
class LocalBadgeInstanceUploadSerializerV1(serializers.Serializer): image = Base64FileField(required=False, write_only=True) url = serializers.URLField(required=False, write_only=True) assertion = serializers.CharField(required=False, write_only=True) recipient_identifier = serializers.CharField(required=False, read_only=True) acceptance = serializers.CharField(default='Accepted') narrative = MarkdownCharField(required=False, read_only=True) evidence_items = EvidenceItemSerializer(many=True, required=False, read_only=True) pending = serializers.ReadOnlyField() extensions = serializers.DictField(source='extension_items', read_only=True) # Reinstantiation using fields from badge instance when returned by .create # id = serializers.IntegerField(read_only=True) # json = V1InstanceSerializer(read_only=True) def to_representation(self, obj): """ If the APIView initialized the serializer with the extra context variable 'format' from a query param in the GET request with the value "plain", make the `json` field for this instance read_only. """ if self.context.get('format', 'v1') == 'plain': self.fields.json = serializers.DictField(read_only=True) representation = super(LocalBadgeInstanceUploadSerializerV1, self).to_representation(obj) # if isinstance(obj, LocalBadgeInstance): # representation['json'] = V1InstanceSerializer(obj.json, context=self.context).data # representation['imagePreview'] = { # "type": "image", # "id": "{}{}?type=png".format(OriginSetting.HTTP, reverse('localbadgeinstance_image', kwargs={'slug': obj.slug})) # } # if isinstance(obj, BadgeInstance): representation['id'] = obj.entity_id representation['json'] = V1BadgeInstanceSerializer( obj, context=self.context).data representation['imagePreview'] = { "type": "image", "id": "{}{}?type=png".format( OriginSetting.HTTP, reverse('badgeclass_image', kwargs={'entity_id': obj.cached_badgeclass.entity_id})) } if obj.cached_issuer.image: representation['issuerImagePreview'] = { "type": "image", "id": "{}{}?type=png".format( OriginSetting.HTTP, reverse('issuer_image', kwargs={'entity_id': obj.cached_issuer.entity_id})) } if obj.image: representation['image'] = obj.image_url() representation['shareUrl'] = obj.share_url return representation # def validate_recipient_identifier(self, data): # user = self.context.get('request').user # current_emails = [e.email for e in user.cached_emails()] + [e.email for e in user.cached_email_variants()] # # if data in current_emails: # return None # if user.can_add_variant(data): # return data # raise serializers.ValidationError("Requested recipient ID {} is not one of your verified email addresses.") # def validate(self, data): """ Ensure only one assertion input field given. """ fields_present = [ 'image' in data, 'url' in data, 'assertion' in data and data.get('assertion') ] if (fields_present.count(True) > 1): raise serializers.ValidationError( "Only one instance input field allowed.") return data def create(self, validated_data): owner = validated_data.get('created_by') try: instance, created = BadgeCheckHelper.get_or_create_assertion( url=validated_data.get('url', None), imagefile=validated_data.get('image', None), assertion=validated_data.get('assertion', None), created_by=owner, ) if not created: if instance.acceptance == BadgeInstance.ACCEPTANCE_ACCEPTED: raise RestframeworkValidationError([{ 'name': "DUPLICATE_BADGE", 'description': "You already have this badge in your backpack" }]) instance.acceptance = BadgeInstance.ACCEPTANCE_ACCEPTED instance.save() owner.publish() # update BadgeUser.cached_badgeinstances() except DjangoValidationError as e: raise RestframeworkValidationError(e.args[0]) return instance def update(self, instance, validated_data): """ Only updating acceptance status (to 'Accepted') is permitted for now. """ # Only locally issued badges will ever have an acceptance status other than 'Accepted' if instance.acceptance == 'Unaccepted' and validated_data.get( 'acceptance') == 'Accepted': instance.acceptance = 'Accepted' instance.save() owner = instance.user if owner: owner.publish() return instance