diff --git a/api/config/api_urls.py b/api/config/api_urls.py index 909dff45ee2de04e5671832f42499e695ec885f8..73df6fc4e90b392f2430feb3c2a2de95bfed928e 100644 --- a/api/config/api_urls.py +++ b/api/config/api_urls.py @@ -74,11 +74,6 @@ v1_patterns += [ include(("funkwhale_api.history.urls", "history"), namespace="history"), ), url(r"^", include(("funkwhale_api.users.api_urls", "users"), namespace="users"),), - # XXX: 1.0: remove this - url( - r"^users/", - include(("funkwhale_api.users.api_urls", "users"), namespace="users-nested"), - ), url( r"^oauth/", include(("funkwhale_api.users.oauth.urls", "oauth"), namespace="oauth"), diff --git a/api/config/routing.py b/api/config/routing.py index d0858e2432457ad9ae06c81c7ab555b998d595db..ce293ff768dddc7ed9083987d8f3b1daa5963d7f 100644 --- a/api/config/routing.py +++ b/api/config/routing.py @@ -2,18 +2,13 @@ from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter from django.conf.urls import url -from funkwhale_api.common.auth import TokenAuthMiddleware from funkwhale_api.instance import consumers application = ProtocolTypeRouter( { # Empty for now (http->django views is added by default) "websocket": AuthMiddlewareStack( - TokenAuthMiddleware( - URLRouter( - [url("^api/v1/activity$", consumers.InstanceActivityConsumer)] - ) - ) + URLRouter([url("^api/v1/activity$", consumers.InstanceActivityConsumer)]) ) } ) diff --git a/api/config/settings/common.py b/api/config/settings/common.py index 646345544530e1df9cf783603861dd05ce9c55b4..9f5a551ed3e5b1fdf31be98dd06c4ce13b4d297a 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -169,17 +169,7 @@ os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = env.bool( "DJANGO_ALLOW_ASYNC_UNSAFE", default="true" ) -# XXX: deprecated, see #186 -FEDERATION_ENABLED = env.bool("FEDERATION_ENABLED", default=True) FEDERATION_HOSTNAME = env("FEDERATION_HOSTNAME", default=FUNKWHALE_HOSTNAME).lower() -# XXX: deprecated, see #186 -FEDERATION_COLLECTION_PAGE_SIZE = env.int("FEDERATION_COLLECTION_PAGE_SIZE", default=50) -# XXX: deprecated, see #186 -FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool( - "FEDERATION_MUSIC_NEEDS_APPROVAL", default=True -) -# XXX: deprecated, see #186 -FEDERATION_ACTOR_FETCH_DELAY = env.int("FEDERATION_ACTOR_FETCH_DELAY", default=60 * 12) FEDERATION_SERVICE_ACTOR_USERNAME = env( "FEDERATION_SERVICE_ACTOR_USERNAME", default="service" ) @@ -1129,11 +1119,6 @@ Exemples: CSRF_USE_SESSIONS = True SESSION_ENGINE = "django.contrib.sessions.backends.cache" -# Playlist settings -# XXX: deprecated, see #186 -PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250) - - ACCOUNT_USERNAME_BLACKLIST = [ "funkwhale", "library", @@ -1170,8 +1155,6 @@ EXTERNAL_REQUESTS_TIMEOUT = env.int("EXTERNAL_REQUESTS_TIMEOUT", default=10) """ Default timeout for external requests. """ -# XXX: deprecated, see #186 -API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True) MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None) """ @@ -1285,8 +1268,6 @@ FUNKWHALE_SUPPORT_MESSAGE_DELAY = env.int("FUNKWHALE_SUPPORT_MESSAGE_DELAY", def """ Delay in days after signup before we show the "support Funkwhale" message """ -# XXX Stable release: remove -USE_FULL_TEXT_SEARCH = env.bool("USE_FULL_TEXT_SEARCH", default=True) MIN_DELAY_BETWEEN_DOWNLOADS_COUNT = env.int( "MIN_DELAY_BETWEEN_DOWNLOADS_COUNT", default=60 * 60 * 6 diff --git a/api/funkwhale_api/common/dynamic_preferences_registry.py b/api/funkwhale_api/common/dynamic_preferences_registry.py index d6dfed78376503387c48247426ee6925772dbdff..6d15fcd8f3fc22aeb66d3a710ec49a5f74e6a95f 100644 --- a/api/funkwhale_api/common/dynamic_preferences_registry.py +++ b/api/funkwhale_api/common/dynamic_preferences_registry.py @@ -1,19 +1,15 @@ from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry -from funkwhale_api.common import preferences - common = types.Section("common") @global_preferences_registry.register -class APIAutenticationRequired( - preferences.DefaultFromSettingMixin, types.BooleanPreference -): +class APIAutenticationRequired(types.BooleanPreference): section = common name = "api_authentication_required" verbose_name = "API Requires authentication" - setting = "API_AUTHENTICATION_REQUIRED" + default = True help_text = ( "If disabled, anonymous users will be able to query the API" "and access music data (as well as other data exposed in the API " diff --git a/api/funkwhale_api/common/fields.py b/api/funkwhale_api/common/fields.py index ffc8e5f95d42171542b2cda6e863a9f157026e30..d354c93eb7e213ea1fdb0bd206071f837fd5db92 100644 --- a/api/funkwhale_api/common/fields.py +++ b/api/funkwhale_api/common/fields.py @@ -1,6 +1,5 @@ import django_filters from django import forms -from django.conf import settings from django.core.serializers.json import DjangoJSONEncoder from django.db import models @@ -40,7 +39,7 @@ class SearchFilter(django_filters.CharFilter): def filter(self, qs, value): if not value: return qs - if settings.USE_FULL_TEXT_SEARCH and self.fts_search_fields: + if self.fts_search_fields: query = search.get_fts_query( value, self.fts_search_fields, model=self.parent.Meta.model ) diff --git a/api/funkwhale_api/common/middleware.py b/api/funkwhale_api/common/middleware.py index b085a18fe84c78b423d33d5603a4887a7ba9f341..4752159106ca2de510f4c8b1ba0fcae32615a4ff 100644 --- a/api/funkwhale_api/common/middleware.py +++ b/api/funkwhale_api/common/middleware.py @@ -113,7 +113,7 @@ def get_spa_html(spa_url): def get_spa_file(spa_url, name): if spa_url.startswith("/"): - # XXX: spa_url is an absolute path to index.html, on the local disk. + # spa_url is an absolute path to index.html, on the local disk. # However, we may want to access manifest.json or other files as well, so we # strip the filename path = os.path.join(os.path.dirname(spa_url), name) diff --git a/api/funkwhale_api/common/serializers.py b/api/funkwhale_api/common/serializers.py index 76e698c5f993a036c7c4198911877a0ad2762234..9210c0603c3925d724dc82d79ba5e1c0fae227f8 100644 --- a/api/funkwhale_api/common/serializers.py +++ b/api/funkwhale_api/common/serializers.py @@ -299,20 +299,6 @@ class AttachmentSerializer(serializers.Serializer): urls["medium_square_crop"] = o.download_url_medium_square_crop return urls - def to_representation(self, o): - repr = super().to_representation(o) - # XXX: BACKWARD COMPATIBILITY - # having the attachment urls in a nested JSON obj is better, - # but we can't do this without breaking clients - # So we extract the urls and include these in the parent payload - repr.update({k: v for k, v in repr["urls"].items() if k != "source"}) - # also, our legacy images had lots of variations (400x400, 200x200, 50x50) - # but we removed some of these, so we emulate these by hand (by redirecting) - # to actual, existing attachment variations - repr["square_crop"] = repr["medium_square_crop"] - repr["small_square_crop"] = repr["medium_square_crop"] - return repr - def create(self, validated_data): return models.Attachment.objects.create( file=validated_data["file"], actor=validated_data["actor"] diff --git a/api/funkwhale_api/favorites/filters.py b/api/funkwhale_api/favorites/filters.py index 0b76a4dd04340da3ad62b2391a82dd9e9534dc9e..32c07a646bd80ca5675fc61fc2a45e25c31e8308 100644 --- a/api/funkwhale_api/favorites/filters.py +++ b/api/funkwhale_api/favorites/filters.py @@ -13,8 +13,7 @@ class TrackFavoriteFilter(moderation_filters.HiddenContentFilterSet): class Meta: model = models.TrackFavorite - # XXX: 1.0 remove the user filter, we have scope=me now - fields = ["user"] + fields = [] hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG[ "TRACK_FAVORITE" ] diff --git a/api/funkwhale_api/federation/dynamic_preferences_registry.py b/api/funkwhale_api/federation/dynamic_preferences_registry.py index 6f7d7171958604d7c69558774abbf459fada556f..c696b95781e5f9e941cf27e197ab2c67cc89474f 100644 --- a/api/funkwhale_api/federation/dynamic_preferences_registry.py +++ b/api/funkwhale_api/federation/dynamic_preferences_registry.py @@ -1,8 +1,6 @@ from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry -from funkwhale_api.common import preferences - federation = types.Section("federation") @@ -22,10 +20,10 @@ class MusicCacheDuration(types.IntPreference): @global_preferences_registry.register -class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference): +class Enabled(types.BooleanPreference): section = federation name = "enabled" - setting = "FEDERATION_ENABLED" + default = True verbose_name = "Federation enabled" help_text = ( "Use this setting to enable or disable federation logic and API" " globally." @@ -33,20 +31,20 @@ class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference): @global_preferences_registry.register -class CollectionPageSize(preferences.DefaultFromSettingMixin, types.IntPreference): +class CollectionPageSize(types.IntPreference): section = federation name = "collection_page_size" - setting = "FEDERATION_COLLECTION_PAGE_SIZE" + default = 50 verbose_name = "Federation collection page size" help_text = "How many items to display in ActivityPub collections." field_kwargs = {"required": False} @global_preferences_registry.register -class ActorFetchDelay(preferences.DefaultFromSettingMixin, types.IntPreference): +class ActorFetchDelay(types.IntPreference): section = federation name = "actor_fetch_delay" - setting = "FEDERATION_ACTOR_FETCH_DELAY" + default = 60 * 12 verbose_name = "Federation actor fetch delay" help_text = ( "How many minutes to wait before refetching actors on " diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py index 00d5d1e4d1d155c5de9a62dc9c2ef91f96df9867..9f68a2375d96cf78a801a2f0d6045bfa3588ce03 100644 --- a/api/funkwhale_api/federation/serializers.py +++ b/api/funkwhale_api/federation/serializers.py @@ -938,8 +938,6 @@ class PaginatedCollectionSerializer(jsonld.JsonLdSerializer): last = common_utils.set_query_parameter(conf["id"], page=paginator.num_pages) d = { "id": conf["id"], - # XXX Stable release: remove the obsolete actor field - "actor": conf["actor"].fid, "attributedTo": conf["actor"].fid, "totalItems": paginator.count, "type": conf.get("type", "Collection"), @@ -1004,9 +1002,8 @@ class LibrarySerializer(PaginatedCollectionSerializer): "name": library.name, "summary": library.description, "page_size": 100, - # XXX Stable release: remove the obsolete actor field - "actor": library.actor, "attributedTo": library.actor, + "actor": library.actor, "items": library.uploads.for_federation(), "type": "Library", } @@ -1108,8 +1105,6 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer): ], } if conf["actor"]: - # XXX Stable release: remove the obsolete actor field - d["actor"] = conf["actor"].fid d["attributedTo"] = conf["actor"].fid if page.has_previous(): @@ -1297,8 +1292,7 @@ class AlbumSerializer(MusicEntitySerializer): child=MultipleSerializer(allowed=[BasicActorSerializer, ArtistSerializer]), min_length=1, ) - # XXX: 1.0 rename to image - cover = ImageSerializer( + image = ImageSerializer( allowed_mimetypes=["image/*"], allow_null=True, required=False, @@ -1306,7 +1300,7 @@ class AlbumSerializer(MusicEntitySerializer): ) updateable_fields = [ ("name", "title"), - ("cover", "attachment_cover"), + ("image", "attachment_cover"), ("musicbrainzId", "mbid"), ("attributedTo", "attributed_to"), ("released", "release_date"), @@ -1320,7 +1314,7 @@ class AlbumSerializer(MusicEntitySerializer): { "released": jsonld.first_val(contexts.FW.released), "artists": jsonld.first_attr(contexts.FW.artists, "@list"), - "cover": jsonld.first_obj(contexts.FW.cover), + "image": jsonld.first_obj(contexts.AS.image), }, ) @@ -1354,11 +1348,6 @@ class AlbumSerializer(MusicEntitySerializer): ] include_content(d, instance.description) if instance.attachment_cover: - d["cover"] = { - "type": "Link", - "href": instance.attachment_cover.download_url_original, - "mediaType": instance.attachment_cover.mimetype or "image/jpeg", - } include_image(d, instance.attachment_cover) if self.context.get("include_ap_context", self.parent is None): diff --git a/api/funkwhale_api/federation/utils.py b/api/funkwhale_api/federation/utils.py index d6a35df281f29ddf20235a9320489997d87a24d0..2bac8daf8fb8dd5e64fc9711e1367360f0ce2651 100644 --- a/api/funkwhale_api/federation/utils.py +++ b/api/funkwhale_api/federation/utils.py @@ -218,7 +218,6 @@ def should_redirect_ap_to_html(accept_header, default=True): "text/html", ] no_redirect_headers = [ - "*/*", # XXX backward compat with older Funkwhale instances that don't send the Accept header "application/json", "application/activity+json", "application/ld+json", diff --git a/api/funkwhale_api/moderation/migrations/0006_auto_20200803_1222.py b/api/funkwhale_api/moderation/migrations/0006_auto_20200803_1222.py new file mode 100644 index 0000000000000000000000000000000000000000..ca1cfc9edd693beec9159fb627c2ebb2bdad35ee --- /dev/null +++ b/api/funkwhale_api/moderation/migrations/0006_auto_20200803_1222.py @@ -0,0 +1,22 @@ +# Generated by Django 3.0.8 on 2020-08-03 12:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('moderation', '0005_auto_20200317_0820'), + ] + + operations = [ + migrations.RemoveField( + model_name='userrequest', + name='url', + ), + migrations.AlterField( + model_name='userrequest', + name='status', + field=models.CharField(choices=[('pending', 'Pending'), ('refused', 'Refused'), ('approved', 'Approved')], default='pending', max_length=40), + ), + ] diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index 1d32a01bd976dfbe028966be5b7a254b5adadbb2..121c0f3ff41842c115b7ee44b7bf1c0520090c5a 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -20,7 +20,6 @@ from django.db.models.signals import post_save, pre_save from django.dispatch import receiver from django.urls import reverse from django.utils import timezone -from versatileimagefield.fields import VersatileImageField from funkwhale_api import musicbrainz from funkwhale_api.common import fields @@ -325,10 +324,6 @@ class Album(APIModelMixin): artist = models.ForeignKey(Artist, related_name="albums", on_delete=models.CASCADE) release_date = models.DateField(null=True, blank=True, db_index=True) release_group_id = models.UUIDField(null=True, blank=True) - # XXX: 1.0 clean this uneeded field in favor of attachment_cover - cover = VersatileImageField( - upload_to="albums/covers/%Y/%m/%d", null=True, blank=True - ) attachment_cover = models.ForeignKey( "common.Attachment", null=True, diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py index c5e4336a6e310e51a642c9a1a7cc751e910cfad2..1dd17b2bffe4d32db71e30050478c608f2ba0b34 100644 --- a/api/funkwhale_api/music/serializers.py +++ b/api/funkwhale_api/music/serializers.py @@ -32,10 +32,7 @@ COVER_WRITE_FIELD = common_serializers.RelatedField( from funkwhale_api.audio import serializers as audio_serializers # NOQA -class CoverField( - common_serializers.NullToEmptDict, common_serializers.AttachmentSerializer -): - # XXX: BACKWARD COMPATIBILITY +class CoverField(common_serializers.AttachmentSerializer): pass diff --git a/api/funkwhale_api/music/tasks.py b/api/funkwhale_api/music/tasks.py index 2e633925b40166dd2715b378ddfb0623827ff719..7f47b402bc5968a8b9a8b6619d0014b93067c5c0 100644 --- a/api/funkwhale_api/music/tasks.py +++ b/api/funkwhale_api/music/tasks.py @@ -364,7 +364,7 @@ def federation_audio_track_to_metadata(payload, references): "mbid": str(payload["album"]["musicbrainzId"]) if payload["album"].get("musicbrainzId") else None, - "cover_data": get_cover(payload["album"], "cover"), + "cover_data": get_cover(payload["album"], "image"), "release_date": payload["album"].get("released"), "tags": [t["name"] for t in payload["album"].get("tags", []) or []], "artists": [ @@ -896,8 +896,6 @@ UPDATE_CONFIG = { @transaction.atomic def update_track_metadata(audio_metadata, track): - # XXX: implement this to support updating metadata when an imported files - # is updated by an outside tool (e.g beets). serializer = metadata.TrackMetadataSerializer(data=audio_metadata) serializer.is_valid(raise_exception=True) new_data = serializer.validated_data diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 18c2b30aa8b4ff9c4066a24e9e672240beee53d9..0df0d46408ac53e6e56a8c4c444733cf70fa0519 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -797,20 +797,11 @@ class Search(views.APIView): return Response(results, status=200) def get_tracks(self, query): - search_fields = [ - "mbid", - "title__unaccent", - "album__title__unaccent", - "artist__name__unaccent", - ] - if settings.USE_FULL_TEXT_SEARCH: - query_obj = utils.get_fts_query( - query, - fts_fields=["body_text", "album__body_text", "artist__body_text"], - model=models.Track, - ) - else: - query_obj = utils.get_query(query, search_fields) + query_obj = utils.get_fts_query( + query, + fts_fields=["body_text", "album__body_text", "artist__body_text"], + model=models.Track, + ) qs = ( models.Track.objects.all() .filter(query_obj) @@ -828,13 +819,9 @@ class Search(views.APIView): return common_utils.order_for_search(qs, "title")[: self.max_results] def get_albums(self, query): - search_fields = ["mbid", "title__unaccent", "artist__name__unaccent"] - if settings.USE_FULL_TEXT_SEARCH: - query_obj = utils.get_fts_query( - query, fts_fields=["body_text", "artist__body_text"], model=models.Album - ) - else: - query_obj = utils.get_query(query, search_fields) + query_obj = utils.get_fts_query( + query, fts_fields=["body_text", "artist__body_text"], model=models.Album + ) qs = ( models.Album.objects.all() .filter(query_obj) @@ -844,11 +831,7 @@ class Search(views.APIView): return common_utils.order_for_search(qs, "title")[: self.max_results] def get_artists(self, query): - search_fields = ["mbid", "name__unaccent"] - if settings.USE_FULL_TEXT_SEARCH: - query_obj = utils.get_fts_query(query, model=models.Artist) - else: - query_obj = utils.get_query(query, search_fields) + query_obj = utils.get_fts_query(query, model=models.Artist) qs = ( models.Artist.objects.all() .filter(query_obj) diff --git a/api/funkwhale_api/playlists/dynamic_preferences_registry.py b/api/funkwhale_api/playlists/dynamic_preferences_registry.py index 5a2043452bc734841c85e7dde2c7f31ba0c20cab..ee1a33dea96ee1319e15d7a22e03d28ffc6dc23f 100644 --- a/api/funkwhale_api/playlists/dynamic_preferences_registry.py +++ b/api/funkwhale_api/playlists/dynamic_preferences_registry.py @@ -1,16 +1,14 @@ from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry -from funkwhale_api.common import preferences - playlists = types.Section("playlists") @global_preferences_registry.register -class MaxTracks(preferences.DefaultFromSettingMixin, types.IntegerPreference): +class MaxTracks(types.IntegerPreference): show_in_api = True section = playlists name = "max_tracks" + default = 250 verbose_name = "Max tracks per playlist" - setting = "PLAYLISTS_MAX_TRACKS" field_kwargs = {"required": False} diff --git a/api/funkwhale_api/playlists/filters.py b/api/funkwhale_api/playlists/filters.py index e12813b38d17cbf4c46080ae111f619149f68916..5270eee802cdbc16ce818a69d392866c3742ccba 100644 --- a/api/funkwhale_api/playlists/filters.py +++ b/api/funkwhale_api/playlists/filters.py @@ -31,7 +31,6 @@ class PlaylistFilter(filters.FilterSet): class Meta: model = models.Playlist fields = { - "user": ["exact"], "name": ["exact", "icontains"], } diff --git a/api/funkwhale_api/playlists/models.py b/api/funkwhale_api/playlists/models.py index a20dbc9373fbbe5c27bab988a70cd5eb40b34819..b227a545d18260197654cf7572429535d502feca 100644 --- a/api/funkwhale_api/playlists/models.py +++ b/api/funkwhale_api/playlists/models.py @@ -227,7 +227,6 @@ class PlaylistTrack(models.Model): class Meta: ordering = ("-playlist", "index") - unique_together = ("playlist", "index") def delete(self, *args, **kwargs): playlist = self.playlist diff --git a/api/funkwhale_api/radios/migrations/0005_auto_20200803_1222.py b/api/funkwhale_api/radios/migrations/0005_auto_20200803_1222.py new file mode 100644 index 0000000000000000000000000000000000000000..8e4cd6770db266edadd089c93cf1776a6d0bc4f3 --- /dev/null +++ b/api/funkwhale_api/radios/migrations/0005_auto_20200803_1222.py @@ -0,0 +1,20 @@ +# Generated by Django 3.0.8 on 2020-08-03 12:22 + +import django.contrib.postgres.fields.jsonb +import django.core.serializers.json +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('radios', '0004_auto_20180107_1813'), + ] + + operations = [ + migrations.AlterField( + model_name='radio', + name='config', + field=django.contrib.postgres.fields.jsonb.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/api/funkwhale_api/tags/migrations/0002_auto_20200803_1222.py b/api/funkwhale_api/tags/migrations/0002_auto_20200803_1222.py new file mode 100644 index 0000000000000000000000000000000000000000..382f24b4c7ca53eeb97c1433fe0c8d34f98f3b21 --- /dev/null +++ b/api/funkwhale_api/tags/migrations/0002_auto_20200803_1222.py @@ -0,0 +1,25 @@ +# Generated by Django 3.0.8 on 2020-08-03 12:22 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('tags', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='taggeditem', + name='content_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='contenttypes.ContentType', verbose_name='Content type'), + ), + migrations.AlterField( + model_name='taggeditem', + name='tag', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='tags.Tag'), + ), + ] diff --git a/api/tests/channels/test_auth.py b/api/tests/channels/test_auth.py deleted file mode 100644 index 505bef1c0761cd972f40f7b4cf09e14cd1fcb627..0000000000000000000000000000000000000000 --- a/api/tests/channels/test_auth.py +++ /dev/null @@ -1,30 +0,0 @@ -import pytest -from rest_framework_jwt.settings import api_settings - -from funkwhale_api.common.auth import TokenAuthMiddleware - -jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER -jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER - - -@pytest.mark.parametrize("query_string", [b"token=wrong", b""]) -def test_header_anonymous(query_string, factories): - def callback(scope): - assert scope["user"].is_anonymous - - scope = {"query_string": query_string} - consumer = TokenAuthMiddleware(callback) - consumer(scope) - - -def test_header_correct_token(factories): - user = factories["users.User"]() - payload = jwt_payload_handler(user) - token = jwt_encode_handler(payload) - - def callback(scope): - assert scope["user"] == user - - scope = {"query_string": "token={}".format(token).encode("utf-8")} - consumer = TokenAuthMiddleware(callback) - consumer(scope) diff --git a/api/tests/common/test_routers.py b/api/tests/common/test_routers.py index 3bd5c4e47f5f823ef75e5d07fd9ce9514d67ab4f..5d1710f09f276aaf19e798fdff39bddd22d781d6 100644 --- a/api/tests/common/test_routers.py +++ b/api/tests/common/test_routers.py @@ -17,7 +17,7 @@ from django import urls "/api/v1/auth/registration/account-confirm-email/key", "/api/v1/history/listenings", "/api/v1/radios/sessions", - "/api/v1/users/users/me", + "/api/v1/users/me", "/api/v1/federation/follows/library", "/api/v1/manage/accounts", "/api/v1/oauth/apps", diff --git a/api/tests/common/test_serializers.py b/api/tests/common/test_serializers.py index 8fdb21edbaa98e556a84fcbe2bd67aecd176d5f9..1d23efb66140d01231a26745c6df4b84f617574b 100644 --- a/api/tests/common/test_serializers.py +++ b/api/tests/common/test_serializers.py @@ -201,15 +201,6 @@ def test_attachment_serializer_existing_file(factories, to_api_date): attachment.file.crop["200x200"].url ), }, - # XXX: BACKWARD COMPATIBILITY - "original": federation_utils.full_url(attachment.file.url), - "medium_square_crop": federation_utils.full_url( - attachment.file.crop["200x200"].url - ), - "small_square_crop": federation_utils.full_url( - attachment.file.crop["200x200"].url - ), - "square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url), } serializer = serializers.AttachmentSerializer(attachment) @@ -237,17 +228,6 @@ def test_attachment_serializer_remote_file(factories, to_api_date): proxy_url + "?next=medium_square_crop" ), }, - # XXX: BACKWARD COMPATIBILITY - "original": federation_utils.full_url(proxy_url + "?next=original"), - "medium_square_crop": federation_utils.full_url( - proxy_url + "?next=medium_square_crop" - ), - "square_crop": federation_utils.full_url( - proxy_url + "?next=medium_square_crop" - ), - "small_square_crop": federation_utils.full_url( - proxy_url + "?next=medium_square_crop" - ), } serializer = serializers.AttachmentSerializer(attachment) diff --git a/api/tests/favorites/test_favorites.py b/api/tests/favorites/test_favorites.py index 48d1857c62540fb1cef2a892c1386013085a7544..06d4caa61ded48aa46eb6c0da398dac54e9f2c55 100644 --- a/api/tests/favorites/test_favorites.py +++ b/api/tests/favorites/test_favorites.py @@ -20,10 +20,11 @@ def test_user_can_get_his_favorites( api_request, factories, logged_in_api_client, client ): request = api_request.get("/") + logged_in_api_client.user.create_actor() favorite = factories["favorites.TrackFavorite"](user=logged_in_api_client.user) factories["favorites.TrackFavorite"]() url = reverse("api:v1:favorites:tracks-list") - response = logged_in_api_client.get(url, {"user": logged_in_api_client.user.pk}) + response = logged_in_api_client.get(url, {"scope": "me"}) expected = [ serializers.UserTrackFavoriteSerializer( favorite, context={"request": request} diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py index addf74b4a65132972eb9717deed66f40107035c4..6617ba07d62fe0f0913a0503023ee85c8a414a87 100644 --- a/api/tests/federation/test_serializers.py +++ b/api/tests/federation/test_serializers.py @@ -388,7 +388,6 @@ def test_paginated_collection_serializer(factories): "@context": jsonld.get_default_context(), "type": "Collection", "id": conf["id"], - "actor": actor.fid, "attributedTo": actor.fid, "totalItems": len(uploads), "current": conf["id"] + "?page=1", @@ -486,7 +485,6 @@ def test_collection_page_serializer(factories): "@context": jsonld.get_default_context(), "type": "CollectionPage", "id": conf["id"] + "?page=2", - "actor": actor.fid, "attributedTo": actor.fid, "totalItems": len(uploads), "partOf": conf["id"], @@ -521,7 +519,6 @@ def test_music_library_serializer_to_ap(factories): "id": library.fid, "name": library.name, "summary": library.description, - "actor": library.actor.fid, "attributedTo": library.actor.fid, "totalItems": 0, "current": library.fid + "?page=1", @@ -764,11 +761,6 @@ def test_activity_pub_album_serializer_to_ap(factories): "type": "Album", "id": album.fid, "name": album.title, - "cover": { - "type": "Link", - "mediaType": "image/jpeg", - "href": utils.full_url(album.attachment_cover.file.url), - }, "image": { "type": "Image", "mediaType": "image/jpeg", @@ -815,7 +807,7 @@ def test_activity_pub_album_serializer_from_ap_create(factories, faker, now): "type": "Album", "id": "https://album.example", "name": faker.sentence(), - "cover": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()}, + "image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()}, "musicbrainzId": faker.uuid4(), "published": now.isoformat(), "released": released.isoformat(), @@ -839,8 +831,8 @@ def test_activity_pub_album_serializer_from_ap_create(factories, faker, now): assert str(album.mbid) == payload["musicbrainzId"] assert album.release_date == released assert album.artist == artist - assert album.attachment_cover.url == payload["cover"]["href"] - assert album.attachment_cover.mimetype == payload["cover"]["mediaType"] + assert album.attachment_cover.url == payload["image"]["href"] + assert album.attachment_cover.mimetype == payload["image"]["mediaType"] assert sorted(album.tagged_items.values_list("tag__name", flat=True)) == [ "Punk", "Rock", @@ -879,7 +871,7 @@ def test_activity_pub_album_serializer_from_ap_update(factories, faker): "type": "Album", "id": album.fid, "name": faker.sentence(), - "cover": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()}, + "image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()}, "musicbrainzId": faker.uuid4(), "published": album.creation_date.isoformat(), "released": released.isoformat(), @@ -904,8 +896,8 @@ def test_activity_pub_album_serializer_from_ap_update(factories, faker): assert album.title == payload["name"] assert str(album.mbid) == payload["musicbrainzId"] assert album.release_date == released - assert album.attachment_cover.url == payload["cover"]["href"] - assert album.attachment_cover.mimetype == payload["cover"]["mediaType"] + assert album.attachment_cover.url == payload["image"]["href"] + assert album.attachment_cover.mimetype == payload["image"]["mediaType"] assert sorted(album.tagged_items.values_list("tag__name", flat=True)) == [ "Punk", "Rock", @@ -996,7 +988,7 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker): "content": "Album summary", "mediaType": "text/markdown", "attributedTo": album_attributed_to.fid, - "cover": { + "image": { "type": "Link", "href": "https://cover.image/test.png", "mediaType": "image/png", @@ -1066,8 +1058,8 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker): assert track.attachment_cover.mimetype == data["image"]["mediaType"] assert album.from_activity == activity - assert album.attachment_cover.url == data["album"]["cover"]["href"] - assert album.attachment_cover.mimetype == data["album"]["cover"]["mediaType"] + assert album.attachment_cover.url == data["album"]["image"]["href"] + assert album.attachment_cover.mimetype == data["album"]["image"]["mediaType"] assert album.title == data["album"]["name"] assert album.fid == data["album"]["id"] assert str(album.mbid) == data["album"]["musicbrainzId"] @@ -1196,7 +1188,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock): "musicbrainzId": str(uuid.uuid4()), "published": published.isoformat(), "released": released.isoformat(), - "cover": { + "image": { "type": "Link", "href": "https://cover.image/test.png", "mediaType": "image/png", @@ -1222,7 +1214,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock): ], }, } - r_mock.get(data["track"]["album"]["cover"]["href"], body=io.BytesIO(b"coucou")) + r_mock.get(data["track"]["album"]["image"]["href"], body=io.BytesIO(b"coucou")) serializer = serializers.UploadSerializer(data=data, context={"activity": activity}) assert serializer.is_valid(raise_exception=True) @@ -1266,7 +1258,7 @@ def test_activity_pub_upload_serializer_from_ap_update(factories, mocker, now, r "library": library.fid, "track": serializers.TrackSerializer(upload.track).data, } - r_mock.get(data["track"]["album"]["cover"]["href"], body=io.BytesIO(b"coucou")) + r_mock.get(data["track"]["album"]["image"]["url"], body=io.BytesIO(b"coucou")) serializer = serializers.UploadSerializer(upload, data=data) assert serializer.is_valid(raise_exception=True) @@ -1628,7 +1620,6 @@ def test_channel_actor_outbox_serializer(factories): "@context": jsonld.get_default_context(), "type": "OrderedCollection", "id": channel.actor.outbox_url, - "actor": channel.actor.fid, "attributedTo": channel.actor.fid, "totalItems": len(uploads), "first": channel.actor.outbox_url + "?page=1", diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py index f6528bab2a23152836f01d05db47839e6da5d388..8b3ec872511c845a3c2eb0e9872fb8cfc73a8783 100644 --- a/api/tests/federation/test_views.py +++ b/api/tests/federation/test_views.py @@ -384,11 +384,6 @@ def test_music_upload_detail_private_approved_follow( ("text/html,application/xhtml+xml", True, True), ("text/html,application/json", True, True), ("", True, False), - ( - "*/*", - True, - False, - ), # XXX: compat with older versions of Funkwhale that miss the Accept header (None, True, False), ("application/json", True, False), ("application/activity+json", True, False), diff --git a/api/tests/music/test_serializers.py b/api/tests/music/test_serializers.py index 1fb5ac120d0ce55dde5a9c526e4cc33dd97f0a69..802f7169c2b907bf55ddcbb1c5c026391eba4eaa 100644 --- a/api/tests/music/test_serializers.py +++ b/api/tests/music/test_serializers.py @@ -196,15 +196,6 @@ def test_album_serializer(factories, to_api_date): assert serializer.data == expected -def test_album_serializer_empty_cover(factories, to_api_date): - # XXX: BACKWARD COMPATIBILITY - album = factories["music.Album"](attachment_cover=None) - - serializer = serializers.AlbumSerializer(album) - - assert serializer.data["cover"] == {} - - def test_track_serializer(factories, to_api_date): actor = factories["federation.Actor"]() upload = factories["music.Upload"]( diff --git a/api/tests/music/test_tasks.py b/api/tests/music/test_tasks.py index edb937d81eb28c07d5d0f740651881983418aaa8..573f04f1f0de0b22be0584a63fdeee6426271a3c 100644 --- a/api/tests/music/test_tasks.py +++ b/api/tests/music/test_tasks.py @@ -660,7 +660,7 @@ def test_federation_audio_track_to_metadata(now, mocker): }, } ], - "cover": { + "image": { "type": "Link", "href": "http://cover.test", "mediaType": "image/png", @@ -713,8 +713,8 @@ def test_federation_audio_track_to_metadata(now, mocker): "tags": ["AlbumTag"], "description": {"content_type": "text/plain", "text": "album desc"}, "cover_data": { - "mimetype": serializer.validated_data["album"]["cover"]["mediaType"], - "url": serializer.validated_data["album"]["cover"]["href"], + "mimetype": serializer.validated_data["album"]["image"]["mediaType"], + "url": serializer.validated_data["album"]["image"]["href"], }, "artists": [ { diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 7e96f46c049ba72a3201fca72c8062320f52b076..81988a6b38d9b82d1f06172be32620e980bbba89 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -1307,9 +1307,7 @@ def test_get_upload_audio_metadata(logged_in_api_client, factories): assert response.data == serializer.validated_data -@pytest.mark.parametrize("use_fts", [True, False]) -def test_search_get(use_fts, settings, logged_in_api_client, factories): - settings.USE_FULL_TEXT_SEARCH = use_fts +def test_search_get(logged_in_api_client, factories): artist = factories["music.Artist"](name="Foo Fighters") album = factories["music.Album"](title="Foo Bar") track = factories["music.Track"](title="Foo Baz") @@ -1332,8 +1330,7 @@ def test_search_get(use_fts, settings, logged_in_api_client, factories): assert response.data == expected -def test_search_get_fts_advanced(settings, logged_in_api_client, factories): - settings.USE_FULL_TEXT_SEARCH = True +def test_search_get_fts_advanced(logged_in_api_client, factories): artist1 = factories["music.Artist"](name="Foo Bighters") artist2 = factories["music.Artist"](name="Bar Fighter") factories["music.Artist"]() @@ -1353,8 +1350,7 @@ def test_search_get_fts_advanced(settings, logged_in_api_client, factories): assert response.data == expected -def test_search_get_fts_stop_words(settings, logged_in_api_client, factories): - settings.USE_FULL_TEXT_SEARCH = True +def test_search_get_fts_stop_words(logged_in_api_client, factories): artist = factories["music.Artist"](name="she") factories["music.Artist"](name="something else") diff --git a/docs/api/definitions.yml b/docs/api/definitions.yml index 249eb7a754cfb81d97af0ab12b7bcca57a9d1aff..71b9893c9f6c10c425eb46cb15506e06dffc126a 100644 --- a/docs/api/definitions.yml +++ b/docs/api/definitions.yml @@ -720,7 +720,7 @@ User: type: "string" example: "Alice Kingsley" avatar: - $ref: "#/Avatar" + $ref: "#/Attachment" Me: type: "object" @@ -767,30 +767,8 @@ Me: via request headers isn't possible. The token expires after 3 days by default. -Avatar: - type: "object" - properties: - original: - type: "string" - format: "uri" - description: "Original image URL" - example: "http://yourinstance/media/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996.jpg" - square_crop: - type: "string" - format: "uri" - description: "400x400 thumbnail URL" - example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-400x400-70.jpg" - small_square_crop: - type: "string" - format: "uri" - description: "50x50 thumbnail URL" - example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-50x50-70.jpg" - medium_square_crop: - type: "string" - format: "uri" - description: "200x200 thumbnail URL" - example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-200x200-70.jpg" -QuotaStatus: + + QuotaStatus: type: "object" properties: max: diff --git a/docs/swagger.yml b/docs/swagger.yml index 0c3a0b1d98598d9929b0c4a12133ae2506a13a1a..4da3a52b47166ea98a0f9ccda9bca779eba67a90 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -296,7 +296,7 @@ paths: responses: 200: $ref: "#/responses/200" - /api/v1/users/users/me/: + /api/v1/users/me/: get: summary: Retrive profile information description: | diff --git a/front/src/EmbedFrame.vue b/front/src/EmbedFrame.vue index 67dc02303618afd72665918f31cd859cea0f5598..93d04d5e7ba05ea7f3b4e2c2623e23c9725d71ec 100644 --- a/front/src/EmbedFrame.vue +++ b/front/src/EmbedFrame.vue @@ -337,7 +337,7 @@ export default { }, getCover(albumCover) { if (albumCover) { - return albumCover.medium_square_crop + return albumCover.urls.medium_square_crop } }, getSources (uploads) { diff --git a/front/src/components/Queue.vue b/front/src/components/Queue.vue index 4df47954e83752f1580bea300570e3212ca13797..8966c889c6f982243f10512d18dd5e186dfc3b9a 100644 --- a/front/src/components/Queue.vue +++ b/front/src/components/Queue.vue @@ -6,8 +6,8 @@ <div class="ui six wide column current-track"> <div class="ui basic segment" id="player"> <template v-if="currentTrack"> - <img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)"> - <img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)"> + <img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)"> + <img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)"> <img class="ui image" alt="" v-else src="../assets/audio/default-cover.png"> <h1 class="ui header"> <div class="content ellipsis"> @@ -159,8 +159,8 @@ <i class="grip lines icon"></i> </td> <td class="image-cell" @click="$store.dispatch('queue/currentIndex', index)"> - <img class="ui mini image" alt="" v-if="track.cover && track.cover.original" :src="$store.getters['instance/absoluteUrl'](track.cover.medium_square_crop)"> - <img class="ui mini image" alt="" v-else-if="track.album && track.album.cover && track.album.cover.original" :src="$store.getters['instance/absoluteUrl'](track.album.cover.medium_square_crop)"> + <img class="ui mini image" alt="" v-if="track.cover && track.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](track.cover.urls.medium_square_crop)"> + <img class="ui mini image" alt="" v-else-if="track.album && track.album.cover && track.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)"> <img class="ui mini image" alt="" v-else src="../assets/audio/default-cover.png"> </td> <td colspan="3" @click="$store.dispatch('queue/currentIndex', index)"> diff --git a/front/src/components/Sidebar.vue b/front/src/components/Sidebar.vue index e41035687223ee90e4e5027448e604ec3fecab9c..5b176d6c73bf32b90625c8420169a5eacdfd4e7d 100644 --- a/front/src/components/Sidebar.vue +++ b/front/src/components/Sidebar.vue @@ -78,7 +78,7 @@ </router-link> <div class="item"> <div class="ui user-dropdown dropdown" > - <img class="ui avatar image" alt="" v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.square_crop" :src="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.square_crop)" /> + <img class="ui avatar image" alt="" v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.urls.square_crop" :src="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.urls.square_crop)" /> <actor-avatar v-else :actor="{preferred_username: $store.state.auth.username, full_username: $store.state.auth.username}" /> <div class="menu"> <router-link class="item" :to="{name: 'profile.overview', params: {username: $store.state.auth.username}}"><translate translate-context="*/*/*/Noun">Profile</translate></router-link> diff --git a/front/src/components/audio/ArtistLabel.vue b/front/src/components/audio/ArtistLabel.vue index a5e98c2577bfda60ca900a83b84768ef2995ccaf..659d0884f689b4abf4448c3cb2faa14cd38820ec 100644 --- a/front/src/components/audio/ArtistLabel.vue +++ b/front/src/components/audio/ArtistLabel.vue @@ -1,6 +1,6 @@ <template> <router-link class="artist-label ui image label" :to="route"> - <img :class="[{circular: artist.content_category != 'podcast'}]" alt="" v-if="artist.cover && artist.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](artist.cover.small_square_crop)" /> + <img alt="" :class="[{circular: artist.content_category != 'podcast'}]" v-if="artist.cover && artist.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](artist.cover.urls.medium_square_crop)" /> <i :class="[artist.content_category != 'podcast' ? 'circular' : 'bordered', 'inverted violet users icon']" v-else /> {{ artist.name }} </router-link> diff --git a/front/src/components/audio/ChannelCard.vue b/front/src/components/audio/ChannelCard.vue index d51123068624171092f2ff3646e35c9656b603a6..78cc14c443cf8d696702ee96adb45af94f8578c6 100644 --- a/front/src/components/audio/ChannelCard.vue +++ b/front/src/components/audio/ChannelCard.vue @@ -60,7 +60,7 @@ export default { computed: { imageUrl () { if (this.object.artist.cover) { - return this.$store.getters['instance/absoluteUrl'](this.object.artist.cover.medium_square_crop) + return this.$store.getters['instance/absoluteUrl'](this.object.artist.cover.urls.medium_square_crop) } }, urlId () { diff --git a/front/src/components/audio/ChannelEntryCard.vue b/front/src/components/audio/ChannelEntryCard.vue index 39c8eb62e3987f5bf0fd54cb90cdbc16c357f74d..5430b81f7d5d20e231f4e98b9b609ef65bdb9f0f 100644 --- a/front/src/components/audio/ChannelEntryCard.vue +++ b/front/src/components/audio/ChannelEntryCard.vue @@ -7,8 +7,8 @@ @click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})" alt="" class="channel-image image" - v-if="cover && cover.original" - v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)"> + v-if="cover && cover.urls.original" + v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)"> <span @click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})" class="channel-image image" @@ -17,8 +17,8 @@ @click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})" alt="" class="channel-image image" - v-else-if="entry.album && entry.album.cover && entry.album.cover.original" - v-lazy="$store.getters['instance/absoluteUrl'](entry.album.cover.square_crop)"> + v-else-if="entry.album && entry.album.cover && entry.album.cover.urls.original" + v-lazy="$store.getters['instance/absoluteUrl'](entry.album.cover.urls.square_crop)"> <img @click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})" alt="" diff --git a/front/src/components/audio/ChannelSerieCard.vue b/front/src/components/audio/ChannelSerieCard.vue index bc6fccad643c4a7feab431e371b7918c19a5d2eb..55466e202f9cf825e7e116ca4e5a697279a2a876 100644 --- a/front/src/components/audio/ChannelSerieCard.vue +++ b/front/src/components/audio/ChannelSerieCard.vue @@ -1,10 +1,10 @@ <template> <div class="channel-serie-card"> <div class="two-images"> - <img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-if="cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)"> - <img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png"> - <img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-if="cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)"> - <img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png"> + <img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-if="cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)"> + <img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-else src="../../assets/audio/default-cover.png"> + <img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-if="cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)"> + <img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-else src="../../assets/audio/default-cover.png"> </div> <div class="content ellipsis"> <strong> diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue index d6e5e95da94672a059da94918098f20b750b2e94..b9f0f660427d0033121ac3acfc0f1c30fe7fdedd 100644 --- a/front/src/components/audio/Player.vue +++ b/front/src/components/audio/Player.vue @@ -10,9 +10,9 @@ <div class="controls track-controls queue-not-focused desktop-and-up"> <div class="ui tiny image" @click.stop.prevent="$router.push({name: 'library.tracks.detail', params: {id: currentTrack.id }})"> - <img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)"> - <img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)"> - <img v-else src="../../assets/audio/default-cover.png" alt=""> + <img alt="" ref="cover" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)"> + <img alt="" ref="cover" v-else-if="currentTrack.album && currentTrack.album.cover.urls && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)"> + <img alt="" v-else src="../../assets/audio/default-cover.png"> </div> <div @click.stop.prevent="" class="middle aligned content ellipsis"> <strong> @@ -30,9 +30,9 @@ </div> <div class="controls track-controls queue-not-focused tablet-and-below"> <div class="ui tiny image"> - <img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)"> - <img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)"> - <img v-else src="../../assets/audio/default-cover.png" alt=""> + <img alt="" ref="cover" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)"> + <img alt="" ref="cover" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)"> + <img alt="" v-else src="../../assets/audio/default-cover.png"> </div> <div class="middle aligned content ellipsis"> <strong> @@ -738,12 +738,12 @@ export default { if (this.currentTrack.album) { metadata.album = this.currentTrack.album.title metadata.artwork = [ - { src: this.currentTrack.album.cover.original, sizes: '96x96', type: 'image/png' }, - { src: this.currentTrack.album.cover.original, sizes: '128x128', type: 'image/png' }, - { src: this.currentTrack.album.cover.original, sizes: '192x192', type: 'image/png' }, - { src: this.currentTrack.album.cover.original, sizes: '256x256', type: 'image/png' }, - { src: this.currentTrack.album.cover.original, sizes: '384x384', type: 'image/png' }, - { src: this.currentTrack.album.cover.original, sizes: '512x512', type: 'image/png' }, + { src: this.currentTrack.album.cover.urls.original, sizes: '96x96', type: 'image/png' }, + { src: this.currentTrack.album.cover.urls.original, sizes: '128x128', type: 'image/png' }, + { src: this.currentTrack.album.cover.urls.original, sizes: '192x192', type: 'image/png' }, + { src: this.currentTrack.album.cover.urls.original, sizes: '256x256', type: 'image/png' }, + { src: this.currentTrack.album.cover.urls.original, sizes: '384x384', type: 'image/png' }, + { src: this.currentTrack.album.cover.urls.original, sizes: '512x512', type: 'image/png' }, ] } navigator.mediaSession.metadata = new MediaMetadata(metadata); diff --git a/front/src/components/audio/album/Card.vue b/front/src/components/audio/album/Card.vue index 9655f75aaadd305c2080ad38dc207d5dfb58ac27..aafa2e4a439b31a2cc586a22fb0ac10287e2c784 100644 --- a/front/src/components/audio/album/Card.vue +++ b/front/src/components/audio/album/Card.vue @@ -2,7 +2,7 @@ <div class="card app-card component-album-card"> <div @click="$router.push({name: 'library.albums.detail', params: {id: album.id}})" - :class="['ui', 'head-image', 'image', {'default-cover': !album.cover.original}]" v-lazy:background-image="imageUrl"> + :class="['ui', 'head-image', 'image', {'default-cover': !album.cover || !album.cover.urls.original}]" v-lazy:background-image="imageUrl"> <play-button :icon-only="true" :is-playable="album.is_playable" :button-classes="['ui', 'circular', 'large', 'vibrant', 'icon', 'button']" :album="album"></play-button> </div> <div class="content"> @@ -38,8 +38,8 @@ export default { }, computed: { imageUrl () { - if (this.album.cover.original) { - return this.$store.getters['instance/absoluteUrl'](this.album.cover.medium_square_crop) + if (this.album.cover && this.album.cover.urls.original) { + return this.$store.getters['instance/absoluteUrl'](this.album.cover.urls.medium_square_crop) } } } diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue index 813a1183ee140d6e8ce7f78163654ed50031de7d..46533fed9345d5b4f7d2c5cb0e3ded8c4808937d 100644 --- a/front/src/components/audio/artist/Card.vue +++ b/front/src/components/audio/artist/Card.vue @@ -2,7 +2,7 @@ <div class="app-card card"> <div @click="$router.push({name: 'library.artists.detail', params: {id: artist.id}})" - :class="['ui', 'head-image', 'circular', 'image', {'default-cover': !cover.original}]" v-lazy:background-image="imageUrl"> + :class="['ui', 'head-image', 'circular', 'image', {'default-cover': !cover || !cover.urls.original}]" v-lazy:background-image="imageUrl"> <play-button :icon-only="true" :is-playable="artist.is_playable" :button-classes="['ui', 'circular', 'large', 'vibrant', 'icon', 'button']" :artist="artist"></play-button> </div> <div class="content"> @@ -40,19 +40,19 @@ export default { computed: { imageUrl () { let cover = this.cover - if (cover.original) { - return this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop) + if (cover && cover.urls.original) { + return this.$store.getters['instance/absoluteUrl'](cover.urls.medium_square_crop) } }, cover () { - if (this.artist.cover && this.artist.cover.original) { + if (this.artist.cover && this.artist.cover.urls.original) { return this.artist.cover } return this.artist.albums.map((a) => { return a.cover }).filter((c) => { - return c && c.original - })[0] || {} + return c && c.urls.original + })[0] }, } } diff --git a/front/src/components/audio/track/Row.vue b/front/src/components/audio/track/Row.vue index 94463a22bd95975f58104c26afcb7b946677508d..66363ea5fa666632a83ea0e060e291e25a0d4f3d 100644 --- a/front/src/components/audio/track/Row.vue +++ b/front/src/components/audio/track/Row.vue @@ -4,8 +4,8 @@ <play-button :class="['basic', {vibrant: currentTrack && isPlaying && track.id === currentTrack.id}, 'icon']" :discrete="true" :is-playable="playable" :track="track"></play-button> </td> <td> - <img class="ui mini image" alt="" v-if="track.album && track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.small_square_crop)"> - <img class="ui mini image" alt="" v-else src="../../../assets/audio/default-cover.png"> + <img alt="" class="ui mini image" v-if="track.album && track.album.cover && track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)"> + <img alt="" class="ui mini image" v-else src="../../../assets/audio/default-cover.png"> </td> <td colspan="6"> <router-link class="track" :to="{name: 'library.tracks.detail', params: {id: track.id }}"> diff --git a/front/src/components/audio/track/Widget.vue b/front/src/components/audio/track/Widget.vue index 0afe4f512a5848c51f539468774e42f6c6b7d1c8..4092d054d55dccdd621f9aecc64bda47145b44bc 100644 --- a/front/src/components/audio/track/Widget.vue +++ b/front/src/components/audio/track/Widget.vue @@ -7,7 +7,7 @@ <div v-if="count > 0" class="ui divided unstackable items"> <div :class="['item', itemClasses]" v-for="object in objects" :key="object.id"> <div class="ui tiny image"> - <img alt="" v-if="object.track.album && object.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.medium_square_crop)"> + <img alt="" v-if="object.track.album && object.track.album.cover" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.urls.medium_square_crop)"> <img alt="" v-else src="../../../assets/audio/default-cover.png"> <play-button class="play-overlay" :icon-only="true" :button-classes="['ui', 'circular', 'tiny', 'vibrant', 'icon', 'button']" :track="object.track"></play-button> </div> diff --git a/front/src/components/auth/Settings.vue b/front/src/components/auth/Settings.vue index 41c60fc44cfe1bef0a72d55a082fa84147486a60..94f033dfe20c301d7bda035694a72e7a5452f582 100644 --- a/front/src/components/auth/Settings.vue +++ b/front/src/components/auth/Settings.vue @@ -416,12 +416,12 @@ export default { this.settings.errors = [] let self = this let payload = this.settingsValues - let url = `users/users/${this.$store.state.auth.username}/` + let url = `users/${this.$store.state.auth.username}/` return axios.patch(url, payload).then( response => { logger.default.info("Updated settings successfully") self.settings.success = true - return axios.get("users/users/me/").then(response => { + return axios.get("users/me/").then(response => { self.$store.dispatch("auth/updateProfile", response.data) }) }, @@ -487,7 +487,7 @@ export default { this.avatarErrors = [] let self = this axios - .patch(`users/users/${this.$store.state.auth.username}/`, {avatar: uuid}) + .patch(`users/${this.$store.state.auth.username}/`, {avatar: uuid}) .then( response => { this.isLoadingAvatar = false @@ -538,7 +538,7 @@ export default { confirm: true, password: this.password, } - axios.delete(`users/users/me/`, {data: payload}) + axios.delete(`users/me/`, {data: payload}) .then( response => { self.isDeletingAccount = false diff --git a/front/src/components/auth/SubsonicTokenForm.vue b/front/src/components/auth/SubsonicTokenForm.vue index 74622f1fa8c395db0e0e0547e01c77411c5fe28d..b724d31fbaf9d8278e8f130b0e3d5e0843fd092e 100644 --- a/front/src/components/auth/SubsonicTokenForm.vue +++ b/front/src/components/auth/SubsonicTokenForm.vue @@ -87,7 +87,7 @@ export default { this.errors = [] this.isLoading = true let self = this - let url = `users/users/${this.$store.state.auth.username}/subsonic-token/` + let url = `users/${this.$store.state.auth.username}/subsonic-token/` return axios.get(url).then(response => { self.token = response.data['subsonic_api_token'] self.isLoading = false @@ -102,7 +102,7 @@ export default { this.errors = [] this.isLoading = true let self = this - let url = `users/users/${this.$store.state.auth.username}/subsonic-token/` + let url = `users/${this.$store.state.auth.username}/subsonic-token/` return axios.post(url, {}).then(response => { self.showToken = true self.token = response.data['subsonic_api_token'] @@ -119,7 +119,7 @@ export default { this.errors = [] this.isLoading = true let self = this - let url = `users/users/${this.$store.state.auth.username}/subsonic-token/` + let url = `users/${this.$store.state.auth.username}/subsonic-token/` return axios.delete(url).then(response => { self.isLoading = false self.token = null diff --git a/front/src/components/channels/UploadForm.vue b/front/src/components/channels/UploadForm.vue index f4b405b140b62f77649667b555161489fdd4594e..f40fe11791f88c676331d96b1158eeeb67882335 100644 --- a/front/src/components/channels/UploadForm.vue +++ b/front/src/components/channels/UploadForm.vue @@ -347,7 +347,7 @@ export default { }, fetchQuota () { let self = this - axios.get('users/users/me/').then((response) => { + axios.get('users/me/').then((response) => { self.quotaStatus = response.data.quota_status }) }, @@ -391,8 +391,8 @@ export default { value: c.uuid, selected: self.channel && self.channel.uuid === c.uuid, } - if (c.artist.cover && c.artist.cover.small_square_crop) { - let coverUrl = self.$store.getters['instance/absoluteUrl'](c.artist.cover.small_square_crop) + if (c.artist.cover && c.artist.cover.urls.medium_square_crop) { + let coverUrl = self.$store.getters['instance/absoluteUrl'](c.artist.cover.urls.medium_square_crop) d.image = coverUrl if (c.artist.content_category === 'podcast') { d.imageClass = 'ui image' diff --git a/front/src/components/common/ActorAvatar.vue b/front/src/components/common/ActorAvatar.vue index 441d10b7d5139148275f944781f51ec3a259f535..742271ab4baa65d712cb197ca4f9fd948e48275e 100644 --- a/front/src/components/common/ActorAvatar.vue +++ b/front/src/components/common/ActorAvatar.vue @@ -1,5 +1,5 @@ <template> - <img alt="" v-if="actor.icon && actor.icon.original" :src="actor.icon.small_square_crop" class="ui avatar circular image" /> + <img alt="" v-if="actor.icon && actor.icon.urls.original" :src="actor.icon.urls.medium_square_crop" class="ui avatar circular image" /> <span v-else :style="defaultAvatarStyle" class="ui avatar circular label">{{ actor.preferred_username[0]}}</span> </template> diff --git a/front/src/components/common/UserLink.vue b/front/src/components/common/UserLink.vue index b2bf821c699a9b543a71c5460ee8ca0e12d01336..6a372e20b3afcf2efc984f7047cb30a1937adda4 100644 --- a/front/src/components/common/UserLink.vue +++ b/front/src/components/common/UserLink.vue @@ -4,8 +4,8 @@ <img class="ui tiny circular avatar" alt="" - v-if="user.avatar && user.avatar.small_square_crop" - v-lazy="$store.getters['instance/absoluteUrl'](user.avatar.small_square_crop)" /> + v-if="user.avatar && user.avatar.urls.medium_square_crop" + v-lazy="$store.getters['instance/absoluteUrl'](user.avatar.urls.medium_square_crop)" /> <span v-else :style="defaultAvatarStyle" class="ui circular label">{{ user.username[0]}}</span> </template> diff --git a/front/src/components/library/AlbumBase.vue b/front/src/components/library/AlbumBase.vue index 33e09896598a2ab9816a30c067d54b8c5ecca306..e50f5914930caabec02bd8ae177d008551413059 100644 --- a/front/src/components/library/AlbumBase.vue +++ b/front/src/components/library/AlbumBase.vue @@ -11,10 +11,10 @@ <div class="ui two column grid" v-if="isSerie"> <div class="column"> <div class="large two-images"> - <img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)"> - <img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png"> - <img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)"> - <img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png"> + <img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)"> + <img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png"> + <img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)"> + <img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png"> </div> </div> <div class="ui column right aligned"> @@ -53,8 +53,8 @@ </header> </div> <div v-else class="ui center aligned text padded basic segment"> - <img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)"> - <img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png"> + <img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)"> + <img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png"> <div class="ui hidden divider"></div> <header> <h2 class="ui header" :title="object.title"> diff --git a/front/src/components/library/ArtistBase.vue b/front/src/components/library/ArtistBase.vue index 87769b4ff2df65f0c437ac108d5be9eef425de8d..22038a88845f73f871e09d8e38e20d671a59fb77 100644 --- a/front/src/components/library/ArtistBase.vue +++ b/front/src/components/library/ArtistBase.vue @@ -235,12 +235,12 @@ export default { ) }, cover() { - if (this.object.cover && this.object.cover.original) { + if (this.object.cover && this.object.cover.urls.original) { return this.object.cover } return this.object.albums .filter(album => { - return album.cover && album.cover.original + return album.cover && album.cover.urls.original }) .map(album => { return album.cover @@ -253,12 +253,12 @@ export default { }) }, headerStyle() { - if (!this.cover || !this.cover.original) { + if (!this.cover || !this.cover.urls.original) { return "" } return ( "background-image: url(" + - this.$store.getters["instance/absoluteUrl"](this.cover.original) + + this.$store.getters["instance/absoluteUrl"](this.cover.urls.original) + ")" ) }, diff --git a/front/src/components/library/FileUpload.vue b/front/src/components/library/FileUpload.vue index 6d7ac605e1b7c231863ea373b290ece9a6e5d0e4..1782f0c188948be4cc14c8389af9d46ca3126c81 100644 --- a/front/src/components/library/FileUpload.vue +++ b/front/src/components/library/FileUpload.vue @@ -274,7 +274,7 @@ export default { fetchQuota () { let self = this self.isLoadingQuota = true - axios.get('users/users/me/').then((response) => { + axios.get('users/me/').then((response) => { self.quotaStatus = response.data.quota_status self.isLoadingQuota = false }) diff --git a/front/src/components/library/TrackBase.vue b/front/src/components/library/TrackBase.vue index 6410942ba1ac1ab0ee918ecb30f0efd5cccb5438..48637abad369d25cfedf02a5bcbf6043fd48159a 100644 --- a/front/src/components/library/TrackBase.vue +++ b/front/src/components/library/TrackBase.vue @@ -264,12 +264,12 @@ export default { return route.href }, headerStyle() { - if (!this.cover || !this.cover.original) { + if (!this.cover || !this.cover.urls.original) { return "" } return ( "background-image: url(" + - this.$store.getters["instance/absoluteUrl"](this.cover.original) + + this.$store.getters["instance/absoluteUrl"](this.cover.urls.original) + ")" ) }, diff --git a/front/src/components/library/TrackDetail.vue b/front/src/components/library/TrackDetail.vue index 62ac9a9e9e4b8af038e335611457bbb9217d7e3a..73015e41cf66ffe98354e3565d62afad4c16a58d 100644 --- a/front/src/components/library/TrackDetail.vue +++ b/front/src/components/library/TrackDetail.vue @@ -4,7 +4,7 @@ <section class="ui vertical stripe segment"> <div class="ui stackable grid row container"> <div class="six wide column"> - <img class="image" alt="" v-if="cover && cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)"> + <img alt="" class="image" v-if="cover && cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)"> <template v-if="upload"> <h3 class="ui header"> <translate key="1" v-if="track.artist.content_category === 'music'" translate-context="Content/*/*">Track Details</translate> @@ -223,7 +223,7 @@ export default { return this.licenseData }, cover () { - if (this.track.cover && this.track.cover.original) { + if (this.track.cover && this.track.cover.urls.original) { return this.track.cover } if (this.track.album && this.track.album.cover) { diff --git a/front/src/components/playlists/Editor.vue b/front/src/components/playlists/Editor.vue index 06c10f95709e7c392425d9c6d01ca4889edb3fd9..acde6f4d2244dcd958efbfe83f7ce2dd5cc66139 100644 --- a/front/src/components/playlists/Editor.vue +++ b/front/src/components/playlists/Editor.vue @@ -64,7 +64,7 @@ <tr v-for="(plt, index) in plts" :key="`${index}-${plt.track.id}`"> <td class="left aligned">{{ plt.index + 1}}</td> <td class="center aligned"> - <img alt="" class="ui mini image" v-if="plt.track.album && plt.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.small_square_crop)"> + <img alt="" class="ui mini image" v-if="plt.track.album && plt.track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.urls.medium_square_crop)"> <img alt="" class="ui mini image" v-else src="../../assets/audio/default-cover.png"> </td> <td colspan="4"> diff --git a/front/src/store/auth.js b/front/src/store/auth.js index 05cbf293d153f5c5db7d9f21a09e54b879703df2..c8dfdc86cfc28d8ea2661629cd8131cb7a347e38 100644 --- a/front/src/store/auth.js +++ b/front/src/store/auth.js @@ -182,7 +182,7 @@ export default { fetchProfile ({commit, dispatch, state}) { return new Promise((resolve, reject) => { - axios.get('users/users/me/').then((response) => { + axios.get('users/me/').then((response) => { logger.default.info('Successfully fetched user profile') dispatch('ui/initSettings', response.data.settings, { root: true }) dispatch('updateProfile', response.data).then(() => { diff --git a/front/src/store/playlists.js b/front/src/store/playlists.js index 60f8771ac994e2773760c2a3f4600c4d29e131f6..6c91208dc93254a3b354996afa6af7008a4e4c27 100644 --- a/front/src/store/playlists.js +++ b/front/src/store/playlists.js @@ -33,7 +33,7 @@ export default { let playlists = [] let url = 'playlists/' while (url != null) { - let response = await axios.get(url, {params: {user: userId}}) + let response = await axios.get(url, {params: {scope: "me"}}) playlists = [...playlists, ...response.data.results] url = response.data.next diff --git a/front/src/views/Notifications.vue b/front/src/views/Notifications.vue index ab2de0038b39a9fead91c267627171bb486eeb04..84315af9f663ede4371222da47bdfed7300471be 100644 --- a/front/src/views/Notifications.vue +++ b/front/src/views/Notifications.vue @@ -167,7 +167,7 @@ export default { } payload[field] = newDisplayDate let self = this - axios.patch(`users/users/${this.$store.state.auth.username}/`, payload).then((response) => { + axios.patch(`users/${this.$store.state.auth.username}/`, payload).then((response) => { self.$store.commit('auth/profilePartialUpdate', response.data) }) }, diff --git a/front/src/views/admin/ChannelDetail.vue b/front/src/views/admin/ChannelDetail.vue index 4183f76b5bddb13dbf1549cb61e64366a47aa73f..d9c4e151f8b14637bd20a8a506fefa08bd4fa897 100644 --- a/front/src/views/admin/ChannelDetail.vue +++ b/front/src/views/admin/ChannelDetail.vue @@ -9,7 +9,7 @@ <div class="ui column"> <div class="segment-content"> <h2 class="ui header"> - <img alt="" v-if="object.artist.cover && object.artist.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.artist.cover.square_crop)"> + <img alt="" v-if="object.artist.cover && object.artist.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.artist.cover.urls.square_crop)"> <img alt="" v-else src="../../assets/audio/default-cover.png"> <div class="content"> {{ object.artist.name | truncate(100) }} diff --git a/front/src/views/admin/library/AlbumDetail.vue b/front/src/views/admin/library/AlbumDetail.vue index 2aea60cd0b6198e89e6a2c23b33e0361912a9701..f9700c3ef0fcfb7cba9d1b188fc45be745a0c9e0 100644 --- a/front/src/views/admin/library/AlbumDetail.vue +++ b/front/src/views/admin/library/AlbumDetail.vue @@ -9,7 +9,7 @@ <div class="ui column"> <div class="segment-content"> <h2 class="ui header"> - <img alt="" v-if="object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)"> + <img alt="" v-if="object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)"> <img alt="" v-else src="../../../assets/audio/default-cover.png"> <div class="content"> {{ object.title | truncate(100) }} diff --git a/front/src/views/admin/library/ArtistDetail.vue b/front/src/views/admin/library/ArtistDetail.vue index cd887e529670913fe96f8bda0b3e75bd87a66000..785cb3d22acf3f008f92f0d98bc444e9a474a0c1 100644 --- a/front/src/views/admin/library/ArtistDetail.vue +++ b/front/src/views/admin/library/ArtistDetail.vue @@ -9,7 +9,7 @@ <div class="ui column"> <div class="segment-content"> <h2 class="ui header"> - <img alt="" v-if="object.cover && object.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)"> + <img alt="" v-if="object.cover && object.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)"> <img alt="" v-else src="../../../assets/audio/default-cover.png"> <div class="content"> {{ object.name | truncate(100) }} diff --git a/front/src/views/admin/library/TrackDetail.vue b/front/src/views/admin/library/TrackDetail.vue index 40517a30408c17a108ae0d745d41192db67732e3..066041f693d59989bfd639d456990a04dfd7599a 100644 --- a/front/src/views/admin/library/TrackDetail.vue +++ b/front/src/views/admin/library/TrackDetail.vue @@ -9,7 +9,7 @@ <div class="ui column"> <div class="segment-content"> <h2 class="ui header"> - <img alt="" v-if="object.cover && object.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)"> + <img alt="" v-if="object.cover && object.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)"> <img alt="" v-else src="../../../assets/audio/default-cover.png"> <div class="content"> {{ object.title | truncate(100) }} diff --git a/front/src/views/auth/ProfileBase.vue b/front/src/views/auth/ProfileBase.vue index 751fa4017ccb647c2bf0f0c369d783c30262075e..d378f743b3bb9fb4a262e907f9a29000b78e731b 100644 --- a/front/src/views/auth/ProfileBase.vue +++ b/front/src/views/auth/ProfileBase.vue @@ -27,7 +27,7 @@ </div> <h1 class="ui center aligned icon header"> <i v-if="!object.icon" class="circular inverted user success icon"></i> - <img alt="" class="ui big circular image" v-else v-lazy="$store.getters['instance/absoluteUrl'](object.icon.square_crop)" /> + <img alt="" class="ui big circular image" v-else v-lazy="$store.getters['instance/absoluteUrl'](object.icon.urls.square_crop)" /> <div class="ellispsis content"> <div class="ui very small hidden divider"></div> <span>{{ displayName }}</span> @@ -49,7 +49,7 @@ @updated="$emit('updated', $event)" :content="object.summary" :field-name="'summary'" - :update-url="`users/users/${$store.state.auth.username}/`" + :update-url="`users/${$store.state.auth.username}/`" :can-update="$store.state.auth.authenticated && object.full_username === $store.state.auth.fullUsername"></rendered-description> </div> </div> diff --git a/front/src/views/auth/ProfileOverview.vue b/front/src/views/auth/ProfileOverview.vue index bd61d63af3084a7572ffccb77b5f1457b87b5da7..7bd38bbf84a98a7423e5dc30f1832f3c43df6b60 100644 --- a/front/src/views/auth/ProfileOverview.vue +++ b/front/src/views/auth/ProfileOverview.vue @@ -5,7 +5,7 @@ @updated="$emit('updated', $event)" :content="object.summary" :field-name="'summary'" - :update-url="`users/users/${$store.state.auth.username}/`" + :update-url="`users/${$store.state.auth.username}/`" :can-update="$store.state.auth.authenticated && object.full_username === $store.state.auth.fullUsername"></rendered-description> <div class="ui hidden divider"></div> </div> diff --git a/front/src/views/channels/DetailBase.vue b/front/src/views/channels/DetailBase.vue index e531518170fbc7c4e202cd971bb2053312a4d424..6ab5395cd46117407be2a0e17672f6025e93a290 100644 --- a/front/src/views/channels/DetailBase.vue +++ b/front/src/views/channels/DetailBase.vue @@ -9,7 +9,7 @@ <div class="seven wide column"> <div class="ui two column grid"> <div class="column"> - <img alt="" class="huge channel-image" v-if="object.artist.cover" :src="$store.getters['instance/absoluteUrl'](object.artist.cover.medium_square_crop)"> + <img alt="" class="huge channel-image" v-if="object.artist.cover" :src="$store.getters['instance/absoluteUrl'](object.artist.cover.urls.medium_square_crop)"> <i v-else class="huge circular inverted users violet icon"></i> </div> <div class="ui column right aligned"> diff --git a/front/src/views/content/libraries/Quota.vue b/front/src/views/content/libraries/Quota.vue index 2a6f2f200eba73ec490c46479558f7b4ce96ff0e..ada8351ea903dff3d4a020103aeebe436a20f261 100644 --- a/front/src/views/content/libraries/Quota.vue +++ b/front/src/views/content/libraries/Quota.vue @@ -114,7 +114,7 @@ export default { fetch () { let self = this self.isLoading = true - axios.get('users/users/me/').then((response) => { + axios.get('users/me/').then((response) => { self.quotaStatus = response.data.quota_status self.isLoading = false }) diff --git a/front/tests/unit/specs/store/auth.spec.js b/front/tests/unit/specs/store/auth.spec.js index 3de563df3efe2e41067a2d68ba0d8acbfd60d75e..ee08c0061cd07847dfbb168a8704adb5972e8d05 100644 --- a/front/tests/unit/specs/store/auth.spec.js +++ b/front/tests/unit/specs/store/auth.spec.js @@ -146,7 +146,7 @@ describe('store/auth', () => { admin: true } } - moxios.stubRequest('users/users/me/', { + moxios.stubRequest('users/me/', { status: 200, response: profile })