Skip to content
Snippets Groups Projects
mutations.py 4.99 KiB
Newer Older
  • Learn to ignore specific revisions
  • from funkwhale_api.common import models as common_models
    
    from funkwhale_api.common import mutations
    
    from funkwhale_api.common import serializers as common_serializers
    
    from funkwhale_api.common import utils as common_utils
    
    
    Eliot Berriot's avatar
    Eliot Berriot committed
    from funkwhale_api.federation import routes
    
    from funkwhale_api.tags import models as tags_models
    from funkwhale_api.tags import serializers as tags_serializers
    
    
    from . import models
    
    
    def can_suggest(obj, actor):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        return obj.is_local
    
    
    
    def can_approve(obj, actor):
    
        if not obj.is_local or not actor.user:
            return False
    
        return (
            actor.id is not None and actor.id == obj.attributed_to_id
        ) or actor.user.get_permissions()["library"]
    
    class TagMutation(mutations.UpdateMutationSerializer):
        tags = tags_serializers.TagsListField()
    
    
        def get_previous_state_handlers(self):
            handlers = super().get_previous_state_handlers()
            handlers["tags"] = lambda obj: list(
    
                sorted(obj.tagged_items.values_list("tag__name", flat=True))
            )
    
    
        def update(self, instance, validated_data):
            tags = validated_data.pop("tags", [])
            r = super().update(instance, validated_data)
            tags_models.set_tags(instance, *tags)
            return r
    
    
    
    class DescriptionMutation(mutations.UpdateMutationSerializer):
        description = common_serializers.ContentSerializer()
    
        def get_previous_state_handlers(self):
            handlers = super().get_previous_state_handlers()
            handlers["description"] = (
                lambda obj: common_serializers.ContentSerializer(obj.description).data
                if obj.description_id
                else None
            )
            return handlers
    
        def update(self, instance, validated_data):
            description = validated_data.pop("description", None)
            r = super().update(instance, validated_data)
            common_utils.attach_content(instance, "description", description)
            return r
    
    
    
    class CoverMutation(mutations.UpdateMutationSerializer):
        cover = common_serializers.RelatedField(
            "uuid", queryset=common_models.Attachment.objects.all().local(), serializer=None
        )
    
        def get_serialized_relations(self):
            serialized_relations = super().get_serialized_relations()
            serialized_relations["cover"] = "uuid"
            return serialized_relations
    
        def get_previous_state_handlers(self):
            handlers = super().get_previous_state_handlers()
            handlers["cover"] = (
                lambda obj: str(obj.attachment_cover.uuid) if obj.attachment_cover else None
            )
            return handlers
    
        def update(self, instance, validated_data):
            if "cover" in validated_data:
                validated_data["attachment_cover"] = validated_data.pop("cover")
            return super().update(instance, validated_data)
    
        def mutation_post_init(self, mutation):
            # link cover_attachment (if any) to mutation
            if "cover" not in mutation.payload:
                return
            try:
                attachment = common_models.Attachment.objects.get(
                    uuid=mutation.payload["cover"]
                )
            except common_models.Attachment.DoesNotExist:
                return
    
            common_models.MutationAttachment.objects.create(
                attachment=attachment, mutation=mutation
            )
    
    
    
    @mutations.registry.connect(
        "update",
        models.Track,
        perm_checkers={"suggest": can_suggest, "approve": can_approve},
    )
    
    class TrackMutationSerializer(CoverMutation, TagMutation, DescriptionMutation):
    
        class Meta:
            model = models.Track
    
            fields = [
                "license",
                "title",
                "position",
                "copyright",
                "tags",
                "description",
                "cover",
            ]
    
        def get_serialized_relations(self):
            serialized_relations = super().get_serialized_relations()
            serialized_relations["license"] = "code"
            return serialized_relations
    
    Eliot Berriot's avatar
    Eliot Berriot committed
    
        def post_apply(self, obj, validated_data):
            routes.outbox.dispatch(
                {"type": "Update", "object": {"type": "Track"}}, context={"track": obj}
            )
    
    
    
    @mutations.registry.connect(
        "update",
        models.Artist,
        perm_checkers={"suggest": can_suggest, "approve": can_approve},
    )
    
    class ArtistMutationSerializer(CoverMutation, TagMutation, DescriptionMutation):
    
        class Meta:
            model = models.Artist
    
            fields = ["name", "tags", "description", "cover"]
    
    
        def post_apply(self, obj, validated_data):
            routes.outbox.dispatch(
                {"type": "Update", "object": {"type": "Artist"}}, context={"artist": obj}
            )
    
    
    @mutations.registry.connect(
        "update",
        models.Album,
        perm_checkers={"suggest": can_suggest, "approve": can_approve},
    )
    
    class AlbumMutationSerializer(CoverMutation, TagMutation, DescriptionMutation):
    
        class Meta:
            model = models.Album
    
            fields = ["title", "release_date", "tags", "cover", "description"]
    
    
        def post_apply(self, obj, validated_data):
            routes.outbox.dispatch(
                {"type": "Update", "object": {"type": "Album"}}, context={"album": obj}
            )