Fixed a federation issue related to images

This commit is contained in:
Eliot Berriot 2020-02-04 14:24:20 +01:00
parent 93c371fe75
commit b38cec3f69
No known key found for this signature in database
GPG Key ID: 6B501DFD73514E14
3 changed files with 72 additions and 39 deletions

View File

@ -31,17 +31,9 @@ class TruncatedCharField(serializers.CharField):
return v
class LinkSerializer(jsonld.JsonLdSerializer):
type = serializers.ChoiceField(choices=[contexts.AS.Link, contexts.AS.Image])
href = serializers.URLField(max_length=500)
class MediaSerializer(jsonld.JsonLdSerializer):
mediaType = serializers.CharField()
class Meta:
jsonld_mapping = {
"href": jsonld.first_id(contexts.AS.href),
"mediaType": jsonld.first_val(contexts.AS.mediaType),
}
def __init__(self, *args, **kwargs):
self.allowed_mimetypes = kwargs.pop("allowed_mimetypes", [])
super().__init__(*args, **kwargs)
@ -62,6 +54,43 @@ class LinkSerializer(jsonld.JsonLdSerializer):
)
class LinkSerializer(MediaSerializer):
type = serializers.ChoiceField(choices=[contexts.AS.Link])
href = serializers.URLField(max_length=500)
class Meta:
jsonld_mapping = {
"href": jsonld.first_id(contexts.AS.href),
"mediaType": jsonld.first_val(contexts.AS.mediaType),
}
class ImageSerializer(MediaSerializer):
type = serializers.ChoiceField(choices=[contexts.AS.Image, contexts.AS.Link])
href = serializers.URLField(max_length=500, required=False)
url = serializers.URLField(max_length=500, required=False)
class Meta:
jsonld_mapping = {
"url": jsonld.first_id(contexts.AS.url),
"href": jsonld.first_id(contexts.AS.href),
"mediaType": jsonld.first_val(contexts.AS.mediaType),
}
def validate(self, data):
validated_data = super().validate(data)
if "url" not in validated_data:
try:
validated_data["url"] = validated_data["href"]
except KeyError:
if self.required:
raise serializers.ValidationError(
"You need to provide a url or href"
)
return validated_data
class EndpointsSerializer(jsonld.JsonLdSerializer):
sharedInbox = serializers.URLField(max_length=500, required=False)
@ -95,7 +124,7 @@ class ActorSerializer(jsonld.JsonLdSerializer):
following = serializers.URLField(max_length=500, required=False, allow_null=True)
publicKey = PublicKeySerializer(required=False)
endpoints = EndpointsSerializer(required=False)
icon = LinkSerializer(
icon = ImageSerializer(
allowed_mimetypes=["image/*"], allow_null=True, required=False
)
@ -202,7 +231,7 @@ class ActorSerializer(jsonld.JsonLdSerializer):
common_utils.attach_file(
actor,
"attachment_icon",
{"url": new_value["href"], "mimetype": new_value["mediaType"]}
{"url": new_value["url"], "mimetype": new_value["mediaType"]}
if new_value
else None,
)
@ -853,7 +882,7 @@ def include_image(repr, attachment, field="image"):
if attachment:
repr[field] = {
"type": "Image",
"href": attachment.download_url_original,
"url": attachment.download_url_original,
"mediaType": attachment.mimetype or "image/jpeg",
}
else:
@ -915,14 +944,14 @@ class MusicEntitySerializer(jsonld.JsonLdSerializer):
if (
instance.attachment_cover
and instance.attachment_cover.url == attachment_cover["href"]
and instance.attachment_cover.url == attachment_cover["url"]
):
# we already have the proper attachment
return validated_data
# create the attachment by hand so it can be attached as the cover
validated_data["attachment_cover"] = common_models.Attachment.objects.create(
mimetype=attachment_cover["mediaType"],
url=attachment_cover["href"],
url=attachment_cover["url"],
actor=instance.attributed_to,
)
return validated_data
@ -938,7 +967,7 @@ class MusicEntitySerializer(jsonld.JsonLdSerializer):
class ArtistSerializer(MusicEntitySerializer):
image = LinkSerializer(
image = ImageSerializer(
allowed_mimetypes=["image/*"], allow_null=True, required=False
)
updateable_fields = [
@ -982,7 +1011,7 @@ class AlbumSerializer(MusicEntitySerializer):
released = serializers.DateField(allow_null=True, required=False)
artists = serializers.ListField(child=ArtistSerializer(), min_length=1)
# XXX: 1.0 rename to image
cover = LinkSerializer(
cover = ImageSerializer(
allowed_mimetypes=["image/*"], allow_null=True, required=False
)
updateable_fields = [
@ -1045,7 +1074,7 @@ class TrackSerializer(MusicEntitySerializer):
album = AlbumSerializer()
license = serializers.URLField(allow_null=True, required=False)
copyright = serializers.CharField(allow_null=True, required=False)
image = LinkSerializer(
image = ImageSerializer(
allowed_mimetypes=["image/*"], allow_null=True, required=False
)

View File

@ -302,7 +302,12 @@ def process_upload(upload, update_denormalization=True):
def get_cover(obj, field):
cover = obj.get(field)
if cover:
return {"mimetype": cover["mediaType"], "url": cover["href"]}
try:
url = cover["url"]
except KeyError:
url = cover["href"]
return {"mimetype": cover["mediaType"], "url": url}
def federation_audio_track_to_metadata(payload, references):

View File

@ -39,7 +39,7 @@ def test_actor_serializer_from_ap(db):
"icon": {
"type": "Image",
"mediaType": "image/jpeg",
"href": "https://image.example/image.png",
"url": "https://image.example/image.png",
},
}
@ -65,7 +65,7 @@ def test_actor_serializer_from_ap(db):
assert actor.private_key is None
assert actor.public_key == payload["publicKey"]["publicKeyPem"]
assert actor.domain_id == "test.federation"
assert actor.attachment_icon.url == payload["icon"]["href"]
assert actor.attachment_icon.url == payload["icon"]["url"]
assert actor.attachment_icon.mimetype == payload["icon"]["mediaType"]
@ -139,7 +139,7 @@ def test_actor_serializer_to_ap(factories):
expected["icon"] = {
"type": "Image",
"mediaType": "image/jpeg",
"href": utils.full_url(ac.attachment_icon.file.url),
"url": utils.full_url(ac.attachment_icon.file.url),
}
serializer = serializers.ActorSerializer(ac)
@ -595,7 +595,7 @@ def test_activity_pub_artist_serializer_to_ap(factories):
"image": {
"type": "Image",
"mediaType": "image/jpeg",
"href": utils.full_url(artist.attachment_cover.file.url),
"url": utils.full_url(artist.attachment_cover.file.url),
},
"tag": [
{"type": "Hashtag", "name": "#Punk"},
@ -626,7 +626,7 @@ def test_activity_pub_album_serializer_to_ap(factories):
"image": {
"type": "Image",
"mediaType": "image/jpeg",
"href": utils.full_url(album.attachment_cover.file.url),
"url": utils.full_url(album.attachment_cover.file.url),
},
"musicbrainzId": album.mbid,
"published": album.creation_date.isoformat(),
@ -661,7 +661,7 @@ def test_activity_pub_artist_serializer_from_ap_update(factories, faker):
"attributedTo": artist.attributed_to.fid,
"mediaType": "text/html",
"content": common_utils.render_html(faker.sentence(), "text/html"),
"image": {"type": "Image", "mediaType": "image/jpeg", "href": faker.url()},
"image": {"type": "Image", "mediaType": "image/jpeg", "url": faker.url()},
"tag": [
{"type": "Hashtag", "name": "#Punk"},
{"type": "Hashtag", "name": "#Rock"},
@ -677,7 +677,7 @@ def test_activity_pub_artist_serializer_from_ap_update(factories, faker):
assert artist.name == payload["name"]
assert str(artist.mbid) == payload["musicbrainzId"]
assert artist.attachment_cover.url == payload["image"]["href"]
assert artist.attachment_cover.url == payload["image"]["url"]
assert artist.attachment_cover.mimetype == payload["image"]["mediaType"]
assert artist.description.text == payload["content"]
assert artist.description.content_type == "text/html"
@ -767,7 +767,7 @@ def test_activity_pub_track_serializer_to_ap(factories):
"image": {
"type": "Image",
"mediaType": "image/jpeg",
"href": utils.full_url(track.attachment_cover.file.url),
"url": utils.full_url(track.attachment_cover.file.url),
},
}
serializer = serializers.TrackSerializer(track)
@ -797,8 +797,8 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
"content": "Hello there",
"attributedTo": track_attributed_to.fid,
"image": {
"type": "Link",
"href": "https://cover.image/track.png",
"type": "Image",
"url": "https://cover.image/track.png",
"mediaType": "image/png",
},
"album": {
@ -829,8 +829,8 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
"attributedTo": album_artist_attributed_to.fid,
"tag": [{"type": "Hashtag", "name": "AlbumArtistTag"}],
"image": {
"type": "Link",
"href": "https://cover.image/album-artist.png",
"type": "Image",
"url": "https://cover.image/album-artist.png",
"mediaType": "image/png",
},
}
@ -848,8 +848,8 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
"published": published.isoformat(),
"tag": [{"type": "Hashtag", "name": "ArtistTag"}],
"image": {
"type": "Link",
"href": "https://cover.image/artist.png",
"type": "Image",
"url": "https://cover.image/artist.png",
"mediaType": "image/png",
},
}
@ -877,7 +877,7 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
assert str(track.mbid) == data["musicbrainzId"]
assert track.description.text == data["content"]
assert track.description.content_type == "text/html"
assert track.attachment_cover.url == data["image"]["href"]
assert track.attachment_cover.url == data["image"]["url"]
assert track.attachment_cover.mimetype == data["image"]["mediaType"]
assert album.from_activity == activity
@ -900,7 +900,7 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
assert artist.attributed_to == artist_attributed_to
assert artist.description.text == data["artists"][0]["content"]
assert artist.description.content_type == data["artists"][0]["mediaType"]
assert artist.attachment_cover.url == data["artists"][0]["image"]["href"]
assert artist.attachment_cover.url == data["artists"][0]["image"]["url"]
assert artist.attachment_cover.mimetype == data["artists"][0]["image"]["mediaType"]
assert album_artist.from_activity == activity
@ -915,8 +915,7 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
== data["album"]["artists"][0]["mediaType"]
)
assert (
album_artist.attachment_cover.url
== data["album"]["artists"][0]["image"]["href"]
album_artist.attachment_cover.url == data["album"]["artists"][0]["image"]["url"]
)
assert (
album_artist.attachment_cover.mimetype
@ -949,7 +948,7 @@ def test_activity_pub_track_serializer_from_ap_update(factories, r_mock, mocker,
"attributedTo": track_attributed_to.fid,
"album": serializers.AlbumSerializer(track.album).data,
"artists": [serializers.ArtistSerializer(track.artist).data],
"image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
"image": {"type": "Image", "mediaType": "image/jpeg", "url": faker.url()},
"tag": [
{"type": "Hashtag", "name": "#Hello"},
# Ensure we can handle tags without a leading #
@ -970,7 +969,7 @@ def test_activity_pub_track_serializer_from_ap_update(factories, r_mock, mocker,
assert track.description.content_type == "text/html"
assert track.description.text == "hello there"
assert str(track.mbid) == data["musicbrainzId"]
assert track.attachment_cover.url == data["image"]["href"]
assert track.attachment_cover.url == data["image"]["url"]
assert track.attachment_cover.mimetype == data["image"]["mediaType"]
set_tags.assert_called_once_with(track, *["Hello", "World"])
@ -1159,7 +1158,7 @@ def test_local_actor_serializer_to_ap(factories):
expected["icon"] = {
"type": "Image",
"mediaType": "image/jpeg",
"href": utils.full_url(ac.attachment_icon.file.url),
"url": utils.full_url(ac.attachment_icon.file.url),
}
serializer = serializers.ActorSerializer(ac)